diff --git a/packages/tabs/src/TabsOverflow.ts b/packages/tabs/src/TabsOverflow.ts index cf21f1b116..3a9aa22d45 100644 --- a/packages/tabs/src/TabsOverflow.ts +++ b/packages/tabs/src/TabsOverflow.ts @@ -46,7 +46,13 @@ export class TabsOverflow extends SizedMixin(SpectrumElement) { } @property({ type: Boolean, reflect: true }) - compact = false; + public compact = false; + + @property({ type: String, attribute: 'label-previous' }) + public labelPrevious = 'Scroll to previous tabs'; + + @property({ type: String, attribute: 'label-next' }) + public labelNext = 'Scroll to next tabs'; @property({ reflect: true }) public override dir!: 'ltr' | 'rtl'; @@ -132,6 +138,8 @@ export class TabsOverflow extends SizedMixin(SpectrumElement) { protected override render(): TemplateResult { const { canScrollRight, canScrollLeft } = this.overflowState; + const ariaLabelPrevious = this.labelPrevious; + const ariaLabelNext = this.labelNext; return html`
` component, simply wrap it around the ``
``` + +### Accessibility + +The `` component is not focusable via Keyboard Tab Navigation. The Tabs Overflow buttons only help visually scroll down the list of Tabs. Keyboard users can navigate through all elements inside the Tabs list using arrow keys, and Keyboard users will always initially focus on the very first Tab element, no matter how visually scrolled the Tab group might be. Therefore, the `` component is not useful for Keyboard Tab Navigation, so it is removed as to not be a hinderance. diff --git a/packages/tabs/test/tabs-overflow.test.ts b/packages/tabs/test/tabs-overflow.test.ts index 58fd686153..80c2ac67b6 100644 --- a/packages/tabs/test/tabs-overflow.test.ts +++ b/packages/tabs/test/tabs-overflow.test.ts @@ -34,6 +34,8 @@ type OverflowProperties = { includeTabPanel: boolean; selected?: number; autoscroll?: boolean; + labelPrev?: string; + labelNext?: string; }; const renderTabsOverflow = async ({ @@ -213,4 +215,86 @@ describe('TabsOverflow', () => { const firstTabPosition = firstTab.getBoundingClientRect(); expect(firstTabPosition.left).to.be.lessThan(0); }); + + it('prev and next buttons have default labels', async () => { + const el = await renderTabsOverflow({ + count: 20, + size: ElementSizes.M, + includeTabPanel: true, + }); + await elementUpdated(el); + + const spTabsOverflows: TabsOverflow = el.querySelector( + 'sp-tabs-overflow' + ) as TabsOverflow; + const leftButton = spTabsOverflows.shadowRoot.querySelector( + '.left-scroll' + ) as ActionButton; + const rightButton = spTabsOverflows.shadowRoot.querySelector( + '.right-scroll' + ) as ActionButton; + + expect(leftButton?.getAttribute('aria-label')).to.equal( + 'Scroll to previous tabs' + ); + expect(rightButton?.getAttribute('aria-label')).to.equal( + 'Scroll to next tabs' + ); + }); + + it('prev and next buttons labels overwritten via attributes', async () => { + const tabsContainer = await fixture( + html` +
+ + + ${repeat( + new Array(20), + (item) => item, + (_item, index) => + html` + + ` + )} + ${repeat( + new Array(20), + (item) => item, + (_item, index) => + html` + + Content for Tab Item ${index + 1} + + ` + )} + + +
+ ` + ); + await elementUpdated(tabsContainer); + const el = tabsContainer; + + const spTabsOverflows: TabsOverflow = el.querySelector( + 'sp-tabs-overflow' + ) as TabsOverflow; + const leftButton = spTabsOverflows.shadowRoot.querySelector( + '.left-scroll' + ) as ActionButton; + const rightButton = spTabsOverflows.shadowRoot.querySelector( + '.right-scroll' + ) as ActionButton; + + expect(leftButton?.getAttribute('aria-label')).to.equal( + 'custom label prev' + ); + expect(rightButton?.getAttribute('aria-label')).to.equal( + 'custom label next' + ); + }); });