Tabs is a compound component: a host, a trigger directive, and an optional panel directive.

tabs.ts
import { KuiTabs, KuiTab, KuiTabPanel } from '@kikita-labs/ui';

Bind value to the active tab and pair each kuiTab with a matching kuiTabPanel.

Overview content.
<kui-tabs [(value)]="activeTab">
  <button kuiTab value="overview">Overview</button>
  <button kuiTab value="settings">Settings</button>
  <button kuiTab value="logs">Logs</button>

  <div kuiTabPanel value="overview">Overview content.</div>
  <div kuiTabPanel value="settings">Settings content.</div>
  <div kuiTabPanel value="logs">Log content.</div>
</kui-tabs>

Set variant to pill for a soft background indicator. hasError adds a small danger dot to a tab without changing its selected state.

Daily report content.
<kui-tabs variant="pill" [(value)]="activeTab">
  <button kuiTab value="daily">Daily</button>
  <button kuiTab value="weekly" hasError errorLabel="Contains validation errors">Weekly</button>
  <button kuiTab value="monthly">Monthly</button>

  <div kuiTabPanel value="daily">Daily report content.</div>
  <div kuiTabPanel value="weekly">Weekly report content.</div>
  <div kuiTabPanel value="monthly">Monthly report content.</div>
</kui-tabs>

Set orientation to vertical to stack the tab list in a column. Add inverted when the panel should sit before the tab list and the indicator should move to the start edge.

Profile content.
<kui-tabs orientation="vertical" [(value)]="activeTab">
  <button kuiTab value="profile">Profile</button>
  <button kuiTab value="billing">Billing</button>
  <button kuiTab value="security">Security</button>

  <div kuiTabPanel value="profile">Profile content.</div>
  <div kuiTabPanel value="billing">Billing content.</div>
  <div kuiTabPanel value="security">Security content.</div>
</kui-tabs>

Set controlsPanels to false when tabs act as navigation and the routed content is rendered elsewhere, such as a router-outlet, instead of local kuiTabPanel elements.

<kui-tabs [(value)]="currentSection" [controlsPanels]="false" aria-label="Sections">
  <button kuiTab value="/overview">Overview</button>
  <button kuiTab value="/settings">Settings</button>
  <button kuiTab value="/team">Team</button>
</kui-tabs>

<p class="navigation-tabs-example__note">
  Selected value: <code>{{ currentSection() }}</code>
</p>

Set defaults.tabs once for the application or for a subtree. Each option resolves as local input > defaults.tabs.<option> > built-in default.

import { provideKikitaUi } from '@kikita-labs/ui';

export const appConfig: ApplicationConfig = {
  providers: [
    provideKikitaUi({
      defaults: {
        tabs: {
          /* options below */
        },
      },
    }),
  ],
};
NameTypeDefaultDescription
size'xs' | 'sm' | 'md' | 'lg' — Component size. Takes precedence over the global defaults.size.
variant'line' | 'pill' — Default variant.
orientation'horizontal' | 'vertical' — Default orientation.
previousIconKuiIconGlyph — Icon of the previous control. Takes precedence over defaults.icons.previous. See Structural Icons.
nextIconKuiIconGlyph — Icon of the next control. Takes precedence over defaults.icons.next. See Structural Icons.

Set any of these on the component or an ancestor to restyle one part. Each token is optional: when it is not set, the part uses the role or scale token in the default column.

NameTypeDefaultDescription
--kui-tabs-scroll-btn-colorCSS custom property--kui-color-text-secondaryS scroll btn color
--kui-tabs-scroll-btn-color-hoverCSS custom property--kui-color-textS scroll btn color, hover
--kui-tabs-scroll-fade-colorCSS custom property--kui-color-bgS scroll fade color
--kui-tab-focus-ring-colorCSS custom property--kui-color-focusfocus ring color
--kui-tab-panel-focus-ring-colorCSS custom property--kui-color-focuspanel focus outline color

Every text the component owns (accessible names, visible words, announcements) is a typed message with an English default. Override it for the application with provideKikitaUi({ messages }), or for a subtree with provideKuiMessages.

NameTypeDefaultDescription
scrollLeftstring — Scroll left button. Default Scroll tabs left.
scrollRightstring — Scroll right button. Default Scroll tabs right.
errorIndicatorstring — Hidden text of the error dot. Default has error.

Inputs verified against @kikita-labs/ui v2.0.0 v2.0.0 public typings.

NameTypeDefaultDescription
variant'line' | 'pill' | undefinedundefinedTab visual style: underline indicator (line) or pill background (pill). Falls back to defaults.tabs.variant, then line.
size'xs' | 'sm' | 'md' | 'lg' | undefinedundefinedTab trigger height and font size. Falls back to defaults.tabs.size, then the root size, then md.
orientation'horizontal' | 'vertical' | undefinedundefinedLayout direction of the tab list (defaults.tabs.orientation, then horizontal). Vertical stacks triggers in a column with the indicator on the side edge.
invertedbooleanfalseFlips the tab edge. Horizontal tabs render panels above and the indicator on top; vertical tabs render panels before the list and the indicator on the start edge.
controlsPanelsbooleantrueWhether tabs expose aria-controls links to projected kuiTabPanel elements. Set to false when tabs are used as navigation and content is rendered elsewhere, such as a router-outlet.
[(value)]string-Value of the active tab.
[(selected)]string-Deprecated alias for value, kept in sync with it. Use value instead; planned for removal in the next major version.
[kuiTab] valuestring-Identifier for this tab trigger. Must match a kuiTabPanel value when controlsPanels is true.
[kuiTab] hasErrorbooleanfalseShows a small danger dot next to the tab label without changing the selected state or tab color.
[kuiTab] errorLabelstring | undefinedundefinedScreen-reader-only text announced alongside the error dot. Falls back to the tabs.errorIndicator message (has error).
[kuiTabPanel] valuestring-Identifier matching a [kuiTab] value. Panel is shown when its value matches the tabs value.
--kui-tabs-gapCSS length2pxGap between tab triggers in the list.
--kui-tabs-borderCSS colorvar(--kui-color-border)Border color of the tab list edge (bottom for horizontal, side for vertical).
--kui-tabs-panel-gapCSS lengthvar(--kui-space-4)Gap between the tab list and the active panel.
--kui-tab-heightCSS lengthvar(--kui-btn-height)Tab trigger block size. Overridden per size.
--kui-tab-pxCSS lengthvar(--kui-btn-px)Tab trigger inline padding. Overridden per size.
--kui-tab-indicatorCSS colorvar(--kui-color-primary-fill)Color of the selected-tab indicator (underline for line, background for pill).
--kui-tab-fg-activeCSS colorvar(--kui-color-text)Text color of the selected tab.
--kui-tab-gapCSS custom property-Gap inside a tab trigger.
--kui-tab-radiusCSS custom property-Tab trigger corner radius.
--kui-tab-fgCSS custom property-Tab foreground.
--kui-tab-fg-hoverCSS custom property-Tab foreground on hover.
--kui-tab-bg-hoverCSS custom property-Tab background on hover.
--kui-tab-indicator-sizeCSS custom property-Thickness of the active indicator.
--kui-tab-font-sizeCSS custom property-Tab font size.
--kui-tab-font-weightCSS custom property-Tab font weight.
--kui-tab-font-weight-activeCSS custom property-Active tab font weight.
--kui-tab-pill-gapCSS custom property-Gap between pill tabs.
--kui-tab-pill-radiusCSS custom property-Pill tab corner radius.
--kui-tab-pill-bg-hoverCSS custom property-Pill tab background on hover.
--kui-tab-pill-bg-activeCSS custom property-Active pill tab background.
--kui-tab-pill-fg-activeCSS custom property-Active pill tab foreground.
KuiTabsOptionsinterface-Shape of defaults.tabs: size, variant, orientation, previousIcon and nextIcon.

Tabs owns keyboard navigation and the tablist/tab/tabpanel ARIA structure.

  • The list container uses role="tablist".
  • Each trigger uses role="tab" with aria-selected and roving tabindex.
  • Each panel uses role="tabpanel".
  • aria-controls is emitted by default and should point to a matching [kuiTabPanel]; disable this wiring with [controlsPanels]="false" for navigation-style tabs without local panels.
  • ArrowLeft / ArrowRight move focus between tabs.
  • Home focuses the first tab; End focuses the last tab.
  • Scroll buttons are named by the tabs.scrollLeft and tabs.scrollRight messages, and the error dot text by tabs.errorIndicator.
  • At narrow widths the tablist scrolls horizontally and exposes accessible scroll buttons when needed.
  • Tabs covers keyboard navigation and static ARIA review. Screen reader and other assistive-technology verification has not been completed for this primitive yet; see state-coverage.md in the library repository for current review status.

Consumer-visible changes of @kikita-labs/ui 2.0 for Tabs.

  • The classes are KuiTabs, KuiTab and KuiTabPanel; the Component and Directive suffixes are gone.
  • Size, variant and orientation defaults moved to provideKuiDefaults({ tabs: { ... } }), together with previousIcon and nextIcon glyphs; the inputs are now undefined until set.
  • Scroll button names and the default errorLabel come from the tabs messages.
  • Hover and pressed fills read --kui-color-state-hover and --kui-color-state-active, and --kui-tab-indicator-size sets the indicator thickness.
  • The scroll fade no longer carries a literal colour fallback.