KQ-1306 · FILE/BROWSER
File Browser
A file manager you work with your hands: grid and list are the same items laid out twice, so the toggle morphs every tile into its row through motion's layout on the spring you choose, and folders slide in from the side you travel on that spring. Press empty space and drag to lasso (items join as the rectangle touches them, or only once inside); drag a selection and it lifts into a stack that follows the pointer, a folder's lid opens as the hover charges until it springs open with you still carrying, a drop on a folder shrinks the stack into it while it bumps on recoil, and a drop into the open folder lands the files on their measured places. Uploads run as rows whose progress glides and each turns into its tile when it resolves; the items are a multi-select listbox where arrows move, Shift extends, Enter opens, Backspace goes up, Ctrl or Cmd with X and V cut and paste, and Delete removes with Undo.
2.09 GB of 15 GB
Arrow keys move, Shift extends the selection, Space toggles, Enter opens, Backspace goes up, Control or Command with X and V cuts and pastes, Delete removes. Drag files onto a folder and hold to open it.
10 items · drag files onto a folder and hold to open it
Install
One command — the source lands in your repo. Or copy it from the Code tab.
$ pnpm dlx shadcn@latest add @kinetiq/file-browser
Props
- view / defaultView
- "grid" | "list"
- default "grid"
- The layout. Changing view morphs every item into the other layout; the toggle also switches it and reports through onViewChange.
- onViewChange
- (view: FileBrowserView) => void
- default —
- Fires from the grid and list toggle with the new layout.
- lasso
- "touch" | "contain" | "off"
- default "touch"
- How the lasso picks: items it touches, only items wholly inside it, or no lasso (empty space just clears).
- spring
- "snap" | "glide" | "recoil"
- default "glide"
- The spring under the grid and list morph, the folder slide and every landing: crisp, settled or bouncy.
- files / defaultFiles
- FileItem[]
- default defaultFiles
- Every item in every folder as one flat list linked by parentId. Controlled or uncontrolled.
- onFilesChange
- (files: FileItem[]) => void
- default —
- Fires from the drop, paste, move, upload or delete that changed the items, with all of them.
- folder / defaultFolder
- string
- default rootId
- The open folder's id. Controlled or uncontrolled.
- onFolderChange
- (folder: string) => void
- default —
- Fires from a crumb, the tree, Enter, Backspace or a folder springing open under a drag.
- selected / defaultSelected
- string[]
- default []
- Selected item ids. A selection brings in the selection bar with Move to and Delete.
- onSelectedChange
- (ids: string[]) => void
- default —
- Fires from the press, lasso or key that changed the selection.
- rootId
- string
- default "root"
- The id top-level items carry as parentId.
- rootLabel
- string
- default "Files"
- The top level's name in the breadcrumb and the tree.
- openDelay
- number
- default 700
- How long, in ms, a dragged stack hovers a folder (a tile, a crumb or a tree row) before it springs open.
- upload
- (file: File, progress: (fraction: number) => void, signal: AbortSignal) => Promise<Partial<FileItem> | void>
- default —
- Stores an uploaded file, reporting progress and honouring the signal; resolves with anything the stored item should carry. Without it a seeded local simulation runs, for demos.
- accept
- string
- default —
- File types uploads take, as an input's accept (".pdf,image/*"). Others are listed with the reason.
- maxSize
- number
- default 26214400
- The largest file an upload takes, in bytes (25 MB).
- quota
- number
- default 16106127360
- Storage shown on the meter under the tree, in bytes (15 GB).
- now
- Date | number
- default defaultFilesNow
- The moment modified dates are read against (Today, 09:12; 28 Sep). Never read from the clock during render.
- zoneOffset
- number
- default 0
- Minutes east of UTC that dates are shown in, so the server and the browser agree.
- onOpen
- (item: FileItem) => void
- default —
- A file was opened by double-click, Enter or Open in the details panel.
- onMove
- (ids: string[], folderId: string) => void
- default —
- Items moved into a folder by drop, paste or Move to (and back, by Undo).
- onDelete
- (ids: string[]) => void
- default —
- Items were removed, with everything inside a removed folder.
- onUploadComplete
- (item: FileItem) => void
- default —
- An upload resolved and landed as an item.
- label
- string
- default "Files"
- The browser's accessible name.
- status
- "ready" | "loading" | "error"
- default "ready"
- Loading draws placeholder tiles; error offers Retry.
- onRetry
- () => void
- default —
- Retry was pressed on the error state.
- ref
- React.Ref<FileBrowserHandle>
- default —
- A handle whose upload(files) uploads into the open folder, as a drop or the picker would.
- sound
- boolean
- default false
- Play a pop when a press selects, items join a lasso or a drop lands, and a swish on the view toggle, navigation and a folder springing open. Off unless asked for.
- disabled
- boolean
- default false
- Makes the whole browser inert.
- className
- string
- default —
- Classes for the root; it is 560px tall by default and lays out by its own width.
| Prop | Type | Default | Description |
|---|---|---|---|
| view / defaultView | "grid" | "list" | "grid" | The layout. Changing view morphs every item into the other layout; the toggle also switches it and reports through onViewChange. |
| onViewChange | (view: FileBrowserView) => void | — | Fires from the grid and list toggle with the new layout. |
| lasso | "touch" | "contain" | "off" | "touch" | How the lasso picks: items it touches, only items wholly inside it, or no lasso (empty space just clears). |
| spring | "snap" | "glide" | "recoil" | "glide" | The spring under the grid and list morph, the folder slide and every landing: crisp, settled or bouncy. |
| files / defaultFiles | FileItem[] | defaultFiles | Every item in every folder as one flat list linked by parentId. Controlled or uncontrolled. |
| onFilesChange | (files: FileItem[]) => void | — | Fires from the drop, paste, move, upload or delete that changed the items, with all of them. |
| folder / defaultFolder | string | rootId | The open folder's id. Controlled or uncontrolled. |
| onFolderChange | (folder: string) => void | — | Fires from a crumb, the tree, Enter, Backspace or a folder springing open under a drag. |
| selected / defaultSelected | string[] | [] | Selected item ids. A selection brings in the selection bar with Move to and Delete. |
| onSelectedChange | (ids: string[]) => void | — | Fires from the press, lasso or key that changed the selection. |
| rootId | string | "root" | The id top-level items carry as parentId. |
| rootLabel | string | "Files" | The top level's name in the breadcrumb and the tree. |
| openDelay | number | 700 | How long, in ms, a dragged stack hovers a folder (a tile, a crumb or a tree row) before it springs open. |
| upload | (file: File, progress: (fraction: number) => void, signal: AbortSignal) => Promise<Partial<FileItem> | void> | — | Stores an uploaded file, reporting progress and honouring the signal; resolves with anything the stored item should carry. Without it a seeded local simulation runs, for demos. |
| accept | string | — | File types uploads take, as an input's accept (".pdf,image/*"). Others are listed with the reason. |
| maxSize | number | 26214400 | The largest file an upload takes, in bytes (25 MB). |
| quota | number | 16106127360 | Storage shown on the meter under the tree, in bytes (15 GB). |
| now | Date | number | defaultFilesNow | The moment modified dates are read against (Today, 09:12; 28 Sep). Never read from the clock during render. |
| zoneOffset | number | 0 | Minutes east of UTC that dates are shown in, so the server and the browser agree. |
| onOpen | (item: FileItem) => void | — | A file was opened by double-click, Enter or Open in the details panel. |
| onMove | (ids: string[], folderId: string) => void | — | Items moved into a folder by drop, paste or Move to (and back, by Undo). |
| onDelete | (ids: string[]) => void | — | Items were removed, with everything inside a removed folder. |
| onUploadComplete | (item: FileItem) => void | — | An upload resolved and landed as an item. |
| label | string | "Files" | The browser's accessible name. |
| status | "ready" | "loading" | "error" | "ready" | Loading draws placeholder tiles; error offers Retry. |
| onRetry | () => void | — | Retry was pressed on the error state. |
| ref | React.Ref<FileBrowserHandle> | — | A handle whose upload(files) uploads into the open folder, as a drop or the picker would. |
| sound | boolean | false | Play a pop when a press selects, items join a lasso or a drop lands, and a swish on the view toggle, navigation and a folder springing open. Off unless asked for. |
| disabled | boolean | false | Makes the whole browser inert. |
| className | string | — | Classes for the root; it is 560px tall by default and lays out by its own width. |