From dc3abe1165136fe444af913c00d57420b77419fc Mon Sep 17 00:00:00 2001 From: "akash.sonune" Date: Sat, 20 Jun 2026 00:03:15 +0530 Subject: [PATCH] fix(tabs): ensure first tab is active when no active tab is provided --- .../element-ng/tabs/si-tabset.component.ts | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/projects/element-ng/tabs/si-tabset.component.ts b/projects/element-ng/tabs/si-tabset.component.ts index 497b3fcf28..1560ac610b 100644 --- a/projects/element-ng/tabs/si-tabset.component.ts +++ b/projects/element-ng/tabs/si-tabset.component.ts @@ -17,6 +17,7 @@ import { INJECTOR, input, signal, + untracked, viewChild } from '@angular/core'; import { RouterLink } from '@angular/router'; @@ -29,6 +30,7 @@ import { SiResizeObserverModule } from '@siemens/element-ng/resize-observer'; import { SiTabBadgeComponent } from './si-tab-badge.component'; import { SiTabBaseDirective } from './si-tab-base.directive'; import { SiTabLinkComponent } from './si-tab-link.component'; +import { SiTabComponent } from './si-tab.component'; import { SI_TABSET } from './si-tabs-tokens'; /** @@ -94,6 +96,30 @@ export class SiTabsetComponent { } constructor() { + // Per the ARIA tabs pattern, at least one tab should be active. If the app + // does not provide an active tab, activate the first non-disabled content + // tab so the tablist stays keyboard reachable. + effect(() => { + const tabs = this.tabPanels(); + const hasActiveTab = !!this.activeTab(); + untracked(() => { + if (hasActiveTab) { + return; + } + const tabToActivate = tabs.find(tab => { + if (tab.disabledTab()) { + return false; + } + if (tab instanceof SiTabComponent) { + const canActivate = tab.canActivate(); + return canActivate ? canActivate() : true; + } + return true; + }); + tabToActivate?.selectTab(); + }); + }); + effect(() => { if (this.showMenuButton() && this.activeTab()) { // wait for menu button to render on DOM