Tabs

One panel at a time from a set of peers, with native tab buttons and roving keyboard focus.

<tp-tabs>
Tabs
Default density Compact density Restart from the initial state Show the copyable source
Account Update how your name appears to teammates. Save changes
Password Use at least 12 characters. Update password

Usage

Author each tab as a native <button slot="tab"> and each panel as an element with slot="panel", matched by value. Tabs supplies roles, type="button", roving tabindex and the aria-controls and aria-labelledby links; label names the tab list.

Tab labels may include tp-icon, tp-badge, or other noninteractive content. Do not nest interactive controls inside a tab. Use tp-button, tp-input, tp-card and other library components inside panels. Nested Tabs own only their direct members. dir="rtl" follows the surrounding direction and reverses horizontal navigation; vertical navigation remains Up/Down.

Native button values are strings. For object or numeric member values, use a non-native tab host with native-action="false" and assign its .value before connection. Values use identity equality. After changing non-reactive member properties such as .value, .keepMounted, .disabled or .nativeAction, call refresh(). String attributes are observed automatically.

Variants

Underline
Default density Compact density Restart from the initial state Show the copyable source

Website redesign: 14 open tasks, due March 28.

Jonas Weber moved “Pricing page” to Review 2 hours ago.

Visibility, integrations and archive options.

enclosed (the default) suits tabs that switch a contained surface; underline sits lighter on page-level navigation. The indicator glides to the selected tab in both.

Vertical

Vertical
Default density Compact density Restart from the initial state Show the copyable source

Workspace name, URL and default language.

12 members, 3 pending invitations.

Team plan, renews on April 1 for $480.

Vertical lists use Up and Down instead of Left and Right, and expose aria-orientation.

Keyboard and activation

Automatic activation
Default density Compact density Restart from the initial state Show the copyable source

1,204 visitors today.

8,931 visitors this week.

36,410 visitors this month.

By default activation is manual: arrow keys move focus and Enter or Space selects. Use automatic when panels are cheap to show, so selection follows focus. Arrows wrap at the ends unless the loopFocus property is set to false.

Tab enters the list at its roving entry; another Tab reaches the active panel and its content. Left/Right navigate horizontal lists, Up/Down vertical lists, and Home/End move to the ends. Wrong-axis and modified arrows do not change selection. External selection does not steal focus or replace the focused tab’s roving entry while focus is in the list. Tabs use aria-selected/aria-controls; panels use aria-labelledby and are sequentially focusable only while selected. Author IDs are preserved.

Responding to changes

Change event and setValue
Default density Compact density Restart from the initial state Show the copyable source

$84,210 in September, up 6% on August.

1,932 orders, 214 from new customers.

37 refunds totalling $2,940; 9 still pending.

Showing revenue Review pending refunds

Selection publishes a cancelable tp-value-change with the proposed value; call preventDefault() to keep the current tab, for example while a panel has unsaved edits. setValue() selects a tab from code through the same proposal and returns whether it was accepted. For controlled Tabs, set the value property from the start and write each accepted detail.value back to it. Equal selections are no-ops. Filter bubbled events by event.target when panels contain other controls.

Guarding unsaved edits

For controlled Tabs, set value from the start and accept proposals in onValueChange. Skipping the write-back, or calling preventDefault(), keeps the current tab. Edit the name below, then try to leave the tab. The profile panel is keep-mounted, so its draft survives while another tab is showing. Programmatic controlled assignments do not emit change proposals. A controlled missing value selects nothing; the first enabled tab remains the keyboard entry.

Controlled with a veto
Default density Compact density Restart from the initial state Show the copyable source
Profile Shown on comments and assignments.

Save Discard
Notifications Email me when someone mentions me or assigns me a task.

Disabled tabs

Disabled
Default density Compact density Restart from the initial state Show the copyable source

Order #10482, placed March 3.

Delivered March 6 by UPS.

Returns open after delivery.

aria-disabled="true" keeps a tab discoverable through arrow navigation; native disabled removes it from focus. Neither can be activated. Setting disabled on Tabs itself locks the whole list, for example while the content behind it is loading. Programmatic selection may select a disabled tab, but disabled tabs are never the sequential tab stop or user-activated.

An explicit disabled defaultValue is honored initially. If a selected tab is removed, renamed or subsequently disabled, uncontrolled selection falls forward to the nearest enabled successor, then backward to a predecessor, then to null.

Panel mounting

Inactive panels are detached from the DOM after their exit and restored on activation, so heavy content costs nothing while hidden. Add keep-mounted to a panel that must stay in the document, for example one holding form fields that still submit, and it is kept hidden and inert instead. Custom elements inside them receive disconnect/connect callbacks. The public panels getter includes retained and detached nodes. Keep application references to panels that need updating while detached; a host querySelector cannot find them. Remove a panel by calling remove() on that node, including while detached.

API Reference

Every element also accepts motion-policy.

Attributes

AttributePropertyTypeDefaultDescriptionvaluevalueunknown—The selected tab's value. Set before the first render, it makes selection controlled: write each accepted proposal back to it.default-valuedefaultValueunknownundefinedInitial selection when Tabs owns it; without one, the first enabled tab is selected.activationactivation'automatic' | 'manual''manual'manual selects on Enter or Space; automatic selects as focus moves, for panels that are cheap to show.activate-on-focusactivateOnFocusboolean—Shorthand for activation="automatic".loop-focusloopFocusbooleantrueWhether arrow keys wrap from the last tab to the first; set the property to false to stop at the ends.render-before-activationrenderBeforeActivationbooleanfalseShows the indicator before any tab is selected and measured.variantvariant'enclosed' | 'underline''enclosed'enclosed for tabs that switch a contained surface, underline for lighter page-level navigation.labellabelstring''Accessible name of the tab list.

Properties

PropertyTypeDefaultDescriptiononValueChange((event: TpValueChangeEvent<unknown>) => void) | undefined—Called with each selection proposal before tp-value-change is dispatched; cancel it to keep the current tab.activationDirectionTabsActivationDirection'none'Which way the last selection moved: left, right, up, down or none.panelsread-onlyreadonly HTMLElement[]—Every panel, including inactive ones detached from the document.

Events

EventTypeDescriptiontp-value-changeTpValueChangeEvent<unknown>Cancelable proposal of the selected tab's value, from a press, a key or setValue(); detail.metadata.activationDirection says which way the selection moved.

Methods

MethodReturnsDescriptionrefresh()voidReads the tabs and panels again after their value, keepMounted, disabled or nativeAction properties change from script.setValue(value)booleanProposes a selection from code, as a press would; returns whether it was accepted.

Slots

SlotDescriptiontabThe tabs, preferably native buttons, each with a unique value; nothing interactive inside them.panelThe panels, each with the value of its tab; keep-mounted keeps an inactive one in the document, hidden and inert.indicatorA decorative element that replaces the default selection indicator.

CSS parts

PartDescription::part(tabs)The root around the tab list and the panels.::part(tabs-indicator)The default indicator that glides to the selected tab.::part(tabs-list)The tab list, which scrolls when the tabs overflow.

Components, widgets and patterns that use this one.