Crate
File manager pane: collapsing breadcrumb path, grid/list views that FLIP between layouts, sort menu, subtree search with highlighted matches, drag-box marquee + ⌘/Shift multi-select with a spring-up Move / Download / Delete bar, drag-to-folder moves, inline rename and New folder, a docked details pane, right-click / Shift+F10 context menu, and drop-anywhere uploads with per-file progress rings via async onUpload. Folders open with a direction-aware slide; the grid is a roving-focus role=grid.
The preview is live. The source is Pro.
One purchase, lifetime access: every pro component's source, CLI install with your own registry token, and all future drops.
Installation
CLI
npx shadcn@latest add @crucible/crateManual — install dependencies, then copy the source
npm install motionProps
| Prop | Type | Default | Description |
|---|---|---|---|
| tree | CrateNode | Controlled tree — the root folder whose children are the top level. Pair with onTreeChange; edits you don't feed back in are not kept. | |
| defaultTree | CrateNode | a sample workspace (projects, design, photos…) | Initial tree for uncontrolled use. |
| onTreeChange | (tree: CrateNode, change: CrateChange) => void | Fires after every edit (rename, move, delete, duplicate, new folder, upload) with the full next tree. | |
| view | CrateView | Controlled view mode. | |
| defaultView | CrateView | "grid" | Initial view mode for uncontrolled use. |
| onViewChange | (view: CrateView) => void | Fires when the user flips between grid and list. | |
| defaultFolder | string | the root | Id of the folder to start in. |
| defaultPreviewOpen | boolean | true | Whether the details pane starts open (it becomes an overlay below ~720px). |
| onOpen | (node: CrateNode, path: CrateNode[]) => void | Fires when a node is opened (double-click, Enter, or the Open action). Folders also navigate. | |
| onMove | (nodes: CrateNode[], target: CrateNode) => void | Promise<unknown> | Items were moved into target. Return a Promise to confirm; a rejection reverts the move. | |
| onDelete | (nodes: CrateNode[]) => void | Promise<unknown> | Items were deleted (after the confirm dialog). A rejected Promise restores them. | |
| onRename | (node: CrateNode, name: string) => void | Promise<unknown> | A node was renamed. A rejected Promise restores the previous name. | |
| onCreateFolder | (folder: CrateNode, parent: CrateNode) => void | Promise<unknown> | A folder was created via "New folder" (fires before the inline rename). | |
| onUpload | ( file: File, onProgress: (fraction: number) => void, folder: CrateNode ) => Promise<void | Partial<Omit<CrateNode, "id" | "children">>> | Upload one dropped/picked file. Report progress (0–1) through onProgress; resolve to finish (optionally with node fields to merge, e.g. a server thumbnail URL) or reject to mark it failed. Omit for a simulated upload. | |
| onDownload | (nodes: CrateNode[]) => void | Download action for the selection. Omit to show a "Download started" notice only. | |
| onSelectionChange | (ids: string[]) => void | Fires whenever the selection changes. | |
| accentColor | string | "#fbbf24" | The single accent: folder glyphs, selection, marquee, drop targets, focus rings, upload rings and the primary button. Any hex color. |
| label | string | "File manager" | Accessible name of the file browser. |
| ref | React.Ref<CrateHandle> | Imperative handle — select(), clearSelection(), navigate(), replay(), focus(). | |
| className | string |
Honors prefers-reduced-motion with a designed static fallback, and passes className through.