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

Headless / Files & documents

Change your avatar

Pick a photo, crop it in a dialog, and store the result in a bucket. The crop, the transforms, the background fill and the filters are local work from image-crop, a client-only service; storing the result is file-storage's, which is why these parts ship with it. The picture's URL comes back through onChange, so the same parts serve a user's avatar, an organization's logo, or any square image.

32 public parts · 2examples

@slices.sh/file-storage/headless/avatarView 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

Avatar.Root · Scope

Avatar.RootImage is <img alt=""> with src locked to the current picture: the stored one, the local one, or the initial URL. Empty renders its children while there is no picture, for a placeholder icon.

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/avatar.

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"// services/index.ts comes from https://slices.sh/r/services.json (or any provider setup)import "@/services"import { Avatar } from "@slices.sh/file-storage/headless/avatar"export function Example({ onChange }: { onChange: (url: string) => void }) {  return (    <Avatar.Root onChange={onChange}>      <Avatar.DropZone>        <Avatar.Image />        <Avatar.Picker aria-label="Choose a photo" />      </Avatar.DropZone>      <Avatar.Content>        <Avatar.Crop shape="circle">          <Avatar.CropForm>            <Avatar.Viewport>              <Avatar.SourceImage />              <Avatar.Selection />            </Avatar.Viewport>            <Avatar.Apply>Use photo</Avatar.Apply>          </Avatar.CropForm>        </Avatar.Crop>      </Avatar.Content>    </Avatar.Root>  )}

onChange receives the stored image URL. Save it to your profile in your application handler.

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.

Avatar.Rootscope

Image is <img alt=""> with src locked to the current picture: the stored one, the local one, or the initial URL. Empty renders its children while there is no picture, for a placeholder icon.

Props

6 documented props

Avatar.Root props
PropTypeDefault
config

The file-storage config, a slug from the registry. The nearest root's, else "default", when left out.

string—
enabled

Left out or true: required, and a missing service throws. "optional": the picture is still picked, cropped and previewed, and kept for this page session; only what needs the store (Progress, the upload) renders nothing. false is the same, even with a store installed. A capability name requires the service with it.

Enabled—
bucket
string—
initialUrl
string—
value
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/avatar/root.tsx

Avatar.Emptygate

Image is <img alt=""> with src locked to the current picture: the stored one, the local one, or the initial URL. Empty renders its children while there is no picture, for a placeholder icon.

Required scope

Avatar.Empty requires Avatar.Root.

Props

1 documented props

Avatar.Empty 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/avatar/empty.tsx

Avatar.DropZonecontent · <label>

DropZone is a <label> that takes a dropped or pasted image as well as a click. Picker is the file input inside it, accepting JPEG, PNG and WebP, and disabled while an upload runs. Hint's function child gets { limit }, the size the cropper enforces, so the words never drift from it.

Required scope

Avatar.DropZone requires Avatar.Root.

Props

2 documented props · Native <label> attributes supported

Avatar.DropZone 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/avatar/drop-zone.tsx

Avatar.Pickerinput · <input>

DropZone is a <label> that takes a dropped or pasted image as well as a click. Picker is the file input inside it, accepting JPEG, PNG and WebP, and disabled while an upload runs. Hint's function child gets { limit }, the size the cropper enforces, so the words never drift from it.

Required scope

Avatar.Picker requires Avatar.Root.

Props

2 documented props · Native <input> attributes supported

Avatar.Picker 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/avatar/picker.tsx

Avatar.Hintcontent · <span>

The picker's hint. Its function child receives the size limit the cropper enforces, so the words never drift from it.

Props

2 documented props · Native <span> attributes supported

Avatar.Hint props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { limit: 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/avatar/hint.tsx

Avatar.Contentcontent · <div>

Content is the dialog, open while a source is chosen; Title and Description label it. Crop is the crop primitive, with shape ("circle" | "square"), minZoom and maxZoom, and remounts for each new source so nothing leaks from the last photo. CropForm submits on Enter and handles the keyboard: arrows nudge, + and - zoom, R rotates, 0 resets. Viewport takes the photo's own proportions and paints the chosen fill behind it. SourceImage is the photo, Selection the draggable frame, and Grid a guide on one axis, shown only while panning.

Required scope

Avatar.Content requires Avatar.Root.

Props

2 documented props · Native <div> attributes supported

Avatar.Content 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/avatar/content.tsx

Avatar.Titlecontent · <h2>

Content is the dialog, open while a source is chosen; Title and Description label it. Crop is the crop primitive, with shape ("circle" | "square"), minZoom and maxZoom, and remounts for each new source so nothing leaks from the last photo. CropForm submits on Enter and handles the keyboard: arrows nudge, + and - zoom, R rotates, 0 resets. Viewport takes the photo's own proportions and paints the chosen fill behind it. SourceImage is the photo, Selection the draggable frame, and Grid a guide on one axis, shown only while panning.

Props

2 documented props · Native <h2> attributes supported

Avatar.Title 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/avatar/title.tsx

Avatar.Descriptioncontent · <p>

Content is the dialog, open while a source is chosen; Title and Description label it. Crop is the crop primitive, with shape ("circle" | "square"), minZoom and maxZoom, and remounts for each new source so nothing leaks from the last photo. CropForm submits on Enter and handles the keyboard: arrows nudge, + and - zoom, R rotates, 0 resets. Viewport takes the photo's own proportions and paints the chosen fill behind it. SourceImage is the photo, Selection the draggable frame, and Grid a guide on one axis, shown only while panning.

Props

2 documented props · Native <p> attributes supported

Avatar.Description 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/avatar/description.tsx

Avatar.Cropcontent · <div>

A changed source remounts the primitive so crop, zoom, fill, filter and transforms cannot leak to the next photo.

Required scope

Avatar.Crop requires Avatar.Root.

Props

5 documented props · Native <div> attributes supported

Avatar.Crop props
PropTypeDefault
shape
CropShape"circle"
minZoom
number—
maxZoom
number—
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/avatar/crop.tsx

Avatar.CropFormaction · <form>

Content is the dialog, open while a source is chosen; Title and Description label it. Crop is the crop primitive, with shape ("circle" | "square"), minZoom and maxZoom, and remounts for each new source so nothing leaks from the last photo. CropForm submits on Enter and handles the keyboard: arrows nudge, + and - zoom, R rotates, 0 resets. Viewport takes the photo's own proportions and paints the chosen fill behind it. SourceImage is the photo, Selection the draggable frame, and Grid a guide on one axis, shown only while panning.

Required scope

Avatar.CropForm requires Avatar.Crop.

Avatar.CropForm requires Avatar.Root.

Props

2 documented props · Native <form> attributes supported

Avatar.CropForm 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/avatar/crop-form.tsx

Avatar.Viewportcontent · <div>

The primitive pans and exports as if the photo exactly fills this box, so the box takes the photo's own proportions. In a square box a wide photo showed past the crop but could not be dragged there, and its edges were out of reach at every zoom. Until the photo has a size the box has no height, so the primitive first measures it at its final shape and centres the crop. A chosen background fill is painted here, behind the photo, which is where the export puts it.

Required scope

Avatar.Viewport requires Avatar.Crop.

Props

2 documented props · Native <div> attributes supported

Avatar.Viewport 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/avatar/viewport.tsx

Avatar.SourceImagecontent · <img>

Content is the dialog, open while a source is chosen; Title and Description label it. Crop is the crop primitive, with shape ("circle" | "square"), minZoom and maxZoom, and remounts for each new source so nothing leaks from the last photo. CropForm submits on Enter and handles the keyboard: arrows nudge, + and - zoom, R rotates, 0 resets. Viewport takes the photo's own proportions and paints the chosen fill behind it. SourceImage is the photo, Selection the draggable frame, and Grid a guide on one axis, shown only while panning.

Required scope

Avatar.SourceImage requires Avatar.Crop.

Avatar.SourceImage requires Avatar.Root.

Props

2 documented props · Native <img> attributes supported

Avatar.SourceImage 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/avatar/source-image.tsx

Avatar.Selectioncontent · <div>

Content is the dialog, open while a source is chosen; Title and Description label it. Crop is the crop primitive, with shape ("circle" | "square"), minZoom and maxZoom, and remounts for each new source so nothing leaks from the last photo. CropForm submits on Enter and handles the keyboard: arrows nudge, + and - zoom, R rotates, 0 resets. Viewport takes the photo's own proportions and paints the chosen fill behind it. SourceImage is the photo, Selection the draggable frame, and Grid a guide on one axis, shown only while panning.

Required scope

Avatar.Selection requires Avatar.Crop.

Props

2 documented props · Native <div> attributes supported

Avatar.Selection 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/avatar/selection.tsx

Avatar.Gridcontent · <div>

Content is the dialog, open while a source is chosen; Title and Description label it. Crop is the crop primitive, with shape ("circle" | "square"), minZoom and maxZoom, and remounts for each new source so nothing leaks from the last photo. CropForm submits on Enter and handles the keyboard: arrows nudge, + and - zoom, R rotates, 0 resets. Viewport takes the photo's own proportions and paints the chosen fill behind it. SourceImage is the photo, Selection the draggable frame, and Grid a guide on one axis, shown only while panning.

Required scope

Avatar.Grid requires Avatar.Crop.

Props

3 documented props · Native <div> attributes supported

Avatar.Grid props
PropTypeDefault
axisRequired
"horizontal" | "vertical"—
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/avatar/grid.tsx

Avatar.Previewcontent · <canvas>

Fill is one background choice with aria-pressed locked; without color it keeps the photo's transparency. Filter is one filter choice (value) and FilterImage shows the photo through it. Preview is a canvas at a given resolution that draws what Apply would store, fill and filter included.

Required scope

Avatar.Preview requires Avatar.Crop.

Avatar.Preview requires Avatar.Root.

Props

3 documented props · Native <canvas> attributes supported

Avatar.Preview props
PropTypeDefault
resolution
24 | 40 | 7272
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/avatar/preview.tsx

Avatar.Zoominput · <input>

Zoom is a range input with min, max, step and value locked to the crop. Rotate turns by 90 degrees, Flip mirrors horizontally, Reset returns to the first framing.

Required scope

Avatar.Zoom requires Avatar.Crop.

Props

2 documented props · Native <input> attributes supported

Avatar.Zoom 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/avatar/zoom.tsx

Avatar.Rotateaction · <button>

Zoom is a range input with min, max, step and value locked to the crop. Rotate turns by 90 degrees, Flip mirrors horizontally, Reset returns to the first framing.

Required scope

Avatar.Rotate requires Avatar.Crop.

Props

2 documented props · Native <button> attributes supported

Avatar.Rotate 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/avatar/rotate.tsx

Avatar.Flipaction · <button>

Zoom is a range input with min, max, step and value locked to the crop. Rotate turns by 90 degrees, Flip mirrors horizontally, Reset returns to the first framing.

Required scope

Avatar.Flip requires Avatar.Crop.

Props

2 documented props · Native <button> attributes supported

Avatar.Flip 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/avatar/flip.tsx

Avatar.Fillaction · <button>

One background choice. Without a `color` it is the photo's own transparency.

Required scope

Avatar.Fill requires Avatar.Crop.

Props

3 documented props · Native <button> attributes supported

Avatar.Fill props
PropTypeDefault
color
string—
children

Content rendered inside this part.

ReactNode | ((state: { active: 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/avatar/fill.tsx

Avatar.Resetaction · <button>

Zoom is a range input with min, max, step and value locked to the crop. Rotate turns by 90 degrees, Flip mirrors horizontally, Reset returns to the first framing.

Required scope

Avatar.Reset requires Avatar.Crop.

Props

2 documented props · Native <button> attributes supported

Avatar.Reset 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/avatar/reset.tsx

Avatar.Filteraction · <button>

One filter choice; `Avatar.FilterImage` inside it shows the photo with that filter.

Required scope

Avatar.Filter requires Avatar.Crop.

Props

3 documented props · Native <button> attributes supported

Avatar.Filter props
PropTypeDefault
valueRequired
AvatarFilter—
children

Content rendered inside this part.

ReactNode | ((state: { active: 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/avatar/filter-option.tsx

Avatar.FilterImagecontent · <img>

Fill is one background choice with aria-pressed locked; without color it keeps the photo's transparency. Filter is one filter choice (value) and FilterImage shows the photo through it. Preview is a canvas at a given resolution that draws what Apply would store, fill and filter included.

Required scope

Avatar.FilterImage requires Avatar.Root.

Avatar.FilterImage requires Avatar.Filter.

Props

2 documented props · Native <img> attributes supported

Avatar.FilterImage 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/avatar/filter-image.tsx

Avatar.Cancelaction · <button>

Apply is the crop form's submit, with { pending } while the export runs, disabled until the photo has a size. Cancel closes the dialog and drops the source.

Required scope

Avatar.Cancel requires Avatar.Root.

Props

2 documented props · Native <button> attributes supported

Avatar.Cancel 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/avatar/cancel.tsx

Avatar.Applyaction · <button>

Apply is the crop form's submit, with { pending } while the export runs, disabled until the photo has a size. Cancel closes the dialog and drops the source.

Required scope

Avatar.Apply requires Avatar.Crop.

Avatar.Apply requires Avatar.Root.

Props

2 documented props · Native <button> attributes supported

Avatar.Apply props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { pending: 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/avatar/apply.tsx

Avatar.Imagecontent · <img>

Image is <img alt=""> with src locked to the current picture: the stored one, the local one, or the initial URL. Empty renders its children while there is no picture, for a placeholder icon.

Required scope

Avatar.Image requires Avatar.Root.

Props

2 documented props · Native <img> attributes supported

Avatar.Image 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/avatar/image.tsx

Avatar.Savedgate

After Apply. Progress is a progressbar while the upload runs. Saved opens once the picture is stored. Retry sends a failed upload again; Undo restores the picture from before, or discards a local one. Feedback is <p role="alert"> with { message } for a refused file or upload; with crop it reports the crop's own errors instead. Local opens when the picture is kept in the page session because no storage is configured. MissingConfiguration is Configuration.Missing pinned to scope="file-storage", learned when a save meets a server that lacks its configuration.

Required scope

Avatar.Saved requires Avatar.Root.

Props

1 documented props

Avatar.Saved 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/avatar/saved.tsx

Avatar.Undoaction · <button>

After Apply. Progress is a progressbar while the upload runs. Saved opens once the picture is stored. Retry sends a failed upload again; Undo restores the picture from before, or discards a local one. Feedback is <p role="alert"> with { message } for a refused file or upload; with crop it reports the crop's own errors instead. Local opens when the picture is kept in the page session because no storage is configured. MissingConfiguration is Configuration.Missing pinned to scope="file-storage", learned when a save meets a server that lacks its configuration.

Required scope

Avatar.Undo requires Avatar.Root.

Props

2 documented props · Native <button> attributes supported

Avatar.Undo 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/avatar/undo.tsx

Avatar.Localgate

After Apply. Progress is a progressbar while the upload runs. Saved opens once the picture is stored. Retry sends a failed upload again; Undo restores the picture from before, or discards a local one. Feedback is <p role="alert"> with { message } for a refused file or upload; with crop it reports the crop's own errors instead. Local opens when the picture is kept in the page session because no storage is configured. MissingConfiguration is Configuration.Missing pinned to scope="file-storage", learned when a save meets a server that lacks its configuration.

Required scope

Avatar.Local requires Avatar.Root.

Props

1 documented props

Avatar.Local 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/avatar/local.tsx

Avatar.Progresscontent · <div>

After Apply. Progress is a progressbar while the upload runs. Saved opens once the picture is stored. Retry sends a failed upload again; Undo restores the picture from before, or discards a local one. Feedback is <p role="alert"> with { message } for a refused file or upload; with crop it reports the crop's own errors instead. Local opens when the picture is kept in the page session because no storage is configured. MissingConfiguration is Configuration.Missing pinned to scope="file-storage", learned when a save meets a server that lacks its configuration.

Required scope

Avatar.Progress requires Avatar.Root.

Props

2 documented props · Native <div> attributes supported

Avatar.Progress 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/avatar/progress.tsx

Avatar.Feedbackcontent · <p>

After Apply. Progress is a progressbar while the upload runs. Saved opens once the picture is stored. Retry sends a failed upload again; Undo restores the picture from before, or discards a local one. Feedback is <p role="alert"> with { message } for a refused file or upload; with crop it reports the crop's own errors instead. Local opens when the picture is kept in the page session because no storage is configured. MissingConfiguration is Configuration.Missing pinned to scope="file-storage", learned when a save meets a server that lacks its configuration.

Required scope

Avatar.Feedback requires Avatar.Root.

Props

3 documented props · Native <p> attributes supported

Avatar.Feedback props
PropTypeDefault
crop
booleanfalse
children

Content rendered inside this part.

ReactNode | ((state: { message: 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/avatar/feedback.tsx

Avatar.Retryaction · <button>

After Apply. Progress is a progressbar while the upload runs. Saved opens once the picture is stored. Retry sends a failed upload again; Undo restores the picture from before, or discards a local one. Feedback is <p role="alert"> with { message } for a refused file or upload; with crop it reports the crop's own errors instead. Local opens when the picture is kept in the page session because no storage is configured. MissingConfiguration is Configuration.Missing pinned to scope="file-storage", learned when a save meets a server that lacks its configuration.

Required scope

Avatar.Retry requires Avatar.Root.

Props

2 documented props · Native <button> attributes supported

Avatar.Retry 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/avatar/retry.tsx

Avatar.MissingConfigurationgate

The server this avatar is stored on answered that it lacks configuration. Saving is the one request an avatar makes, so this is learned when somebody applies a crop, and not before: nothing is drawn for a deployment that has not said so. → docs/rules/missing-configuration-is-said.md

Props

1 documented props

Avatar.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/avatar/missing-configuration.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 →