Skip to content

fix(VTextArea/VSelect): Fix labelling of select components for screen readers (a11y only) #20339

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

Open
wants to merge 7 commits into
base: master
Choose a base branch
from

Conversation

Martin-Idel
Copy link
Contributor

@Martin-Idel Martin-Idel commented Aug 15, 2024

Closes #19155
Closes #19156

Description

This PR solves accessibility problems in selection components. The current behaviour of a select field is the following:

  • The screen reader never reads the label
  • When in multi-select mode, the screen reader never announces which fields are actually selected in the list

The two separate commits solve these two issues: The first commit actually correctly attaches the lable of the selectbox to its input so that screen readers can pick this up and associate the label with the input, while the second commit puts a label to the Multiselect boxes (VSelect and VAutocomplete) which screen readers can use to read out whether that entry is currently selected or not.

This PR should introduce no change in behaviour for anybody not using a screenreader. It was tested with the screenreaders orca and JAWS (some of the latest versions).

Markup(s)

Bug: Not reading out the label. Playground link for reproduction:

https://play.vuetifyjs.com/#eNpdT8sKwjAQ/JVlL1HQVlBQpArevHj2YD3UukohaUKSFqT0392kFcVT5rHMTC4dOlumB2OStiHcYuZJGVl42uc1QNbOC2MijKTUtS+qmuwoRdGRpNJDO1f6TnKXo3LPHGFbcZRjGl8WZHGL9uk1QJbST3T6nx2UoTpLfyYxdaWtjAdHvhmWVcpo66EDSw/o4WG1AsG/EeEcgHOdB94Eu3AxEUeSUovp14sD2b2M1gzEWVt5F9fQPvRxE/YzXCarZLnBANbJAq9v6ylnYQ==
Using a screen reader, one can verify, that the label is not read out

Using the same Playground file with these fixes, the screen reader is now able to read it out.

Playground file for convenience:

<template>
  <v-app>
    <v-container>
      <v-select v-model="msg" :items="items" label="My label" />
    </v-container>
  </v-app>
</template>

<script setup>
  import { ref } from 'vue'

  const msg = ref('Hello')
  const items = ['Hello', 'World']
</script>

Bug: Not reading out the label in text areas. Playground link for reproduction:

https://play.vuetifyjs.com/#eNpdj81uwkAMhF/F3UtaqSTqD5cqVOLWS2+Veuj2sCQGIu2fvCYCId4dbxYkxM0zY3k+/x1Voq5ZxliPO1QfqmV00RrGT+0B2nFmYpzGSXTBsxk80sWaTMY9G0ID48yFHu1CK5c2WoE1q0l9H8oolpzucBtsj1SCG0Pi5lrV3Hdlp6C0zQ2iyNTREBkS8q6QDi4GYjgC4RpOsKbgoJLvqrwOIHcTgxDCIm88Vl9obYDfQLZ/0Nr/oMSBtwKk/dL3YDaCUT3l5tIlLer0rN7q9/plrvIwr1/V/xkW9G3G

Using the same Playground file with these fixes, the screen reader is now able to read it out.

Playground file for convenience:

<template>
  <v-app>
    <v-container>
      <v-textarea v-model="msg" label="My label" placeholder="My placeholder" />
    </v-container>
  </v-app>
</template>

<script setup>
  import { ref } from 'vue'

  const msg = ref('Hello World!\nTest other\nAnd again')
</script>

Bug: No information about which boxes are clicked in multiselect. Playground link for reproduction:

https://play.vuetifyjs.com/#eNpdkEFrwzAMhf+K8MUbtMmgg42SDnbbZecdmhyyVB0GOTa2Ehil/72y05C2J0vvE3pP3p9UDF356X0xDqi2qmK0nlrGj7oHqMZ1630uc9O5nlvTY7hKWYxI2PEsAIxr6w5Iu1rZ+FerBWztQGw8oSAOA94xI8ZRQH5vCbW/edn3/1QurJyDlY/JkjIFr8qbg6SNXTCeISIP013GehcYThDwCGc4BmdBy1/oNA4geyODHAK7NPG0119I5HTzvNAcWfjMVqB/XKCDbpL/5Che6rxSm+K12LyrVLwVL6q5AE2jduo=

Using the same Playground file with these fixes, the screen reader is now able to read it out.

Playground file for convenience:

<template>
  <v-app>
    <v-container>
      <v-select
        v-model="msg"
        :multiple="true"
        :items="items"
        label="My label"
      />
    </v-container>
  </v-app>
</template>

<script setup>
  import { ref } from 'vue'

  const msg = ref(['Hello'])
  const items = ['Hello', 'World']
</script>

Screenreaders don't read out the label for several
components, because it's not connected to the
component.
In multiselect comboboxes, screen readers currently
don't read out the checkboxes, which informs the
user which elements are selected

fixes vuetifyjs#19156
@Martin-Idel Martin-Idel changed the title Fix labelling fix(VTextArea/VSelect): Fix labelling Aug 15, 2024
@Martin-Idel Martin-Idel changed the title fix(VTextArea/VSelect): Fix labelling fix(VTextArea/VSelect): Fix labelling of select components for screen readers (a11y only) Aug 20, 2024
@KaelWD KaelWD force-pushed the master branch 3 times, most recently from 4c970f9 to 6a3285f Compare September 3, 2024 18:11
Copy link
Member

@johnleider johnleider left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are there any other inputs that we need to consider this for?

@@ -520,6 +520,7 @@ export const VAutocomplete = genericComponent<new <
modelValue={ isSelected }
ripple={ false }
tabindex="-1"
aria-label={ isSelected ? 'checked' : 'not checked' }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this need to use i18n?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably makes sense. I tried to add i18n (added English for most languages, I hope that would be okay).

@@ -440,6 +439,7 @@ export const VSelect = genericComponent<new <
modelValue={ isSelected }
ripple={ false }
tabindex="-1"
aria-label={ isSelected ? 'checked' : 'not checked' }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this need to use i18n?

@Martin-Idel Martin-Idel force-pushed the fix_labelling branch 3 times, most recently from f8a8069 to 941ef68 Compare February 28, 2025 20:17
@Martin-Idel
Copy link
Contributor Author

Regarding other parts where this might be needed: It needs to be multiselect checkboxes within a listbox and I could only find those in those two components - it works correctly for regular checkboxes.

@KaelWD
Copy link
Member

KaelWD commented Mar 3, 2025

Bug: Not reading out the label.

VFieldLabel already has for, it shouldn't need id and aria-labeledby as well if VSelect didn't also add aria-label to the input element (#17786)

Bug: Not reading out the label in text areas.

#21025, there's two labels with for but both are hidden when the field is active.

Bug: No information about which boxes are clicked in multiselect.

NVDA at least already reads "Hello not selected 1 of 2", adding the label to the checkbox seems redundant because now it says "Not checked hello not selected 1 of 2". Does JAWS support aria-selected and if so why isn't our current implementation of it working?
On android talkback I can't even get to the list items, the menu closes as soon as I try to focus it.

@J-Sek
Copy link
Contributor

J-Sek commented Mar 3, 2025

I don't see VCombobox among changes. Is it just an oversight or intentional?

@Martin-Idel
Copy link
Contributor Author

@KaelWD

Bug: Not reading out the label.

VFieldLabel already has for, it shouldn't need id and aria-labeledby as well if VSelect didn't also add aria-label to the input element (#17786)

So what you are suggesting is that removing the aria-label for the input element should be enough here? That sounds correct, I'll give that a try.

Bug: Not reading out the label in text areas.

#21025, there's two labels with for but both are hidden when the field is active.

I guess what you are suggesting is that the labels aria-hidden or visibility: hidden are not switched correctly between variants so your suggestion is to fix that bug instead of my approach here. Will you do this and I just remove my approach here?

Bug: No information about which boxes are clicked in multiselect.

NVDA at least already reads "Hello not selected 1 of 2", adding the label to the checkbox seems redundant because now it says "Not checked hello not selected 1 of 2". Does JAWS support aria-selected and if so why isn't our current implementation of it working?
On android talkback I can't even get to the list items, the menu closes as soon as I try to focus it.

Both JAWS and orca should in principle support "aria-selected". Checking my own reproduction link above I can now no longer reproduce it with orca, so maybe it was fixed on the screenreader's end. I'll ping my colleague to see whether they can still reproduce it with JAWS.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C: VSelect C: VTextarea T: bug Functionality that does not work as intended/expected
Projects
None yet
5 participants