Skip to content

Commit bad3cc9

Browse files
committed
feat(aria/tabs): add label inputs coordinated by LabelControl
1 parent 0270c9f commit bad3cc9

2 files changed

Lines changed: 22 additions & 3 deletions

File tree

goldens/aria/tabs/index.api.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,9 @@ export class TabPanel implements OnInit, OnDestroy {
7575
constructor();
7676
readonly element: HTMLElement;
7777
readonly id: _angular_core.InputSignal<string>;
78+
readonly label: _angular_core.InputSignal<string | undefined>;
79+
readonly _labelControl: LabelControl;
80+
readonly labelledBy: _angular_core.InputSignal<string[]>;
7881
// (undocumented)
7982
ngOnDestroy(): void;
8083
// (undocumented)
@@ -84,7 +87,7 @@ export class TabPanel implements OnInit, OnDestroy {
8487
readonly value: _angular_core.InputSignal<string>;
8588
readonly visible: _angular_core.Signal<boolean>;
8689
// (undocumented)
87-
static ɵdir: _angular_core.ɵɵDirectiveDeclaration<TabPanel, "[ngTabPanel]", ["ngTabPanel"], { "id": { "alias": "id"; "required": false; "isSignal": true; }; "value": { "alias": "value"; "required": true; "isSignal": true; }; }, {}, never, never, true, [{ directive: typeof DeferredContentAware; inputs: { "preserveContent": "preserveContent"; }; outputs: {}; }]>;
90+
static ɵdir: _angular_core.ɵɵDirectiveDeclaration<TabPanel, "[ngTabPanel]", ["ngTabPanel"], { "id": { "alias": "id"; "required": false; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "labelledBy": { "alias": "labelledBy"; "required": false; "isSignal": true; }; "value": { "alias": "value"; "required": true; "isSignal": true; }; }, {}, never, never, true, [{ directive: typeof DeferredContentAware; inputs: { "preserveContent": "preserveContent"; }; outputs: {}; }]>;
8891
// (undocumented)
8992
static ɵfac: _angular_core.ɵɵFactoryDeclaration<TabPanel, never>;
9093
}

src/aria/tabs/tab-panel.ts

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import {
1919
input,
2020
signal,
2121
} from '@angular/core';
22-
import {TabPattern, TabPanelPattern, DeferredContentAware} from '../private';
22+
import {DeferredContentAware, LabelControl, TabPattern, TabPanelPattern} from '../private';
2323
import {TABS} from './tab-tokens';
2424

2525
/**
@@ -49,7 +49,8 @@ import {TABS} from './tab-tokens';
4949
'[attr.id]': '_pattern.id()',
5050
'[attr.tabindex]': '_pattern.tabIndex()',
5151
'[attr.inert]': '!visible() ? true : null',
52-
'[attr.aria-labelledby]': '_pattern.labelledBy()',
52+
'[attr.aria-label]': '_labelControl.label()',
53+
'[attr.aria-labelledby]': '_labelControl.labelledBy()',
5354
},
5455
hostDirectives: [
5556
{
@@ -71,9 +72,18 @@ export class TabPanel implements OnInit, OnDestroy {
7172
/** The parent Tabs. */
7273
private readonly _tabs = inject(TABS);
7374

75+
/** Controls label for this tabpanel. */
76+
readonly _labelControl: LabelControl;
77+
7478
/** A global unique identifier for the tab. */
7579
readonly id = input(inject(_IdGenerator).getId('ng-tabpanel-', true));
7680

81+
/** The (optional) label for the accordion panel. */
82+
readonly label = input<string | undefined>(undefined);
83+
84+
/** The (optional) labelledBy ids for the accordion panel. */
85+
readonly labelledBy = input<string[]>([]);
86+
7787
/** The Tab UIPattern associated with the tabpanel */
7888
readonly _tabPattern: WritableSignal<TabPattern | undefined> = signal(undefined);
7989

@@ -90,6 +100,12 @@ export class TabPanel implements OnInit, OnDestroy {
90100
});
91101

92102
constructor() {
103+
this._labelControl = new LabelControl({
104+
defaultLabelledBy: computed(() => this._pattern!.labelledBy()),
105+
label: this.label,
106+
labelledBy: this.labelledBy,
107+
});
108+
93109
afterRenderEffect({
94110
write: () => {
95111
this._deferredContentAware.contentVisible.set(this.visible());

0 commit comments

Comments
 (0)