Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve accessibility in prerendered form fields #1069

Open
royvanv opened this issue Oct 27, 2023 · 2 comments · May be fixed by statamic/cms#10993
Open

Improve accessibility in prerendered form fields #1069

royvanv opened this issue Oct 27, 2023 · 2 comments · May be fixed by statamic/cms#10993
Labels

Comments

@royvanv
Copy link

royvanv commented Oct 27, 2023

Currently, the prerendered form fields have no id attribute, so they can not be linked in the <label> using the for attribute. This hurts accessibility.

It would nice to have an autogenerated ID property in the field object. Probably the handle with a random suffix, to prevent duplicate IDs in the HTML of the page. In the templates these IDs should be used in the id attribute.

Antlers template:

{{ fields }}
    <div class="mb-2">
        <label for="{{ someGeneratedId }}" class="block">{{ display }}</label>
        {{ field }}
    </div>
{{ /fields }}

Output:

<div class="mb-2">
    <label for="name-a382c0" class="block">Name</label>
    <input type="text" name="name" id="name-a382c0" value="">
</div>
@benfurfie
Copy link

It might be better to wrap the input and error in the label to make rendering simpler. E.g.

<div class="mb-2">
    <label class="block">
        <span class="block">Name</span>
        <input type="text" name="name" value="">
        <span>Error</span>
    </label>
</div>

But I agree this would be a good improvement.

@rachelmflowers
Copy link

rachelmflowers commented Apr 17, 2024

I was just about to create a similar issue. I actually have a few additional suggestions for accessibility.

I also personally prefer NOT to have my labels surround the inputs (unless they're checkboxes). But that's mainly personal preference

The default form views are missing some basic attributes necessary for making forms more accessible and easier to navigate with a screen reader.

Here's an overview of suggested updates.

  1. The form must indicate to a user how required fields are marked
  2. All labels should have a "for" attribute the corresponds to the input fields "id" attribute value
  3. All required fields need to have a visual indicator to show they are required and differentiate between non-required fields
  4. Form errors should include aria attributes to announce to a user when there is an error and where to find a description of the error
  5. Checkbox and radio groups must be surrounded by a <fieldset> with a <legend>

Here is how we have handled these requirements:
Forms > fields.antlers.html

{{ fields }}
    {{ if type != checkboxes || radio }}
        <div class="p-4 {{ error ?= "has-error" }}">
            <label for="{{ handle }}">
                {{ display }} {{ (validate | contains:required) ?= "<sup class='text-red-800'>*</sup>" }}
            </label>
            <div class="p-2">{{ field }}</div>
    {{ else }}
        <fieldset class="p-4" {{ if error }}aria-invalid="true" aria-describedby="{{ handle }}-error"{{ /if }}>
            <legend>{{ instructions }}</legend>  
            <div class="p-2">{{ field }}</div>
    {{ /if }}

    {{ if error }}
        <p id="{{ handle }}-error" class="text-red-800" aria-live="assertive">{{ error }}</p>
    {{ /if }}
    
    {{ type != 'checkboxes' || 'radio' ? '</div>' : '</fieldset>' }}
{{ /fields }}

Then for ALL fields the following attributes need to be added:

  1. id
  2. aria-invalid and aria-describedby if there is an error

As shown here in the forms > fields > default.antlers.html file:

<input
    id="{{ handle }}"
    type="{{ input_type ?? 'text' }}"
    name="{{ handle }}"
    value="{{ value }}"
    {{ if placeholder }}placeholder="{{ placeholder }}"{{ /if }}
    {{ if character_limit }}maxlength="{{ character_limit }}"{{ /if }}
    {{ if js_driver }}{{ js_attributes }}{{ /if }}
    {{ if validate|contains:required }}required{{ /if }}
    {{ if error }}aria-invalid="true" aria-describedby="{{ handle }}-error"{{ /if }}
>

Happy to get additional feedback from anyone else that has to meet WCAG AA standards :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants