Skip to content

HyTab

Usage examples on this page are written for Lit / plain HTML (<hy-tab>). The same component ships as HyTab in @whitespaceux/harmony-react (native React 19), with typed wrappers for Angular, Solid, Svelte, and Vue. The API reference below applies to all frameworks.

A tab component designed to work within a tab group to control associated tab panels. Provides keyboard navigation, accessibility features, and customizable styling. Supports both horizontal and vertical orientations and can include icons alongside text labels.

Hybrid SSR/CSR Icon Visibility System

The tab works seamlessly in both SSR and CSR-only (SPAs, Storybook) environments using a hybrid visibility approach:

In SSR environments:

  1. The host framework detects icon slot presence at render time via its own slot API
  2. Passes boolean attribute (has-icon) to the Lit component
  3. CSS uses this attribute for immediate icon wrapper visibility during initial render
  4. After hydration, HasSlotController confirms slot content and adds .has-content class

In CSR-only environments (SPAs, Storybook):

  1. Icon wrapper renders to DOM (no has-icon attribute)
  2. Wrapper is hidden by default via CSS (display: none)
  3. firstUpdated() runs and hideIconWrapperWithoutContent() detects actual content
  4. Adds .has-content class which triggers CSS visibility rules

This approach ensures consistent behavior across all rendering environments while optimizing for SSR performance and preventing layout shifts from flex gap.

Usage Guidelines

Tabs should be used within an hy-tab-group component for proper state management and keyboard navigation. Each tab controls a corresponding hy-tab-panel via the panel attribute.

Orientations

  • horizontal (default): Tabs displayed in a row with bottom indicator
  • vertical-left: Tabs displayed in a column with left-side indicator
  • vertical-right: Tabs displayed in a column with right-side indicator

States

  • default: Inactive tab state
  • active: Selected tab that controls the visible panel
  • disabled: Non-interactive tab state

Keyboard Navigation

When used within hy-tab-group:

  • Arrow Right/Down: Move to next tab
  • Arrow Left/Up: Move to previous tab
  • Home: Move to first tab
  • End: Move to last tab
  • Enter/Space: Activate focused tab

Examples

Basic usage

html
<hy-tab-group>
  <hy-tab slot="tab" label="Dashboard" panel="dashboard-panel"></hy-tab>
  <hy-tab slot="tab" label="Settings" panel="settings-panel"></hy-tab>

  <hy-tab-panel slot="panel" name="dashboard-panel"> Dashboard content </hy-tab-panel>
  <hy-tab-panel slot="panel" name="settings-panel"> Settings content </hy-tab-panel>
</hy-tab-group>

With active state

html
<hy-tab-group>
  <hy-tab slot="tab" label="Overview" panel="overview-panel" active></hy-tab>
  <hy-tab slot="tab" label="Analytics" panel="analytics-panel"></hy-tab>
  <hy-tab slot="tab" label="Reports" panel="reports-panel"></hy-tab>
</hy-tab-group>

With icons

html
<hy-tab-group>
  <hy-tab slot="tab" label="Home" panel="home-panel">
    <hy-icon slot="icon" name="home"></hy-icon>
  </hy-tab>
  <hy-tab slot="tab" label="Settings" panel="settings-panel">
    <hy-icon slot="icon" name="settings"></hy-icon>
  </hy-tab>
  <hy-tab slot="tab" label="Profile" panel="profile-panel">
    <hy-icon slot="icon" name="user"></hy-icon>
  </hy-tab>
</hy-tab-group>

Disabled tab

html
<hy-tab-group>
  <hy-tab slot="tab" label="Available" panel="available-panel" active></hy-tab>
  <hy-tab slot="tab" label="Premium" panel="premium-panel" disabled>
    <hy-icon slot="icon" name="lock"></hy-icon>
  </hy-tab>
</hy-tab-group>

Vertical orientation with left indicator

html
<hy-tab-group orientation="vertical-left">
  <hy-tab slot="tab" label="Profile" panel="profile-panel" orientation="vertical-left">
    <hy-icon slot="icon" name="user"></hy-icon>
  </hy-tab>
  <hy-tab slot="tab" label="Security" panel="security-panel" orientation="vertical-left">
    <hy-icon slot="icon" name="shield"></hy-icon>
  </hy-tab>
  <hy-tab slot="tab" label="Billing" panel="billing-panel" orientation="vertical-left">
    <hy-icon slot="icon" name="credit-card"></hy-icon>
  </hy-tab>
</hy-tab-group>

Vertical orientation with right indicator

html
<hy-tab-group orientation="vertical-right">
  <hy-tab slot="tab" label="Profile" panel="profile-panel" orientation="vertical-right">
    <hy-icon slot="icon" name="user"></hy-icon>
  </hy-tab>
  <hy-tab slot="tab" label="Security" panel="security-panel" orientation="vertical-right">
    <hy-icon slot="icon" name="shield"></hy-icon>
  </hy-tab>
  <hy-tab slot="tab" label="Billing" panel="billing-panel" orientation="vertical-right">
    <hy-icon slot="icon" name="credit-card"></hy-icon>
  </hy-tab>
</hy-tab-group>

Complete tabbed interface

html
<div>
  <hy-tab-group>
    <hy-tab slot="tab" label="Home" panel="home-content" active>
      <hy-icon slot="icon" name="home"></hy-icon>
    </hy-tab>
    <hy-tab slot="tab" label="Products" panel="products-content">
      <hy-icon slot="icon" name="package"></hy-icon>
    </hy-tab>
    <hy-tab slot="tab" label="Support" panel="support-content">
      <hy-icon slot="icon" name="help-circle"></hy-icon>
    </hy-tab>
  </hy-tab-group>

  <hy-tab-panel name="home-content">
    <h2>Welcome Home</h2>
    <p>This is the home content area.</p>
  </hy-tab-panel>

  <hy-tab-panel name="products-content">
    <h2>Our Products</h2>
    <p>Browse our product catalog.</p>
  </hy-tab-panel>

  <hy-tab-panel name="support-content">
    <h2>Support Center</h2>
    <p>Get help and support.</p>
  </hy-tab-panel>
</div>

Programmatic Methods

javascript
const tab = document.querySelector('hy-tab');

// Set active state
tab.active = true;

// Focus the tab
tab.focus();

// Blur the tab
tab.blur();

// Check if disabled
console.log(tab.disabled);

API

Properties

PropertyAttributeTypeDefaultDescription
labellabelstring'Tab'The text content of the tab.
panelpanelstring''The name of the tab panel this tab controls.
disableddisabledbooleanfalseDisables the tab, making it non-interactive.
activeactivebooleanfalseMarks the tab as active/selected.
orientationorientation'horizontal' | 'vertical-left' | 'vertical-right''horizontal'The orientation and indicator position of the tab, typically inherited from the parent tab-group. - 'horizontal': Horizontal layout with bottom indicator (default) - 'vertical-left': Vertical layout with left indicator - 'vertical-right': Vertical layout with right indicator
emphasisemphasis'solid' | 'soft' | 'outlined' | 'plain''plain'Visual chrome weight, typically inherited from the parent tab-group. - plain (default) — transparent rest, role underline indicator - soft — role-tinted pill on the active tab - outlined — boxed/bordered tabs - solid — fully filled active tab
sizesize'small' | 'medium' | 'large''medium'Type + padding rung, typically inherited from the parent tab-group. - smalllabel-md type on row-nav-md padding - medium (default) — body-md type on row-nav-lg padding - largebody-lg type on row-nav-lg padding
hasIconhas-iconbooleanfalseSSR optimization hint indicating icon slot has content.

Events

EventDetailDescription
selectFired when the tab is clicked or activated, includes panel ID and tab reference

Slots

SlotDescription
iconIcon content to display before the tab label

CSS Parts

PartDescription
baseThe tab's base button element
labelThe tab's text label element

CSS Custom Properties

PropertyDescription
--hy-tab-radiusBorder radius of the plain tab (default: none)
--hy-tab-radius-formBorder radius of the soft / outlined / solid tab (default: var(--hy-radius-form-md); set var(--hy-radius-pill-md) for a full pill)
--hy-tab-text-transformText transform for tab label
--hy-tab-font-familyFont family override for tab label
--hy-tab-hover-durationTransition duration for hover and focus state feedback
--hy-tab-hover-easingTransition easing for hover and focus state feedback
--hy-tab-expand-durationTransition duration for the active-indicator slide animation
--hy-tab-expand-easingTransition easing for the active-indicator slide animation

Methods

focus()

Sets focus on the tab.

Parameters:

  • options - Optional focus options
javascript
const tab = document.querySelector('hy-tab');
tab.focus();

blur()

Removes focus from the tab.

javascript
const tab = document.querySelector('hy-tab');
tab.blur();

Built with Lit. Documented with VitePress.