Tab titeled {{ tab.title }} with id
diff --git a/packages/bits/src/constants/tabgroup.constants.ts b/packages/bits/src/constants/tabgroup.constants.ts
new file mode 100644
index 000000000..27ae11b7a
--- /dev/null
+++ b/packages/bits/src/constants/tabgroup.constants.ts
@@ -0,0 +1,22 @@
+// © 2026 SolarWinds Worldwide, LLC. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+export const TAB_ID_PREFIX = "tab-";
+export const TAB_PANEL_ID_PREFIX = "panel-";
diff --git a/packages/bits/src/lib/tabgroup/tab-group/tab-group.component.html b/packages/bits/src/lib/tabgroup/tab-group/tab-group.component.html
index 488f2acf1..a09363639 100644
--- a/packages/bits/src/lib/tabgroup/tab-group/tab-group.component.html
+++ b/packages/bits/src/lib/tabgroup/tab-group/tab-group.component.html
@@ -32,7 +32,7 @@
= new EventEmitter();
protected _active: boolean;
+ private _tabId = _uniqueId("nui-tab-heading-");
constructor(
private changeDetector: ChangeDetectorRef,
diff --git a/packages/bits/src/lib/tabgroup/tab/tab.component.ts b/packages/bits/src/lib/tabgroup/tab/tab.component.ts
index d4086747b..e7e91e746 100644
--- a/packages/bits/src/lib/tabgroup/tab/tab.component.ts
+++ b/packages/bits/src/lib/tabgroup/tab/tab.component.ts
@@ -29,6 +29,11 @@ import {
ViewEncapsulation,
} from "@angular/core";
+import {
+ TAB_ID_PREFIX,
+ TAB_PANEL_ID_PREFIX,
+} from "../../../constants/tabgroup.constants";
+import { _uniqueId } from "../../../functions/unique-id";
import { TabGroupComponent } from "../tab-group/tab-group.component";
/** @ignore */
@Component({
@@ -42,10 +47,16 @@ import { TabGroupComponent } from "../tab-group/tab-group.component";
standalone: false,
})
export class TabComponent {
- private static nextId = 0;
- /** Unique id for the tab and its panel. */
- public readonly tabId = `nui-tab-${TabComponent.nextId++}`;
- public readonly panelId = `${this.tabId}-panel`;
+ /** Unique identifier for the tab and its panel. Can be supplied by a consumer or generated automatically. */
+ @Input() public tabId = _uniqueId("nui-tab-");
+
+ public get tabControlId(): string {
+ return TAB_ID_PREFIX + this.tabId;
+ }
+
+ public get panelId(): string {
+ return TAB_PANEL_ID_PREFIX + this.tabId;
+ }
/** Tab header text */
@Input() heading: string;
@@ -89,7 +100,7 @@ export class TabComponent {
return this.panelId;
}
@HostBinding("attr.aria-labelledby") get ariaLabelledbyAttr() {
- return this.tabId;
+ return this.tabControlId;
}
public headingRef: TemplateRef
;
From 89e7c9bab7374edba258216dbf89e5eee7b800fa Mon Sep 17 00:00:00 2001
From: Petra Kubesova <133044666+kubeska@users.noreply.github.com>
Date: Tue, 11 Aug 2026 10:18:55 +0200
Subject: [PATCH 02/12] test(bits): NUI-6283 - cover tab-to-panel ARIA
relationships
---
.../tab-group/tab-group.component.spec.ts | 75 +++++++++++++++++
.../tab-heading-group.component.spec.ts | 82 ++++++++++++++++---
.../tab-heading/tab-heading.component.spec.ts | 10 +++
3 files changed, 156 insertions(+), 11 deletions(-)
create mode 100644 packages/bits/src/lib/tabgroup/tab-group/tab-group.component.spec.ts
diff --git a/packages/bits/src/lib/tabgroup/tab-group/tab-group.component.spec.ts b/packages/bits/src/lib/tabgroup/tab-group/tab-group.component.spec.ts
new file mode 100644
index 000000000..ad0fbf613
--- /dev/null
+++ b/packages/bits/src/lib/tabgroup/tab-group/tab-group.component.spec.ts
@@ -0,0 +1,75 @@
+// © 2026 SolarWinds Worldwide, LLC. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+import { Component, QueryList, ViewChildren } from "@angular/core";
+import { ComponentFixture, TestBed } from "@angular/core/testing";
+
+import { TabComponent } from "../tab/tab.component";
+import { NuiTabsModule } from "../tabs.module";
+
+@Component({
+ template: `
+
+ Overview
+ Details
+
+ `,
+ standalone: false,
+})
+class TestTabGroupComponent {
+ @ViewChildren(TabComponent) public tabs: QueryList;
+}
+
+describe("components > tab group", () => {
+ let componentFixture: ComponentFixture;
+ let subject: TestTabGroupComponent;
+
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ imports: [NuiTabsModule],
+ declarations: [TestTabGroupComponent],
+ });
+ componentFixture = TestBed.createComponent(TestTabGroupComponent);
+ subject = componentFixture.componentInstance;
+ componentFixture.detectChanges();
+ });
+
+ it("should connect every tab to its panel", () => {
+ const tabs =
+ componentFixture.nativeElement.querySelectorAll("[role=\"tab\"]");
+ const panels =
+ componentFixture.nativeElement.querySelectorAll(
+ "[role=\"tabpanel\"]"
+ );
+
+ expect(tabs.length).toBe(2);
+ expect(panels.length).toBe(2);
+
+ tabs.forEach((tab: HTMLElement, index: number) => {
+ const tabComponent = subject.tabs.toArray()[index];
+ const panel = panels[index] as HTMLElement;
+
+ expect(tab.id).toBe(`tab-${tabComponent.tabId}`);
+ expect(tab.getAttribute("aria-controls")).toBe(panel.id);
+ expect(panel.id).toBe(`panel-${tabComponent.tabId}`);
+ expect(panel.getAttribute("aria-labelledby")).toBe(tab.id);
+ });
+ });
+});
diff --git a/packages/bits/src/lib/tabgroup/tab-heading-group/tab-heading-group.component.spec.ts b/packages/bits/src/lib/tabgroup/tab-heading-group/tab-heading-group.component.spec.ts
index 1b31de93f..ce536d37a 100644
--- a/packages/bits/src/lib/tabgroup/tab-heading-group/tab-heading-group.component.spec.ts
+++ b/packages/bits/src/lib/tabgroup/tab-heading-group/tab-heading-group.component.spec.ts
@@ -37,18 +37,24 @@ import { TabHeadingComponent } from "../tab-heading/tab-heading.component";
@Component({
selector: "nui-test-tab-heading-group-cmp",
template: `
-
-
-
-
- `,
+
+
+
`,
standalone: false,
})
class TestTabHeadingComponent {
@@ -82,6 +88,24 @@ class TestTabHeadingComponent {
}
}
+@Component({
+ template: `
+
+ Overview
+
+
+ `,
+ standalone: false,
+})
+class TestGeneratedTabHeadingComponent {
+ @ViewChild(TabHeadingComponent, { static: true })
+ public tabHeading: TabHeadingComponent;
+}
+
describe("components >", () => {
describe("tab heading group >", () => {
let componentFixture: ComponentFixture
;
@@ -94,6 +118,7 @@ describe("components >", () => {
TabHeadingGroupComponent,
TabHeadingComponent,
TestTabHeadingComponent,
+ TestGeneratedTabHeadingComponent,
],
})
.compileComponents()
@@ -152,5 +177,40 @@ describe("components >", () => {
componentFixture.detectChanges();
expect(subject.currentTabId).toBe("3");
});
+
+ it("should relate headings to consumer-owned panels", () => {
+ componentFixture.detectChanges();
+
+ const tab =
+ componentFixture.nativeElement.querySelector("[role=\"tab\"]");
+ const panel =
+ componentFixture.nativeElement.querySelector(
+ "[role=\"tabpanel\"]"
+ );
+
+ expect(tab.id).toBe("tab-1");
+ expect(tab.getAttribute("aria-controls")).toBe(panel.id);
+ expect(panel.getAttribute("aria-labelledby")).toBe(tab.id);
+ });
+
+ it("should generate an id for a heading without one", () => {
+ const generatedFixture = TestBed.createComponent(
+ TestGeneratedTabHeadingComponent
+ );
+ generatedFixture.detectChanges();
+
+ const { tabHeading } = generatedFixture.componentInstance;
+ const tab =
+ generatedFixture.nativeElement.querySelector("[role=\"tab\"]");
+ const panel =
+ generatedFixture.nativeElement.querySelector(
+ "[role=\"tabpanel\"]"
+ );
+
+ expect(tabHeading.tabId).toMatch(/^nui-tab-heading-/);
+ expect(tab.id).toBe(tabHeading.tabControlId);
+ expect(tab.getAttribute("aria-controls")).toBe(panel.id);
+ expect(panel.getAttribute("aria-labelledby")).toBe(tab.id);
+ });
});
});
diff --git a/packages/bits/src/lib/tabgroup/tab-heading/tab-heading.component.spec.ts b/packages/bits/src/lib/tabgroup/tab-heading/tab-heading.component.spec.ts
index 81a513d6f..d86493e5b 100644
--- a/packages/bits/src/lib/tabgroup/tab-heading/tab-heading.component.spec.ts
+++ b/packages/bits/src/lib/tabgroup/tab-heading/tab-heading.component.spec.ts
@@ -44,5 +44,15 @@ describe("components >", () => {
subject.selectTab();
expect(subject.selected.emit).toHaveBeenCalled();
});
+
+ it("should expose an explicit id and controlled panel", () => {
+ subject.tabId = "overview";
+ componentFixture.detectChanges();
+
+ const tab =
+ componentFixture.nativeElement.querySelector("[role=\"tab\"]");
+ expect(tab.id).toBe("tab-overview");
+ expect(tab.getAttribute("aria-controls")).toBe("panel-overview");
+ });
});
});
From 5da0911f71512c2a96798f8c3a90ece3a2be7cce Mon Sep 17 00:00:00 2001
From: ludmila-fialova_swi
Date: Wed, 19 Aug 2026 07:54:19 +0200
Subject: [PATCH 03/12] NUI-6283 Nova version upgrade
---
docs/CHANGELOG.md | 7 ++++++-
package.json | 2 +-
packages/bits/package.json | 2 +-
packages/bits/schematics/package.json | 2 +-
packages/charts/package.json | 4 ++--
packages/dashboards/package.json | 6 +++---
packages/dashboards/schematics/package.json | 2 +-
7 files changed, 15 insertions(+), 10 deletions(-)
diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md
index 7eafbda22..d533712d5 100644
--- a/docs/CHANGELOG.md
+++ b/docs/CHANGELOG.md
@@ -1,9 +1,14 @@
# Changelog
-## [Unreleased]
+
+## [20.0.11] 📅 2026-08-24
### Fixes
- `@nova-ui/bits` | Align tab and tab-panel IDs with the accessible `tab-{id}` / `panel-{id}` relationship.
+## [20.0.10] 📅 2026-08-11
+### Fixes
+- `@nova-ui/bits` | SkipSpace a11y regression fixed
+
## [20.0.9] 📅 2026-08-05
### Fixes
- Essentional A11y fixies
diff --git a/package.json b/package.json
index 47531cbe2..ac941cbb7 100644
--- a/package.json
+++ b/package.json
@@ -129,7 +129,7 @@
"trigger-pipeline-build-ci": "bash scripts/trigger-pipeline-build",
"verify-ci": "bash scripts/verify-published"
},
- "version": "20.0.10",
+ "version": "20.0.11",
"workspaces": [
"packages/*"
]
diff --git a/packages/bits/package.json b/packages/bits/package.json
index 5201c3e50..ebbfbfc66 100644
--- a/packages/bits/package.json
+++ b/packages/bits/package.json
@@ -133,6 +133,6 @@
"visual:watch": "npx watch \"yarn run visual:base\" src demo spec --watch=1"
},
"typings": "public_api.d.ts",
- "version": "20.0.10",
+ "version": "20.0.11",
"packageManager": "yarn@1.22.18"
}
diff --git a/packages/bits/schematics/package.json b/packages/bits/schematics/package.json
index 1e8b9dcc8..e6541a834 100644
--- a/packages/bits/schematics/package.json
+++ b/packages/bits/schematics/package.json
@@ -1,7 +1,7 @@
{
"name": "nova-schematics",
"license": "Apache-2.0",
- "version": "20.0.10",
+ "version": "20.0.11",
"scripts": {
"assemble": "run-s build copy:json copy:data test copy:dist",
"build": "tsc -p tsconfig.json",
diff --git a/packages/charts/package.json b/packages/charts/package.json
index 2880c87b9..411f606ed 100644
--- a/packages/charts/package.json
+++ b/packages/charts/package.json
@@ -45,7 +45,7 @@
"license": "Apache-2.0",
"name": "@nova-ui/charts",
"dependencies": {
- "@nova-ui/bits": "~20.0.10"
+ "@nova-ui/bits": "~20.0.11"
},
"peerDependencies": {
"@types/d3": "^5.0.0",
@@ -114,6 +114,6 @@
"visual:gui": "yarn run visual:base -c gui",
"visual:serve": "yarn run visual:base -c serve"
},
- "version": "20.0.10"
+ "version": "20.0.11"
}
diff --git a/packages/dashboards/package.json b/packages/dashboards/package.json
index d841207a9..7b5a27ec2 100644
--- a/packages/dashboards/package.json
+++ b/packages/dashboards/package.json
@@ -41,8 +41,8 @@
"license": "Apache-2.0",
"name": "@nova-ui/dashboards",
"dependencies": {
- "@nova-ui/bits": "~20.0.10",
- "@nova-ui/charts": "~20.0.10"
+ "@nova-ui/bits": "~20.0.11",
+ "@nova-ui/charts": "~20.0.11"
},
"devDependencies": {
"@apollo/client": "3.13.9",
@@ -116,6 +116,6 @@
"visual:gui": "yarn run visual:base -c gui",
"visual:serve": "yarn run visual:base -c serve"
},
- "version": "20.0.10"
+ "version": "20.0.11"
}
diff --git a/packages/dashboards/schematics/package.json b/packages/dashboards/schematics/package.json
index c097f15e3..d1243eeb2 100644
--- a/packages/dashboards/schematics/package.json
+++ b/packages/dashboards/schematics/package.json
@@ -1,7 +1,7 @@
{
"name": "dashboards-schematics",
"license": "Apache-2.0",
- "version": "20.0.10",
+ "version": "20.0.11",
"scripts": {
"assemble": "run-s build copy:json copy:data test copy:dist",
"build": "tsc -p tsconfig.json",
From 9c76577aea747287a607f70e4fcdb2427742b5af Mon Sep 17 00:00:00 2001
From: ludmila-fialova_swi
Date: Wed, 19 Aug 2026 08:24:51 +0200
Subject: [PATCH 04/12] NUI-6283 fix(bits): make tab heading aria-controls
explicit
---
docs/CHANGELOG.md | 2 +-
.../repeat/repeat-test/repeat-test.component.html | 1 +
...tab-heading-group-dynamic.example.component.html | 1 +
...eading-group-with-content.example.component.html | 1 +
.../tab-heading-group.component.spec.ts | 7 ++++++-
.../tabgroup/tab-heading/tab-heading.component.html | 2 +-
.../tab-heading/tab-heading.component.spec.ts | 13 ++++++++++++-
.../tabgroup/tab-heading/tab-heading.component.ts | 3 +++
8 files changed, 26 insertions(+), 4 deletions(-)
diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md
index d533712d5..0d52bf3e1 100644
--- a/docs/CHANGELOG.md
+++ b/docs/CHANGELOG.md
@@ -3,7 +3,7 @@
## [20.0.11] 📅 2026-08-24
### Fixes
-- `@nova-ui/bits` | Align tab and tab-panel IDs with the accessible `tab-{id}` / `panel-{id}` relationship.
+- `@nova-ui/bits` | Fixed tab accessibility relationships by aligning `nui-tab` and consumer-owned tab panels with `tab-{id}` / `panel-{id}` IDs. `nui-tab-heading` now sets `aria-controls` only when the consumer provides the controlled panel ID through `ariaControls`.
## [20.0.10] 📅 2026-08-11
### Fixes
diff --git a/packages/bits/demo/src/components/demo/repeat/repeat-test/repeat-test.component.html b/packages/bits/demo/src/components/demo/repeat/repeat-test/repeat-test.component.html
index c453c8c88..ddc8c9c17 100644
--- a/packages/bits/demo/src/components/demo/repeat/repeat-test/repeat-test.component.html
+++ b/packages/bits/demo/src/components/demo/repeat/repeat-test/repeat-test.component.html
@@ -5,6 +5,7 @@
{{ tab.title }}
diff --git a/packages/bits/demo/src/components/demo/tabgroup/tab-heading-group-dynamic/tab-heading-group-dynamic.example.component.html b/packages/bits/demo/src/components/demo/tabgroup/tab-heading-group-dynamic/tab-heading-group-dynamic.example.component.html
index 90046e9cf..8bf0d5a1b 100644
--- a/packages/bits/demo/src/components/demo/tabgroup/tab-heading-group-dynamic/tab-heading-group-dynamic.example.component.html
+++ b/packages/bits/demo/src/components/demo/tabgroup/tab-heading-group-dynamic/tab-heading-group-dynamic.example.component.html
@@ -3,6 +3,7 @@
diff --git a/packages/bits/demo/src/components/demo/tabgroup/tab-heading-group-with-content/tab-heading-group-with-content.example.component.html b/packages/bits/demo/src/components/demo/tabgroup/tab-heading-group-with-content/tab-heading-group-with-content.example.component.html
index 15dfdbc05..3593182b2 100644
--- a/packages/bits/demo/src/components/demo/tabgroup/tab-heading-group-with-content/tab-heading-group-with-content.example.component.html
+++ b/packages/bits/demo/src/components/demo/tabgroup/tab-heading-group-with-content/tab-heading-group-with-content.example.component.html
@@ -4,6 +4,7 @@
*ngFor="let tab of tabsetContent"
[disabled]="tab.isDisabled"
[tabId]="tab.id"
+ [ariaControls]="'panel-' + tab.id"
>
diff --git a/packages/bits/src/lib/tabgroup/tab-heading-group/tab-heading-group.component.spec.ts b/packages/bits/src/lib/tabgroup/tab-heading-group/tab-heading-group.component.spec.ts
index ce536d37a..106f48b89 100644
--- a/packages/bits/src/lib/tabgroup/tab-heading-group/tab-heading-group.component.spec.ts
+++ b/packages/bits/src/lib/tabgroup/tab-heading-group/tab-heading-group.component.spec.ts
@@ -40,6 +40,7 @@ import { TabHeadingComponent } from "../tab-heading/tab-heading.component";
@@ -91,7 +92,11 @@ class TestTabHeadingComponent {
@Component({
template: `
- Overview
+ Overview
", () => {
expect(subject.selected.emit).toHaveBeenCalled();
});
- it("should expose an explicit id and controlled panel", () => {
+ it("should expose an explicit id without assuming a controlled panel", () => {
subject.tabId = "overview";
componentFixture.detectChanges();
+ const tab =
+ componentFixture.nativeElement.querySelector("[role=\"tab\"]");
+ expect(tab.id).toBe("tab-overview");
+ expect(tab.getAttribute("aria-controls")).toBeNull();
+ });
+
+ it("should expose an explicitly provided controlled panel", () => {
+ subject.tabId = "overview";
+ subject.ariaControls = subject.panelId;
+ componentFixture.detectChanges();
+
const tab =
componentFixture.nativeElement.querySelector("[role=\"tab\"]");
expect(tab.id).toBe("tab-overview");
diff --git a/packages/bits/src/lib/tabgroup/tab-heading/tab-heading.component.ts b/packages/bits/src/lib/tabgroup/tab-heading/tab-heading.component.ts
index 417e43f01..7c670b465 100644
--- a/packages/bits/src/lib/tabgroup/tab-heading/tab-heading.component.ts
+++ b/packages/bits/src/lib/tabgroup/tab-heading/tab-heading.component.ts
@@ -75,6 +75,9 @@ export class TabHeadingComponent {
return this._tabId;
}
+ /** ID of the panel controlled by this tab, when a consumer-owned panel exists. */
+ @Input() public ariaControls: string | null;
+
public get tabControlId(): string {
return TAB_ID_PREFIX + this.tabId;
}
From e5f3d5ef507cabcf950f730032bd209b17febed2 Mon Sep 17 00:00:00 2001
From: ludmila-fialova_swi
Date: Wed, 19 Aug 2026 08:34:14 +0200
Subject: [PATCH 05/12] NUI-6283 OnDestroy fix
---
.../tabgroup/tab-heading-group/tab-heading-group.component.ts | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/packages/bits/src/lib/tabgroup/tab-heading-group/tab-heading-group.component.ts b/packages/bits/src/lib/tabgroup/tab-heading-group/tab-heading-group.component.ts
index 9fe881983..f0ee8da2c 100644
--- a/packages/bits/src/lib/tabgroup/tab-heading-group/tab-heading-group.component.ts
+++ b/packages/bits/src/lib/tabgroup/tab-heading-group/tab-heading-group.component.ts
@@ -245,8 +245,8 @@ export class TabHeadingGroupComponent implements OnDestroy, AfterViewInit {
}
public ngOnDestroy(): void {
- this._changesSubscription.unsubscribe();
+ this._changesSubscription?.unsubscribe();
this._tabSelectedSubscriptions.forEach((sub) => sub.unsubscribe());
- this._ro.disconnect();
+ this._ro?.disconnect();
}
}
From 30d6c601874dd968b752cbd260179d13b7064916 Mon Sep 17 00:00:00 2001
From: ludmila-fialova_swi
Date: Wed, 19 Aug 2026 08:40:08 +0200
Subject: [PATCH 06/12] NUI-6283 test(bits): cover tab heading group early
cleanup
---
.../tab-group/tab-group.component.spec.ts | 4 ++--
.../tab-heading-group.component.spec.ts | 16 +++++++++-------
.../tab-heading/tab-heading.component.spec.ts | 4 ++--
3 files changed, 13 insertions(+), 11 deletions(-)
diff --git a/packages/bits/src/lib/tabgroup/tab-group/tab-group.component.spec.ts b/packages/bits/src/lib/tabgroup/tab-group/tab-group.component.spec.ts
index ad0fbf613..2414763a0 100644
--- a/packages/bits/src/lib/tabgroup/tab-group/tab-group.component.spec.ts
+++ b/packages/bits/src/lib/tabgroup/tab-group/tab-group.component.spec.ts
@@ -53,10 +53,10 @@ describe("components > tab group", () => {
it("should connect every tab to its panel", () => {
const tabs =
- componentFixture.nativeElement.querySelectorAll("[role=\"tab\"]");
+ componentFixture.nativeElement.querySelectorAll('[role="tab"]');
const panels =
componentFixture.nativeElement.querySelectorAll(
- "[role=\"tabpanel\"]"
+ '[role="tabpanel"]'
);
expect(tabs.length).toBe(2);
diff --git a/packages/bits/src/lib/tabgroup/tab-heading-group/tab-heading-group.component.spec.ts b/packages/bits/src/lib/tabgroup/tab-heading-group/tab-heading-group.component.spec.ts
index 106f48b89..a70005b03 100644
--- a/packages/bits/src/lib/tabgroup/tab-heading-group/tab-heading-group.component.spec.ts
+++ b/packages/bits/src/lib/tabgroup/tab-heading-group/tab-heading-group.component.spec.ts
@@ -92,9 +92,7 @@ class TestTabHeadingComponent {
@Component({
template: `
- Overview
@@ -135,6 +133,10 @@ describe("components >", () => {
});
}));
+ it("should safely clean up before view initialization", () => {
+ expect(() => subject.tabHeadingGroup.ngOnDestroy()).not.toThrow();
+ });
+
it("should add tabs initially", () => {
componentFixture.detectChanges();
expect(subject.tabHeadings.toArray().length).toEqual(2);
@@ -187,10 +189,10 @@ describe("components >", () => {
componentFixture.detectChanges();
const tab =
- componentFixture.nativeElement.querySelector("[role=\"tab\"]");
+ componentFixture.nativeElement.querySelector('[role="tab"]');
const panel =
componentFixture.nativeElement.querySelector(
- "[role=\"tabpanel\"]"
+ '[role="tabpanel"]'
);
expect(tab.id).toBe("tab-1");
@@ -206,10 +208,10 @@ describe("components >", () => {
const { tabHeading } = generatedFixture.componentInstance;
const tab =
- generatedFixture.nativeElement.querySelector("[role=\"tab\"]");
+ generatedFixture.nativeElement.querySelector('[role="tab"]');
const panel =
generatedFixture.nativeElement.querySelector(
- "[role=\"tabpanel\"]"
+ '[role="tabpanel"]'
);
expect(tabHeading.tabId).toMatch(/^nui-tab-heading-/);
diff --git a/packages/bits/src/lib/tabgroup/tab-heading/tab-heading.component.spec.ts b/packages/bits/src/lib/tabgroup/tab-heading/tab-heading.component.spec.ts
index 0c125e6ab..e355eab9d 100644
--- a/packages/bits/src/lib/tabgroup/tab-heading/tab-heading.component.spec.ts
+++ b/packages/bits/src/lib/tabgroup/tab-heading/tab-heading.component.spec.ts
@@ -50,7 +50,7 @@ describe("components >", () => {
componentFixture.detectChanges();
const tab =
- componentFixture.nativeElement.querySelector("[role=\"tab\"]");
+ componentFixture.nativeElement.querySelector('[role="tab"]');
expect(tab.id).toBe("tab-overview");
expect(tab.getAttribute("aria-controls")).toBeNull();
});
@@ -61,7 +61,7 @@ describe("components >", () => {
componentFixture.detectChanges();
const tab =
- componentFixture.nativeElement.querySelector("[role=\"tab\"]");
+ componentFixture.nativeElement.querySelector('[role="tab"]');
expect(tab.id).toBe("tab-overview");
expect(tab.getAttribute("aria-controls")).toBe("panel-overview");
});
From 88e95f75f106598e82801b22a0821fa70f645771 Mon Sep 17 00:00:00 2001
From: ludmila-fialova_swi
Date: Wed, 19 Aug 2026 08:41:42 +0200
Subject: [PATCH 07/12] chore(repo): enforce LF line endings
---
.gitattributes | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/.gitattributes b/.gitattributes
index 84c40ccaa..6313b56c5 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1,4 +1 @@
-[core]
-autocrlf=false
-eol=lf
-* text=auto
+* text=auto eol=lf
From d3e6dde6ede3c21796c317e036e7caa74f1e2709 Mon Sep 17 00:00:00 2001
From: ludmila-fialova_swi
Date: Wed, 19 Aug 2026 09:15:33 +0200
Subject: [PATCH 08/12] lint fix
---
.../lib/tabgroup/tab-group/tab-group.component.spec.ts | 4 ++--
.../tab-heading-group/tab-heading-group.component.spec.ts | 8 ++++----
.../tabgroup/tab-heading/tab-heading.component.spec.ts | 4 ++--
3 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/packages/bits/src/lib/tabgroup/tab-group/tab-group.component.spec.ts b/packages/bits/src/lib/tabgroup/tab-group/tab-group.component.spec.ts
index 2414763a0..9adfba1d7 100644
--- a/packages/bits/src/lib/tabgroup/tab-group/tab-group.component.spec.ts
+++ b/packages/bits/src/lib/tabgroup/tab-group/tab-group.component.spec.ts
@@ -53,10 +53,10 @@ describe("components > tab group", () => {
it("should connect every tab to its panel", () => {
const tabs =
- componentFixture.nativeElement.querySelectorAll('[role="tab"]');
+ componentFixture.nativeElement.querySelectorAll("[role='tab']");
const panels =
componentFixture.nativeElement.querySelectorAll(
- '[role="tabpanel"]'
+ "[role='tabpanel']"
);
expect(tabs.length).toBe(2);
diff --git a/packages/bits/src/lib/tabgroup/tab-heading-group/tab-heading-group.component.spec.ts b/packages/bits/src/lib/tabgroup/tab-heading-group/tab-heading-group.component.spec.ts
index a70005b03..a56c2361c 100644
--- a/packages/bits/src/lib/tabgroup/tab-heading-group/tab-heading-group.component.spec.ts
+++ b/packages/bits/src/lib/tabgroup/tab-heading-group/tab-heading-group.component.spec.ts
@@ -189,10 +189,10 @@ describe("components >", () => {
componentFixture.detectChanges();
const tab =
- componentFixture.nativeElement.querySelector('[role="tab"]');
+ componentFixture.nativeElement.querySelector("[role='tab']");
const panel =
componentFixture.nativeElement.querySelector(
- '[role="tabpanel"]'
+ "[role='tabpanel']"
);
expect(tab.id).toBe("tab-1");
@@ -208,10 +208,10 @@ describe("components >", () => {
const { tabHeading } = generatedFixture.componentInstance;
const tab =
- generatedFixture.nativeElement.querySelector('[role="tab"]');
+ generatedFixture.nativeElement.querySelector("[role='tab']");
const panel =
generatedFixture.nativeElement.querySelector(
- '[role="tabpanel"]'
+ "[role='tabpanel']"
);
expect(tabHeading.tabId).toMatch(/^nui-tab-heading-/);
diff --git a/packages/bits/src/lib/tabgroup/tab-heading/tab-heading.component.spec.ts b/packages/bits/src/lib/tabgroup/tab-heading/tab-heading.component.spec.ts
index e355eab9d..705e4c67c 100644
--- a/packages/bits/src/lib/tabgroup/tab-heading/tab-heading.component.spec.ts
+++ b/packages/bits/src/lib/tabgroup/tab-heading/tab-heading.component.spec.ts
@@ -50,7 +50,7 @@ describe("components >", () => {
componentFixture.detectChanges();
const tab =
- componentFixture.nativeElement.querySelector('[role="tab"]');
+ componentFixture.nativeElement.querySelector("[role='tab']");
expect(tab.id).toBe("tab-overview");
expect(tab.getAttribute("aria-controls")).toBeNull();
});
@@ -61,7 +61,7 @@ describe("components >", () => {
componentFixture.detectChanges();
const tab =
- componentFixture.nativeElement.querySelector('[role="tab"]');
+ componentFixture.nativeElement.querySelector("[role='tab']");
expect(tab.id).toBe("tab-overview");
expect(tab.getAttribute("aria-controls")).toBe("panel-overview");
});
From 9d644bb13c5f09e2681b31d22a3a3d6bb2b9dd71 Mon Sep 17 00:00:00 2001
From: ludmila-fialova_swi
Date: Wed, 19 Aug 2026 13:01:58 +0200
Subject: [PATCH 09/12] NUI-6283 fix(bits): complete router tab example a11y
bindings
---
...ading-group-with-router.example.component.html | 15 +++++++++++++--
1 file changed, 13 insertions(+), 2 deletions(-)
diff --git a/packages/bits/demo/src/components/demo/tabgroup/tab-heading-group-with-router/tab-heading-group-with-router.example.component.html b/packages/bits/demo/src/components/demo/tabgroup/tab-heading-group-with-router/tab-heading-group-with-router.example.component.html
index f1249a8bc..bac49d728 100644
--- a/packages/bits/demo/src/components/demo/tabgroup/tab-heading-group-with-router/tab-heading-group-with-router.example.component.html
+++ b/packages/bits/demo/src/components/demo/tabgroup/tab-heading-group-with-router/tab-heading-group-with-router.example.component.html
@@ -3,6 +3,9 @@
@@ -28,6 +31,14 @@
-
-
+
+
+
+
From 6ddfa15220c1577db46a5c98714d856cd9710d22 Mon Sep 17 00:00:00 2001
From: ludmila-fialova_swi
Date: Wed, 19 Aug 2026 13:13:57 +0200
Subject: [PATCH 10/12] NUI-6283 fix: prevent duplicate tabgroup demo IDs
---
.../tab-heading-group-dynamic.example.component.html | 8 ++++----
...roup-horizontal-with-icons-only.example.component.html | 2 +-
...ing-group-horizontal-with-icons.example.component.html | 2 +-
.../tab-heading-group-horizontal.example.component.html | 2 +-
.../tab-heading-group-responsive.example.component.html | 2 +-
...ading-group-vertical-with-icons.example.component.html | 6 +++---
.../tab-heading-group-vertical.example.component.html | 2 +-
.../tab-heading-group-with-content.example.component.html | 8 ++++----
.../tab-heading-group-with-icons.example.component.html | 2 +-
9 files changed, 17 insertions(+), 17 deletions(-)
diff --git a/packages/bits/demo/src/components/demo/tabgroup/tab-heading-group-dynamic/tab-heading-group-dynamic.example.component.html b/packages/bits/demo/src/components/demo/tabgroup/tab-heading-group-dynamic/tab-heading-group-dynamic.example.component.html
index 8bf0d5a1b..a9db7f07f 100644
--- a/packages/bits/demo/src/components/demo/tabgroup/tab-heading-group-dynamic/tab-heading-group-dynamic.example.component.html
+++ b/packages/bits/demo/src/components/demo/tabgroup/tab-heading-group-dynamic/tab-heading-group-dynamic.example.component.html
@@ -2,8 +2,8 @@
@@ -19,8 +19,8 @@
diff --git a/packages/bits/demo/src/components/demo/tabgroup/tab-heading-group-horizontal-with-icons-only/tab-heading-group-horizontal-with-icons-only.example.component.html b/packages/bits/demo/src/components/demo/tabgroup/tab-heading-group-horizontal-with-icons-only/tab-heading-group-horizontal-with-icons-only.example.component.html
index 190b600a3..cbf77dc64 100644
--- a/packages/bits/demo/src/components/demo/tabgroup/tab-heading-group-horizontal-with-icons-only/tab-heading-group-horizontal-with-icons-only.example.component.html
+++ b/packages/bits/demo/src/components/demo/tabgroup/tab-heading-group-horizontal-with-icons-only/tab-heading-group-horizontal-with-icons-only.example.component.html
@@ -3,7 +3,7 @@
diff --git a/packages/bits/demo/src/components/demo/tabgroup/tab-heading-group-horizontal-with-icons/tab-heading-group-horizontal-with-icons.example.component.html b/packages/bits/demo/src/components/demo/tabgroup/tab-heading-group-horizontal-with-icons/tab-heading-group-horizontal-with-icons.example.component.html
index 5b88ad165..80cea4898 100644
--- a/packages/bits/demo/src/components/demo/tabgroup/tab-heading-group-horizontal-with-icons/tab-heading-group-horizontal-with-icons.example.component.html
+++ b/packages/bits/demo/src/components/demo/tabgroup/tab-heading-group-horizontal-with-icons/tab-heading-group-horizontal-with-icons.example.component.html
@@ -3,7 +3,7 @@
diff --git a/packages/bits/demo/src/components/demo/tabgroup/tab-heading-group-horizontal/tab-heading-group-horizontal.example.component.html b/packages/bits/demo/src/components/demo/tabgroup/tab-heading-group-horizontal/tab-heading-group-horizontal.example.component.html
index ee12957a2..aa535b174 100644
--- a/packages/bits/demo/src/components/demo/tabgroup/tab-heading-group-horizontal/tab-heading-group-horizontal.example.component.html
+++ b/packages/bits/demo/src/components/demo/tabgroup/tab-heading-group-horizontal/tab-heading-group-horizontal.example.component.html
@@ -3,7 +3,7 @@
diff --git a/packages/bits/demo/src/components/demo/tabgroup/tab-heading-group-responsive/tab-heading-group-responsive.example.component.html b/packages/bits/demo/src/components/demo/tabgroup/tab-heading-group-responsive/tab-heading-group-responsive.example.component.html
index 4f037735e..ae65fba96 100644
--- a/packages/bits/demo/src/components/demo/tabgroup/tab-heading-group-responsive/tab-heading-group-responsive.example.component.html
+++ b/packages/bits/demo/src/components/demo/tabgroup/tab-heading-group-responsive/tab-heading-group-responsive.example.component.html
@@ -3,7 +3,7 @@
diff --git a/packages/bits/demo/src/components/demo/tabgroup/tab-heading-group-vertical-with-icons/tab-heading-group-vertical-with-icons.example.component.html b/packages/bits/demo/src/components/demo/tabgroup/tab-heading-group-vertical-with-icons/tab-heading-group-vertical-with-icons.example.component.html
index dd16640d7..d38e2e458 100644
--- a/packages/bits/demo/src/components/demo/tabgroup/tab-heading-group-vertical-with-icons/tab-heading-group-vertical-with-icons.example.component.html
+++ b/packages/bits/demo/src/components/demo/tabgroup/tab-heading-group-vertical-with-icons/tab-heading-group-vertical-with-icons.example.component.html
@@ -3,12 +3,12 @@
-
{{ tab.title }}
diff --git a/packages/bits/demo/src/components/demo/tabgroup/tab-heading-group-with-content/tab-heading-group-with-content.example.component.html b/packages/bits/demo/src/components/demo/tabgroup/tab-heading-group-with-content/tab-heading-group-with-content.example.component.html
index 3593182b2..a0958eb3d 100644
--- a/packages/bits/demo/src/components/demo/tabgroup/tab-heading-group-with-content/tab-heading-group-with-content.example.component.html
+++ b/packages/bits/demo/src/components/demo/tabgroup/tab-heading-group-with-content/tab-heading-group-with-content.example.component.html
@@ -3,8 +3,8 @@
@@ -31,8 +31,8 @@
diff --git a/packages/bits/demo/src/components/demo/tabgroup/tab-heading-group-with-icons/tab-heading-group-with-icons.example.component.html b/packages/bits/demo/src/components/demo/tabgroup/tab-heading-group-with-icons/tab-heading-group-with-icons.example.component.html
index 45140443c..287cbc981 100644
--- a/packages/bits/demo/src/components/demo/tabgroup/tab-heading-group-with-icons/tab-heading-group-with-icons.example.component.html
+++ b/packages/bits/demo/src/components/demo/tabgroup/tab-heading-group-with-icons/tab-heading-group-with-icons.example.component.html
@@ -3,7 +3,7 @@
From d074d088c3c5395ef12473eb9534affd24ad52f4 Mon Sep 17 00:00:00 2001
From: ludmila-fialova_swi
Date: Wed, 19 Aug 2026 15:31:03 +0200
Subject: [PATCH 11/12] NUI-6283 test: cover routed tab ARIA relationships
---
...g-group-with-router.example.component.html | 2 +
.../tab-heading-group.e2e.spec.ts | 69 +++++++++++++++++++
2 files changed, 71 insertions(+)
diff --git a/packages/bits/demo/src/components/demo/tabgroup/tab-heading-group-with-router/tab-heading-group-with-router.example.component.html b/packages/bits/demo/src/components/demo/tabgroup/tab-heading-group-with-router/tab-heading-group-with-router.example.component.html
index bac49d728..a97bd48f1 100644
--- a/packages/bits/demo/src/components/demo/tabgroup/tab-heading-group-with-router/tab-heading-group-with-router.example.component.html
+++ b/packages/bits/demo/src/components/demo/tabgroup/tab-heading-group-with-router/tab-heading-group-with-router.example.component.html
@@ -1,5 +1,7 @@
+
{
await lastTab.click();
await lastTab.toBeActive();
});
+
+ test("should relate each routed tab to the current panel", async ({
+ page,
+ }) => {
+ const routes = ["tab-settings", "tab-statistics", "tab-about"];
+
+ for (const route of routes) {
+ await Helpers.prepareBrowser(`tabgroup/${route}`, page);
+
+ const routerExample = page.locator(
+ "nui-tab-heading-group-with-router-example"
+ );
+ const activeTab = routerExample.locator(
+ "[role='tab'][aria-selected='true']"
+ );
+ const panel = routerExample.locator("[role='tabpanel']");
+
+ await expect(activeTab).toHaveAttribute("id", `tab-${route}`);
+ await expect(activeTab).toHaveAttribute(
+ "aria-controls",
+ `panel-${route}`
+ );
+ await expect(panel).toHaveCount(1);
+ await expect(panel).toHaveAttribute("id", `panel-${route}`);
+ await expect(panel).toHaveAttribute(
+ "aria-labelledby",
+ `tab-${route}`
+ );
+ await expect(
+ routerExample.locator(
+ "[role='tab'][aria-selected='false'][aria-controls]"
+ )
+ ).toHaveCount(0);
+ }
+ });
+
+ test("should update the routed panel relationship when switching tabs", async ({
+ page,
+ }) => {
+ await Helpers.prepareBrowser("tabgroup/tab-settings", page);
+
+ const routerExample = page.locator(
+ "nui-tab-heading-group-with-router-example"
+ );
+ await routerExample.locator("nui-tab-heading").nth(1).click();
+
+ await expect(page).toHaveURL(/\/#\/tabgroup\/tab-statistics$/);
+
+ const activeTab = routerExample.locator(
+ "[role='tab'][aria-selected='true']"
+ );
+ const panel = routerExample.locator("[role='tabpanel']");
+
+ await expect(activeTab).toHaveAttribute("id", "tab-tab-statistics");
+ await expect(activeTab).toHaveAttribute(
+ "aria-controls",
+ "panel-tab-statistics"
+ );
+ await expect(panel).toHaveAttribute("id", "panel-tab-statistics");
+ await expect(panel).toHaveAttribute(
+ "aria-labelledby",
+ "tab-tab-statistics"
+ );
+ await expect(
+ routerExample.locator(
+ "[role='tab'][aria-selected='false'][aria-controls]"
+ )
+ ).toHaveCount(0);
+ });
});
From 4f55e12c334b9d2add73bf982c6ba49ea8ba9152 Mon Sep 17 00:00:00 2001
From: ludmila-fialova_swi
Date: Wed, 19 Aug 2026 16:31:57 +0200
Subject: [PATCH 12/12] NUI-6283: fix tab heading keyboard activation and focus
---
...g-group-with-router.example.component.html | 1 +
.../tab-heading-group.e2e.spec.ts | 28 ++++++++++++++++++-
.../tab-heading/tab-heading.component.spec.ts | 9 ++++++
.../tab-heading/tab-heading.component.ts | 1 +
4 files changed, 38 insertions(+), 1 deletion(-)
diff --git a/packages/bits/demo/src/components/demo/tabgroup/tab-heading-group-with-router/tab-heading-group-with-router.example.component.html b/packages/bits/demo/src/components/demo/tabgroup/tab-heading-group-with-router/tab-heading-group-with-router.example.component.html
index a97bd48f1..632548e0e 100644
--- a/packages/bits/demo/src/components/demo/tabgroup/tab-heading-group-with-router/tab-heading-group-with-router.example.component.html
+++ b/packages/bits/demo/src/components/demo/tabgroup/tab-heading-group-with-router/tab-heading-group-with-router.example.component.html
@@ -8,6 +8,7 @@
[ariaControls]="
currentTabRoute === tab.id ? 'panel-' + tab.id : null
"
+ tabindex="-1"
routerLink="/tabgroup/{{ tab.id }}"
[active]="currentTabRoute === tab.id"
>
diff --git a/packages/bits/e2e/components/tab-heading-group/tab-heading-group.e2e.spec.ts b/packages/bits/e2e/components/tab-heading-group/tab-heading-group.e2e.spec.ts
index 0279af16d..fe17b2f89 100644
--- a/packages/bits/e2e/components/tab-heading-group/tab-heading-group.e2e.spec.ts
+++ b/packages/bits/e2e/components/tab-heading-group/tab-heading-group.e2e.spec.ts
@@ -95,6 +95,24 @@ test.describe("USERCONTROL tab heading group", () => {
await lastTab.toBeActive();
});
+ test("should activate a focused tab with Enter and Space", async ({
+ page,
+ }) => {
+ await Helpers.prepareBrowser("tabgroup", page);
+
+ const tabs = page.locator(
+ "nui-tab-heading-group-dynamic-example [role='tab']"
+ );
+
+ await tabs.nth(1).focus();
+ await page.keyboard.press("Enter");
+ await expect(tabs.nth(1)).toHaveAttribute("aria-selected", "true");
+
+ await tabs.nth(0).focus();
+ await page.keyboard.press("Space");
+ await expect(tabs.nth(0)).toHaveAttribute("aria-selected", "true");
+ });
+
test("should relate each routed tab to the current panel", async ({
page,
}) => {
@@ -138,7 +156,9 @@ test.describe("USERCONTROL tab heading group", () => {
const routerExample = page.locator(
"nui-tab-heading-group-with-router-example"
);
- await routerExample.locator("nui-tab-heading").nth(1).click();
+ const statisticsTab = routerExample.locator("[role='tab']").nth(1);
+ await statisticsTab.focus();
+ await page.keyboard.press("Enter");
await expect(page).toHaveURL(/\/#\/tabgroup\/tab-statistics$/);
@@ -162,5 +182,11 @@ test.describe("USERCONTROL tab heading group", () => {
"[role='tab'][aria-selected='false'][aria-controls]"
)
).toHaveCount(0);
+ await expect(
+ routerExample.locator("nui-tab-heading[tabindex='-1']")
+ ).toHaveCount(3);
+ await expect(
+ routerExample.locator("[role='tab'][tabindex='0']")
+ ).toHaveCount(3);
});
});
diff --git a/packages/bits/src/lib/tabgroup/tab-heading/tab-heading.component.spec.ts b/packages/bits/src/lib/tabgroup/tab-heading/tab-heading.component.spec.ts
index 705e4c67c..63f9d79b2 100644
--- a/packages/bits/src/lib/tabgroup/tab-heading/tab-heading.component.spec.ts
+++ b/packages/bits/src/lib/tabgroup/tab-heading/tab-heading.component.spec.ts
@@ -45,6 +45,15 @@ describe("components >", () => {
expect(subject.selected.emit).toHaveBeenCalled();
});
+ it("should emit event when activated with Enter or Space", () => {
+ spyOn(subject.selected, "emit");
+
+ subject.onKeyDown(new KeyboardEvent("keydown", { code: "Enter" }));
+ subject.onKeyDown(new KeyboardEvent("keydown", { code: "Space" }));
+
+ expect(subject.selected.emit).toHaveBeenCalledTimes(2);
+ });
+
it("should expose an explicit id without assuming a controlled panel", () => {
subject.tabId = "overview";
componentFixture.detectChanges();
diff --git a/packages/bits/src/lib/tabgroup/tab-heading/tab-heading.component.ts b/packages/bits/src/lib/tabgroup/tab-heading/tab-heading.component.ts
index 7c670b465..477530eb1 100644
--- a/packages/bits/src/lib/tabgroup/tab-heading/tab-heading.component.ts
+++ b/packages/bits/src/lib/tabgroup/tab-heading/tab-heading.component.ts
@@ -109,6 +109,7 @@ export class TabHeadingComponent {
event.code === KEYBOARD_CODE.SPACE
) {
event.preventDefault();
+ this.selectTab();
this.elementRef.nativeElement.click();
}
}