GitHub

Anatomy

The compound File Viewer structure: root, header, content, sidebar slot, inset, viewport, and routed document.

FileViewerPreview is the one-line preview shell:

<FileViewerPreview source={source} />

When the file needs its own header, sidebar, or surrounding workflow chrome, compose the same primitive parts explicitly:

<FileViewerProvider source={source} defaultSidebarOpen>
  <FileViewer>
    <FileViewerHeader>
      <FileViewerSidebarTrigger />
      <FileViewerTitle />
      <FileViewerControls />
    </FileViewerHeader>
 
    <FileViewerContent>
      <FileViewerSidebar aria-label="Document navigation">
        <FileViewerThumbnails />
      </FileViewerSidebar>
 
      <FileViewerInset>
        <FileViewerViewport>
          <FileViewerDocument />
        </FileViewerViewport>
      </FileViewerInset>
    </FileViewerContent>
  </FileViewer>
</FileViewerProvider>

Boundaries

  • FileViewerProvider owns file identity, source loading, route detection, sidebar open state, and the file-scoped provider stack.
  • FileViewer owns the spatial frame: layout, sidebar mode, side, and breakpoint behavior.
  • FileViewerPreview composes the provider, frame, inset, viewport, and routed document for the one-line preview case.
  • FileViewerHeader owns the full-width file row.
  • FileViewerContent owns the horizontal layout under the header.
  • FileViewerSidebar is the optional navigation slot. It does not decide what the rows mean.
  • FileViewerInset owns the main file inset beside the sidebar.
  • FileViewerViewport owns the scroll and clipping boundary inside the inset.
  • FileViewerDocument renders the routed file renderer.
  • FileViewerLoadingState, FileViewerEmptyState, FileViewerUnavailableState, FileViewerErrorState, and FileViewerUnsupportedState provide shared state surfaces.

Navigation components live inside FileViewerSidebar. They are not part of the irreducible shell:

<FileViewerSidebar aria-label="Attachments">
  <AttachmentSidebar
    items={attachments}
    selectedId={selectedId}
    onSelect={setSelectedId}
  />
</FileViewerSidebar>

Use FileViewerPreview for a nested file leaf when a parent viewer already owns the surrounding frame:

<FileViewerPreview source={attachment.source} />

Mental model

File Viewer separates provider state from spatial anatomy. FileViewerProvider owns file identity and routing state. FileViewer owns the frame inside the host surface. Renderers own pixels. Navigation owns movement inside the file surface. Workflow viewers own domain semantics outside the file.