Composable Layout
The default FileList renders a compact row per file. Passing a render function as children gives you full control over each card’s layout, including where the thumbnail goes, how sub-components are arranged, and what the grid looks like.
import { DropZone, FileItem, FileList, Thumbnail, ViewModeProvider,} from "@hyperserve/video-uploader-react";import { UploadProvider } from "@hyperserve/video-uploader";
function App() { return ( <UploadProvider config={config}> <ViewModeProvider defaultMode="grid"> <DropZone /> <FileList> {(file) => ( <FileItem file={file} key={file.id} layout="column"> <Thumbnail file={file} playback /> <FileItem.FileName /> <FileItem.Meta> <FileItem.FileSize /> <FileItem.StatusIcon /> </FileItem.Meta> <FileItem.UploadProgress /> <FileItem.ErrorMessage /> <FileItem.Actions> <FileItem.RemoveButton /> <FileItem.RetryButton /> </FileItem.Actions> </FileItem> )} </FileList> </ViewModeProvider> </UploadProvider> );}FileList reads the view mode from ViewModeProvider context and switches between list and grid CSS layout automatically. Each card is a FileItem, a compound component whose named sub-components (FileName, Meta, UploadProgress, etc.) read their state from the parent FileItem context, so you never pass file down manually.
What each sub-component does
Section titled “What each sub-component does”| Sub-component | When it renders |
|---|---|
Thumbnail | Thumbnail image while uploading; <video> when playback is set and file is ready |
FileItem.FileName | Always |
FileItem.FileSize | Always |
FileItem.StatusIcon | Spinner during processing, check when ready |
FileItem.UploadProgress | Only during uploading |
FileItem.ErrorMessage | Only when file.error is set |
FileItem.RemoveButton | Hidden during processing and ready |
FileItem.RetryButton | Only when failed |
See the FileItem and FileList reference pages for the full prop API.
When you need a fully custom layout
Section titled “When you need a fully custom layout”If styles slots cover what but not how (e.g., you want the file name and size on one line, with the thumbnail beside the actions instead of below them), compose FileItem from primitives instead of using FileItem.Content.
<FileItem file={file} styles={fileItemStyles}> <div style={{ display: "flex", alignItems: "center", gap: 12 }}> <Thumbnail file={file} /> <div style={{ flex: 1 }}> <FileItem.FileName /> <FileItem.FileSize /> </div> <FileItem.Actions> <FileItem.RemoveButton /> <FileItem.RetryButton /> </FileItem.Actions> </div> <FileItem.UploadProgress /> <FileItem.ErrorMessage /></FileItem>Slots passed to FileItem flow to all compound sub-components via context, so theming still works through one prop. Only the layout is custom.