Skip to content

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

Hierarchy

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.

3 items
src
assets
archiveoffline
drafts
README.md3.4 KB
LICENSE1.1 KB
components
routes
main.tsx1.2 KB
Loading

path · onOpensrc / src/components

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"]}
    />
  );
}

This code, running — no configuration beyond the data

2 items
Books
Films
Dune1965
Piranesi2020

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.

sh
npx shadcn@latest add 0xuser64bit/mizu/column-browser

For 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.

Open full source ↗

Props

PropTypeDefaultDescription
label / itemsstring / 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 / onPathChangestring[]—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 / emptynumber / 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.

Works alongside