Skip to contents

Tabs

A component for toggling between related panels on the same page.

Workspace stats and activity.

import { Tabs } from 'base-ui-solid/tabs';
import styles from './index.module.css';

export default function ExampleTabs() {
  return (
    <Tabs.Root class={styles.Root} defaultValue="overview">
      <Tabs.List class={styles.List}>
        <Tabs.Tab class={styles.Tab} value="overview">
          Overview
        </Tabs.Tab>
        <Tabs.Tab class={styles.Tab} value="projects">
          Projects
        </Tabs.Tab>
        <Tabs.Tab class={styles.Tab} value="account">
          Account
        </Tabs.Tab>
        <Tabs.Indicator class={styles.Indicator} />
      </Tabs.List>
      <div class={styles.PanelViewport}>
        <Tabs.Panel class={styles.Panel} value="overview">
          <p class={styles.Paragraph}>Workspace stats and activity.</p>
        </Tabs.Panel>
        <Tabs.Panel class={styles.Panel} value="projects">
          <p class={styles.Paragraph}>Milestones and deadlines.</p>
        </Tabs.Panel>
        <Tabs.Panel class={styles.Panel} value="account">
          <p class={styles.Paragraph}>Profile and preferences.</p>
        </Tabs.Panel>
      </div>
    </Tabs.Root>
  );
}

Anatomy

Import the component and assemble its parts:

Anatomy
import { Tabs } from 'base-ui-solid/tabs';

<Tabs.Root>
  <Tabs.List>
    <Tabs.Tab />
    <Tabs.Indicator />
  </Tabs.List>
  <Tabs.Panel />
</Tabs.Root>;

Examples

Animated panels

Animate panels as they activate using the data-starting-style and data-ending-style attributes. The data-activation-direction attribute indicates which direction the newly active tab is relative to the previously active one, letting panels slide in from the correct side.

Workspace stats and activity.

import { Tabs } from 'base-ui-solid/tabs';
import styles from './index.module.css';

export default function ExampleAnimatedTabs() {
  return (
    <Tabs.Root class={styles.Root} defaultValue="overview">
      <Tabs.List class={styles.List}>
        <Tabs.Tab class={styles.Tab} value="overview">
          Overview
        </Tabs.Tab>
        <Tabs.Tab class={styles.Tab} value="projects">
          Projects
        </Tabs.Tab>
        <Tabs.Tab class={styles.Tab} value="account">
          Account
        </Tabs.Tab>
        <Tabs.Indicator class={styles.Indicator} />
      </Tabs.List>
      <div class={styles.PanelViewport}>
        <Tabs.Panel class={styles.Panel} value="overview">
          <p class={styles.Paragraph}>Workspace stats and activity.</p>
        </Tabs.Panel>
        <Tabs.Panel class={styles.Panel} value="projects">
          <p class={styles.Paragraph}>Milestones and deadlines.</p>
        </Tabs.Panel>
        <Tabs.Panel class={styles.Panel} value="account">
          <p class={styles.Paragraph}>Profile and preferences.</p>
        </Tabs.Panel>
      </div>
    </Tabs.Root>
  );
}

Use the render prop and set nativeButton={false} on <Tabs.Tab> to render tabs as anchor elements.

Tabs as links
import { Tabs } from 'base-ui-solid/tabs';
import Link from 'next/link';

<Tabs.Root>
  <Tabs.List>
    <Tabs.Tab
      nativeButton={false}
      render={(renderProps) => <Link {...renderProps} href="/overview" />}
      value="overview"
    >
      Overview
    </Tabs.Tab>
  </Tabs.List>
  {/* ... */}
</Tabs.Root>;

API reference

Root

Groups the tabs and the corresponding panels. Renders a <div> element.

Prop
Type
Default
defaultValueTabs.Tab.Value0
The default value. Use when the component is not controlled. When the value is null, no Tab will be active.Tabs.Tab.Value
valueTabs.Tab.Value—
The value of the currently active Tab. Use when the component is controlled. When the value is null, no Tab will be active.Tabs.Tab.Value
onValueChangefunction—
Callback invoked when new value is being set. The event reason is 'none' for user-initiated changes, such as a click or keyboard navigation; 'initial' for the first automatic selection or fallback in uncontrolled roots when defaultValue is omitted or undefined, including when the implicit initial value is disabled or missing; 'disabled' for automatic fallback when the selected tab becomes disabled in uncontrolled roots; or 'missing' for automatic fallback when the selected tab is removed, or when an explicit defaultValue never matches a mounted tab in uncontrolled roots. For automatic changes, the selected value can be null when no enabled Tab is available as a fallback. Automatic changes cannot be canceled; calling eventDetails.cancel() for 'initial', 'disabled', or 'missing' has no effect.((value: Tabs.Tab.Value, eventDetails: Tabs.Root.ChangeEventDetails) => void)
orientationTabs.Root.Orientation'horizontal'
The component orientation (layout flow direction).Tabs.Root.Orientation
classfunction—
CSS class applied to the element, or a function that returns a class based on the component’s state.JSX.ClassValue | ((state) => JSX.ClassValue)
stylefunction—
Style applied to the element, or a function that returns a style object based on the component’s state.JSX.CSSProperties | string | ((state) => JSX.CSSProperties | string | undefined)
renderfunction—
Replace the default element with a tag name, component, or render function.keyof JSX.IntrinsicElements | Component | ((props, state) => JSX.Element)

Data attributes

Name
Type
Default
data-orientationUnion—
Indicates the orientation of the tabs.'horizontal' | 'vertical'
data-activation-directionUnion—
Indicates the direction of the activation (based on the previous active tab).'left' | 'right' | 'up' | 'down' | 'none'
Attribute
Description
data-orientation
Indicates the orientation of the tabs.
data-activation-direction
Indicates the direction of the activation (based on the previous active tab).
Root.State
type TabsRootState = {
  /** The component orientation. */
  orientation: Tabs.Root.Orientation;
  /** The direction used for tab activation. */
  tabActivationDirection: Tabs.Tab.ActivationDirection;
};
Root.ChangeEventReason
type TabsRootChangeEventReason = 'none' | 'disabled' | 'missing' | 'initial';
Root.ChangeEventDetails
type TabsRootChangeEventDetails = (
  { reason: 'none' } | { reason: 'disabled' } | { reason: 'missing' } | { reason: 'initial' }
) & {
  /** The native event associated with the custom event. */
  event: Event;
  /** Cancels Base UI from handling the event. */
  cancel: () => void;
  /** Allows the event to propagate in cases where Base UI will stop the propagation. */
  allowPropagation: () => void;
  /** Indicates whether the event has been canceled. */
  isCanceled: boolean;
  /** Indicates whether the event is allowed to propagate. */
  isPropagationAllowed: boolean;
  /** The element that triggered the event, if applicable. */
  trigger: Element | undefined;
  activationDirection: Tabs.Tab.ActivationDirection;
};
Root.Orientation
type TabsRootOrientation = 'horizontal' | 'vertical';

List

Groups the individual tab buttons. Renders a <div> element.

Prop
Type
Default
activateOnFocusbooleanfalse
Whether to automatically change the active tab on arrow key focus. Otherwise, tabs will be activated using Enter or Space key press.boolean
loopFocusbooleantrue
Whether to loop keyboard focus back to the first item when the end of the list is reached while using the arrow keys.boolean
classfunction—
CSS class applied to the element, or a function that returns a class based on the component’s state.JSX.ClassValue | ((state) => JSX.ClassValue)
stylefunction—
Style applied to the element, or a function that returns a style object based on the component’s state.JSX.CSSProperties | string | ((state) => JSX.CSSProperties | string | undefined)
renderfunction—
Replace the default element with a tag name, component, or render function.keyof JSX.IntrinsicElements | Component | ((props, state) => JSX.Element)

Data attributes

Name
Type
Default
data-orientationUnion—
Indicates the orientation of the tabs.'horizontal' | 'vertical'
data-activation-directionUnion—
Indicates the direction of the activation (based on the previous active tab).'left' | 'right' | 'up' | 'down' | 'none'
Attribute
Description
data-orientation
Indicates the orientation of the tabs.
data-activation-direction
Indicates the direction of the activation (based on the previous active tab).
List.State
type TabsListState = {
  /** The component orientation. */
  orientation: Tabs.Root.Orientation;
  /** The direction used for tab activation. */
  tabActivationDirection: Tabs.Tab.ActivationDirection;
};

Tab

An individual interactive tab button that toggles the corresponding panel. Renders a <button> element.

Prop
Type
Default
value*Tabs.Tab.Value—
The value of the Tab.Tabs.Tab.Value
nativeButtonbooleantrue
Whether the component renders a native <button> element when replacing it via the render prop. Set to false if the rendered element is not a button (for example, <div>).boolean
disabledboolean—
Whether the Tab is disabled. If a first Tab on a <Tabs.List> is disabled, it won’t initially be selected. Instead, the next enabled Tab will be selected. However, it does not work like this during server-side rendering, as it is not known during pre-rendering which Tabs are disabled. To work around it, ensure that defaultValue or value on <Tabs.Root> is set to an enabled Tab’s value.boolean
classfunction—
CSS class applied to the element, or a function that returns a class based on the component’s state.JSX.ClassValue | ((state) => JSX.ClassValue)
stylefunction—
Style applied to the element, or a function that returns a style object based on the component’s state.JSX.CSSProperties | string | ((state) => JSX.CSSProperties | string | undefined)
renderfunction—
Replace the default element with a tag name, component, or render function.keyof JSX.IntrinsicElements | Component | ((props, state) => JSX.Element)

Data attributes

Name
Type
Default
data-orientationUnion—
Indicates the orientation of the tabs.'horizontal' | 'vertical'
data-disabled-—
Present when the tab is disabled.-
data-activation-directionUnion—
Indicates the direction of the activation (based on the previous active tab).'left' | 'right' | 'up' | 'down' | 'none'
data-active-—
Present when the tab is active.-
Attribute
Description
data-orientation
Indicates the orientation of the tabs.
data-disabled
Present when the tab is disabled.
data-activation-direction
Indicates the direction of the activation (based on the previous active tab).
data-active
Present when the tab is active.
Tab.State
type TabsTabState = {
  /** Whether the component should ignore user interaction. */
  disabled: boolean;
  /** Whether the component is active. */
  active: boolean;
  /** The component orientation. */
  orientation: Tabs.Root.Orientation;
  /** The direction used for tab activation. */
  tabActivationDirection: Tabs.Tab.ActivationDirection;
};
Tab.Value
type TabsTabValue = Tabs.Tab.Value;
Tab.ActivationDirection
type TabsTabActivationDirection = 'left' | 'right' | 'up' | 'down' | 'none';
Tab.Metadata
type TabsTabMetadata = {
  disabled: boolean;
  id: string | undefined;
  value: Tabs.Tab.Value | undefined;
};
Tab.Position
type TabsTabPosition = { left: number; right: number; top: number; bottom: number };
Tab.Size
type TabsTabSize = { width: number; height: number };

Indicator

A visual indicator that can be styled to match the position of the currently active tab. Renders a <span> element.

Prop
Type
Default
renderBeforeHydrationbooleanfalse
Whether to render itself before Solid hydrates. This minimizes the time that the indicator isn’t visible after server-side rendering.boolean
classfunction—
CSS class applied to the element, or a function that returns a class based on the component’s state.JSX.ClassValue | ((state) => JSX.ClassValue)
stylefunction—
Style applied to the element, or a function that returns a style object based on the component’s state.JSX.CSSProperties | string | ((state) => JSX.CSSProperties | string | undefined)
renderfunction—
Replace the default element with a tag name, component, or render function.keyof JSX.IntrinsicElements | Component | ((props, state) => JSX.Element)

Data attributes

Name
Type
Default
data-orientationUnion—
Indicates the orientation of the tabs.'horizontal' | 'vertical'
data-activation-directionUnion—
Indicates the direction of the activation (based on the previous active tab).'left' | 'right' | 'up' | 'down' | 'none'
Attribute
Description
data-orientation
Indicates the orientation of the tabs.
data-activation-direction
Indicates the direction of the activation (based on the previous active tab).

CSS variables

Name
Type
Default
--active-tab-bottomnumber—
Indicates the distance on the bottom side from the parent’s container if the tab is active.number
--active-tab-heightnumber—
Indicates the height of the tab if it is active.number
--active-tab-leftnumber—
Indicates the distance on the left side from the parent’s container if the tab is active.number
--active-tab-rightnumber—
Indicates the distance on the right side from the parent’s container if the tab is active.number
--active-tab-topnumber—
Indicates the distance on the top side from the parent’s container if the tab is active.number
--active-tab-widthnumber—
Indicates the width of the tab if it is active.number
CSS Variable
Description
--active-tab-bottom
Indicates the distance on the bottom side from the parent’s container if the tab is active.
--active-tab-height
Indicates the height of the tab if it is active.
--active-tab-left
Indicates the distance on the left side from the parent’s container if the tab is active.
--active-tab-right
Indicates the distance on the right side from the parent’s container if the tab is active.
--active-tab-top
Indicates the distance on the top side from the parent’s container if the tab is active.
--active-tab-width
Indicates the width of the tab if it is active.
Indicator.State
type TabsIndicatorState = {
  /** The active tab position. */
  activeTabPosition: Tabs.Tab.Position | null;
  /** The active tab size. */
  activeTabSize: Tabs.Tab.Size | null;
  /** The component orientation. */
  orientation: Tabs.Root.Orientation;
  /** The direction used for tab activation. */
  tabActivationDirection: Tabs.Tab.ActivationDirection;
};

Panel

A panel displayed when the corresponding tab is active. Renders a <div> element.

Prop
Type
Default
value*Tabs.Tab.Value—
The value of the TabPanel. It will be shown when the Tab with the corresponding value is active.Tabs.Tab.Value
classfunction—
CSS class applied to the element, or a function that returns a class based on the component’s state.JSX.ClassValue | ((state) => JSX.ClassValue)
stylefunction—
Style applied to the element, or a function that returns a style object based on the component’s state.JSX.CSSProperties | string | ((state) => JSX.CSSProperties | string | undefined)
keepMountedbooleanfalse
Whether to keep the HTML element in the DOM while the panel is hidden.boolean
renderfunction—
Replace the default element with a tag name, component, or render function.keyof JSX.IntrinsicElements | Component | ((props, state) => JSX.Element)

Data attributes

Name
Type
Default
data-orientationUnion—
Indicates the orientation of the tabs.'horizontal' | 'vertical'
data-activation-directionUnion—
Indicates the direction of the activation (based on the previous active tab).'left' | 'right' | 'up' | 'down' | 'none'
data-hidden-—
Present when the panel is hidden.-
data-index-—
Indicates the index of the tab panel.-
data-starting-style-—
Present when the panel begins animating in.-
data-ending-style-—
Present when the panel is animating out.-
Attribute
Description
data-orientation
Indicates the orientation of the tabs.
data-activation-direction
Indicates the direction of the activation (based on the previous active tab).
data-hidden
Present when the panel is hidden.
data-index
Indicates the index of the tab panel.
data-starting-style
Present when the panel begins animating in.
data-ending-style
Present when the panel is animating out.
Panel.State
type TabsPanelState = {
  /** Whether the component is hidden. */
  hidden: boolean;
  /** The transition status of the component. */
  transitionStatus: TransitionStatus;
  /** The component orientation. */
  orientation: Tabs.Root.Orientation;
  /** The direction used for tab activation. */
  tabActivationDirection: Tabs.Tab.ActivationDirection;
};
Panel.Metadata
type TabsPanelMetadata = { id?: string; value: Tabs.Tab.Value };