List View
Table-like file and folder rows with composable item slots.
Overview
Files.List lays out consumer-owned Files.Item children in the same compact row treatment as the previous Files surface. Cubitt owns the row visuals, selection interaction, focus treatment, upload/error display, and file/folder icon rendering. Consumers own row metadata, filtering, sorting, folder navigation, upload state, and actions.
Usage
import {
Files,
type FilesItem,
} from "@tilt-legal/cubitt-components/files";
function FileList({
items,
selectedIds,
setSelectedIds,
}: {
items: FilesItem[];
selectedIds: string[];
setSelectedIds: (ids: string[]) => void;
}) {
return (
<Files
selectedIds={selectedIds}
onSelectedIdsChange={setSelectedIds}
selectionMode="multiple"
>
<Files.List>
{items.map((item) => (
<Files.Item
item={item}
key={item.id}
onOpen={(openedItem) => {
if (openedItem.kind === "folder") {
navigateToFolder(openedItem.id);
}
}}
/>
))}
</Files.List>
</Files>
);
}List Item
Files.Item renders one file or folder row inside Files.List. Its data
state controls only file lifecycle display:
| State | Description |
|---|---|
default | Normal folder, thumbnail, virtual file, or MIME icon display. |
loading | Skeleton placeholder row for an item whose data is not ready yet. |
uploading | Circular progress treatment. Use progress for the value. |
error | Failed upload treatment. |
Selection, active highlight, inline rename, drag, drop-target, disabled,
hover, and focus are interaction states owned by Files and item props, not
FilesItem.state values.
Custom Rows
Files.Item renders sensible default row cells. Consumers can provide children when they need app-specific columns while still reusing the same item slots. Use the header prop to replace or remove the default list header when your custom rows have a different column shape.
<Files.List header={<MyListHeader />}>
<Files.Item item={item}>
<div className="flex justify-center">
<Files.ItemIcon />
</div>
<div className="flex min-w-0 items-center gap-1.5 py-2 ps-1 pe-3">
<Files.ItemName />
<Files.ItemBadge />
</div>
<span>{item.kind === "folder" ? "Folder" : item.mediaType}</span>
<span>{item.sizeLabel}</span>
<span>{item.source?.owner}</span>
<Files.ItemProgress />
</Files.Item>
</Files.List>Props
Files.List
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | - | Files.Item rows or compatible custom row children. |
header | ReactNode | default header | Pass null to remove the header or a node to provide a custom header. |
className | string | - | Extends the list root. |
Also accepts standard div props. Files.List has no items prop.
Files.Item
| Prop | Type | Default | Description |
|---|---|---|---|
item | FilesItem<TSource> | - | File or folder display data. |
onOpen | (item, event) => void | - | Called on double click, or Enter when inline rename is unavailable. |
disabled | boolean | false | Disables the item in addition to root and item data disabled state. |
children | ReactNode | - | Optional custom row content built from item slots. |
className | string | - | Extends the item root. |
Selection is controlled by the root Files props: selectedIds,
onSelectedIdsChange, selectionMode, selectionBehavior, and optional
canSelect.