Bug 1894492 - add accesskey support to moz-checkbox r=reusable-components-reviewers,tgiles

Differential Revision: https://phabricator.services.mozilla.com/D216215
This commit is contained in:
Hanna Jones 2024-07-17 18:10:13 +00:00
Родитель 13e8640154
Коммит 2bb134a537
4 изменённых файлов: 110 добавлений и 2 удалений

Просмотреть файл

@ -388,6 +388,74 @@
});
add_task(async function testCheckboxAccesskey() {
let mozCheckbox1 = document.getElementById("moz-checkbox-1");
let mozCheckbox2 = document.getElementById("moz-checkbox-2");
let accesskey = "t";
mozCheckbox1.setAttribute("accesskey", accesskey);
mozCheckbox1.checked = false;
await mozCheckbox1.updateComplete;
mozCheckbox1.blur();
isnot(document.activeElement, mozCheckbox1, "Checkbox is not focused.");
isnot(
mozCheckbox1.shadowRoot.activeElement,
mozCheckbox1.checkboxEl,
"Checkbox input element is not focused."
);
ok(!mozCheckbox1.checked, "Checkbox is not checked.");
synthesizeKey(
accesskey,
navigator.platform.includes("Mac")
? { altKey: true, ctrlKey: true }
: { altKey: true, shiftKey: true }
);
is(
document.activeElement,
mozCheckbox1,
"Checkbox recieves focus after accesskey is pressed."
);
is(
mozCheckbox1.shadowRoot.activeElement,
mozCheckbox1.checkboxEl,
"Checkbox input element is focused after accesskey is pressed."
);
ok(mozCheckbox1.checked, "Checkbox is checked after accesskey is pressed.");
mozCheckbox2.setAttribute("accesskey", accesskey);
mozCheckbox2.checked = false;
await mozCheckbox2.updateComplete;
synthesizeKey(
accesskey,
navigator.platform.includes("Mac")
? { altKey: true, ctrlKey: true }
: { altKey: true, shiftKey: true }
);
is(
document.activeElement,
mozCheckbox2,
"Focus cycles between checkboxes with the same accesskey."
);
ok(!mozCheckbox2.checked, "Second checkbox is not checked.");
synthesizeKey(
accesskey,
navigator.platform.includes("Mac")
? { altKey: true, ctrlKey: true }
: { altKey: true, shiftKey: true }
);
is(
document.activeElement,
mozCheckbox1,
"Focus cycles between checkboxes with the same accesskey."
);
});
</script>
</pre>
</body>

Просмотреть файл

@ -2,7 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
import { html } from "../vendor/lit.all.mjs";
import { html, ifDefined } from "../vendor/lit.all.mjs";
import { MozLitElement } from "../lit-utils.mjs";
// eslint-disable-next-line import/no-unassigned-import
@ -31,6 +31,12 @@ export default class MozCheckbox extends MozLitElement {
checked: { type: Boolean, reflect: true },
disabled: { type: Boolean, reflect: true },
description: { type: String, fluent: true },
accessKeyAttribute: {
type: String,
attribute: "accesskey",
reflect: true,
},
accessKey: { type: String, state: true },
};
static get queries() {
@ -78,6 +84,13 @@ export default class MozCheckbox extends MozLitElement {
this.dispatchEvent(newEvent);
}
willUpdate(changes) {
if (changes.has("accessKeyAttribute")) {
this.accessKey = this.accessKeyAttribute;
this.accessKeyAttribute = null;
}
}
iconTemplate() {
if (this.iconSrc) {
return html`<img src=${this.iconSrc} role="presentation" class="icon" />`;
@ -99,7 +112,11 @@ export default class MozCheckbox extends MozLitElement {
rel="stylesheet"
href="chrome://global/content/elements/moz-checkbox.css"
/>
<label is="moz-label" for="moz-checkbox">
<label
is="moz-label"
for="moz-checkbox"
shownaccesskey=${ifDefined(this.accessKey)}
>
<input
id="moz-checkbox"
type="checkbox"
@ -110,6 +127,7 @@ export default class MozCheckbox extends MozLitElement {
@change=${this.redispatchEvent}
.disabled=${this.disabled}
aria-describedby="description"
accesskey=${ifDefined(this.accessKey)}
/>
<span class="label-content">
${this.iconTemplate()}

Просмотреть файл

@ -35,6 +35,7 @@ const Template = ({
iconSrc,
description,
hasSlottedDescription,
accesskey,
}) => html`
<moz-checkbox
?checked=${checked}
@ -43,6 +44,7 @@ const Template = ({
data-l10n-id=${ifDefined(l10nId)}
.iconSrc=${iconSrc}
?disabled=${disabled}
accesskey=${ifDefined(accesskey)}
>
${hasSlottedDescription
? html`<div slot="description">test slot text</div>`
@ -60,6 +62,7 @@ Default.args = {
iconSrc: "",
description: "",
label: "",
accesskey: "",
};
export const WithIcon = Template.bind({});
@ -91,3 +94,9 @@ WithSlottedDescription.args = {
...Default.args,
hasSlottedDescription: true,
};
export const WithAccesskey = Template.bind({});
WithAccesskey.args = {
...Default.args,
accesskey: "c",
};

Просмотреть файл

@ -16,6 +16,7 @@ class MozTextLabel extends HTMLLabelElement {
#insertSeparator = false;
#alwaysAppendAccessKey = false;
#lastFormattedAccessKey = null;
#observer = null;
// Default to underlining accesskeys for Windows and Linux.
static #underlineAccesskey = !navigator.platform.includes("Mac");
@ -67,6 +68,18 @@ class MozTextLabel extends HTMLLabelElement {
connectedCallback() {
this.#setStyles();
this.formatAccessKey();
if (!this.#observer) {
this.#observer = new MutationObserver(() => {
this.formatAccessKey();
}).observe(this, { characterData: true, childList: true, subtree: true });
}
}
disconnectedCallback() {
if (this.#observer) {
this.#observer.disconnect();
this.#observer = null;
}
}
// Bug 1820588 - we may want to generalize this into