mirror of
https://github.com/discourse/discourse.git
synced 2025-02-25 18:55:32 -06:00
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.
This commit is contained in:
parent
6b4b279141
commit
2933baa0ce
@ -15,8 +15,9 @@
|
|||||||
|
|
||||||
<LoadMore @class="users-list-container" @selector=".users-list tr" @action={{action "loadMore"}}>
|
<LoadMore @class="users-list-container" @selector=".users-list tr" @action={{action "loadMore"}}>
|
||||||
{{#if this.model}}
|
{{#if this.model}}
|
||||||
<table class="table users-list grid">
|
<table class="table users-list grid" role="table" aria-label={{this.title}}>
|
||||||
<thead>
|
<thead>
|
||||||
|
<tr>
|
||||||
<TableHeaderToggle @field="username" @labelKey="username" @order={{this.order}} @asc={{this.asc}} @automatic={{true}} />
|
<TableHeaderToggle @field="username" @labelKey="username" @order={{this.order}} @asc={{this.asc}} @automatic={{true}} />
|
||||||
<TableHeaderToggle @class={{if this.showEmails "" "hidden"}} @field="email" @labelKey="email" @order={{this.order}} @asc={{this.asc}} @automatic={{true}} />
|
<TableHeaderToggle @class={{if this.showEmails "" "hidden"}} @field="email" @labelKey="email" @order={{this.order}} @asc={{this.asc}} @automatic={{true}} />
|
||||||
<TableHeaderToggle @field="last_emailed" @labelKey="admin.users.last_emailed" @order={{this.order}} @asc={{this.asc}} @automatic={{true}} />
|
<TableHeaderToggle @field="last_emailed" @labelKey="admin.users.last_emailed" @order={{this.order}} @asc={{this.asc}} @automatic={{true}} />
|
||||||
@ -31,6 +32,7 @@
|
|||||||
<th>{{i18n "admin.users.approved"}}</th>
|
<th>{{i18n "admin.users.approved"}}</th>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
<th> </th>
|
<th> </th>
|
||||||
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{{#each this.model as |user|}}
|
{{#each this.model as |user|}}
|
||||||
|
@ -1,18 +1,32 @@
|
|||||||
import Component from "@ember/component";
|
import Component from "@ember/component";
|
||||||
import { iconHTML } from "discourse-common/lib/icon-library";
|
import { iconHTML } from "discourse-common/lib/icon-library";
|
||||||
import { htmlSafe } from "@ember/template";
|
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({
|
export default Component.extend({
|
||||||
tagName: "th",
|
tagName: "th",
|
||||||
classNames: ["sortable"],
|
classNames: ["sortable"],
|
||||||
attributeBindings: ["title", "colspan"],
|
attributeBindings: ["title", "colspan", "ariaSort:aria-sort", "role"],
|
||||||
|
role: "columnheader",
|
||||||
labelKey: null,
|
labelKey: null,
|
||||||
chevronIcon: null,
|
chevronIcon: null,
|
||||||
columnIcon: null,
|
columnIcon: null,
|
||||||
translated: false,
|
translated: false,
|
||||||
automatic: false,
|
automatic: false,
|
||||||
onActiveRender: null,
|
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() {
|
toggleProperties() {
|
||||||
if (this.order === this.field) {
|
if (this.order === this.field) {
|
||||||
this.set("asc", this.asc ? null : true);
|
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.set("id", `table-header-toggle-${this.field.replace(/\s/g, "")}`);
|
||||||
this.toggleChevron();
|
this.toggleChevron();
|
||||||
|
this._updateA11yAttributes();
|
||||||
},
|
},
|
||||||
didRender() {
|
didRender() {
|
||||||
if (this.onActiveRender && this.chevronIcon) {
|
if (this.onActiveRender && this.chevronIcon) {
|
||||||
this.onActiveRender(this.element);
|
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();
|
||||||
|
});
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
@ -2,7 +2,9 @@
|
|||||||
class="header-contents"
|
class="header-contents"
|
||||||
id={{this.id}}
|
id={{this.id}}
|
||||||
role="button"
|
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}}
|
{{directory-table-header-title field=this.field labelKey=this.labelKey icon=this.icon translated=this.translated}}
|
||||||
{{this.chevronIcon}}
|
{{this.chevronIcon}}
|
||||||
</span>
|
</span>
|
||||||
|
@ -720,6 +720,8 @@ en:
|
|||||||
reset_to_default: "Reset to default"
|
reset_to_default: "Reset to default"
|
||||||
group:
|
group:
|
||||||
all: "all groups"
|
all: "all groups"
|
||||||
|
sort:
|
||||||
|
label: "Sort by %{criteria}"
|
||||||
|
|
||||||
group_histories:
|
group_histories:
|
||||||
actions:
|
actions:
|
||||||
|
Loading…
Reference in New Issue
Block a user