SIG—18 Signature system
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.
Live — this one is real
Choose a folder and its contents open alongside; arrows walk the columns and typing jumps to a name. Folders load on first visit, and the archive fails once so you can retry. Narrow the preview to push and pop panes. Invented data.
path · onOpensrc / src/components
Usage
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"]}
/>
);
}
This code, running — no configuration beyond the data
Keyboard
- ↑↓
- Move within a column
- →Enter
- Open the chosen folder; Enter opens a file
- ←
- Back to the parent column
- HomeEnd
- First or last item
- a–z
- Jump to a name
Source & setup
Add this component to your project with the shadcn CLI. The command copies its source and styles into your configured UI directory.
npx shadcn@latest add 0xuser64bit/mizu/column-browserFor npm imports, import mizu-ui/styles.css once. Fonts are optional via mizu-ui/fonts.css. Override --mizu-* tokens or use className for local styling. Uses native React and CSS; install the package peers for root imports.
Inspect signature/ColumnBrowser.tsx
Source is included in the npm package under src/signature/ColumnBrowser.tsx.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| 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). |
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.