Skip to content
SLICES / TECHNICAL FOLIO Nº 001FULL-STACK ASSEMBLIES — OPEN SOURCE

Headless / Files & documents

Browse files

Compose file explorer with storage permissions, loading and failure states.

72 public parts · 2examples

@slices.sh/file-storage/headlessView as Markdown ↗

Your design. Our behavior.

Explore the tree to see what each part controls. Gates reveal the relevant state; roots outline their scope.

Behavior / inputGateGenericRenderer · not headlessScope
COMPONENT ANATOMYHover · focus · tap
ONE POSSIBLE DESIGNStatic preview

Files.Container · Scope

Files.ContainerThe one place a file explorer talks to the file service.

Installation

Choose what your component needs. Run these commands in an initialized Next.js app.

0

Before you start

The steps below run in a Next.js app with shadcn set up (it has a components.json). In an existing Next.js app, such as one from create-next-app, set shadcn up first:

npx shadcn@latest init -t next -b base -p nova

Or start fresh: the slices CLI creates the app and sets it up.

npx slices.sh install
1

Install the service registry

Adds services/index.ts, which import "@/services" loads. A provider setup writes the same file, so skip this if your app has one.

npx add services
2

Install the headless library

npm

Add the React parts to your app, then compose them with your own elements.

npm install @slices.sh/file-storage@^0.2.7

Import from @slices.sh/file-storage/headless.

3

Install the service

Connect the parts to a provider. Skip this step if this service is already configured in your app.

Provider
npx add file-storage.local

Adds service configuration and API routes to your app, with the provider dependencies. For a headless composition, add import "@/services" after "use client".

The slices CLI installs the service and provisions its required resources in one command.

Provider setup notes
  • Add .data/ to .gitignore: the bytes and the index live there.
  • This store lives on one disk. A serverless deployment loses the files between requests, so deploy with @slices.sh/file-storage.s3.
  • A screen works in a bucket, a private corner of the config ("files" by default). The config lists the ones its screens work in (`buckets`, which installs grow); list more, or a prefix such as "playground/", in `buckets` in services/file-storage/rules.ts. Any other is not-found.
  • Set maxUploadBytes and accept in services/file-storage/default.config.ts: nothing is capped until you do.

Start small

Parts bring the behavior. Use their default elements, or supply your own with render.

example.tsx
"use client"import "@/services"import { Files } from "@slices.sh/file-storage/headless"export function Example() {  return (    <Files.Root>      <Files.Breadcrumb>        <Files.Crumb />      </Files.Breadcrumb>      <Files.Up>Parent folder</Files.Up>      <Files.Entries>        <Files.Entry>          <Files.Open>            <Files.Thumbnail />            <Files.EntryName />          </Files.Open>        </Files.Entry>      </Files.Entries>      <Files.Empty>No files here.</Files.Empty>      <Files.Loading>Loading…</Files.Loading>    </Files.Root>  )}

Configure a file-storage provider. Mutating actions follow the storage rules and current user permissions.

API reference

Every public part used by this experience is listed below. Gates render children without adding an element. Element parts accept native element props and render; function children receive the state declared in their props. Scopes provide context rather than a visual element.

Files.Rootscope

The browser's root, and Files.Root with Files.Children in one, the seam that reads what the config's client can do.

Props

9 documented props

Files.Root props
PropTypeDefault
config

The file-storage config, a slug from the registry (services/file-storage/<config>.config.ts). The nearest root's, else "default", when left out.

string—
enabled

Left out or true: required, and a missing service throws. "optional": renders its children and every part inside renders nothing except Files.Unavailable, and a Composer inside finds its sink switched off. false: off. A capability name such as "trash" requires the service with it.

Enabled—
bucket
string—
initialPath

Where the browser opens. Give path and onPath instead to keep it in the address.

string"/"
path
string—
multiple
booleantrue
searchLeavesWithFolder

Opening another folder ends a search, as in Finder, instead of carrying it into the folder.

booleanfalse
ifExists

What moving an entry into a folder that has one of that name does. Left out, it is refused. "ask" raises a question for Files.Clash to put to the person: replace, keep both or skip.

IfExists | "ask"—
children

Content rendered inside this part.

ReactNode—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/file-storage/src/headless/files-root.tsx

Files.Navigationcontent · <ul>

Opt-in roving primary controls; secondary buttons retain their normal Tab behavior.

Required scope

Files.Navigation requires Files.Root.

Props

4 documented props · Native <ul> attributes supported

Files.Navigation props
PropTypeDefault
layout
"linear" | "grid""linear"
windowed
booleanfalse
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/file-storage/src/headless/navigation.tsx

Files.Backaction · <button>

The folder this panel was looking at before. Disabled rather than hidden, unlike `Files.Up`: back and forward sit in a row of controls whose places people learn, and one that comes and goes moves the other one under the pointer. Up has no such pair — at the root there is genuinely nothing there.

Required scope

Files.Back must be inside <Files.Root>.

Props

2 documented props · Native <button> attributes supported

Files.Back props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/file-storage/src/headless/back.tsx

Files.Forwardaction · <button>

The folder this panel came back from, until opening another one replaces it.

Required scope

Files.Forward must be inside <Files.Root>.

Props

2 documented props · Native <button> attributes supported

Files.Forward props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/file-storage/src/headless/forward.tsx

Files.Upaction · <button>

One folder up. Not rendered at the root, where there is no up.

Required scope

Files.Up must be inside <Files.Root>.

Props

2 documented props · Native <button> attributes supported

Files.Up props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/file-storage/src/headless/up.tsx

Files.Breadcrumbscope

Every folder from the root down to where the browser is, each in its own scope.

Required scope

Files.Breadcrumb must be inside <Files.Root>.

Props

1 documented props

Files.Breadcrumb props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/file-storage/src/headless/breadcrumb.tsx

Files.Crumbaction · <button>

One step of the trail. The last one is where you already are, so it is disabled.

Required scope

Files.Crumb must be inside <Files.Breadcrumb>.

Files.Crumb must be inside <Files.Root>.

Props

2 documented props · Native <button> attributes supported

Files.Crumb props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/file-storage/src/headless/crumb.tsx

Files.Windowcontent · <ul>

Window linear rows while preserving native Tab order and the last focused entry.

Required scope

Files.Window requires Files.Root.

Props

4 documented props · Native <ul> attributes supported

Files.Window props
PropTypeDefault
windowed
booleantrue
maxHeight
CSSProperties["maxHeight"]"24rem"
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/file-storage/src/headless/window.tsx

Files.ViewAreacontent · <div>

Which view is drawn (icons, list, columns, gallery), the area it measures, a pressed button per view, and a gate per view.

Required scope

Files.ViewArea requires Files.Views.

Props

2 documented props · Native <div> attributes supported

Files.ViewArea props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/file-storage/src/headless/view-area.tsx

Files.Containerscope

The one place a file explorer talks to the file service. It maps the client onto what the screen below draws: the folder that is open and its pages (`Files.Root`), the folders read besides it, from the store's listings or from `loadChildren`, and the address of every file and every picture, which the parts ask the client for and the server signs. What the screen may do is read here too, from what the client has: a part that needs `upload` asks `Files.CanUpload`, so a service with none gets a browser with no upload button and no drop, and not a button that fails when pressed. The screen never calls the service itself: pattern code calls no hook, and every part under here reaches the service through this container's contexts. → docs/rules/patterns-read-no-state.md

Props

2 documented props

Files.Container props
PropTypeDefault
loadChildren

Where a folder's children come from when it is not the store's own listing.

LoadChildren—
children

Content rendered inside this part.

ReactNode—

Required props are marked. A dash means no explicit default is declared in this component.

Also inherits Omit<FilesRootProps, "children">. See TypeScript for the complete declaration.

Source: @slices.sh/file-storage/src/headless/container.tsx

Files.Viewsscope

Which view is drawn (icons, list, columns, gallery), the area it measures, a pressed button per view, and a gate per view.

Required scope

Files.Views requires Files.Root.

Props

3 documented props

Files.Views props
PropTypeDefault
view
"list" | "icons" | "columns" | "gallery"—
defaultView
"list" | "icons" | "columns" | "gallery"—
children

Content rendered inside this part.

ReactNode—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/file-storage/src/headless/views.tsx

Files.WhenViewgate

Which view is drawn (icons, list, columns, gallery), the area it measures, a pressed button per view, and a gate per view.

Required scope

Files.WhenView requires Files.Views.

Props

2 documented props

Files.WhenView props
PropTypeDefault
valueRequired
FileView | readonly FileView[]—
children

Content rendered inside this part.

ReactNode—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/file-storage/src/headless/when-view.tsx

Files.Entriesscope

What the browser is showing: the directory's children, or what the search found. Under a folder that is open, in a tree, its entries follow it with how far in they are. One part for both, because a screen that drew them separately would be two lists whose rows, selection and actions drifted apart — and a search that showed a different kind of row than the folder it searched is the thing people report as a bug. Where the screen draws uploads in place, each one that is on its way is a row among these, in the order of the rest, with `Files.Pending` to say how far it has got. A row that is not there yet cannot be opened, picked, renamed or moved: its parts say so themselves.

Props

1 documented props

Files.Entries props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/file-storage/src/headless/entries.tsx

Files.Listedgate

The folder is being listed, or has been: where its headings and its rows go. Everything a listing is made of belongs inside this — the column headings, the skeletons that wait for the rows, the rows, the empty state that stands in for them, the page after this one — so that they share one place in the layout. A folder with nothing in it then keeps its headings over a body that says so, rather than a sentence above headings with nothing under them. Nothing when the read failed, where `Files.Failed` says why and headings over no rows would say nothing, nor where no backend is installed, where `Files.Unavailable` is the answer.

Required scope

Files.Listed must be inside <Files.Root>.

Props

1 documented props

Files.Listed props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/file-storage/src/headless/listed.tsx

Files.Entrycontent · <li>

The gate around everything a listed folder draws, the repeater of rows on screen, the row, the next page, roving keys over the rows, a windowed list for long folders and the live announcement of what the folder now holds.

Required scope

Files.Entry must be inside <Files.Entries>.

Files.Entry must be inside <Files.Root>.

Props

2 documented props · Native <li> attributes supported

Files.Entry props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: EntryState) => ReactNode)—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/file-storage/src/headless/entry.tsx

Files.Filegate

This row is a file: what a folder has no use for, a picture of its contents or a size. The other half of `Files.Folder`.

Required scope

Files.File must be inside <Files.Entries>.

Props

1 documented props

Files.File props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/file-storage/src/headless/file-only.tsx

Files.EntryNamecontent · <span>

Opening a folder or selecting a file, the file manager's pick (a click picks, a double click opens), gates for a folder row and a file row, the thumbnail of a picture, the facts a row says, the folder an entry sits in for a search result, and a signed download link. Files.Folder is also a sink: a Composer inside it posts to that folder.

Required scope

File.EntryName must be inside <File.Entries>.

Props

2 documented props · Native <span> attributes supported

Files.EntryName props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/file-storage/src/headless/entry-name.tsx

Files.EntryKindcontent · <span>

What an entry is, in the words the screen has for it. The part says the facts (the kind, the extension and the declared type) and its function child turns them into "PDF Document" or "Folder", because those are words and the words are the screen's. Without one it says the kind, which is the one thing that is not a guess.

Required scope

Files.EntryKind must be inside <Files.Entries>.

Props

2 documented props · Native <span> attributes supported

Files.EntryKind props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: EntryKindState) => ReactNode)—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/file-storage/src/headless/entry-kind.tsx

Files.EntryModifiedcontent · <time>

When it last changed, as a `<time>` carrying the machine-readable value. The text is the date in the reader's own locale, computed on the client — which is why `dateTime` matters: it is the one form a screen reader and a test can both rely on while the visible text depends on where you are.

Required scope

File.EntryModified must be inside <File.Entries>.

Props

2 documented props · Native <time> attributes supported

Files.EntryModified props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/file-storage/src/headless/entry-modified.tsx

Files.Foldergate

This row is a folder. What a row that is not a file needs in place of what only a file has: `Files.Download` renders nothing for a folder, so a chip whose name is its download link shows the folder's name through this instead.

Required scope

Files.Folder must be inside <Files.Entries>.

Props

1 documented props

Files.Folder props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/file-storage/src/headless/folder.tsx

Files.FolderNamecontent · <span>

The name of the folder that is open, as a toolbar says it. At the root that is the bucket's own name, which is not a word anybody chose, so the function child is told it is the root and says what the screen calls it.

Required scope

Files.FolderName must be inside <Files.Root>.

Props

2 documented props · Native <span> attributes supported

Files.FolderName props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { name: string; root: boolean }) => ReactNode)—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/file-storage/src/headless/folder-name.tsx

Files.EntryItemscontent · <span>

How many entries a folder holds, once somebody has looked: `null` until then, which is not zero. A row that said "0 items" for a folder nobody had opened would be calling it empty before it had looked. → docs/rules/capability-honesty.md Only for a folder, and only where `Files.Children` is, which is what reads one. The count is what was read, so while the pages of a long folder are still arriving it is what has.

Required scope

Files.EntryItems must be inside <Files.Entries>.

Props

2 documented props · Native <span> attributes supported

Files.EntryItems props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { count: number | null }) => ReactNode)—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/file-storage/src/headless/entry-items.tsx

Files.ViewOptionaction · <button>

Which view is drawn (icons, list, columns, gallery), the area it measures, a pressed button per view, and a gate per view.

Required scope

Files.ViewOption requires Files.Views.

Props

3 documented props · Native <button> attributes supported

Files.ViewOption props
PropTypeDefault
valueRequired
"list" | "icons" | "columns" | "gallery"—
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/file-storage/src/headless/view-option.tsx

Files.Openaction · <button>

The control that opens a row: a folder to browse into, a file to select. One part for both, because a folder and a file are opened the same way by everybody who has used a file browser, and only the row knows which it is.

Required scope

Files.Open must be inside <Files.Entries>.

Files.Open must be inside <Files.Root>.

Props

2 documented props · Native <button> attributes supported

Files.Open props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/file-storage/src/headless/open.tsx

Files.Pickaction · <button>

The control of a row as a file manager has it: a click picks it, and opening is a double click or Enter. Apart from `Files.Open`, where one click opens a folder: here a folder is picked like a file, which is what lets its neighbours stay on screen while it is looked at, and it is browsed into on the second press. Opening a file is whatever the screen has wired to open one (`FilePreview.Root` opens the viewer); with nothing wired, the file stays picked. Shift extends from the last row touched and Ctrl or Command adds one, over the rows on screen; without either the row is the whole selection. A tree's rows and a column's go through the same keys, since both are drawn from `Files.Entries`. An upload that has not arrived is a row that is not there to pick: the control is disabled, and is no stop of the keys, until the file is. `data-state` says what else the row is to the screen it is in: `trail`, the folder whose contents are the next column of a Miller view, and `stage`, the entry on the stage of a gallery, which is the picked one or else the first.

Required scope

Files.Pick must be inside <Files.Entries>.

Files.Pick must be inside <Files.Root>.

Props

2 documented props · Native <button> attributes supported

Files.Pick props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/file-storage/src/headless/pick.tsx

Files.Downloadcontent · <a>

Saves the file it is in, by a URL the server signed for saving rather than for showing. An anchor and not a button, so the browser's own "save link as" and middle-click work. Until the server has said where the bytes are there is no `href`, which makes this not a link yet rather than a link to nowhere — `data-pending` is how a skin says so instead of offering something that would do nothing. `download` names the file: an object store's key is a hash often enough that saving one without this produces a folder full of them. The file's name is in `state` as well, because a list of these reads as "Download, link" once per row otherwise, with nothing saying which row. What to do with it — a name, or a sentence around one — is the pattern's. → docs/rules/words-in-copy-looks-in-skin.md

Required scope

Files.Download must be inside <Files.Entries> or <Files.Preview>.

Props

2 documented props · Native <a> attributes supported

Files.Download props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { name: string }) => ReactNode)—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/file-storage/src/headless/download-entry.tsx

Files.Thumbnailcontent · <img>

The picture a row is of, at the size the skin draws it. Nothing at all for anything that is not an image, and nothing until the server has said where the bytes are: a grid of photographs drawn as identical grey glyphs is unusable, and a grid of broken-image icons is worse. The icon beside it is the skin's business — this part's answer to "no picture" is to render none. → docs/rules/capability-honesty.md An upload on its way is the picture on this device, which is there from the moment the file was chosen; the store has nothing to ask for yet. Which is also the answer when the bytes do not arrive. A signed URL is good for minutes, and a folder left open for longer would otherwise turn every picture in it into a broken one; the glyph underneath is still the truth about what the file is. Remembered against the URL that failed, so the next one is tried.

Required scope

Files.Thumbnail must be inside <Files.Entries>.

Props

2 documented props · Native <img> attributes supported

Files.Thumbnail props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/file-storage/src/headless/thumbnail.tsx

Files.EntrySizecontent · <span>

A file's size. A directory has none of its own, so it renders nothing rather than "0 B", unless it is a folder on its way, which is as large as the files going into it.

Required scope

File.EntrySize must be inside <File.Entries>.

Props

2 documented props · Native <span> attributes supported

Files.EntrySize props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/file-storage/src/headless/entry-size.tsx

Files.EntryLocationcontent · <span>

The folder an entry sits in, from the one the browser has open: `Invoices/2026` for a file found by a search two levels down. Nothing for an entry that is in the open folder itself, because a column that repeated the folder in every row would say nothing. What a recursive search needs beside the name: a list of `report.pdf` from five folders is five files nobody can tell apart.

Required scope

Files.EntryLocation must be inside <Files.Entries>.

Files.EntryLocation must be inside <Files.Root>.

Props

2 documented props · Native <span> attributes supported

Files.EntryLocation props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/file-storage/src/headless/entry-location.tsx

Files.EntryDatecontent · <time>

One of an entry's two dates as a `<time>`, with the date itself for a function child to say in the screen's words: `Jan 8, 2026 at 12:24 PM` is a choice of format and of "at". Nothing when the store did not say, rather than the epoch: a date that is a guess is worse than none. → docs/rules/capability-honesty.md

Required scope

Files.EntryDate must be inside <Files.Entries>.

Props

3 documented props · Native <time> attributes supported

Files.EntryDate props
PropTypeDefault
ofRequired
"createdAt" | "updatedAt"—
children

Content rendered inside this part.

ReactNode | ((state: { date: Date }) => ReactNode)—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/file-storage/src/headless/entry-date.tsx

Files.Previewscope

The one file that is selected, in its own scope. A scope rather than a gate, so everything already written for a row works inside it: `Files.EntryName` is the preview's title and `Files.EntrySize` is its subtitle, with no second set of parts that could disagree with the first about what a name is. Exactly one, and a file: two selected files are not a preview, and a folder has nothing to show. The record comes from the listing on screen rather than being fetched again, so a selection left behind by a folder that has since changed simply stops matching and this closes itself. Escape puts it away. This is not a dialog — nothing is trapped in it, the list behind it stays live, and no focus is moved — but on a phone it is drawn over that list, and the key everybody presses to dismiss something drawn over something else is this one. `useEscape` owns the listener: the thing being dismissed is rarely what has the focus.

Capability: previews

Required scope

Files.Preview must be inside <Files.Root>.

Props

1 documented props

Files.Preview props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/file-storage/src/headless/preview.tsx

Files.PreviewImagecontent · <img>

The picture itself, once the server has said where it is. Nothing until then, and nothing at all for a file that is not an image: an `<img>` with no `src` is a broken-image icon, which tells somebody the file is damaged when it is only the URL that has not arrived. → docs/rules/capability-honesty.md

Capability: previews

Required scope

Files.PreviewImage must be inside <Files.Preview>.

Props

2 documented props · Native <img> attributes supported

Files.PreviewImage props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/file-storage/src/headless/preview-image.tsx

Files.ClosePreviewaction · <button>

Puts the preview away, which is the same thing as selecting nothing.

Capability: previews

Required scope

Files.ClosePreview must be inside <Files.Root>.

Props

2 documented props · Native <button> attributes supported

Files.ClosePreview props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/file-storage/src/headless/close-preview.tsx

Files.PreviewFramecontent · <iframe>

A PDF, a text file, a video: the things a browser opens for itself. `sandbox` with nothing in it, because the bytes in a bucket are whatever somebody uploaded. An SVG or an HTML file is a document with script in it, and a frame without this would be running that script on this origin, against this session.

Capability: previews

Required scope

Files.PreviewFrame must be inside <Files.Preview>.

Props

2 documented props · Native <iframe> attributes supported

Files.PreviewFrame props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/file-storage/src/headless/preview-frame.tsx

Files.PreviewPendinggate

This file can be drawn, and where its bytes are has not been said yet. On a store that signs its URLs that is a round trip, and until it answers the panel is a title, a size and a hole where the file goes — which reads as a preview that failed. This is where the shape of what is coming belongs. → docs/rules/capability-honesty.md

Capability: previews

Required scope

Files.PreviewPending must be inside <Files.Preview>.

Props

1 documented props

Files.PreviewPending props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/file-storage/src/headless/preview-pending.tsx

Files.NoPreviewgate

This file is not something a browser can draw. A spreadsheet, a deck, an archive: real files that simply have no viewer here. Saying so and offering `Files.Download` beside it is the honest screen; a blank frame is the one people report as broken. → docs/rules/capability-honesty.md

Capability: previews

Required scope

Files.NoPreview must be inside <Files.Preview>.

Props

1 documented props

Files.NoPreview props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/file-storage/src/headless/no-preview.tsx

Files.Uploaderscope

An upload queue that belongs to the folder around it. `Upload.Root` on its own has to be told where to put things. This one asks: files land in the directory that is on screen, and when one arrives the listing reads again — so a file you dropped is in the list a moment later rather than after a reload nobody thought to do. Both of those are wiring between two hooks, which is why they are here and not in a pattern: pattern code calls no hook, and a screen that passed `path` and `onUploaded` itself would have to hold the browser's state to do it. `inPlace` is the screen that has no list of uploads of its own: each one is a row of the folder it is going to, as `Files.Entries` draws them, and a file the person cannot yet open is a row they cannot open. Inside a `Files.Container` the service has the last word: where it has no upload, the queue is not mounted at all, and `Files.CanUpload` is what keeps every part that needs the queue from drawing. The server's log says so once, since a missing button is otherwise a mystery.

Capability: upload

Required scope

Files.Uploader must be inside <Files.Root>.

Props

9 documented props

Files.Uploader props
PropTypeDefault
bucket
string—
maxSize

Bytes. A larger file is refused before anything is sent.

number—
maxFiles
number—
accept

An accept attribute: "image/*,.pdf". Offered to the picker and checked in the queue.

string—
multipart

Resumable parts for large files where the backend has them. On unless turned off.

boolean—
includeHidden
boolean—
inPlace

Draw each upload among the rows of the folder it is going to (Files.Entries), where it will land, until the file is there. Off, the screen draws the queue itself.

boolean—
ifExists

What a name that is taken does. "ask" holds the file for Files.Clash to put to the person. Left out, it replaces.

IfExists | "ask"—
children

Content rendered inside this part.

ReactNode—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/file-storage/src/headless/uploader.tsx

Files.CanUploadgate

The service takes files: where an upload button, a drop target and the rows of what is on its way go. Nothing at all where it does not, and nothing outside a `Files.Container`, which is the one thing that can say. A control for something the backend cannot do is a promise it breaks. → docs/rules/capability-honesty.md

Capability: upload

Props

1 documented props

Files.CanUpload props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/file-storage/src/headless/can-upload.tsx

Files.DropAreacontent · <div>

A place files are dropped where the service takes them, and an ordinary element where it does not. `Upload.DropZone` is the first half and is an error outside an upload queue, which is right for a message box that is nothing without one. A folder is something without it: the same box, drawn the same, that takes no drag.

Capability: upload

Props

2 documented props · Native <div> attributes supported

Files.DropArea props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: DropAreaState) => ReactNode)—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/file-storage/src/headless/drop-area.tsx

Files.Receivingcontent · <div>

How far the files going into this folder have got, on the row of the folder: what files dropped from the desktop on a folder that is not open say, since nothing else on screen is theirs until it is. Nothing for a file, for a folder nothing is going into, and for a row that is itself an upload on its way, which has `Files.PendingRing`. The folder's name is its accessible name, and `files` and `percent` are in the state for the sentence a pattern says about them. Without a byte counted yet it is an unknown, which a skin draws as a stationary arc.

Capability: upload

Required scope

Files.Receiving must be inside <Files.Entries>.

Props

2 documented props · Native <div> attributes supported

Files.Receiving props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { files: number; percent: number | null }) => ReactNode)—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/file-storage/src/headless/receiving.tsx

Files.Pendinggate

This row is an upload that has not arrived: where what is said about its journey goes. Nothing for a stored entry, which is what makes it the one place a row says "42%" or "3 of 12 files" without a pattern asking whether it is looking at an upload. The words are the pattern's; this says how far it has got. → docs/rules/states-gate-themselves.md

Capability: upload

Props

1 documented props

Files.Pending props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: PendingSaid) => ReactNode)—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/file-storage/src/headless/pending.tsx

Files.PendingRingcontent · <div>

How far an upload on its way has got, as the progress of the row it is drawn in. Nothing once it has stopped, whether it arrived or was refused: a full ring that stays full reads as still working. Without a byte counted yet it is an unknown, which a skin draws as a stationary arc rather than a bar at nought. For a folder that was dropped it is every file behind it, by bytes. The name of what it is for is its accessible name, since a folder with five of these on it is five "40 percent"s otherwise.

Capability: upload

Props

2 documented props · Native <div> attributes supported

Files.PendingRing props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/file-storage/src/headless/pending-ring.tsx

Files.PendingCancelaction · <button>

Stops an upload on its way, every file of it for a folder that was dropped. The row goes with it: a file nobody is sending is not a row of the folder. Not drawn once nothing of it can be stopped, as `Upload.Cancel`: a file that has been sent and is being put together on the other side can no longer be called back. The name is in `state`, so that a folder of twenty rows is not twenty buttons called "Stop".

Capability: upload

Props

2 documented props · Native <button> attributes supported

Files.PendingCancel props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { name: string }) => ReactNode)—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/file-storage/src/headless/pending-cancel.tsx

Files.PendingFailedgate

An upload on its way was refused, with the reason: the row stays where the file would have been, and says why it is not there. For a folder that was dropped it is the first file that was refused, with how many were.

Capability: upload

Props

1 documented props

Files.PendingFailed props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { error: FileErrorSlug; name: string; failed: number }) => ReactNode)—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/file-storage/src/headless/pending-failed.tsx

Files.PendingRetryaction · <button>

Sends again what was refused: the file, or the files of a folder that were. Drawn once there is nothing left on its way, so a folder that is still sending is not sent twice.

Capability: upload

Props

2 documented props · Native <button> attributes supported

Files.PendingRetry props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { name: string }) => ReactNode)—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/file-storage/src/headless/pending-retry.tsx

Files.PendingDismissaction · <button>

Lets go of a row that was refused, for somebody who does not mean to try again. What was not sent is not in the folder, so the row has nothing left to be.

Capability: upload

Props

2 documented props · Native <button> attributes supported

Files.PendingDismiss props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { name: string }) => ReactNode)—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/file-storage/src/headless/pending-dismiss.tsx

Files.NoUploadsgate

Nothing is on its way: where a folder's "this is empty" goes, so it is not said while a file is landing in it. Where the uploads are drawn in place, what counts is what is drawn in this folder: a file the listing has caught up with, that was stopped or that is going into another folder is not on its way here, and a folder somebody emptied after filling it is empty again. One that was refused still is a row of the folder it was meant for, with a reason. `Upload.Empty` is this for a queue that must be there. Where the service takes no uploads there is no queue, and a folder with nothing in it is empty, so this holds too.

Capability: upload

Props

1 documented props

Files.NoUploads props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/file-storage/src/headless/no-uploads.tsx

Files.LoadMoreaction · <button>

The rest of a folder. Rendered only where the store said there is another page, so a folder that fits shows nothing and a folder of ten thousand never pretends to have ended. `data-pending` while the next page is on its way; a second press does nothing. `loading` is in `state` too, so the button can say it is fetching rather than going quiet and disabled — which reads as a button that did not work.

Required scope

Files.LoadMore must be inside <Files.Root>.

Props

2 documented props · Native <button> attributes supported

Files.LoadMore props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { loading: boolean }) => ReactNode)—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/file-storage/src/headless/load-more.tsx

Files.Loadinggate

The first read. A reload keeps the rows on screen rather than blanking them. Nothing at all where no backend is installed: `useDirectory` never asks, so its read stays `loading` for good, and three skeletons pulsing under "no storage backend is installed" is a screen promising rows that are never coming. `Files.Unavailable` is the whole answer there. → docs/rules/capability-honesty.md

Required scope

Files.Loading must be inside <Files.Root>.

Props

1 documented props

Files.Loading props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/file-storage/src/headless/loading.tsx

Files.Emptygate

Nothing to show. `searched` tells the two apart, because the remedies differ: "drop something here" against "try another word", and `query` is the word that was tried.

Required scope

Files.Empty must be inside <Files.Root>.

Props

1 documented props

Files.Empty props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { searched: boolean; query: string }) => ReactNode)—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/file-storage/src/headless/empty.tsx

Files.Failedgate

The read was refused, and the child is told which refusal it was.

Required scope

Files.Failed must be inside <Files.Root>.

Props

1 documented props

Files.Failed props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { error: FileErrorSlug }) => ReactNode)—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/file-storage/src/headless/failed.tsx

Files.MutationFailedgate

The last change to this folder was refused, with the reason. Making a folder, moving an entry into one and deleting one can all be refused, and until this there was nowhere for any of those answers to go: the row simply stayed where it was, which reads as a screen that ignored the press. → docs/rules/states.md

Required scope

Files.MutationFailed must be inside <Files.Root>.

Props

1 documented props

Files.MutationFailed props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { error: FileErrorSlug }) => ReactNode)—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/file-storage/src/headless/mutation-failed.tsx

Files.Offlinegate

The first read, nothing to show (with the search that found nothing), the read refused, a change refused, the service missing under enabled="optional", a production server that answers config-missing, and the browser offline.

Props

1 documented props

Files.Offline props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/file-storage/src/headless/offline.tsx

Files.Unavailablegate

No storage backend is installed at all. Distinct from a refused read, because nothing the person does will help: the app is missing an implementation, and the only useful sentence names the command that adds one.

Props

1 documented props

Files.Unavailable props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/file-storage/src/headless/unavailable.tsx

Files.MissingConfigurationgate

The server this screen keeps its files on answered that it lacks configuration. The family's own name for the shared gate, with the service already chosen: a screen that draws files should not have to know which string the file routes answer with, and another service's trouble (a transcription key) is not its notice. Not `Unavailable`, which is no backend installed at all: that has a command to run, this has a log to read. → docs/rules/missing-configuration-is-said.md

Props

1 documented props

Files.MissingConfiguration props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { scopes: readonly string[] }) => ReactNode)—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/file-storage/src/headless/missing-configuration.tsx

Files.Announcercontent · <div>

What the listing is showing, for somebody who cannot see it change. Opening a folder, searching, and asking for another page all replace the rows under a heading that never moves: there is no navigation, no focus change and nothing said, so a person using a screen reader presses a button and is told nothing at all. Counts rather than events, and `aria-atomic`, so a folder of two hundred is one sentence. The words are the pattern's — "empty", "nothing matched" and "twelve items" are three different things to say. → docs/rules/words-in-copy-looks-in-skin.md A live region announces what appears *inside* it, so the element is here from the first render either way — and empty while no backend is installed, because `useDirectory` never asks and its read stays `loading` for good. A region saying "Loading…" for the rest of the session would be the one untrue thing on that screen. → docs/rules/capability-honesty.md

Required scope

Files.Announcer must be inside <Files.Root>.

Props

2 documented props · Native <div> attributes supported

Files.Announcer props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: FolderSaid) => ReactNode)—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/file-storage/src/headless/folder-announcer.tsx

Files.Treescope

Folders that open in place: the list as a tree, where a folder's row has its entries under it and an arrow to show them. Which are open is held here, above the views, so switching to icons and back finds the branches as they were left. The rows are a tree only in the list view: the strip of a gallery and a column are lists of their own folder, and read the same entries unchanged. An open folder is asked for from `Files.Children`, which is why it has to be inside one: the read starts when the folder opens, not when its row is listed.

Required scope

Files.Tree must be inside <Files.Children>.

Props

1 documented props

Files.Tree props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/file-storage/src/headless/tree.tsx

Files.Childrenscope

The folders this screen reads besides the open one, each when something on screen asks to see it: the branches of a tree, the columns of a Miller view, the folder behind a tile. `loadChildren` is where they come from when it is not the store: called with a path and the cursor of the page it wants, answering `{ entries, cursor }` as a listing does, and read to its last page. The store's own listing is the default, so a screen on a bucket passes nothing. They are read again whenever the open folder is. A rename, a delete or a file landing in it all read it again, and a branch left as it was would go on drawing the file that is gone. What is on screen stays until the new reading arrives.

Props

2 documented props

Files.Children props
PropTypeDefault
loadChildren
LoadChildren—
children

Content rendered inside this part.

ReactNode—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/file-storage/src/headless/children.tsx

Files.ChildEntriesscope

The entries of a folder, each in its row's scope: asking for the folder when this is drawn, and narrowed and ordered as the open folder is. Mounting it is the request, which is why a branch that is closed draws none of it and reads nothing: the folder is read when somebody opens it, not when its row is listed.

Required scope

Files.ChildEntries must be inside <Files.Children>.

Props

2 documented props

Files.ChildEntries props
PropTypeDefault
of
string—
children

Content rendered inside this part.

ReactNode—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/file-storage/src/headless/child-entries.tsx

Files.WhenChildrengate

Where a folder's reading is: not asked (`unknown`), asked and nothing back yet (`loading`), refused (`failed`), read and holding nothing (`empty`), or holding something (`ready`). `unknown` is its own answer and never `empty`: a folder nobody has read is not a folder with nothing in it, and a tree that drew the first as the second would tell people a branch was bare before it had looked. → docs/rules/capability-honesty.md `loading` is only until the first page: after it the rows that came are drawn, and the pages still to come are not a reason to hide them.

Required scope

Files.WhenChildren must be inside <Files.Children>.

Props

3 documented props

Files.WhenChildren props
PropTypeDefault
of
string—
stateRequired
"unknown" | "loading" | "failed" | "empty" | "ready"—
children

Content rendered inside this part.

ReactNode—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/file-storage/src/headless/when-children.tsx

Files.TreeToggleaction · <button>

The arrow that opens a folder's row in place, and shuts it again. Nothing for a file: it has nothing under it, and a row that offered an arrow it could not keep would be saying it had contents. Nothing either where the screen is not a tree, in a column or a strip, where the folder's entries are not drawn under it. The arrow keys do the same from the keyboard, which is why this one is not a stop of its own. → docs/rules/capability-honesty.md A folder that is still arriving has the arrow, disabled: its contents are not there to show, and the room the arrow takes is what keeps its name in line with the names beside it. `data-state` is `open` or `closed`, and `aria-expanded` says it as well. Children get the folder's name, so a button can be named for the row it belongs to.

Required scope

Files.TreeToggle must be inside <Files.Entries>.

Files.TreeToggle must be inside <Files.Tree>.

Props

2 documented props · Native <button> attributes supported

Files.TreeToggle props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { open: boolean; name: string }) => ReactNode)—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/file-storage/src/headless/tree-toggle.tsx

Files.Columnscontent · <div>

Miller columns: the trail of folders picked on the way down, a column per folder with its name, the column of the open folder, and the last column where the preview goes.

Required scope

Files.Columns requires Files.Root.

Props

2 documented props · Native <div> attributes supported

Files.Columns props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/file-storage/src/headless/columns.tsx

Files.Columncontent · <section>

Miller columns: the trail of folders picked on the way down, a column per folder with its name, the column of the open folder, and the last column where the preview goes.

Required scope

Files.Column requires Files.Columns.

Props

2 documented props · Native <section> attributes supported

Files.Column props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/file-storage/src/headless/column.tsx

Files.Cascadecontent · <div>

Miller columns: the open folder, and a column after it for each folder picked on the way down, each drawn from the children it is given. Each column is a folder of its own, drawn as the open one is, so it has its rows, its skeletons and its empty state as the list does, and the keys of `Files.Navigation` inside it. The folders after the first are read through `Files.Children`, which this has to be inside. What picking a folder does is show it in the next column and leave the open folder where it is, which is what a Miller view is: double clicking it goes into it. `Files.CascadeEnd` is where the last column ends, and what is drawn after it, a preview of the picked file, goes in it.

Required scope

Files.Cascade requires Files.Root.

Props

2 documented props · Native <div> attributes supported

Files.Cascade props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/file-storage/src/headless/cascade.tsx

Files.CurrentColumngate

Miller columns: the trail of folders picked on the way down, a column per folder with its name, the column of the open folder, and the last column where the preview goes.

Required scope

Files.CurrentColumn requires Files.Columns.

Props

1 documented props

Files.CurrentColumn props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/file-storage/src/headless/current-column.tsx

Files.ColumnNamecontent · <h3>

Miller columns: the trail of folders picked on the way down, a column per folder with its name, the column of the open folder, and the last column where the preview goes.

Required scope

Files.ColumnName requires Files.Columns.

Props

2 documented props · Native <h3> attributes supported

Files.ColumnName props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { name: string; path: string }) => ReactNode)—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/file-storage/src/headless/column-name.tsx

Files.CascadeEndgate

The last column of the trail, and nothing in the others: where what follows the columns goes.

Required scope

Files.CascadeEnd requires Files.Cascade.

Props

1 documented props

Files.CascadeEnd props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/file-storage/src/headless/cascade-end.tsx

Files.Galleryscope

One entry large and the rest in a strip: which is the large one, and which the stage has stopped on. The strip is `Files.Entries`, so it is the listing the filters and the sort already narrowed; the stage is `Files.GalleryActive`, and a preview worth waiting for goes in `Files.GallerySettled`.

Capability: previews

Required scope

Files.Gallery must be inside <Files.Root>.

Props

1 documented props

Files.Gallery props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/file-storage/src/headless/gallery.tsx

Files.GalleryActivescope

The entry on the stage, in its own scope, so `Files.EntryName` and the rest are about it.

Capability: previews

Required scope

Files.GalleryActive must be inside <Files.Gallery>.

Props

1 documented props

Files.GalleryActive props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/file-storage/src/headless/gallery-active.tsx

Files.GallerySettledscope

What a gallery has stopped on, in its scope: where a viewer that is slow to start goes. Nothing while the active entry is still moving, because a stage that mounted a viewer for every file an arrow key crossed would spend the whole scrub parsing documents nobody read.

Capability: previews

Required scope

Files.GallerySettled must be inside <Files.Gallery>.

Props

1 documented props

Files.GallerySettled props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/file-storage/src/headless/gallery-settled.tsx

Files.GalleryStepaction · <button>

Moves the stage to the entry before or after it. Disabled at either end: a strip does not wrap.

Capability: previews

Required scope

Files.GalleryStep must be inside <Files.Gallery>.

Files.GalleryStep must be inside <Files.Root>.

Props

3 documented props · Native <button> attributes supported

Files.GalleryStep props
PropTypeDefault
byRequired
-1 | 1—
children

Content rendered inside this part.

ReactNode—
render

Replace the default element with your own while retaining the part’s behavior and accessibility.

ReactElement—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/file-storage/src/headless/gallery-step.tsx

Files.GalleryPendinggate

The stage has an entry and has not stopped on it: where a spinner goes while somebody scrubs past files, so a viewer is only started for the one they land on.

Capability: previews

Required scope

Files.GalleryPending must be inside <Files.Gallery>.

Props

1 documented props

Files.GalleryPending props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—

Required props are marked. A dash means no explicit default is declared in this component.

Source: @slices.sh/file-storage/src/headless/gallery-pending.tsx

When something is missing

No service configuration
Install the file-storage setup below and import "@/services". Required service roots report missing setup; gates do not replace that configuration.
Missing capability or parent scope
Follow each part’s context requirements and the example composition. Capability-aware controls hide when the provider cannot perform their action.
Read the setup guide →