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

Headless / Files & documents

Find files

Compose file search & filters with storage permissions, loading and failure states.

33 public parts · 1examples

@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.Search aria-label="Search files" />      <Files.SearchClear>Clear search</Files.SearchClear>      <Files.Sorting>        <Files.SortKey by="name">Name</Files.SortKey>        <Files.SortKey by="updatedAt">Modified</Files.SortKey>      </Files.Sorting>      <Files.Entries>        <Files.Entry>          <Files.EntryName />          <Files.EntrySize />        </Files.Entry>      </Files.Entries>      <Files.Unmatched>No matching files.</Files.Unmatched>    </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.Filtersscope

What narrows the listing besides the words in the search box: file types and dates, as the pills in a bar say them. Its own part rather than something `Files.Root` always holds, because most browsers have no filter bar and should not re-render for one. Everything that draws rows reads it where it is provided (`useShownEntries`), so a filter chosen here is what `Files.Entries`, the keys, the preview and select-all all agree is on screen.

Props

1 documented props

Files.Filters 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/filters.tsx

Files.WhenSearchinggate

There is something in the search box: a dot on the button that opens it has a reason to be there.

Capability: search

Required scope

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

Props

1 documented props

Files.WhenSearching 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/when-searching.tsx

Files.Searchinput · <input>

The search box. Escape empties it, as in a toolbar search everywhere; with nothing in it the key goes on to whatever it was pressed for, a popover that holds the box closing.

Capability: search

Required scope

File.Search must be inside <File.Browser>.

Props

2 documented props · Native <input> attributes supported

Files.Search 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/search.tsx

Files.SearchClearaction · <button>

Empties the search box. Nothing while it is empty: there is nothing to clear, and a button drawn over an empty box is a button that does nothing. The box gets the focus back, since the person who pressed this is about to type again.

Capability: search

Required scope

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

Props

2 documented props · Native <button> attributes supported

Files.SearchClear 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/search-clear.tsx

Files.WhenFilteredgate

Something is narrowing the listing, which is when a bar of pills and a dot on the menu have a reason to be there.

Required scope

Files.WhenFiltered must be inside <Files.Filters>.

Props

1 documented props

Files.WhenFiltered 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/when-filtered.tsx

Files.AppliedFiltersscope

One copy of its children per filter that is on, each in that filter's scope: the pills.

Required scope

Files.AppliedFilters must be inside <Files.Filters>.

Props

1 documented props

Files.AppliedFilters 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/applied-filters.tsx

Files.WhenFiltergate

This pill is a filter of that kind, with that operator. The words a pill says for what it is are the screen's, and which of them to say is a fact about the filter: this is how a pattern chooses without reading it.

Required scope

Files.WhenFilter must be inside <Files.AppliedFilters>.

Props

4 documented props

Files.WhenFilter props
PropTypeDefault
type
"fileType" | "dateModified" | "dateCreated"—
operator
"is" | "is-any-of" | "is-not" | "after" | "before" | "in-range" | "not-in-range"—
range

A date filter that holds a range of two days rather than one preset.

boolean—
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-filter.tsx

Files.FilterTypecontent · <span>

What kind of filter a pill is and how it compares, for the screen's words: `File type`, and `is any of`. Without a function child it says the two in the model's own terms.

Required scope

Files.FilterType must be inside <Files.AppliedFilters>.

Props

2 documented props · Native <span> attributes supported

Files.FilterType props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { type: FileFilterType; operator: FileFilterOperator }) => 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/filter-type.tsx

Files.FilterOperatoraction · <button>

One operator a pill may be turned into: `after` or `before` for a preset, `in range` or `not in range` for two days, `is`, `is any of` or `is not` for types. Only the ones this filter's value allows are drawn, so a menu of these never offers a choice the filter would refuse. → docs/rules/capability-honesty.md

Required scope

Files.FilterOperator must be inside <Files.AppliedFilters>.

Files.FilterOperator must be inside <Files.Filters>.

Props

3 documented props · Native <button> attributes supported

Files.FilterOperator props
PropTypeDefault
operatorRequired
"is" | "is-any-of" | "is-not" | "after" | "before" | "in-range" | "not-in-range"—
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/filter-operator.tsx

Files.FilterValuecontent · <span>

What a pill is filtering by: the preset or the days of a range as dates, and for a type filter the types joined, until its function child says it in words (`3 selected`, `1 week ago`), which are the screen's to choose.

Required scope

Files.FilterValue must be inside <Files.AppliedFilters>.

Props

2 documented props · Native <span> attributes supported

Files.FilterValue props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: FilterValueState) => 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/filter-value.tsx

Files.FilterRemoveaction · <button>

Takes this pill's filter off. Its function child is told which kind it is, for a name that says what is being removed.

Required scope

Files.FilterRemove must be inside <Files.AppliedFilters>.

Files.FilterRemove must be inside <Files.Filters>.

Props

2 documented props · Native <button> attributes supported

Files.FilterRemove props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { type: FileFilterType }) => 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/filter-remove.tsx

Files.FilterClearaction · <button>

Takes every filter off. Nothing while there are none: there is nothing to clear.

Required scope

Files.FilterClear must be inside <Files.Filters>.

Props

2 documented props · Native <button> attributes supported

Files.FilterClear 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/filter-clear.tsx

Files.TypeMenuscope

A menu of file types that is searched by typing, and the words the screen has for each type (`PDF`, `Word document`), which is what a person types against. Mount it inside the menu, so the search starts empty each time the menu opens. The types themselves are `Files.TypeOptions`, which follow what is typed here.

Props

2 documented props

Files.TypeMenu props
PropTypeDefault
label
FileTypeMenu["label"]—
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/type-menu.tsx

Files.TypeSearchinput · <input>

The box a menu of file types is searched in. Its keys stay in it, except Escape and Tab: a menu moves its highlight and jumps to an item by a letter, and letters typed into a box are not a request for either.

Required scope

Files.TypeSearch must be inside <Files.TypeMenu>.

Props

2 documented props · Native <input> attributes supported

Files.TypeSearch 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/type-search.tsx

Files.TypeGroupgate

A group of file types that has some: where its heading goes, so a menu never shows `Code` over nothing.

Props

2 documented props

Files.TypeGroup props
PropTypeDefault
groupRequired
"documents" | "spreadsheets" | "images" | "code" | "text" | "other"—
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/type-group.tsx

Files.TypeOptionsscope

One copy of its children per file type among the files read, in one group when given.

Props

2 documented props

Files.TypeOptions props
PropTypeDefault
group
"documents" | "spreadsheets" | "images" | "code" | "text" | "other"—
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/type-options.tsx

Files.TypeOptionaction · <button>

One file type as a choice that stays ticked: the first creates the type filter, and the last one unticked takes it off. The words (`PDF`, `Word document`) are the screen's, from the `mime` its function child is given; a type nobody named is shown as itself.

Required scope

Files.TypeOption must be inside <Files.TypeOptions>.

Files.TypeOption must be inside <Files.Filters>.

Props

2 documented props · Native <button> attributes supported

Files.TypeOption props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: TypeOptionState) => 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/type-option.tsx

Files.TypeEmptygate

No file type matches: what a menu of them says in place of its rows.

Props

1 documented props

Files.TypeEmpty 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/type-empty.tsx

Files.Sortingscope

The order the listing is drawn in, with the five keys a file browser sorts by: name, kind, date created, date modified and size. Apart from `Files.SortBy`, which asks the store for three of them one folder at a time: this one is the screen's, over every folder it has read, and is what `Files.Entries` and `Files.ChildEntries` follow when it is provided.

Props

2 documented props

Files.Sorting props
PropTypeDefault
initial
FileOrder—
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/sorting.tsx

Files.SortKeyaction · <button>

A key to sort by, as a column heading or a menu item. No `aria-sort`, for the reason `Files.SortBy` has none: it means something on a `columnheader` in a grid and nothing on a button. The direction is in `state`, so a pattern can put it in the button's name.

Required scope

Files.SortKey must be inside <Files.Sorting>.

Props

4 documented props · Native <button> attributes supported

Files.SortKey props
PropTypeDefault
byRequired
"name" | "kind" | "createdAt" | "updatedAt" | "size"—
mode

toggle, for a column heading: the same key again turns the order around. choose, for a menu item: the same key again changes nothing, and the order stays as it is.

"toggle" | "choose""toggle"
children

Content rendered inside this part.

ReactNode | ((state: { active: boolean; direction: "asc" | "desc" }) => 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/sort-key.tsx

Files.SortActivecontent · <span>

The key the listing is in the order of, for a menu's button to say: `Modified`, with the direction in `state` for a screen that shows an arrow. The word is the screen's; without one it is the key.

Required scope

Files.SortActive must be inside <Files.Sorting>.

Props

2 documented props · Native <span> attributes supported

Files.SortActive props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { key: FileSortKey; direction: FileSortDirection }) => 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/sort-active.tsx

Files.SortByaction · <button>

A column header that sorts. The same one twice turns the order around. No `aria-sort`: it means something on a `columnheader` inside a grid and nothing at all on a button, so a list of rows that is not a grid was telling assistive technology which way it was sorted through an attribute nothing reads. What replaces it is the direction in `state`, so the pattern can put the answer in the button's own accessible name — a word, which is the pattern's to choose. → https://www.w3.org/WAI/ARIA/apg/patterns/treegrid/

Required scope

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

Props

3 documented props · Native <button> attributes supported

Files.SortBy props
PropTypeDefault
byRequired
"name" | "updatedAt" | "size"—
children

Content rendered inside this part.

ReactNode | ((state: { active: boolean; direction: "asc" | "desc" }) => 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/sort-by.tsx

Files.DateRangescope

Two days being picked for a date filter: what a custom range dialog holds while it is open. It starts from the range the filter already has, so a pill that is pressed to change its range opens on it, and from nothing otherwise. Nothing leaves it until `Files.FilterRange` applies it, so closing the dialog changes nothing. Mount it inside the dialog's content: it is then new each time the dialog opens, and starts from whatever the filter says by then.

Required scope

Files.DateRange must be inside <Files.Filters>.

Props

2 documented props

Files.DateRange props
PropTypeDefault
dateRequired
Exclude<FileFilterType, "fileType">—
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/range-root.tsx

Files.FilterPresetaction · <button>

One date preset: `1 week ago` and the rest, as a choice. On a pill it changes that filter where it stands; in a menu, with a `date`, it starts the date filter of that kind, `after` the preset, in place of any there was.

Required scope

Files.FilterPreset must be inside <Files.Filters>.

Props

4 documented props · Native <button> attributes supported

Files.FilterPreset props
PropTypeDefault
presetRequired
DatePreset—
date

Which date to start filtering by, when this is in a menu and not on a pill.

Exclude<FileFilterType, "fileType">—
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/filter-preset.tsx

Files.FilterRangeaction · <button>

Applies a custom range of days to a date filter, from the start of the first to the end of the last. Inside a `Files.DateRange` it applies what that has picked, and is disabled until both ends are. Given `from` and `to` itself it applies those: what a dialog that keeps its own days (a calendar of another library) hands over.

Required scope

Files.FilterRange must be inside <Files.Filters>.

Props

5 documented props · Native <button> attributes supported

Files.FilterRange props
PropTypeDefault
date

Which date: dateModified or dateCreated. From the Files.DateRange it is inside, when it is inside one.

Exclude<FileFilterType, "fileType">—
from

What the dialog has picked so far, when it is not a Files.DateRange. The part is disabled until both ends are.

Date—
to
Date—
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/filter-range.tsx

Files.RangePresetaction · <button>

A shortcut for a range, `last-7-days` and the like: it fills both days, the calendar and the boxes.

Required scope

Files.RangePreset must be inside <Files.DateRange>.

Props

3 documented props · Native <button> attributes supported

Files.RangePreset props
PropTypeDefault
presetRequired
RangePreset—
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/range-preset.tsx

Files.RangeInputinput · <input>

One end of the range as a text box, `2026-01-08`: the same two days the calendar marks. A day typed that is not one yet stays as it was typed and moves nothing.

Required scope

Files.RangeInput must be inside <Files.DateRange>.

Props

3 documented props · Native <input> attributes supported

Files.RangeInput props
PropTypeDefault
endRequired
"from" | "to"—
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/range-input.tsx

Files.RangeStepaction · <button>

Moves the calendar a month back or on.

Required scope

Files.RangeStep must be inside <Files.DateRange>.

Props

3 documented props · Native <button> attributes supported

Files.RangeStep 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/range-step.tsx

Files.RangeMonthsscope

The months a calendar draws, two of them side by side, each in its own scope. Whether the second one fits is the screen's to say, with CSS: on a phone it is drawn and hidden.

Required scope

Files.RangeMonths must be inside <Files.DateRange>.

Props

1 documented props

Files.RangeMonths 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/range-months.tsx

Files.RangeMonthNamecontent · <div>

The month's name and year in the reader's own language, `June 2026`, unless a function child says it otherwise.

Required scope

Files.RangeMonthName must be inside <Files.RangeMonths>.

Props

2 documented props · Native <div> attributes supported

Files.RangeMonthName props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { month: Date; index: number }) => 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/range-month-name.tsx

Files.RangeDaysscope

Every day of the month in its scope, each with the weekday it falls on, for a grid to place.

Required scope

Files.RangeDays must be inside <Files.RangeMonths>.

Props

1 documented props

Files.RangeDays 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/range-days.tsx

Files.RangeDayaction · <button>

One day of the calendar, a button that picks it. `data-state` says where it is in the range: `from`, `to` (both, for a range of one day, is `from`), `within` or `none`. The first of the month sits in its weekday's column, so the rows of the grid line up with the names above them, `data-today` marks today, and `data-joined` an end of a range of more than one day.

Required scope

Files.RangeDay must be inside <Files.DateRange>.

Files.RangeDay must be inside <Files.RangeDays>.

Props

2 documented props · Native <button> attributes supported

Files.RangeDay 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/range-day.tsx

Files.Unmatchedgate

The folder holds entries and the filters leave none of them. Not `Files.Empty`, which is a folder with nothing in it: the remedy is different, to take a filter off and not to put something in. Never under a search, whose own empty answer is `Files.Empty` with `searched`.

Required scope

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

Props

1 documented props

Files.Unmatched props
PropTypeDefault
children

Content rendered inside this part.

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

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

Source: @slices.sh/file-storage/src/headless/unmatched.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.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

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 →