Not sure if this has been asked before (I wasn't able to find an issue for it).
HTML5 allows two ways to associate a label with an input field. The first one is via the "for" attribute and an id, like
<div>
<label for="myInput">My Input</label>
<input type="text" id="myInput" />
</div>
The other is to use the label as a wrapper, like
<label>
My Input
<input type="text" />
</label>
When using the first method if no id is set the browser does not know about the relation between the label and the input. This isn't ideal for accessibility reasons. It's also not ideal when using "Testing Library" with the getByLabelText method to get the input - which simply won't return the correct input as there is no obvious relation.
Current versions of material ui input components use the first method. I propose to switch to the label wrapping method. I see two major benefits from this:
Possible disadvantages:
Yeah that would be nice. Styling is quite tricky though so it might not be viable or require a lot of effort. Adding an id prop to the TextField does not though which is all that is required to make it accessible.
The getByLabelText from @testing-library/react might be problematic because it doesn't use textContent but joins text nodes.
If you have problems with accessibility either check out our demos (94% lighthouse score; only contrast issues) or our tests for TextField which are written with @testing-library/react (especially the test with labels).
@konqi I believe It's in the public API landscape, I'm not sure we can change anything before v5 without introducing a breaking change. However, it's worth exploring.
I have done a quick benchmark, Bootstrap and Reakit use the same approach we do. I would suspect the label wrapping approach has customization issues, to explore.
I have done a quick benchmark, Bootstrap and Reakit, uses the same approach we do. I would suspect the label wrapping approach has customization issues.
Or they don't know about it?
Or they don't know about it?
I don't know, let's ask.
Hey @diegohaz, I was looking at your experimental API for solving the form problem in https://reakit.io/docs/form/, it's interesting! :). I was wondering, what's the tradeoff behind doing:
<Form>
<FormLabel name="name">
Name
</FormLabel>
<FormInput name="name" placeholder="John Doe" />
<FormMessage name="name" />
<FormSubmitButton>Submit</FormSubmitButton>
</Form>
and not?
<Form>
<FormLabel>
Name
<FormInput name="name" placeholder="John Doe" />
</FormLabel>
<FormMessage name="name" />
<FormSubmitButton>Submit</FormSubmitButton>
</Form>
Thanks.
94% lighthouse score; only contrast issues
@eps1lon Do we still have a few contrast issues?
@eps1lon to be honest, accessibility is not really my main concern here. I believe it's a side-effect of me having an id-allergy. So being forced to use Ids is my greatest pain. Reusability of components using Inputs is also reduced. e.g. when I render the same component twice, the same id exists twice on the dom - that simply shouldn't happen and is the reason why I avoid ids if possible.
I'd like to contribute to this (if I can) but wanted to give the idea a spin before I oversee some obvious reasons why the id-version makes perfect sense and/or is the better solution.
Yeah I totally get that. Creating ids is a common pain point currently. The upside of using ids is that you get to use aria-describedby or aria-controls. So even if we can switch to by default we would still advice our users to pass an id for the helper text.
Of the top of my head I can't find any strong concern against it. Only issue might be stacking context. Somebody would just have to look into it.
Just remember a11y isn't just for visually impaired. Label association helps mouse users as well (label clicking focuses inputs) and I believe password managers might as well. In the end it's about making your site more semantic which helps everyone to understand your page. Be it human or machine.
Reakit supports wrapping inputs with the native <label> (not <FormLabel>) just like one would do with HTML. The documentation uses this method specifically for checkboxes and radio buttons, but nothing prevents someone from using this for other input types.
FormLabel just exists so you can use the separate label approach without worrying about generating IDs. Reakit does this already.
But, as you noted, this is all experimental right now and may change in the future.
@diegohaz Thanks for the feedback!
I would like to change the labeling for the textField component, if you'd like me to do.
Having dived more into how accessible names are computed I can only see a benefit with not having to provide ids which would be quite nice since it gives less opportunity to make mistakes.
If somebody wants to work on this I would suggest making this work for
<FormControl>
<InputLabel>
label
<Input variant="outlined" />
</InputLabel>
</FormControl>
-- https://material-ui.com/components/text-fields/#components
Then we'll see how we can incorporate this approach into TextField and how backwards compatibility looks.
Most helpful comment
Having dived more into how accessible names are computed I can only see a benefit with not having to provide ids which would be quite nice since it gives less opportunity to make mistakes.
If somebody wants to work on this I would suggest making this work for
-- https://material-ui.com/components/text-fields/#components
Then we'll see how we can incorporate this approach into TextField and how backwards compatibility looks.