# Tabs
> Tabs whose underline is forty pixels that stream from the old tab to the new one, with panels that slide in from the side.
- React: `import { PxTabs } from "@/components/lumesec/px-tabs"`
- Collection: Pixel UI (https://elements.lumesec.ai/components/pixel-ui)
- Registry item: https://elements.lumesec.ai/r/px-tabs.json
- Page: https://elements.lumesec.ai/components/pixel-ui/tabs



Live preview: https://elements.lumesec.ai/view/px-tabs

Demo source:

```tsx
import { PxTabs } from "@/components/lumesec/px-tabs";

export default function PxTabsDemo() {
  return (
    <div className="w-full max-w-[400px] rounded-[14px] border border-border bg-card px-5 py-[18px] shadow-[0_14px_34px_-20px_rgb(0_0_0/0.4)]">
      <PxTabs
        items={[
          { label: "Overview", content: "Usage is steady this week. Most runs come from the Research project." },
          { label: "Activity", count: 12, content: "12 events since Monday, including 3 deploys and 2 new members." },
          { label: "Settings", content: "Default model, retention and notification settings live here." },
        ]}
      />
    </div>
  );
}
```

## Playground

Change a prop and the component re-renders. Props marked remounts set an initial value, so the component starts over.

## Installation

```bash
npx shadcn@latest add @lumesec/px-tabs
```

First time with the @lumesec registry? Register it once, or install by URL:

```bash
npx shadcn@latest registry add @lumesec=https://elements.lumesec.ai/r/{name}.json
npx shadcn@latest add https://elements.lumesec.ai/r/px-tabs.json
```

## Usage

React:

```tsx
import { PxTabs } from "@/components/lumesec/px-tabs";

export function Example() {
  return (
    <PxTabs
      items={[
        { label: "Overview", content: "Usage is steady this week." },
        { label: "Activity", count: 12, content: "12 events since Monday." },
        { label: "Settings", content: "Default model, retention and notifications." },
      ]}
    />
  );
}
```

## Behaviour

The underline is forty pixels that stream from the old tab to the new one. Each item brings its own panel content.

## API reference

### Props

Also accepts every prop of `<div>` (`React.ComponentProps<"div">`), spread onto the root element.

| Prop            | Type                      | Default     | Description                                                                                                                                                                 |
| --------------- | ------------------------- | ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `value`         | `string`                  | —           | Controlled selected tab (an item's `value`, or its `label`). Use with `onValueChange`.                                                                                      |
| `defaultValue`  | `string`                  | `first tab` | Initially selected tab when uncontrolled.                                                                                                                                   |
| `items`         | `readonly PxTabsItem[]`   | —           | The tabs: `{ value?: string; label: string; count?: string \| number; content: React.ReactNode }`. `value` defaults to `label`; `count` adds a small badge after the label. |
| `onValueChange` | `(value: string) => void` | —           | Called when the user selects another tab by click or key.                                                                                                                   |

### Ref

`ref` points at the root `HTMLDivElement`.

## Keyboard

| Keys                   | Action                                              |
| ---------------------- | --------------------------------------------------- |
| ArrowRight / ArrowLeft | Select and focus the next / previous tab, wrapping. |
| Home / End             | Select and focus the first / last tab.              |

## Accessibility

* Tabs are native buttons with `role="tab"` and `aria-selected` in a `role="tablist"`, with roving tabindex: only the selected tab is in the tab order.
* Each tab points to its panel with `aria-controls`. Panels have `role="tabpanel"`, an `aria-label` with the tab name and `tabindex="0"`; inactive panels are `hidden`.
* The underline canvas is `aria-hidden`.
* Reduced motion: the underline jumps to the new tab and the panel appears without sliding in.

## Theming

Styled with Tailwind classes on your shadcn theme tokens, so light and dark follow your theme. The accent comes from `--lumesec`. See [Theming](/docs/theming).

This component reads `--lumesec`, `--lumesec-shine`, `--foreground`, `--muted-foreground` and `--border`.

## Notes

* Every panel stays mounted; inactive ones are hidden, so their state survives switching tabs.
* Selecting the tab that is already selected does nothing.


