- Overview
- Anatomy
- Header
- Navigation
- Renderers
FileViewerHeader is the file row. It should answer three questions in one
line: what file is open, what passive facts matter, and what actions the active
renderer exposes.
The default header renders title, metadata, and renderer controls. Add a
FileViewerSidebarTrigger when FileViewerContent contains a sidebar.
Installation
pnpm dlx shadcn@latest add @retab/file-viewer
Example
The header stays file-type agnostic. The active renderer registers controls
into FileViewerControls, while FileViewerTitle owns the file name and
FileViewerMeta owns passive metadata.
"use client";
import {
FileViewer,
FileViewerContent,
FileViewerDocument,
FileViewerHeader,
FileViewerTitle,
FileViewerProvider,
FileViewerSidebar,Usage
The compact default composition is enough when there is no sidebar:
import {
FileViewer,
FileViewerContent,
FileViewerDocument,
FileViewerHeader,
FileViewerMeta,
FileViewerTitle,
FileViewerProvider,
FileViewerInset,
FileViewerControls,
FileViewerViewport,
} from "@/components/ui/file-viewer";
export function Example() {
return (
<FileViewerProvider source={source}>
<FileViewer>
<FileViewerHeader>
<div className="flex min-w-0 flex-1 items-baseline gap-2">
<FileViewerTitle />
<FileViewerMeta />
</div>
<FileViewerControls />
</FileViewerHeader>
<FileViewerContent>
<FileViewerInset>
<FileViewerViewport>
<FileViewerDocument />
</FileViewerViewport>
</FileViewerInset>
</FileViewerContent>
</FileViewer>
</FileViewerProvider>
);
}When FileViewerContent contains FileViewerSidebar, place the trigger before
the title:
<FileViewerProvider source={source} defaultSidebarOpen>
<FileViewer>
<FileViewerHeader>
<FileViewerSidebarTrigger />
<div className="flex min-w-0 flex-1 items-baseline gap-2">
<FileViewerTitle />
<FileViewerMeta />
</div>
<FileViewerControls />
</FileViewerHeader>
<FileViewerContent>
<FileViewerSidebar aria-label="Document sections" width="18rem" />
<FileViewerInset>
<FileViewerViewport>
<FileViewerDocument />
</FileViewerViewport>
</FileViewerInset>
</FileViewerContent>
</FileViewer>
</FileViewerProvider>FileViewerHeader can also be rendered without children. In that case it uses
the default title/meta/controls composition:
<FileViewerProvider source={source}>
<FileViewer>
<FileViewerHeader />
<FileViewerContent>
<FileViewerInset>
<FileViewerViewport>
<FileViewerDocument />
</FileViewerViewport>
</FileViewerInset>
</FileViewerContent>
</FileViewer>
</FileViewerProvider>Parts
The header is composed from small context-aware parts. None of them take a
source prop; each reads what it needs from the file viewer state or from the
surrounding viewer frame.
| Component | Role |
|---|---|
FileViewerTitle | File name. |
FileViewerMeta | Optional passive file metadata. |
FileViewerControls | Renderer-registered operational controls. |
FileViewerSidebarTrigger | Sidebar toggle; documented under Navigation. |
FileViewerTitle
Renders the current file display name.
<FileViewerTitle />- Reads
descriptor.displayNamefrom file-viewer context. It takes nosourceor name prop of its own. - Renders a
data-slot="file-viewer-title"element with truncating labels, so long file names clip cleanly. - Do not add a decorative file icon beside the title. The file name carries the identity; metadata and controls provide the surrounding context.
FileViewerMeta
Renders passive file facts such as MIME type or resolved category.
<FileViewerMeta />- Reads MIME type and category from file-viewer context.
- Renders a
data-slot="file-viewer-meta"element and returnsnullwhen no metadata is available. - Use
visibility="visible"when metadata should stay visible on small screens.
FileViewerControls
Renders operational controls registered by the active renderer: page position, zoom, rotate, retry, copy, and download.
<FileViewerControls />Add workflow actions beside the renderer controls with extra:
<FileViewerControls extra={<ApproveButton />} />- Reads the registered control set (
position,zoom,rotate,loading,extra) from file-viewer context. The header takes no PDF- or spreadsheet-specific props — renderers register their controls upward. - Download defaults to the file's original download action. A renderer can
register its own
downloads(and registering an empty list hides the download button entirely). - Renders a
data-slot="file-viewer-controls"row, right-aligned in the header. - The
extraprop is merged with any renderer-registered extras, so workflow actions can sit beside the renderer's own controls.
FileViewerSidebarTrigger
Toggles the nearest FileViewerSidebar. Place it before the title when
FileViewerContent contains a sidebar.
<FileViewerSidebarTrigger />The header does not know whether the document is a PDF, spreadsheet, image, or
email. Renderer-specific controls register into the file viewer state and appear
through FileViewerControls.
Layout Rule
Keep title and metadata on the left, controls on the right:
<FileViewerHeader>
<div className="flex min-w-0 flex-1 items-baseline gap-2">
<FileViewerTitle />
<FileViewerMeta />
</div>
<FileViewerControls />
</FileViewerHeader>Avoid file-type icons in the title row. The file name is the primary identity; metadata and controls are enough.
API Reference
| Component | Props |
|---|---|
FileViewerHeader | React.ComponentProps<typeof ViewerHeader> |
FileViewerTitle | React.ComponentProps<"span"> |
FileViewerMeta | React.ComponentProps<"span"> |
FileViewerControls | ViewerControls props except registered controls |
FileViewerSidebarTrigger | ViewerSidebarTrigger props |
FileViewerControls receives renderer-registered position, zoom, rotate,
downloads, loading, and extra from file-viewer state. Pass extra for
workflow actions that should sit beside renderer controls.
Source
"use client";
export type { ViewerSource } from "./file-viewer-core";
export {
FileViewerContent,
FileViewerInset,
FileViewerLegend,
FileViewerViewport,
type FileViewerContentProps,
type FileViewerInsetProps,
type FileViewerLegendProps,
type FileViewerViewportProps,