Tabs
Tabbed content panels using the <primus-tabs> web component from @primus/ui-core. Handles keyboard navigation, ARIA attributes, and panel switching automatically.
Requires JS bundle
<primus-tabs> is a Web Component โ requires @primus/ui-core JS bundle loaded in your app.
Codeโ
- HTML ยท @primus/ui-core
- React
- Angular
<!-- Pill style (default) -->
<primus-tabs>
<div role="tablist">
<button role="tab">Overview</button>
<button role="tab">Transactions</button>
<button role="tab">Settings</button>
</div>
<div role="tabpanel">
<p>Overview content here.</p>
</div>
<div role="tabpanel">
<p>Transaction list here.</p>
</div>
<div role="tabpanel">
<p>Settings form here.</p>
</div>
</primus-tabs>
<!-- Underline style -->
<primus-tabs>
<div role="tablist" class="underline">
<button role="tab">General</button>
<button role="tab">Security</button>
<button role="tab">Notifications</button>
</div>
<div role="tabpanel">General settings</div>
<div role="tabpanel">Security settings</div>
<div role="tabpanel">Notification preferences</div>
</primus-tabs>
<!-- Listen for tab change event -->
<script>
document.querySelector('primus-tabs')
.addEventListener('primus-tab-change', (e) => {
const { index, tab } = e.detail;
console.log(`Switched to tab ${index}: ${tab.textContent}`);
});
</script>
import { useEffect, useRef } from 'react';
// Declare web component type (add to globals.d.ts)
declare namespace JSX {
interface IntrinsicElements {
'primus-tabs': React.HTMLAttributes<HTMLElement>;
}
}
function TenantTabs({ tenant }) {
const tabsRef = useRef<HTMLElement>(null);
useEffect(() => {
const el = tabsRef.current;
const handler = (e: Event) => {
const { index } = (e as CustomEvent).detail;
console.log('Active tab:', index);
};
el?.addEventListener('primus-tab-change', handler);
return () => el?.removeEventListener('primus-tab-change', handler);
}, []);
return (
<primus-tabs ref={tabsRef}>
<div role="tablist" className="underline">
<button role="tab">Overview</button>
<button role="tab">Users</button>
<button role="tab">Billing</button>
<button role="tab">Settings</button>
</div>
<div role="tabpanel"><TenantOverview tenant={tenant} /></div>
<div role="tabpanel"><TenantUsers tenantId={tenant.id} /></div>
<div role="tabpanel"><TenantBilling tenantId={tenant.id} /></div>
<div role="tabpanel"><TenantSettings tenant={tenant} /></div>
</primus-tabs>
);
}
// tenant-detail.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-tenant-detail',
templateUrl: './tenant-detail.component.html',
})
export class TenantDetailComponent {
activeTab = 0;
onTabChange(event: CustomEvent) {
this.activeTab = event.detail.index;
}
}
<!-- tenant-detail.component.html -->
<primus-tabs (primus-tab-change)="onTabChange($event)">
<div role="tablist" class="underline">
<button role="tab">Overview</button>
<button role="tab">Users</button>
<button role="tab">Billing</button>
<button role="tab">Settings</button>
</div>
<div role="tabpanel">
<app-tenant-overview *ngIf="activeTab === 0"></app-tenant-overview>
</div>
<div role="tabpanel">
<app-tenant-users *ngIf="activeTab === 1"></app-tenant-users>
</div>
<div role="tabpanel">
<app-tenant-billing *ngIf="activeTab === 2"></app-tenant-billing>
</div>
<div role="tabpanel">
<app-tenant-settings *ngIf="activeTab === 3"></app-tenant-settings>
</div>
</primus-tabs>
API Referenceโ
Structureโ
| Element | Role | Description |
|---|---|---|
<primus-tabs> | Container | Web Component โ manages state and ARIA |
<div role="tablist"> | Tab bar | Wrapper for tab buttons |
<button role="tab"> | Tab button | Clickable tab โ active one gets aria-selected="true" |
<div role="tabpanel"> | Panel | Content panel โ shown/hidden by the component |
Stylesโ
| Class on tablist | Appearance |
|---|---|
| (none) | Pill style โ active tab has card background |
underline | Underline style โ active tab has coloured bottom border |
Eventsโ
| Event | event.detail | Description |
|---|---|---|
primus-tab-change | { index: number, tab: HTMLElement } | Fired when active tab changes |
Keyboard navigationโ
| Key | Action |
|---|---|
โ / โ | Move between tabs |
Home | Go to first tab |
End | Go to last tab |
Enter / Space | Activate focused tab |
Version history
See the Changelog for version history and breaking changes.