-
Notifications
You must be signed in to change notification settings - Fork 53
feat(Radio): added value, disabled, name, checked, defaultChecked and onChange props #206
Conversation
… the Radio component
Codecov Report
@@ Coverage Diff @@
## master #206 +/- ##
==========================================
+ Coverage 91.53% 91.78% +0.24%
==========================================
Files 61 61
Lines 1028 1047 +19
Branches 155 143 -12
==========================================
+ Hits 941 961 +20
Misses 83 83
+ Partials 4 3 -1
Continue to review full report at Codecov.
|
examplePath="components/Radio/States/RadioExampleChecked" | ||
> | ||
<Segment style={{ marginTop: '10px' }}> | ||
Use{' '} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I stole this from SUIR, I didn't know we can do this. Very cool! :D
Radio group is necessary for accessibility purposes. |
@jurokapsiar so according to the post, we should render the RadioGroup and the Radio as div elements with the proper roles. Should I actually replace the implementation with and style the ::before part to look like a radio button as part of this PR? If this is the final decision about how it should be defined, I would rather do this now then later.
|
-reverted the Radio to extend UIComponent
We'll pause this work while we first style the radio. This will require an icon or pseudo elements and some custom event handling. Let's make sure that works before designing this next phase, groups. |
-styles the Radio button with custom icon
looking into accessibility, but it will take more time to come up with a working solution if we do not want to use default input as is. looks like the missing thing is handling of the focused state. If not possible, you can take a look at https://www.w3.org/TR/wai-aria-practices/examples/radio/radio-1/radio-1.html which unfortunately does not work correctly with JAWS screen reader, but is a better starting point. |
@@ -1,6 +1,10 @@ | |||
import React from 'react' | |||
import { Radio } from '@stardust-ui/react' | |||
|
|||
const RadioExample = () => <Radio label="Make your choice" /> | |||
const handleChange = () => { | |||
console.log('The radio checked value was changed!') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
probably, it is better to use alert
calls here, if the intent is to make it clear to the client that some changes have happened
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense, will change it!
@@ -30,7 +30,7 @@ class ButtonGroup extends UIComponent<Extendable<IButtonGroupProps>, any> { | |||
/** An element type to render as (string or function). */ | |||
as: customPropTypes.as, | |||
|
|||
/** A button can take the width of its container. */ | |||
/** The buttons contained inside the ButtonGroup. */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 👍
/** Child content * */ | ||
children: PropTypes.node, | ||
|
||
/** Additional classes. */ | ||
className: PropTypes.string, | ||
|
||
/** Initial checked value. */ | ||
defaultChecked: PropTypes.bool, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this one is not used anywhere - should we delete it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
also, it seems that this one is rather pertains to RadioGroup
concept, rather than to individual Radio
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Every auto-controlled prop must have a default prop associated to it, that is why we have it. I may need to provide example usage of it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@kuzhelov , I added the usage of the default checked value. This value is intended to be used as a initial check value of the radio button. As the component is auto-controlled, the user should be able to initially set the value of the checked property. Please comment if you have some more doubts on this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok - but in that case let me share what my concerns are about. Now we have this defaultChecked
to be defined in prop types, but there is no such a property in the component's TS interface - with that it, essentially, means that me as a client is not able to safely specify value for it in the TS code (I mean, this prop won't be advertised as one that is supported by the component, so I could provide some string
value, for example).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, that is my fault, the defaultChecked prop SHOULD be provide in the TS interface. Thanks for the catch!
The current implementation of the Radio and the example of the group regarding accessibility are behaving the same as the https://www.w3.org/TR/wai-aria-practices/examples/radio/radio-1/radio-1.html The next thing that should be implemented is having the focused border around the buttons. Should we immediately check the button if it is focused, or should be have the same implementation as in the W3 example? What's the proposal for further checks/fixes? |
src/components/Radio/Radio.tsx
Outdated
} | ||
|
||
if (onChange) { | ||
onChange(e, { ...this.props, checked: !checked }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
worrying about the fact that this callback method is invoked before state change will be applied to component - in case of potential error in the logic provided by the callback state change won't be applied
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed, will move it before invoking the callback.
src/components/Radio/Radio.tsx
Outdated
|
||
private handleChange = (e: React.SyntheticEvent) => { | ||
const { onChange, disabled } = this.props | ||
const { checked } = this.state |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it would be more robust to obtain this flag directly from e.target.checked
- due to async state updates there is a room (although very small one) for the state
being out of sync with the component's visual look
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense. Will change it!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
couple of comments that we could discuss/address, other than that everything is 👍
-addressed comments in the PR
As the accessibility aspect of the radio group are pretty complicated, this PR will address ONLY the properties that needs to be implemented in the Radio, and then a dedicated PR will be created for the RadioGroup. |
src/components/Radio/Radio.tsx
Outdated
|
||
this.trySetState({ checked }) | ||
|
||
if (onChange) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
_.invoke()
does the check for you
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I replaced this with _.invoke, but I prefer much this type of invoking because I know for sure when clicking the property that it is used and invoke somewhere in the code, and with using the invoke, the name of the callback is just a string.
src/components/Radio/Radio.tsx
Outdated
circular: true, | ||
size: 'mini', | ||
variables: { | ||
color: checked ? variables.checkedIconColor : variables.uncheckedIconColor, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see you are already discussing this in #207. It would be great if, eventually, we would not need to touch variables in component code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unfortunately, this makes 'variables defined in theme' story a bit more complicated, as now we might need to get an access to component props there - as it is discussed in #207. This would be quite significant move, and we should consider whether there are any other not-so-radical alternatives. Still, totally agree that we should finally come up with solution that will eliminate this code from component's logic
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Exactly, I was not satisfied with having to use the variable in the renderComponent, but as I mention in the other PR we should either be able to define the variables depending on the state and props, or rethink about the API provided so far for the components.
-replaced onChange with _.invoke
# Conflicts: # CHANGELOG.md
-changed conformance test regarding the transparent handling of the events to check that the second argument is object containing all props instead of just all props -changed checked value to be read from state instead of event
-fixed console error for onChange not being provided to the input
Radio
This PR introduces the following props to the Radio component: value, disabled, checked, and onChange.
TODO
API Proposal
value
The HTML input value.
disabled
A radio can appear disabled and be unable to change states.
onChange
Callback invoked when the radio is clicked.
checked
Whether or not the radio is checked.