From 2933baa0cebdc16fb2fc42cdf381064e112a4737 Mon Sep 17 00:00:00 2001 From: Roman Rizzi Date: Fri, 14 Oct 2022 13:28:20 -0300 Subject: [PATCH] A11Y: Signal the toggle header can reorder table elements. (#18597) While navigating the table, indicate what the button does and if the user pressed it or not. Also, don't lose focus after reordering elements. --- .../admin/addon/templates/users-list-show.hbs | 30 ++++++----- .../app/components/table-header-toggle.js | 54 ++++++++++++++++++- .../components/table-header-toggle.hbs | 4 +- config/locales/client.en.yml | 2 + 4 files changed, 74 insertions(+), 16 deletions(-) diff --git a/app/assets/javascripts/admin/addon/templates/users-list-show.hbs b/app/assets/javascripts/admin/addon/templates/users-list-show.hbs index c56b8a08627..87200df9ab4 100644 --- a/app/assets/javascripts/admin/addon/templates/users-list-show.hbs +++ b/app/assets/javascripts/admin/addon/templates/users-list-show.hbs @@ -15,22 +15,24 @@ {{#if this.model}} - +
- - - - - - - - - + + + + + + + + + + - {{#if this.siteSettings.must_approve_users}} - - {{/if}} - + {{#if this.siteSettings.must_approve_users}} + + {{/if}} + + {{#each this.model as |user|}} diff --git a/app/assets/javascripts/discourse/app/components/table-header-toggle.js b/app/assets/javascripts/discourse/app/components/table-header-toggle.js index 259bb0ca4ed..78dc01dffee 100644 --- a/app/assets/javascripts/discourse/app/components/table-header-toggle.js +++ b/app/assets/javascripts/discourse/app/components/table-header-toggle.js @@ -1,18 +1,32 @@ import Component from "@ember/component"; import { iconHTML } from "discourse-common/lib/icon-library"; import { htmlSafe } from "@ember/template"; +import { schedule } from "@ember/runloop"; +import discourseComputed from "discourse-common/utils/decorators"; +import I18n from "I18n"; export default Component.extend({ tagName: "th", classNames: ["sortable"], - attributeBindings: ["title", "colspan"], + attributeBindings: ["title", "colspan", "ariaSort:aria-sort", "role"], + role: "columnheader", labelKey: null, chevronIcon: null, columnIcon: null, translated: false, automatic: false, onActiveRender: null, + pressedState: null, + ariaLabel: null, + @discourseComputed("order", "field", "asc") + ariaSort() { + if (this.order === this.field) { + return this.asc ? "ascending" : "descending"; + } else { + return "none"; + } + }, toggleProperties() { if (this.order === this.field) { this.set("asc", this.asc ? null : true); @@ -43,10 +57,48 @@ export default Component.extend({ } this.set("id", `table-header-toggle-${this.field.replace(/\s/g, "")}`); this.toggleChevron(); + this._updateA11yAttributes(); }, didRender() { if (this.onActiveRender && this.chevronIcon) { this.onActiveRender(this.element); } }, + _updateA11yAttributes() { + let criteria = ""; + const pressed = this.order === this.field; + + if (this.icon === "heart") { + criteria += `${I18n.t("likes_lowercase", { count: 2 })} `; + } + + if (this.translated) { + criteria += this.field; + } else { + const labelKey = this.labelKey || `directory.${this.field}`; + + criteria += I18n.t(labelKey + "_long", { + defaultValue: I18n.t(labelKey), + }); + } + + this.set("ariaLabel", I18n.t("directory.sort.label", { criteria })); + + if (pressed) { + if (this.asc) { + this.set("pressedState", "mixed"); + } else { + this.set("pressedState", "true"); + } + + this._focusHeader(); + } else { + this.set("pressedState", "false"); + } + }, + _focusHeader() { + schedule("afterRender", () => { + document.getElementById(this.id)?.focus(); + }); + }, }); diff --git a/app/assets/javascripts/discourse/app/templates/components/table-header-toggle.hbs b/app/assets/javascripts/discourse/app/templates/components/table-header-toggle.hbs index b4a450f6491..998f8ad30c5 100644 --- a/app/assets/javascripts/discourse/app/templates/components/table-header-toggle.hbs +++ b/app/assets/javascripts/discourse/app/templates/components/table-header-toggle.hbs @@ -2,7 +2,9 @@ class="header-contents" id={{this.id}} role="button" - tabindex="0"> + tabindex="0" + aria-label={{this.ariaLabel}} + aria-pressed={{this.pressedState}}> {{directory-table-header-title field=this.field labelKey=this.labelKey icon=this.icon translated=this.translated}} {{this.chevronIcon}} diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml index 350d32feb01..a29be711cfc 100644 --- a/config/locales/client.en.yml +++ b/config/locales/client.en.yml @@ -720,6 +720,8 @@ en: reset_to_default: "Reset to default" group: all: "all groups" + sort: + label: "Sort by %{criteria}" group_histories: actions:
{{i18n "admin.users.approved"}} {{i18n "admin.users.approved"}}