File List Table

A list view with a sortable header, 20pt rows, alternating stripes and disclosure triangles.

@cupertinoui-pro/file-list-tableCupertinoUI Pro

Installation

pnpm dlx shadcn@latest add @cupertinoui-pro/file-list-table

Part of CupertinoUI Pro: the CLI installs it with your license key, once the @cupertinoui-pro registry is in components.json.

Usage

import { FileListTable } from "@/components/ui/file-list-table"
import type { FileNode } from "@/lib/file-tree"

const files: FileNode[] = [
  {
    name: "Documents",
    modified: "Today at 09:41",
    children: [
      { name: "Notes.txt", kind: "Plain Text", modified: "Today at 09:41", size: "4 KB" },
    ],
  },
]

<FileListTable files={files} defaultExpanded={["Documents"]} />
files is plain JSON, the same structure FileListColumns takes, so both can show one tree. Click a disclosure triangle or double-click a folder to expand it; the arrow keys move the selection and open and close folders.
Like Finder, drag over rows to select them, from a row or from the empty space below; the table scrolls when the pointer leaves it. Shift-click selects a range, ⌘-click adds or removes a row, and neighbouring selected rows join into one highlight.
With onFilesChange, drag selected rows onto a folder to move them there, or onto a file to move them next to it; the folder lights up and a badge follows the pointer. Escape cancels. A folder can't move into itself, and a name that's taken gets a number, as in Finder. ⌘⌫ deletes the selection.
Right-click for Finder's menu: Open, Move to Trash, Rename, Duplicate, Copy and the tag colors; on empty space, New Folder. Renaming edits the name in place (Return also starts it), ⌘D duplicates and ⇧⌘N makes a folder. Without onFilesChange the menu only opens and copies.
Expanded folders and the selection are keys: the ids from the top of the tree down to the file, joined by "/", e.g. "Invoices/2026/October.pdf".
Columns are set once, as a CSS grid template, so the header and every row line up. Stripes are drawn behind the rows, so they continue into the empty space below.

Examples

Composition

Without files, build the header and rows from the parts yourself, e.g. for other columns or data that isn't a file tree.

API Reference

Every part forwards the props of the underlying element. The props below are the ones CupertinoUI adds or changes.

FileNode

One file or folder in files: plain JSON, the same for every file list. Import the type from @/lib/file-tree.

PropTypeDescription
namestringThe file name.
idstringUnique among its siblings, for keys; defaults to the name. Can't contain "/".
childrenFileNode[]Makes it a folder; folders nest to any depth. Use [] for an empty folder.
thumbnailstringAn image URL shown instead of the icon in the icon and gallery views, and as the preview.
kind / size / created / modifiedstringShown as they are, so format them the way you want them displayed.
infoRecord<string, string>More Information rows for the column and gallery previews, e.g. { Dimensions: "2007×2853" }.
iconstringA hint for renderIcon, e.g. "image" or "movie".
tagstringA Finder tag color: "red", "orange", "yellow", "green", "blue", "purple" or "gray".
onOpen(file: FileNode) => voidCalled when this file or folder is opened: double-clicked, or ⌘O.

FileListTable

PropTypeDescription
filesFileNode[]The tree to show, with Finder's Name, Date Modified, Size and Kind columns. Leave it out to compose the table from its parts.
columnsstring
Default: "minmax(0,1fr) 181px 97px 121px"
A grid-template-columns value, e.g. "1fr 160px 100px".
defaultExpandedstring[]The keys of the folders that start open.
expandedstring[]The keys of the open folders, controlled. Update it from onExpandedChange.
onExpandedChange(expanded: string[]) => voidCalled when a folder opens or closes.
multipleboolean
Default: true
Lets people select several rows: drag over them, Shift-click a range, ⌘-click single rows, Shift with the arrow keys or ⌘A. false allows one row.
defaultSelectedstring[]The keys of the files that start selected.
selectedstring[]The keys of the selected files, controlled. Update it from onSelectedChange.
onSelectedChange(keys: string[], files: FileNode[]) => voidCalled when the selection changes, with the keys and files in row order.
renderIcon(file: FileNode) => ReactNodeThe 16px icon of a file. Defaults to a folder or a document.
renderActions(file: FileNode) => ReactNodeShown at the end of the name, e.g. an eject button for a volume.
onFilesChange(files: FileNode[], change: FileChange) => voidTurns on editing: dragging selected items onto a folder moves them, ⌘⌫ deletes them. Gets the new tree to store, and what changed: { action: "move", keys, to } or { action: "delete", keys }.
onOpen(file: FileNode, key: string) => voidCalled when a file is opened: double-clicked, or ⌘O or ⌘↓ on the selection. Use it to show the file, e.g. in a new window.
menuItems(files: FileNode[], keys: string[]) => ReactNodeMore ContextMenuItems for the right-click menu, after Finder's own.
classNamestringExtra classes, merged with the component's own.

FileListTableHead

PropTypeDescription
sort"ascending" | "descending"Shows the sort chevron and highlights the column.
align"start" | "end"
Default: "start"
Text alignment.

FileListTableBody

PropTypeDescription
stripedboolean
Default: true
Alternating row stripes.

FileListTableRow

PropTypeDescription
selectedboolean
Default: false
Highlights the row.

FileListTableCell

PropTypeDescription
align"start" | "end"
Default: "start"
Text alignment.

FileListTableDisclosure

The chevron of an outline view.

PropTypeDescription
openboolean
Default: false
Points down when open.