Skip to content

Commit

Permalink
Merge branch 'main' into Issue-3313-ColorArea-a11y
Browse files Browse the repository at this point in the history
  • Loading branch information
majornista committed Jul 11, 2023
2 parents 1f8f2b3 + d244a63 commit 950595e
Show file tree
Hide file tree
Showing 12 changed files with 184 additions and 30 deletions.
18 changes: 9 additions & 9 deletions linters/stylelint-header/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2672,19 +2672,19 @@ saxes@^5.0.1:
xmlchars "^2.2.0"

"semver@2 || 3 || 4 || 5":
version "5.7.1"
resolved "https://artifactory.corp.adobe.com/artifactory/api/npm/npm-unified-experience-components-release/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
integrity sha1-qVT5Ma66UI0we78Gnv8MAclhFvc=
version "5.7.2"
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8"
integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==

semver@^6.0.0, semver@^6.3.0:
version "6.3.0"
resolved "https://artifactory.corp.adobe.com/artifactory/api/npm/npm-unified-experience-components-release/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
integrity sha1-7gpkyK9ejO6mdoexM3YeG+y9HT0=
version "6.3.1"
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4"
integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==

semver@^7.3.2, semver@^7.3.4:
version "7.3.7"
resolved "https://artifactory.corp.adobe.com/artifactory/api/npm/npm-unified-experience-components-release/semver/-/semver-7.3.7.tgz#12c5b649afdbf9049707796e22a4028814ce523f"
integrity sha1-EsW2Sa/b+QSXB3luIqQCiBTOUj8=
version "7.5.4"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e"
integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==
dependencies:
lru-cache "^6.0.0"

Expand Down
18 changes: 17 additions & 1 deletion packages/action-button/src/ActionButton.ts
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,13 @@ export class ActionButton extends SizedMixin(ButtonBase, {
protected override updated(changes: PropertyValues): void {
super.updated(changes);
const isButton = this.role === 'button';
const canBePressed = isButton && (this.selected || this.toggles);
const canBePressed =
isButton &&
(this.selected || this.toggles) &&
!(
this.hasAttribute('aria-haspopup') &&
this.hasAttribute('aria-expanded')
);
if (changes.has('selected') || changes.has('role')) {
// When role !== 'button' then the Action Button is within
// an Action Group that manages selects which means the
Expand All @@ -224,6 +230,16 @@ export class ActionButton extends SizedMixin(ButtonBase, {
} else {
// When !this.toggles the lack of "aria-pressed" is inconsequential.
this.removeAttribute('aria-pressed');
if (
isButton &&
this.toggles &&
this.hasAttribute('aria-expanded')
) {
this.setAttribute(
'aria-expanded',
this.selected ? 'true' : 'false'
);
}
}
}
}
Expand Down
44 changes: 44 additions & 0 deletions packages/action-button/test/action-button.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -235,4 +235,48 @@ describe('ActionButton', () => {
expect(el.selected).to.be.true;
expect(button.getAttribute('aria-pressed')).to.equal('true');
});
it('toggles [aria-haspopup][aria-expanded]', async () => {
const el = await fixture<ActionButton>(
html`
<sp-action-button
toggles
aria-haspopup="true"
aria-expanded="false"
>
Button
</sp-action-button>
`
);

await elementUpdated(el);
const button = el.focusElement;

expect(el.toggles).to.be.true;
expect(el.selected).to.be.false;
expect(button).not.to.have.attribute('aria-pressed');
expect(button).to.have.attribute('aria-haspopup', 'true');
expect(button).to.have.attribute('aria-expanded', 'false');

el.focus();
await sendKeys({
press: 'Space',
});
await elementUpdated(el);

expect(el.toggles).to.be.true;
expect(el.selected).to.be.true;
expect(button).not.to.have.attribute('aria-pressed');
expect(button).to.have.attribute('aria-haspopup', 'true');
expect(button).to.have.attribute('aria-expanded', 'true');

el.addEventListener('change', (event: Event) => event.preventDefault());
el.click();
await elementUpdated(el);

expect(el.toggles).to.be.true;
expect(el.selected).to.be.true;
expect(button).not.to.have.attribute('aria-pressed');
expect(button).to.have.attribute('aria-haspopup', 'true');
expect(button).to.have.attribute('aria-expanded', 'true');
});
});
2 changes: 1 addition & 1 deletion packages/action-menu/src/ActionMenu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ export class ActionMenu extends ObserveSlotText(PickerBase, 'label') {
?quiet=${this.quiet}
?selected=${this.open}
aria-haspopup="true"
aria-controls="popover"
aria-controls=${ifDefined(this.open ? 'menu' : undefined)}
aria-expanded=${this.open ? 'true' : 'false'}
aria-label=${ifDefined(this.label || undefined)}
id="button"
Expand Down
17 changes: 17 additions & 0 deletions packages/action-menu/test/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,9 @@ export const testActionMenu = (mode: 'sync' | 'async'): void => {
button.click();
await elementUpdated(el);
expect(el.open).to.be.true;
expect(button).to.have.attribute('aria-haspopup', 'true');
expect(button).to.have.attribute('aria-expanded', 'true');
expect(button).to.have.attribute('aria-controls', 'menu');
});
it('opens unmeasured with deprecated syntax', async () => {
const el = await deprecatedActionMenuFixture();
Expand All @@ -290,6 +293,12 @@ export const testActionMenu = (mode: 'sync' | 'async'): void => {
const el = await actionMenuFixture();

await elementUpdated(el);

const button = el.button as HTMLButtonElement;
expect(button).to.have.attribute('aria-haspopup', 'true');
expect(button).to.have.attribute('aria-expanded', 'false');
expect(button).not.to.have.attribute('aria-controls');

let items = el.querySelectorAll('sp-menu-item');
const count = items.length;
expect(items.length).to.equal(count);
Expand All @@ -299,6 +308,8 @@ export const testActionMenu = (mode: 'sync' | 'async'): void => {
await opened;

expect(el.open).to.be.true;
expect(button).to.have.attribute('aria-expanded', 'true');
expect(button).to.have.attribute('aria-controls', 'menu');
items = el.querySelectorAll('sp-menu-item');
expect(items.length).to.equal(0);

Expand All @@ -307,6 +318,8 @@ export const testActionMenu = (mode: 'sync' | 'async'): void => {
await closed;

expect(el.open).to.be.false;
expect(button).to.have.attribute('aria-expanded', 'false');
expect(button).not.to.have.attribute('aria-controls');
items = el.querySelectorAll('sp-menu-item');
expect(items.length).to.equal(count);

Expand All @@ -315,6 +328,8 @@ export const testActionMenu = (mode: 'sync' | 'async'): void => {
await opened;

expect(el.open).to.be.true;
expect(button).to.have.attribute('aria-expanded', 'true');
expect(button).to.have.attribute('aria-controls', 'menu');
items = el.querySelectorAll('sp-menu-item');
expect(items.length).to.equal(0);

Expand All @@ -323,6 +338,8 @@ export const testActionMenu = (mode: 'sync' | 'async'): void => {
await closed;

expect(el.open).to.be.false;
expect(button).to.have.attribute('aria-expanded', 'false');
expect(button).not.to.have.attribute('aria-controls');
items = el.querySelectorAll('sp-menu-item');
expect(items.length).to.equal(count);
});
Expand Down
2 changes: 1 addition & 1 deletion packages/color-slider/src/ColorSlider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ export class ColorSlider extends Focusable {
100,
Math.max(0, this.sliderHandlePosition + delta * mult)
);
this.value = 360 * (this.sliderHandlePosition / 100);
this.value = Math.min(100, Math.max(0, this.value + delta));
this.colorController.applyColorFromState();

if (delta != 0) {
Expand Down
56 changes: 48 additions & 8 deletions packages/color-slider/test/color-slider.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ describe('ColorSlider', () => {
await sendKeys({
press: 'ArrowRight',
});
await elementUpdated(el);
expect(el.value).to.not.equal(value);
await sendKeys({
press: 'Tab',
Expand Down Expand Up @@ -217,6 +218,7 @@ describe('ColorSlider', () => {
await elementUpdated(el);

expect(el.sliderHandlePosition).to.equal(0);
expect(el.value).to.equal(0);

const input = el.focusElement;

Expand All @@ -227,7 +229,12 @@ describe('ColorSlider', () => {

await elementUpdated(el);

expect(el.sliderHandlePosition).to.equal(0.5555555555555556);

expect(el.sliderHandlePosition).to.be.approximately(
(2 * 100) / 360,
0.000001
);
expect(el.value).to.equal(2);

input.dispatchEvent(arrowRightEvent());
input.dispatchEvent(arrowRightKeyupEvent());
Expand All @@ -236,7 +243,11 @@ describe('ColorSlider', () => {

await elementUpdated(el);

expect(el.sliderHandlePosition).to.equal(1.1111111111111112);
expect(el.sliderHandlePosition).to.be.approximately(
(4 * 100) / 360,
0.000001
);
expect(el.value).to.equal(4);

input.dispatchEvent(arrowDownEvent());
input.dispatchEvent(arrowDownKeyupEvent());
Expand All @@ -245,7 +256,11 @@ describe('ColorSlider', () => {

await elementUpdated(el);

expect(el.sliderHandlePosition).to.equal(0.5555555555555556);
expect(el.sliderHandlePosition).to.be.approximately(
(2 * 100) / 360,
0.000001
);
expect(el.value).to.equal(2);

input.dispatchEvent(arrowLeftEvent());
input.dispatchEvent(arrowLeftKeyupEvent());
Expand All @@ -255,6 +270,7 @@ describe('ColorSlider', () => {
await elementUpdated(el);

expect(el.sliderHandlePosition).to.equal(0);
expect(el.value).to.equal(0);
});
it('accepts "Arrow*" keypresses in dir="rtl"', async () => {
const el = await fixture<ColorSlider>(
Expand All @@ -276,7 +292,11 @@ describe('ColorSlider', () => {

await elementUpdated(el);

expect(el.sliderHandlePosition).to.equal(0.5555555555555556);
expect(el.sliderHandlePosition).to.be.approximately(
(2 * 100) / 360,
0.000001
);
expect(el.value).to.equal(2);

input.dispatchEvent(arrowRightEvent());
input.dispatchEvent(arrowRightKeyupEvent());
Expand All @@ -286,6 +306,7 @@ describe('ColorSlider', () => {
await elementUpdated(el);

expect(el.sliderHandlePosition).to.equal(0);
expect(el.value).to.equal(0);

input.dispatchEvent(arrowLeftEvent());
input.dispatchEvent(arrowLeftKeyupEvent());
Expand All @@ -294,7 +315,11 @@ describe('ColorSlider', () => {

await elementUpdated(el);

expect(el.sliderHandlePosition).to.equal(0.5555555555555556);
expect(el.sliderHandlePosition).to.be.approximately(
(2 * 100) / 360,
0.000001
);
expect(el.value).to.equal(2);

input.dispatchEvent(arrowDownEvent());
input.dispatchEvent(arrowDownKeyupEvent());
Expand All @@ -304,6 +329,7 @@ describe('ColorSlider', () => {
await elementUpdated(el);

expect(el.sliderHandlePosition).to.equal(0);
expect(el.value).to.equal(0);
});
it('accepts "Arrow*" keypresses with alteration', async () => {
const el = await fixture<ColorSlider>(
Expand All @@ -315,6 +341,7 @@ describe('ColorSlider', () => {
await elementUpdated(el);
el.focus();
expect(el.sliderHandlePosition).to.equal(0);
expect(el.value).to.equal(0);

await sendKeys({
down: 'Shift',
Expand All @@ -328,7 +355,11 @@ describe('ColorSlider', () => {

await elementUpdated(el);

expect(el.sliderHandlePosition).to.equal(5.555555555555555);
expect(el.sliderHandlePosition).to.be.approximately(
(20 * 100) / 360,
0.000001
);
expect(el.value).to.equal(20);

await sendKeys({
press: 'ArrowRight',
Expand All @@ -339,7 +370,11 @@ describe('ColorSlider', () => {

await elementUpdated(el);

expect(el.sliderHandlePosition).to.equal(11.11111111111111);
expect(el.sliderHandlePosition).to.be.approximately(
(40 * 100) / 360,
0.000001
);
expect(el.value).to.equal(40);

await sendKeys({
press: 'ArrowDown',
Expand All @@ -350,7 +385,11 @@ describe('ColorSlider', () => {

await elementUpdated(el);

expect(el.sliderHandlePosition).to.equal(5.5555555555555545);
expect(el.sliderHandlePosition).to.be.approximately(
(20 * 100) / 360,
0.000001
);
expect(el.value).to.equal(20);

await sendKeys({
press: 'ArrowLeft',
Expand All @@ -365,6 +404,7 @@ describe('ColorSlider', () => {
await elementUpdated(el);

expect(el.sliderHandlePosition).to.equal(0);
expect(el.value).to.equal(0);
});
it('accepts pointer events', async () => {
const color = new TinyColor({ h: '0', s: '20%', l: '70%' });
Expand Down
5 changes: 3 additions & 2 deletions packages/picker/src/Picker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -458,6 +458,7 @@ export class PickerBase extends SizedMixin(Focusable) {
></span>
<button
aria-haspopup="true"
aria-controls=${ifDefined(this.open ? 'menu' : undefined)}
aria-expanded=${this.open ? 'true' : 'false'}
aria-labelledby="icon label applied-label"
id="button"
Expand Down Expand Up @@ -539,7 +540,7 @@ export class PickerBase extends SizedMixin(Focusable) {
return html`
<sp-tray
id="popover"
role="dialog"
role="presentation"
@sp-menu-item-added-or-updated=${this.updateMenuItems}
.overlayOpenCallback=${this.overlayOpenCallback}
.overlayCloseCallback=${this.overlayCloseCallback}
Expand All @@ -551,7 +552,7 @@ export class PickerBase extends SizedMixin(Focusable) {
return html`
<sp-popover
id="popover"
role="dialog"
role="presentation"
@sp-menu-item-added-or-updated=${this.updateMenuItems}
.overlayOpenCallback=${this.overlayOpenCallback}
.overlayCloseCallback=${this.overlayCloseCallback}
Expand Down
3 changes: 3 additions & 0 deletions packages/split-button/src/SplitButton.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,9 @@ export class SplitButton extends SizedMixin(PickerBase) {
<sp-button
aria-haspopup="true"
aria-expanded=${this.open ? 'true' : 'false'}
aria-controls=${ifDefined(
this.open ? this.optionsMenu.id : undefined
)}
class="button trigger ${this.variant}"
@blur=${this.onButtonBlur}
@click=${this.onButtonClick}
Expand Down

0 comments on commit 950595e

Please sign in to comment.