vpat 6: aria labels for buttons in item/context panes (#3957)

Added aria labels and button roles for buttons in the
item/Collection pane. This includes buttons in the header
as well as rows from notes, related, collections, and
attachments section that act as buttons. Also added
missing aria-labelledby for mini-itembox rows below
attachment preview to have filename, dateModified
and etc. properly labelled.

This also covers most of vpat 16.

This does not affect how tags/header/itemBox entries are announced.
There is a separate issue with NVDA and JAWS sometimes struggling
with announcing text inside of `editable-text` component,
so this will be handled separately.
This commit is contained in:
abaevbog 2024-04-12 04:53:35 -04:00 committed by GitHub
parent 7f573d7717
commit 91bc1a3e2d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 46 additions and 10 deletions

View file

@ -32,7 +32,7 @@
content = MozXULElement.parseXULToFragment(`
<collapsible-section data-l10n-id="section-attachment-info" data-pane="attachment-info">
<html:div class="body">
<attachment-preview id="attachment-preview" tabindex="0"/>
<attachment-preview id="attachment-preview" tabindex="0" data-l10n-id="attachment-preview"/>
<html:div style="display: grid;">
<label id="url" is="zotero-text-link" crop="end" tabindex="0"
ondragstart="let dt = event.dataTransfer; dt.setData('text/x-moz-url', this.value); dt.setData('text/uri-list', this.value); dt.setData('text/plain', this.value);"/>
@ -40,19 +40,19 @@
<html:div class="metadata-table">
<html:div id="fileNameRow" class="meta-row">
<html:div class="meta-label"><html:label id="fileName-label" class="key" data-l10n-id="attachment-info-filename"/></html:div>
<html:div class="meta-data"><editable-text id="fileName" nowrap="true" tight="true"/></html:div>
<html:div class="meta-data"><editable-text id="fileName" aria-labelledby="fileName-label" nowrap="true" tight="true"/></html:div>
</html:div>
<html:div id="accessedRow" class="meta-row">
<html:div class="meta-label"><html:label id="accessed-label" class="key" data-l10n-id="attachment-info-accessed"/></html:div>
<html:div class="meta-data"><editable-text id="accessed" nowrap="true" tight="true" readonly="true"/></html:div>
<html:div class="meta-data"><editable-text id="accessed" aria-labelledby="accessed-label" nowrap="true" tight="true" readonly="true"/></html:div>
</html:div>
<html:div id="pagesRow" class="meta-row">
<html:div class="meta-label"><html:label id="pages-label" class="key" data-l10n-id="attachment-info-pages"/></html:div>
<html:div class="meta-data"><editable-text id="pages" nowrap="true" tight="true" readonly="true"/></html:div>
<html:div class="meta-data"><editable-text id="pages" aria-labelledby="pages-label" nowrap="true" tight="true" readonly="true"/></html:div>
</html:div>
<html:div id="dateModifiedRow" class="meta-row" hidden="true" >
<html:div class="meta-label"><html:label id="dateModified-label" class="key" data-l10n-id="attachment-info-modified"/></html:div>
<html:div class="meta-data"><editable-text id="dateModified" nowrap="true" tight="true" readonly="true"/></html:div>
<html:div class="meta-data"><editable-text id="dateModified" aria-labelledby="dateModified-label" nowrap="true" tight="true" readonly="true"/></html:div>
</html:div>
<html:div id="indexStatusRow" class="meta-row">
<html:div class="meta-label"><html:label id="index-status-label" class="key" data-l10n-id="attachment-info-index"/></html:div>

View file

@ -29,7 +29,7 @@
content = MozXULElement.parseXULToFragment(`
<collapsible-section data-l10n-id="section-attachment-preview" data-pane="attachment-preview">
<html:div class="body">
<attachment-preview id="attachment-preview"/>
<attachment-preview id="attachment-preview" data-l10n-id="attachment-preview"/>
<html:span id="preview-placeholder" data-l10n-id="attachment-preview-placeholder"></html:span>
</html:div>
</collapsible-section>

View file

@ -31,11 +31,11 @@ import { getCSSItemTypeIcon } from 'components/icons';
class AttachmentRow extends XULElementBase {
content = MozXULElement.parseXULToFragment(`
<html:div class="head">
<html:div class="clicky-item attachment-btn keyboard-clickable" tabindex="0">
<html:div class="clicky-item attachment-btn keyboard-clickable" tabindex="0" role="button">
<html:span class="icon"/>
<html:div class="label"/>
</html:div>
<html:div class="clicky-item annotation-btn">
<html:div class="clicky-item annotation-btn keyboard-clickable" tabindex="0" role="button" data-l10n-id="section-button-annotations" data-l10n-attrs="tooltiptext,aria-label" >
<html:span class="icon"/>
<html:span class="label"/>
</html:div>
@ -112,8 +112,10 @@ import { getCSSItemTypeIcon } from 'components/icons';
if (!this.initialized) return;
this._attachmentButton.querySelector(".icon").replaceWith(getCSSItemTypeIcon(this._attachment.getItemTypeIconName()));
this._attachmentButton.setAttribute("aria-label", this._attachment.getField('title'));
this._attachmentButton.querySelector(".label").textContent = this._attachment.getField('title');
let annotationCount = this.attachment.isFileAttachment() ? this.attachment.getAnnotations().length : 0;
this._annotationButton.setAttribute('data-l10n-args', JSON.stringify({ count: annotationCount }));
this._annotationButton.hidden = annotationCount == 0;
this._annotationButton.querySelector(".label").textContent = annotationCount;
}

View file

@ -30,7 +30,7 @@
content = MozXULElement.parseXULToFragment(`
<collapsible-section data-l10n-id="section-attachments" data-pane="attachments" extra-buttons="add">
<html:div class="body">
<attachment-preview tabindex="0"/>
<attachment-preview tabindex="0" data-l10n-id="attachment-preview"/>
<html:div class="attachments-container"></html:div>
</html:div>
</collapsible-section>

View file

@ -258,6 +258,7 @@
if (!buttonType) continue;
let button = document.createXULElement('toolbarbutton');
button.classList.add(buttonType, 'section-custom-button');
button.setAttribute("data-l10n-id", `section-button-${buttonType}`);
button.setAttribute("tabindex", "0");
button.addEventListener('command', (event) => {
this.dispatchEvent(new CustomEvent(buttonType, {
@ -417,9 +418,11 @@
}
this._head.setAttribute('aria-expanded', this.open);
this._head.setAttribute("aria-label", this.label);
this._title.textContent = this.label;
this._summary.textContent = this.summary;
this._head.querySelector('.twisty').hidden = this._disableCollapsing;
this._head.querySelector('.twisty').setAttribute('data-l10n-id', `section-button-${this.open ? "collapse" : "expand"}`);
}
}
customElements.define("collapsible-section", CollapsibleSection);

View file

@ -91,8 +91,10 @@ import { getCSSIcon } from 'components/icons';
row.classList.toggle('context', isContext);
let box = document.createElement('div');
box.className = 'box keyboard_clickable';
box.className = 'box keyboard-clickable';
box.setAttribute("tabindex", "0");
box.setAttribute('aria-label', obj.name);
box.setAttribute('role', "button");
let iconName;
if (obj instanceof Zotero.Group) {
@ -118,6 +120,7 @@ import { getCSSIcon } from 'components/icons';
let remove = document.createXULElement('toolbarbutton');
remove.className = 'zotero-clicky zotero-clicky-minus';
remove.setAttribute("tabindex", "0");
remove.setAttribute("data-l10n-id", 'section-button-remove');
remove.addEventListener('command', () => {
if (Services.prompt.confirm(
window,

View file

@ -103,6 +103,8 @@ import { getCSSItemTypeIcon } from 'components/icons';
box.addEventListener('click', () => this._handleShowItem(id));
box.className = 'box keyboard-clickable';
box.setAttribute("tabindex", 0);
box.setAttribute("aria-label", label.textContent);
box.setAttribute("role", "button");
box.append(icon, label);
row.append(box);
@ -112,6 +114,7 @@ import { getCSSItemTypeIcon } from 'components/icons';
remove.addEventListener('command', () => this._handleRemove(id));
remove.className = 'zotero-clicky zotero-clicky-minus';
remove.setAttribute("tabindex", "0");
remove.setAttribute("data-l10n-id", 'section-button-remove');
row.append(remove);
}

View file

@ -111,6 +111,8 @@ import { getCSSItemTypeIcon } from 'components/icons';
let box = document.createElement('div');
box.addEventListener('click', () => this._handleShowItem(id));
box.setAttribute("tabindex", "0");
box.setAttribute("role", "button");
box.setAttribute("aria-label", label.textContent);
box.className = 'box keyboard-clickable';
box.appendChild(icon);
box.appendChild(label);
@ -120,6 +122,7 @@ import { getCSSItemTypeIcon } from 'components/icons';
let remove = document.createXULElement("toolbarbutton");
remove.addEventListener('command', () => this._handleRemove(id));
remove.className = 'zotero-clicky zotero-clicky-minus';
remove.setAttribute("data-l10n-id", 'section-button-remove');
remove.setAttribute("tabindex", "0");
row.append(remove);
}

View file

@ -5,6 +5,9 @@ return-or-enter =
*[other] Enter
}
general-remove = Remove
general-add = Add
menu-print =
.label = { general-print }
@ -371,6 +374,25 @@ section-related =
section-attachment-info =
.label = { pane-attachment-info }
section-button-remove =
.tooltiptext = { general-remove }
section-button-add =
.tooltiptext = { general-add }
section-button-expand =
.tooltiptext = Expand section
section-button-collapse =
.tooltiptext = Collapse section
annotations-count =
{ $count ->
[one] { $count } Annotation
*[other] { $count } Annotations
}
section-button-annotations =
.title = { annotations-count }
.aria-label = { annotations-count }
attachment-preview =
.aria-label = { pane-attachment-preview }
sidenav-info =
.tooltiptext = { pane-info }
sidenav-abstract =