• English
  • Tabs

    Switch between content views within the same region.

    Basic usage

    Live previewBasic usage

    View project activity, members and recent updates.

    View project activity, members and recent updates.

    View project activity, members and recent updates.

    basic.tsx
    import { Input, type TabItem, Tabs } from '@sudden3/leaf-ui';
    import { ChartNoAxesColumn, Settings } from 'lucide-react';
    
    const items: readonly TabItem[] = [
      {
        key: 'overview',
        label: 'Overview',
        icon: <ChartNoAxesColumn />,
        children: <p>View project activity, members and recent updates.</p>,
      },
      {
        key: 'settings',
        label: 'Settings',
        icon: <Settings />,
        children: (
          <Input
            aria-label="Project name"
            placeholder="Type, switch tabs, and your draft is preserved"
          />
        ),
      },
      { key: 'history', label: 'History', disabled: true, children: null },
    ];
    export function TabsBasic() {
      return (
        <div className="leaf-demo-stack leaf-demo-stack--wide">
          <Tabs aria-label="Project information" items={items} />
          <Tabs items={items} type="card" size="sm" />
          <Tabs items={items} placement="left" />
        </div>
      );
    }
    

    Closable tabs

    Live previewClosable tabs
    First project content
    closable.tsx
    import { Button, type TabItem, Tabs } from '@sudden3/leaf-ui';
    import { useRef, useState } from 'react';
    export function TabsClosable() {
      const sequence = useRef(2);
      const [items, setItems] = useState<TabItem[]>([
        { key: '1', label: 'First project', children: 'First project content', closable: true },
        { key: '2', label: 'Second project', children: 'Second project content', closable: true },
      ]);
      return (
        <Tabs
          items={items}
          type="card"
          onClose={(key) => setItems((list) => list.filter((item) => item.key !== key))}
          extra={
            <Button
              size="sm"
              variant="outline"
              onClick={() => {
                const key = String(++sequence.current);
                setItems((list) => [
                  ...list,
                  { key, label: `Project ${key}`, children: `Project ${key}`, closable: true },
                ]);
              }}
            >
              Add
            </Button>
          }
        />
      );
    }
    

    Tabs API

    PropTypeDefaultDescription
    itemsreadonly TabItem[]RequiredTab items
    activeKey / defaultActiveKeystringFirst enabled itemControlled / initial active key
    onChange(key: string) => void—Active key change
    type'line' | 'card''line'Tab appearance
    placement'top' | 'left''top'Tab bar placement
    size'sm' | 'md' | 'lg''md'Tab size
    activationMode'automatic' | 'manual''automatic'Activate on arrow navigation / Enter or Space
    destroyInactivebooleanfalseUnmount content when inactive
    extraReactNode—Extra tab bar content
    onClose(key: string, event: MouseEvent<HTMLButtonElement>) => void—Close request: remove the item in the application; preventDefault cancels selection changes

    TabItem

    PropTypeDefaultDescription
    keystringRequiredUnique identifier
    labelReactNodeRequiredTab label
    childrenReactNodeRequiredTab content
    iconReactNode—Leading icon
    disabledbooleanfalseDisable this tab
    closablebooleanfalseShow a close button; requires onClose

    Types

    Import the component props and item types when preparing your own values.

    import type { TabsProps, TabItem } from '@sudden3/leaf-ui';

    Usage notes

    Content mounts on first visit. Visited panels and their input state are kept by default. Arrow keys skip disabled tabs, and Home / End move to the first / last tab. Use manual activation when changing content takes time.