quasarframework / quasar

Quasar Framework - Build high-performance VueJS user interfaces in record time
https://quasar.dev
MIT License
25.56k stars 3.45k forks source link

Improve accessibility for QTable #9689

Open dsl101 opened 3 years ago

dsl101 commented 3 years ago

Is your feature request related to a problem? Please describe. We have a number of visually impaired users, and are making app improvements to support screen-readers and other assistive tech. But the QTable component is proving to be a challenge—specifically the pagination controls. None of the focussable controls (number of records per page, back, forward, beginning, end) announce themselves properly.

Describe the solution you'd like Setting the aria-label for the number of rows picker to match the rows-per-page-label prop, and setting the aria-labels for the 4 'movement' buttons, either via a prop or as defaults.

Describe alternatives you've considered Using vue-announcer and focus tracking to announce the purpose of whatever is in focus, but this is clunky, error-prone, and vue-announcer announcements are easily defeated by the browser or focus changing (they appear to be low priority in screen-reader terms).

Additional context This was the specific feedback we had from one user:

“Pagination buttons in lists are unlabelled. I was looking at the participants list and was able to interact with the controls (like changing the number of items per page), but I had to guess which were the Next/Previous page buttons”

dsl101 commented 3 years ago

Actually, I think I can 'fix' this in our app using the pagination slot—I will do that, and once it's tested with visually impaired users, I can make a PR.

pdanpdan commented 2 years ago

We would need some help with this issue - if someone can do the research on the roles and aria attributes that are needed. I think it's a little more complex because I can see no way to avoid adding localized strings for the words page, 'first/last/prev/next page`.

dsl101 commented 2 years ago

Yes, localisation isn't something we've had to contend with yet, so I'm unfamiliar with the approach in the rest of Quasar. But in case it helps, only aria-label was needed to make it fully functional in our use case. This was the pagination component I used, based very much on the QTable one. There are 4 'fixed' strings for the buttons, and 2 'dynamic' ones for the QSelect and 'Showing...' div.

<q-select
  v-model="pagination.rowsPerPage"
  filled dense
  class="col-auto"
  :aria-label="`profiles per page: ${pagination.rowsPerPage}`"
  :options="[10, 20, 30, 50]"
/>
<div class="col-auto self-center">Showing {{tableStartUser}} to {{tableEndUser}} of {{customProfileData.length}}</div>
<div class="col-auto self-center">
  <q-btn
    round dense flat
    icon="first_page"
    aria-label="first page"
    :disable="pagination.page < 2"
    @click="pagination.page = 1"
  />
  <q-btn
    round dense flat
    icon="chevron_left"
    aria-label="page back"
    :disable="pagination.page < 2"
    @click="pagination.page--"
  />
  <q-btn
    round dense unelevated
    icon="chevron_right"
    aria-label="page forward"
    :disable="pagination.page >= maxTablePageNumber"
    @click="pagination.page++"
  />
  <q-btn
    round dense unelevated
    icon="last_page"
    aria-label="last page"
    :disable="pagination.page >= maxTablePageNumber"
    @click="pagination.page = maxTablePageNumber"
  />