зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
2bb134a537
Коммит
0a9f64d0ac
|
@ -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"),
|
||||
};
|
||||
|
|
Загрузка…
Ссылка в новой задаче