# ColumnBrowser

Miller columns: choose an item and its contents open alongside, loading on demand, until a leaf opens in a preview — a stack you push and pop on narrow screens.

- Family: Signature, imported from `mizu-ui` or `mizu-ui/signature`
- Docs: https://mizu.user64bit.world/components/column-browser
- Source: https://github.com/0xuser64bit/mizu/blob/main/packages/mizu/src/signature/ColumnBrowser.tsx

## Usage

```tsx
import { ColumnBrowser } from "mizu-ui";

export function Example() {
  return (
    <ColumnBrowser
      label="Library"
      items={[
        {
          id: "books",
          label: "Books",
          children: [
            { id: "dune", label: "Dune", meta: "1965" },
            { id: "piranesi", label: "Piranesi", meta: "2020" },
          ],
        },
        { id: "films", label: "Films", children: [] },
      ]}
      defaultPath={["books"]}
    />
  );
}
```

## Copy it with the shadcn CLI

```sh
npx shadcn@latest init 0xuser64bit/mizu/preset # once, where there is no components.json
npx shadcn@latest add 0xuser64bit/mizu/column-browser
```

## Props

- `label / items`: `string / BrowserItem[]`. The hierarchy's name and top level: id, label, children or hasChildren, with an optional icon, meta and disabled.
- `loadChildren`: `(item) => Promise<BrowserItem[]>`. Fetches the children of items marked hasChildren on first visit; results are kept, and failures offer a retry.
- `path / defaultPath / onPathChange`: `string[]`. The selected ids from the top level down.
- `renderPreview / onOpen`: `(item, trail) => ReactNode / (item) => void`. The last pane for an item without children, and what Enter or a double-click does with it.
- `columnWidth / empty`: `number / ReactNode`. Column width (240) and what an empty column says. Height comes from --mizu-columns-height (420px).

## Keyboard

- ↑ ↓: Move within a column
- → Enter: Open the chosen folder; Enter opens a file
- ←: Back to the parent column
- Home End: First or last item
- a–z: Jump to a name

## Accessibility

Each column is a listbox named after its parent, with one tab stop for the whole browser. Arrow keys walk up and down a column and into or out of the next, Home and End jump, and typing finds an item by name. Entering a column announces its size or that it is loading; failures are alerts with a retry. A labelled breadcrumb marks the current location, and on narrow screens a back button names where it returns to.

## Motion

New columns slide in from the one that opened them while the track glides to keep the newest in view; the selection bar grows in the focused column and the chevron of an open folder steps forward. On narrow screens panes push in from the right and pop back from the left. Loading columns sweep a hairline over skeleton rows. Reduced motion keeps every state and drops the travel.
