Bug 1858808 - add accesskey support to moz-button r=reusable-components-reviewers,tgiles

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

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

@ -227,6 +227,82 @@
await new Promise(resolve => requestAnimationFrame(resolve));
verifyImageIcon(nine);
});
add_task(async function testAccesskey() {
let firstButton = document.querySelector(".one");
let secondButton = document.querySelector(".two");
let accesskey = "t";
let seenEvents = [];
function trackEvent(event) {
seenEvents.push(event.type);
}
[firstButton, secondButton].forEach(button => {
button.addEventListener("click", trackEvent);
});
firstButton.setAttribute("accesskey", accesskey);
await firstButton.updateComplete;
firstButton.blur();
isnot(document.activeElement, firstButton, "First button is not focused.");
isnot(
firstButton.shadowRoot.activeElement,
firstButton.buttonEl,
"Inner button element is not focused."
);
synthesizeKey(
accesskey,
navigator.platform.includes("Mac")
? { altKey: true, ctrlKey: true }
: { altKey: true, shiftKey: true }
);
is(
document.activeElement,
firstButton,
"First button recieves focus after accesskey is pressed."
);
is(
firstButton.shadowRoot.activeElement,
firstButton.buttonEl,
"Inner button input element is focused after accesskey is pressed."
);
is(seenEvents.length, 1, "One event was triggered.");
is(seenEvents[0], "click", "The first button was clicked.");
secondButton.setAttribute("accesskey", accesskey);
await secondButton.updateComplete;
synthesizeKey(
accesskey,
navigator.platform.includes("Mac")
? { altKey: true, ctrlKey: true }
: { altKey: true, shiftKey: true }
);
is(
document.activeElement,
secondButton,
"Focus cycles between buttons with the same accesskey."
);
synthesizeKey(
accesskey,
navigator.platform.includes("Mac")
? { altKey: true, ctrlKey: true }
: { altKey: true, shiftKey: true }
);
is(
document.activeElement,
firstButton,
"Focus cycles between buttons with the same accesskey."
);
is(seenEvents.length, 1, "No additional click events were triggered.");
});
</script>
</head>
<body>

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

@ -26,7 +26,6 @@ button {
display: flex;
justify-content: center;
align-items: center;
gap: var(--space-small);
&[size=small] {
min-height: var(--button-min-height-small);
@ -129,6 +128,10 @@ button {
}
}
&.labelled {
gap: var(--space-small)
}
&[type~=icon]:not(.labelled) {
background-size: var(--icon-size-default);
background-position: center;

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

@ -5,6 +5,9 @@
import { html, ifDefined, classMap } from "../vendor/lit.all.mjs";
import { MozLitElement } from "../lit-utils.mjs";
// eslint-disable-next-line import/no-unassigned-import
import "chrome://global/content/elements/moz-label.mjs";
/**
* A button with multiple types and two sizes.
*
@ -49,6 +52,8 @@ export default class MozButton extends MozLitElement {
ariaLabel: { type: String, state: true },
iconSrc: { type: String },
hasVisibleLabel: { type: Boolean, state: true },
accessKeyAttribute: { type: String, attribute: "accesskey", reflect: true },
accessKey: { type: String, state: true },
};
static queries = {
@ -73,6 +78,10 @@ export default class MozButton extends MozLitElement {
this.ariaLabel = this.ariaLabelAttribute;
this.ariaLabelAttribute = null;
}
if (changes.has("accessKeyAttribute")) {
this.accessKey = this.accessKeyAttribute;
this.accessKeyAttribute = null;
}
}
// Delegate clicks on host to the button element.
@ -107,11 +116,14 @@ export default class MozButton extends MozLitElement {
aria-label=${ifDefined(this.ariaLabel)}
part="button"
class=${classMap({ labelled: this.label || this.hasVisibleLabel })}
accesskey=${ifDefined(this.accessKey)}
>
${this.iconSrc
? html`<img src=${this.iconSrc} role="presentation" />`
: ""}
${this.labelTemplate()}
<label is="moz-label" shownaccesskey=${ifDefined(this.accessKey)}>
${this.labelTemplate()}
</label>
</button>
`;
}

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

@ -44,14 +44,24 @@ moz-button-aria-labelled =
},
};
const Template = ({ type, size, l10nId, iconSrc, disabled }) => html`
const Template = ({
type,
size,
l10nId,
iconSrc,
disabled,
accesskey,
clickHandler,
}) => html`
<moz-button
@click=${clickHandler}
data-l10n-id=${l10nId}
data-l10n-attrs="label"
type=${type}
size=${size}
?disabled=${disabled}
iconSrc=${ifDefined(iconSrc)}
accesskey=${ifDefined(accesskey)}
></moz-button>
`;
@ -106,3 +116,9 @@ IconText.args = {
iconSrc: "chrome://global/skin/icons/edit-copy.svg",
l10nId: "moz-button-labelled",
};
export const WithAccesskey = Template.bind({});
WithAccesskey.args = {
...Default.args,
accesskey: "t",
clickHandler: () => alert("Activating the accesskey clicks the button"),
};