patternfly-react
patternfly-react copied to clipboard
feat(NumberInput): add status validate icons
What: Closes #7730
used validated property based on TextInput using that property for such styling.
example: https://patternfly-react-pr-7806.surge.sh/components/number-input#with-status
Additional issues:
Preview: https://patternfly-react-pr-7806.surge.sh
A11y report: https://patternfly-react-pr-7806-a11y.surge.sh
LGTM! The only thing I noticed is if I try to enter a value in that input manually and hit backspace to enter a new number, it replaces the value with
0. That seems to just be an example thing in theonChangecallback - up/down arrows work to change the number, so works for me!
@mcoker - You'll see the same thing here https://www.patternfly.org/v4/components/number-input#with-unit-and-thresholds
It has to do with the fact we are limiting it to numbers (empty string isn't a number) between 0 and 10 in these cases.
@mcarrano - in this PR i've utilized the textinput inside of the numberinput... however, there is logic within InputGroup is checking whether any (non select/textarea/textinput) children have an ID and then using that ID to set a describedby on the TextInput
This makes sense if we are using a label with an ID.. but in this case, if we put an ID on the up/down buttons for the NumberInput it will use that ID in the describedby for the TextInput which doesn't really make sense. I can't imagine why a button would be used as a describedby.
I've made it so that Button is one of the excluded types to get an ID from for describedby, but noticed there was actually a test wanting exactly that (a button ID used for describedby) https://github.com/patternfly/patternfly-react/blob/main/packages/react-core/src/components/InputGroup/tests/InputGroup.test.tsx#L16
I've updated the test to use a label instead. I've asked around a bit and it seems to be going back to you as the person who can make the decision on whether or not we can stop using a button ID in the inputGroup as the describedby for the input.
there is logic within InputGroup is checking whether any (non select/textarea/textinput) children have an ID and then using that ID to set a describedby on the TextInput
@gitdallas IMO we should have a prop that disables that, and I'd argue making that the default when we can introduce that breaking change. The core examples show that same basic id/aria-describedby association (also using <button>s) - https://www.patternfly.org/v4/components/input-group/html#variations. I'm guessing when we created the <InputGroup> component, the automatic assigning of aria-describedby by any non-form-control with an id was based off of that and an attempt to improve the a11y of that form field. Though I'd argue that's too arbitrary of a way to describe a form control, and usage of this component has changed in a way that this logic is too simple. From my perspective, the input group component is more of a layout that puts a group of "controls" (have the common border/box formatting - dropdown, select, text input, control buttons, etc) next to one another and otherwise isn't particularly opinionated about what goes inside of it.
@mcoker - i agree about inputGroup should not be so opinionated, and found it odd to have it automatically generate describedby on a button id. As far as disabling that.. what if you did have multiple elements with IDs and you only wanted a specific one that wasn't the first (right now it just finds the first)?
To me it would make more sense to just pass the value for describedby if you want it - but at this point that would be a breaking change. Perhaps we could add a formControlDescribedBy prop where if set it would use that and otherwise it could keep doing what it's doing? But then if you don't want a describedby even though you do want an ID on something within the inputgroup.. what then? empty string for formControlDescribedBy? allow formControlDescribedBy to be string | false?
As far as the NumberInput - It's creating an inputGroup just around the [minus][input][plus] with no way to even put a label within that inputgroup. Maybe something should change there?
IMO, we shouldn't build on top of the functionality, just add the option to disable it. If we have the option to pass an id to the input group to describe a form control, it's no more work to just pass that to the form control itself, and a lot more straight forward. Also, there are more things that can go in input groups that presumably need good labels (and maybe description) just like those form controls - if we do this with form select, why not any other menu like that? Dropdown, select, a custom menu/menu-toggle, etc. Similar to a text input, we would describe text input group, search input, etc. Unless we build support for that, I think this "feature" is odd and not of that much value.
As far as the NumberInput - It's creating an inputGroup just around the [minus][input][plus] with no way to even put a label within that inputgroup. Maybe something should change there?
If I understand the question, we have props for aria-label for all of the number input elements, and the ability to pass props directly to them (to add an id to the input to associate it with a form <label>'s for attribute or add aria-describedby, for example) so I think that's good?
https://github.com/patternfly/patternfly-react/blob/bb63f5f216f6582c1b8a07a06082c190c9ace34a/packages/react-core/src/components/NumberInput/NumberInput.tsx#L45-L55
@mcoker - this would override the describedby passed in inputProps... but I suppose if we add your disableAssignDescribedby or something it could be used together... or maybe just letting inputProps.describedby have priority would be enough
@nicolethoen @tlabaj wanted to get your thoughts on the above convo. Looks like the enhacement is working as expected from a UX perspective, but it's unclear to me whether we should try to address the issue that @gitdallas raises about IDs. Thoughts?
TLDR on coker and my exchange, our final options were narrowed down to:
- allow
inputProps['aria-describedby']to persist over the automatic describedby creation this would basically mean changing this line in inputGroup to add&& child.props['aria-describedby'] === undefinedand I could also make it so that if an empty string exists for inputProps[aria-describedby] it would just leave out the property all together. - have a new property on
NumberInputcomponent that is something likedisabledAssignDescribedBythat just bypasses the feature.. with this they could still add the inputProps describedby if they wanted and it would be added. if they didn't add an inputProps describedby, the describedby prop wouldn't exist at all
this whole thing seems pretty edge casey, but need to figure something out
I went ahead and just made it so that if someone adds aria-describedby to the input props, they don't get overridden by the existing feature. Seems least invasive for this edge case. Functionality can be seen in new InputGroup tests.
do you have any more information about this scenario?
@nicolethoen it looks like this is partially an issue with Chromium (https://stackoverflow.com/questions/48299571/screen-reader-cannot-read-number-input-values-on-chrome).
With Firefox, changing the Number Input via Voice Over + arrow keys while in the input has the new value announced, though pressing the - or + buttons does not announce the new value. Safari acts similary to Firefox with some slight differences (works better when you just focus the input and press up/down arrow rather than "entering" the input via VO modifier + Shift + Down).
It is definitely odd that the change in value doesn't get announced in Chrome by default, even when changing the value via the actual input and not our own +/- buttons.
Adding aria live like I noted above seems to help resolve that in Chrome, but in Firefox the value ends up getting repeated by VO (pressing the minus button once would announce "89, 89, 89, 89" for me). So that may require a little more investigation.