Tabs

Tabs can be used to display information in a structured way.

Source
Theme Source
pnpm dlx dreamy add tabs

Tab 1

<Tabs.Root>
  <Tabs.List>
    <Tabs.Tab>Tab 1</Tabs.Tab>
    <Tabs.Tab>Tab 2</Tabs.Tab>
    <Tabs.Tab>Tab 3</Tabs.Tab>
  </Tabs.List>
  <Tabs.Panels>
    <Tabs.Panel>
      <p>Tab 1</p>
    </Tabs.Panel>
    <Tabs.Panel>
      <p>Tab 2</p>
    </Tabs.Panel>
    <Tabs.Panel>
      <p>Tab 3</p>
    </Tabs.Panel>
  </Tabs.Panels>
</Tabs.Root>

You can change the variant of the Tabs by passing the variant prop to the Tabs.Root component.

Filled Variant

Tab 1 content

Underline Variant

Tab 1 content

Filled-simple Variant

Tab 1 content

function TabsVariants() {
    return (
        <VStack gap={6}>
            <Flex
                col
                gap={2}
            >
                {(["filled", "underline", "filled-simple"] as const).map((variant) => (
                    <React.Fragment key={variant}>
                        <Text bold>{capitalize(variant)} Variant</Text>
                        <Tabs.Root variant={variant}>
                            <Tabs.List>
                                <Tabs.Tab>Tab 1</Tabs.Tab>
                                <Tabs.Tab>Tab 2</Tabs.Tab>
                                <Tabs.Tab>Tab 3</Tabs.Tab>
                            </Tabs.List>
                            <Tabs.Panels>
                                <Tabs.Panel>
                                    <p>Tab 1 content</p>
                                </Tabs.Panel>
                                <Tabs.Panel>
                                    <p>Tab 2 content</p>
                                </Tabs.Panel>
                                <Tabs.Panel>
                                    <p>Tab 3 content</p>
                                </Tabs.Panel>
                            </Tabs.Panels>
                        </Tabs.Root>
                    </React.Fragment>
                ))}
            </Flex>
        </VStack>
    );
}

Add fitted prop, to fit the tabs width to the container.

Tab 1

<Tabs.Root fitted>
  <Tabs.List>
    <Tabs.Tab>Tab 1</Tabs.Tab>
    <Tabs.Tab>Tab 2</Tabs.Tab>
    <Tabs.Tab>Tab 3</Tabs.Tab>
  </Tabs.List>
  <Tabs.Panels>
    <Tabs.Panel>
      <p>Tab 1</p>
    </Tabs.Panel>
    <Tabs.Panel>
      <p>Tab 2</p>
    </Tabs.Panel>
    <Tabs.Panel>
      <p>Tab 3</p>
    </Tabs.Panel>
  </Tabs.Panels>
</Tabs.Root>

You can control the selected tab by passing the index and onChange props to the Tabs.Root component.

Current Tab: 3

Tab 3 content

function ControlledTabs() {
    const [index, setIndex] = useState(2);
 
    return (
        <>
            <Text bold>Current Tab: {index + 1}</Text>
 
            <Tabs.Root
                index={index}
                onChange={setIndex}
            >
                <Tabs.List>
                    <Tabs.Tab>Tab 1</Tabs.Tab>
                    <Tabs.Tab>Tab 2</Tabs.Tab>
                    <Tabs.Tab>Tab 3</Tabs.Tab>
                </Tabs.List>
                <Tabs.Panels>
                    <Tabs.Panel>
                        <p>Tab 1 content</p>
                    </Tabs.Panel>
                    <Tabs.Panel>
                        <p>Tab 2 content</p>
                    </Tabs.Panel>
                    <Tabs.Panel>
                        <p>Tab 3 content</p>
                    </Tabs.Panel>
                </Tabs.Panels>
            </Tabs.Root>
        </>
    );
}

You can lazy mount the panel by passing the isLazy prop to the Tabs.Root component. This will only render the active tab panel, instead of switching the visibility of all panels.

Tab 1

<Tabs.Root isLazy>
  <Tabs.List>
    <Tabs.Tab>Tab 1</Tabs.Tab>
    <Tabs.Tab>Tab 2</Tabs.Tab>
    <Tabs.Tab>Tab 3</Tabs.Tab>
  </Tabs.List>
  <Tabs.Panels>
    <Tabs.Panel>
      <p>Tab 1</p>
    </Tabs.Panel>
    <Tabs.Panel>
      <p>Tab 2</p>
    </Tabs.Panel>
    <Tabs.Panel>
      <p>Tab 3</p>
    </Tabs.Panel>
  </Tabs.Panels>
</Tabs.Root>

Add overflowX="scroll" to the Tabs.List if your tabs are overflowing the container.

1
<Box maxW="xs" w='xs' >
  <Tabs.Root>
    <Tabs.List overflowX="scroll">
      <Tabs.Tab>Tab 1</Tabs.Tab>
      <Tabs.Tab>Tab 2</Tabs.Tab>
      <Tabs.Tab>Tab 3</Tabs.Tab>
      <Tabs.Tab>Tab 4</Tabs.Tab>
      <Tabs.Tab>Tab 5</Tabs.Tab>
      <Tabs.Tab>Tab 6</Tabs.Tab>
      <Tabs.Tab>Tab 7</Tabs.Tab>
    </Tabs.List>
    <Tabs.Panels>
      <Tabs.Panel>1</Tabs.Panel>
      <Tabs.Panel>2</Tabs.Panel>
      <Tabs.Panel>3</Tabs.Panel>
      <Tabs.Panel>4</Tabs.Panel>
      <Tabs.Panel>5</Tabs.Panel>
      <Tabs.Panel>6</Tabs.Panel>
      <Tabs.Panel>7</Tabs.Panel>
    </Tabs.Panels>
  </Tabs.Root>
</Box>