diff --git a/src/aria/tabs/tabs.ts b/src/aria/tabs/tabs.ts index f6442a604f70..1ae0d1056243 100644 --- a/src/aria/tabs/tabs.ts +++ b/src/aria/tabs/tabs.ts @@ -107,6 +107,17 @@ export class Tabs { this._unorderedPanels.set(new Set(this._unorderedPanels())); } } + + /** Opens the tab panel with the specified value. */ + open(value: string) { + const tab = this._findTabPatternByValue(value); + + tab?.expansion.open(); + } + + _findTabPatternByValue(value: string) { + return this.tabs()?.find(t => t.value() === value); + } } /** @@ -120,10 +131,10 @@ export class Tabs { host: { 'role': 'tablist', 'class': 'ng-tablist', - '[attr.tabindex]': '_pattern.tabindex()', - '[attr.aria-disabled]': '_pattern.disabled()', - '[attr.aria-orientation]': '_pattern.orientation()', - '[attr.aria-activedescendant]': '_pattern.activedescendant()', + '[attr.tabindex]': 'tabindex()', + '[attr.aria-disabled]': 'disabled()', + '[attr.aria-orientation]': 'orientation()', + '[attr.aria-activedescendant]': 'activedescendant()', '(keydown)': '_pattern.onKeydown($event)', '(pointerdown)': '_pattern.onPointerdown($event)', '(focusin)': 'onFocus()', @@ -173,6 +184,15 @@ export class TabList implements OnInit, OnDestroy { /** The current selected tab. */ readonly selectedTab = model(); + /** The id of the current active tab. */ + readonly activedescendant = computed(() => this._pattern.activedescendant()); + + /** Whether selection should follow focus. */ + readonly followFocus = computed(() => this._pattern.followFocus()); + + /** The tabindex of the tablist. */ + readonly tabindex = computed(() => this._pattern.tabindex()); + /** The TabList UIPattern. */ readonly _pattern: TabListPattern = new TabListPattern({ ...this, @@ -225,11 +245,11 @@ export class TabList implements OnInit, OnDestroy { host: { 'role': 'tab', 'class': 'ng-tab', - '[attr.data-active]': '_pattern.active()', + '[attr.data-active]': 'active()', '[attr.id]': '_pattern.id()', - '[attr.tabindex]': '_pattern.tabindex()', - '[attr.aria-selected]': '_pattern.selected()', - '[attr.aria-disabled]': '_pattern.disabled()', + '[attr.tabindex]': 'tabindex()', + '[attr.aria-selected]': 'selected()', + '[attr.aria-disabled]': 'disabled()', '[attr.aria-controls]': '_pattern.controls()', }, }) @@ -263,6 +283,18 @@ export class Tab implements HasElement, OnInit, OnDestroy { /** A local unique identifier for the tab. */ readonly value = input.required(); + /** Whether the tab is active. */ + readonly active = computed(() => this._pattern.active()); + + /** Whether the tab is expanded. */ + readonly expanded = computed(() => this._pattern.expanded()); + + /** Whether the tab is selected. */ + readonly selected = computed(() => this._pattern.selected()); + + /** The tabindex of the tab. */ + readonly tabindex = computed(() => this._pattern.tabindex()); + /** The Tab UIPattern. */ readonly _pattern: TabPattern = new TabPattern({ ...this, @@ -272,6 +304,11 @@ export class Tab implements HasElement, OnInit, OnDestroy { value: this.value, }); + /** Opens this tab panel. */ + open() { + this._pattern.expansion.open(); + } + ngOnInit() { this._tabList.register(this); } @@ -296,8 +333,8 @@ export class Tab implements HasElement, OnInit, OnDestroy { 'role': 'tabpanel', 'class': 'ng-tabpanel', '[attr.id]': '_pattern.id()', - '[attr.tabindex]': '_pattern.tabindex()', - '[attr.inert]': '_pattern.hidden() ? true : null', + '[attr.tabindex]': 'tabindex()', + '[attr.inert]': 'hidden() ? true : null', '[attr.aria-labelledby]': '_pattern.labelledBy()', }, hostDirectives: [ @@ -323,6 +360,12 @@ export class TabPanel implements OnInit, OnDestroy { /** A local unique identifier for the tabpanel. */ readonly value = input.required(); + /** Whether the tab panel is hidden. */ + readonly hidden = computed(() => this._pattern.hidden()); + + /** The tabindex of the tab panel. */ + readonly tabindex = computed(() => this._pattern.tabindex()); + /** The TabPanel UIPattern. */ readonly _pattern: TabPanelPattern = new TabPanelPattern({ ...this,