Search code examples
accessibilitywai-aria

ARIA - How to indicate the maximum amount checkboxes the user may check


In my web application I present the user with a set of options, of which they are allowed to select a variable number. What is an accessible way to prevent the user from selecting too many items?

My markup looks like this:

<h3>Option Name</h3>
<p id="xyz">Select up to 3 items</p>
<div role="group" aria-describedby="xyz">
  <div role="checkbox"  aria-checked="true" > ... </div>
  ...
</div>

Initially I wanted to use aria-invalid="true" on the checkbox divs if the user tries to select an additional option beyond the maximum, but the spec indicates that aria-invalid is for a value that has been entered, whereas checking or unchecking options may not be considered entering a value.

I also considered using the aria-valuemax set of attributes on the parent group div, but like with aria-invalid the spec defines this in terms of values that are entered into the element, rather than state which is toggled by the actions of the user.

Currently, my thinking is to apply aria-disabled="true" to all non-selected checkbox divs if the user has selected the maximum, but I'm not sure if there's a way to indicate the reason for the aria-disabled attribute in the same way as you would for an aria-invalid element with an aria-errormessage.

I appreciate any feedback, thank you all for your time.


Solution

  • Notes:

    1. explicitly associate both the group label and the instruction with the grouping element. (you can use multiple sources to make up the accessible name for the group).
    2. aria-labelledby is used as aria-describedby on role=group without an acc name will not be announced.
    3. once the maximum number of checkboxes have been checked set aria-disabled=true on remaining.

    suggested code:

    <h3 id="grouplabel">Option Name </h3>
    <p id="xyz">Select up to 3 items</p>
    <div role="group" aria-labelledby="grouplabel xyz">
      <div role="checkbox"  aria-checked="true" > ... </div>
      ...
    </div>