Skip to content

Commit dc3abe1

Browse files
committed
fix(tabs): ensure first tab is active when no active tab is provided
1 parent adc3e41 commit dc3abe1

1 file changed

Lines changed: 26 additions & 0 deletions

File tree

projects/element-ng/tabs/si-tabset.component.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import {
1717
INJECTOR,
1818
input,
1919
signal,
20+
untracked,
2021
viewChild
2122
} from '@angular/core';
2223
import { RouterLink } from '@angular/router';
@@ -29,6 +30,7 @@ import { SiResizeObserverModule } from '@siemens/element-ng/resize-observer';
2930
import { SiTabBadgeComponent } from './si-tab-badge.component';
3031
import { SiTabBaseDirective } from './si-tab-base.directive';
3132
import { SiTabLinkComponent } from './si-tab-link.component';
33+
import { SiTabComponent } from './si-tab.component';
3234
import { SI_TABSET } from './si-tabs-tokens';
3335

3436
/**
@@ -94,6 +96,30 @@ export class SiTabsetComponent {
9496
}
9597

9698
constructor() {
99+
// Per the ARIA tabs pattern, at least one tab should be active. If the app
100+
// does not provide an active tab, activate the first non-disabled content
101+
// tab so the tablist stays keyboard reachable.
102+
effect(() => {
103+
const tabs = this.tabPanels();
104+
const hasActiveTab = !!this.activeTab();
105+
untracked(() => {
106+
if (hasActiveTab) {
107+
return;
108+
}
109+
const tabToActivate = tabs.find(tab => {
110+
if (tab.disabledTab()) {
111+
return false;
112+
}
113+
if (tab instanceof SiTabComponent) {
114+
const canActivate = tab.canActivate();
115+
return canActivate ? canActivate() : true;
116+
}
117+
return true;
118+
});
119+
tabToActivate?.selectTab();
120+
});
121+
});
122+
97123
effect(() => {
98124
if (this.showMenuButton() && this.activeTab()) {
99125
// wait for menu button to render on DOM

0 commit comments

Comments
 (0)