Search code examples
javascripthtmlaccessibilitywai-aria

How to build an accesible button that is meant to toggle the readonly state of an entire form


I have a user account page where I would like users to see a very basic form with the details of their account and, on page load, I would like this form to be in a read-only state. If users want to edit their account details, they can click on an edit button which will dynamically remove the readonly state of all of the input fields.

I have the following:

<button
  type="button"
  aria-pressed="false"
  aria-controls="EditAccount"
>
  Edit Account Details
</button>
<form id="EditAccount" class="profile-form">
  <label for="first_name">First name</label>
  <input type="text" name="first_name" id="first_name" value="Maria" readonly>
  <label for="last_name">Last name</label>
  <input type="text" name="last_name" id="last_name" value="Juana" readonly>
  <button type="submit" hidden>Submit</button>
</form>

Would using the aria-controls attribute on the button be enough to let users that use assistive technologies know that the button is toggling the readonly state of the entire form?

I've found similar questions on Stack Overflow on how to toggle the readonly state of an entire form but none that address my accessibility concerns.

Would I need to use a different approach to make it clear to these users that the form is toggling between an editable and readonly state?


Solution

  • No, aria-controls is not what you want. While there are many ARIA attributes that allow toggling the value, and the toggling is announced by screen readers, there isn't one specifically for changing the readonly attribute.

    Yes, there is an aria-readonly that you could potentially toggle but it's a property attribute and not a state attribute. It's a fine distinction but in general, state attributes, such as aria-checked or aria-expanded, are expected to change/toggle, usually based on user interaction, and thus their state change is automatically announced by the screen reader without you having to do any extra coding (other than actually changing the value of the attribute).

    Property attributes are generally set once and don't change so the screen reader will not announce changes to these attributes. For example, aria-label or aria-multiline or aria-readonly. There's nothing that prevents you from changing the value of these attributes, and it's perfectly valid to do so, but the change will not be announced.

    In your case, it doesn't sound like you're changing the value of any ARIA attributes. You're using the built in readonly attribute on the <input>, right?

    When the user makes the change, do you visually notify the user that all the fields are editable now? Or do you rely on the appearance of the input field changing from readonly to editable to be the indicator?

    If you display a visible text message that says something like "all fields are editable now", then you can make that text message an aria-live region. If you don't display a message like that, then you can create a visibly hidden message just for screen reader users. From a UX perspective, it'd be better for everyone to know about the change, but without seeing your application, perhaps you're already notifying the users in some way.

    Assuming you have a text message that you display to users, then you could have something like this:

    <div aria-live="polite">
    </div>
    

    Then when you inject text into the container, it'll automatically be announced by screen readers.

    <div aria-live="polite">
      all fields are editable now
    </div>
    

    If you don't want that message to be visible, you can use a "sr-only" type class. There's nothing special about the name of that class. It's just a common name to use. See What is sr-only in Bootstrap 3?

    <div aria-live="polite" class="sr-only">
    </div>