feat(tabs): add tabs property to retrieve tab elements

PiperOrigin-RevId: 563784477
This commit is contained in:
Elizabeth Mitchell 2023-09-08 10:12:58 -07:00 committed by Copybara-Service
parent 23b291b2dd
commit bf48fc307e
2 changed files with 21 additions and 18 deletions

View File

@ -53,9 +53,8 @@ export class TabsHarness extends Harness<Tabs> {
get harnessedItems() {
// Test access to protected property
// tslint:disable-next-line:no-dict-access-on-struct-type
return (this.element['items'] as Array<ElementWithHarness<Tab>>)
.map(item => {
return (item.harness ?? new TabHarness(item)) as TabHarness;
});
return (this.element.tabs as Array<ElementWithHarness<Tab>>).map(item => {
return (item.harness ?? new TabHarness(item)) as TabHarness;
});
}
}

View File

@ -47,6 +47,13 @@ export class Tabs extends LitElement {
setupHostAria(Tabs, {focusable: false});
}
/**
* The tabs of this tab bar.
*/
get tabs() {
return this.maybeTabItems.filter(isTab);
}
/**
* Index of the selected item.
*/
@ -63,9 +70,6 @@ export class Tabs extends LitElement {
@queryAssignedElements({flatten: true})
private readonly maybeTabItems!: HTMLElement[];
private get items(): Tab[] {
return this.maybeTabItems.filter(isTab);
}
// this tracks if items have changed, which triggers rendering so they can
// be kept in sync
@ -75,21 +79,21 @@ export class Tabs extends LitElement {
* The item currently selected.
*/
get selectedItem() {
return this.items[this.selected];
return this.tabs[this.selected];
}
/**
* The item previously selected.
*/
get previousSelectedItem() {
return this.items[this.previousSelected];
return this.tabs[this.previousSelected];
}
/**
* The item currently focused.
*/
private get focusedItem() {
return this.items.find((el: HTMLElement) => el.matches(':focus-within'));
return this.tabs.find((el: HTMLElement) => el.matches(':focus-within'));
}
private readonly internals = polyfillElementInternalsAria(
@ -116,19 +120,19 @@ export class Tabs extends LitElement {
}
let indexToFocus = -1;
const focused = this.focusedItem ?? this.selectedItem;
const itemCount = this.items.length;
const itemCount = this.tabs.length;
const isPrevKey = key === 'ArrowLeft' || key === 'ArrowUp';
if (key === 'Home') {
indexToFocus = 0;
} else if (key === 'End') {
indexToFocus = itemCount - 1;
} else {
const focusedIndex = this.items.indexOf(focused) || 0;
const focusedIndex = this.tabs.indexOf(focused) || 0;
indexToFocus = focusedIndex + (isPrevKey ? -1 : 1);
indexToFocus =
indexToFocus < 0 ? itemCount - 1 : indexToFocus % itemCount;
}
const itemToFocus = this.items[indexToFocus];
const itemToFocus = this.tabs[indexToFocus];
if (itemToFocus !== null && itemToFocus !== focused) {
this.updateFocusableItem(itemToFocus);
itemToFocus.focus();
@ -150,7 +154,7 @@ export class Tabs extends LitElement {
const nowFocused =
(this.getRootNode() as unknown as DocumentOrShadowRoot).activeElement as
Tab;
if (this.items.indexOf(nowFocused) === -1) {
if (this.tabs.indexOf(nowFocused) === -1) {
this.updateFocusableItem(this.selectedItem);
}
};
@ -209,7 +213,7 @@ export class Tabs extends LitElement {
const itemsChanged = changed.has('itemsDirty');
// sync state with items.
if (itemsChanged) {
this.items.forEach((item, i) => {
this.tabs.forEach((item, i) => {
item.active = this.selected === i;
});
}
@ -227,7 +231,7 @@ export class Tabs extends LitElement {
}
private updateFocusableItem(focusableItem: HTMLElement|null) {
for (const item of this.items) {
for (const item of this.tabs) {
item.tabIndex = item === focusableItem ? 0 : -1;
}
}
@ -248,7 +252,7 @@ export class Tabs extends LitElement {
return;
}
const item = (target as Element).closest(`${this.localName} > *`) as Tab;
const i = this.items.indexOf(item);
const i = this.tabs.indexOf(item);
if (i > -1 && this.selected !== i) {
this.selected = i;
this.updateFocusableItem(this.selectedItem);
@ -264,7 +268,7 @@ export class Tabs extends LitElement {
}
private async itemsUpdateComplete() {
for (const item of this.items) {
for (const item of this.tabs) {
await item.updateComplete;
}
return true;