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

Headless / Collections

Select and edit records

Build selection & actions on your collection's schema, query and permissions.

32 public parts · 2examples

@slices.sh/collection/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

Collection.Root · Scope

Collection.RootThe root, and the parts that choose what is drawn under it: one of several views, the data a view needs, and one of two screens by width.

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/collection@^0.1.6

Import from @slices.sh/collection/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 collection.memory

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
  • Rows are lost when the server restarts, and live updates reach only watchers in the process that wrote. Move on with npx shadcn@latest add @slices/collection.mongodb (or -neon, -supabase): services/collection/*.config.ts and rules.ts are yours and stay.

Start small

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

example.tsx
"use client"import "@/services"import { Collection } from "@slices.sh/collection/headless"import type { CollectionSchema } from "@slices.sh/collection/services/types"export function Example({ schema }: { schema: CollectionSchema }) {  return (    <Collection.Root collection={schema.collection} schema={schema}>      <Collection.SelectAll>Select all</Collection.SelectAll>      <Collection.Row render={<div />}>        <Collection.SelectRow />        <Collection.Cell render={<span />}>          <Collection.Value />        </Collection.Cell>      </Collection.Row>      <Collection.WhenSelected>        <Collection.SelectionCount />        <Collection.ClearSelection>          Clear selection        </Collection.ClearSelection>      </Collection.WhenSelected>    </Collection.Root>  )}

Supply a registered collection schema. Parts use its fields, permissions and provider capabilities.

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.

Collection.SelectRowinput · <input>

Ticking a row or the rows on screen, the gate around what shows while something is selected, the count (null when everything matching is selected and the provider did not count) and letting go.

Required scope

Collection.SelectRow must be inside <Collection.Row>.

Collection.SelectRow must be inside <Collection.Root>.

Props

2 documented props · Native <input> attributes supported

Collection.SelectRow props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { checked: 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/collection/src/headless/select-row.tsx

Collection.SelectAllinput · <input>

Ticking a row or the rows on screen, the gate around what shows while something is selected, the count (null when everything matching is selected and the provider did not count) and letting go.

Required scope

Collection.SelectAll must be inside <Collection.Root>.

Props

2 documented props · Native <input> attributes supported

Collection.SelectAll props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: SelectAllState) => 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/collection/src/headless/select-all.tsx

Collection.WhenSelectedgate

While anything is selected, and how much. `matching` says the selection is the filter rather than a list of ids, and `count` is then the whole result — which is the number a bulk action is about to touch.

Required scope

Collection.WhenSelected must be inside <Collection.Root>.

Props

1 documented props

Collection.WhenSelected props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { count: number; matching: boolean }) => ReactNode)—

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

Source: @slices.sh/collection/src/headless/when-selected.tsx

Collection.BulkBarcontent · <div>

A toolbar that appears while records are selected, its buttons, turning the selection into the filter, and a delete that arms on the first press. SelectMatching renders nothing when the provider did not count or the page is already the whole result.

Capability: countMatching (SelectMatching)

Required scope

Collection.BulkBar requires Collection.Root.

Props

3 documented props · Native <div> attributes supported

Collection.BulkBar props
PropTypeDefault
toolbar

The animated toolbar the bar renders into; its frame places it (a bar floating over a list).

ReactElement<ToolbarProps>—
children

Content rendered inside this part.

ReactNode | ((state: { count: number; matching: 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/collection/src/headless/bulk-bar.tsx

Collection.SelectionCountcontent · <span>

Ticking a row or the rows on screen, the gate around what shows while something is selected, the count (null when everything matching is selected and the provider did not count) and letting go.

Required scope

Collection.PaletteCount requires Collection.Root.

Props

2 documented props · Native <span> attributes supported

Collection.SelectionCount props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { count: number | null; matching: 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/collection/src/headless/palette-count.tsx

Collection.SelectMatchingaction · <button>

"Select all 312" — the selection stops being a list of ids and becomes the filter itself. Without it, bulk work over a filter is unreachable: ticking two hundred of three hundred rows is two hundred clicks, and `removeMany(filter)` and `updateMany(filter, patch)` sit in the contract with no way to ask for them. With it, "delete selected" is one statement. Away when the backend did not count the rows — "all of them" with no number is not an offer anybody can judge — and away once the whole page is already the whole result, or when the selection is already the filter. → docs/rules/capability-honesty.md

Capability: countMatching (SelectMatching)

Required scope

Collection.SelectMatching must be inside <Collection.Root>.

Props

2 documented props · Native <button> attributes supported

Collection.SelectMatching props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { count: 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/collection/src/headless/select-matching.tsx

Collection.BulkActionaction · <button>

A toolbar that appears while records are selected, its buttons, turning the selection into the filter, and a delete that arms on the first press. SelectMatching renders nothing when the provider did not count or the page is already the whole result.

Capability: countMatching (SelectMatching)

Props

2 documented props · Native <button> attributes supported

Collection.BulkAction 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/collection/src/headless/bulk-action.tsx

Collection.DeleteSelectedaction · <button>

Deletes what is ticked — and asks first. Two presses rather than a dialog: one click and gone was the whole of the safety here, and a modal is the wrong shape on a phone. `armed` is the question, so a skin restyles it and a copy dictionary asks it in its own words; the question goes away when focus leaves the button or the selection changes under it, because a button left asking is a trap. What it is asking *about* is the selection itself, rather than a flag plus an effect to clear it: a question about these three rows is not an answer about those three, so the moment the selection moves the button is no longer armed, with no render spent noticing. In `matching` mode this is one statement over the filter rather than a list of ids, so "delete all 312" never has to read page two.

Capability: countMatching (SelectMatching)

Required scope

Collection.DeleteSelected must be inside <Collection.Root>.

Props

2 documented props · Native <button> attributes supported

Collection.DeleteSelected props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { pending: boolean; count: number; armed: 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/collection/src/headless/delete-selected.tsx

Collection.ClearSelectionaction · <button>

Ticking a row or the rows on screen, the gate around what shows while something is selected, the count (null when everything matching is selected and the provider did not count) and letting go.

Required scope

Collection.ClearSelection requires Collection.Root.

Props

2 documented props · Native <button> attributes supported

Collection.ClearSelection 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/collection/src/headless/clear-selection.tsx

Collection.RowMenucontent · <div>

One popup per collection, anchored by the selected row's native detached trigger.

Required scope

Collection.RowMenu requires Collection.Root.

Props

3 documented props · Native <div> attributes supported

Collection.RowMenu props
PropTypeDefault
popup

The menu popup and its positioner, which the pattern styles.

ReactElement<ComponentProps<typeof MotionMenu>>—
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/collection/src/headless/row-menu.tsx

Collection.RowMenuTriggeraction · <button>

One menu per root, rendered outside the rows, opened from a trigger inside a row and scoped to that row; its items, and deleting the row.

Required scope

Collection.RowMenuTrigger requires Collection.Row.

Collection.RowMenuTrigger requires Collection.Root.

Props

2 documented props · Native <button> attributes supported

Collection.RowMenuTrigger 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/collection/src/headless/row-menu-trigger.tsx

Collection.RowMenuItemaction · <button>

One menu per root, rendered outside the rows, opened from a trigger inside a row and scoped to that row; its items, and deleting the row.

Props

2 documented props · Native <button> attributes supported

Collection.RowMenuItem 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/collection/src/headless/row-menu-item.tsx

Collection.DeleteRowaction · <button>

One menu per root, rendered outside the rows, opened from a trigger inside a row and scoped to that row; its items, and deleting the row.

Required scope

Collection.DeleteRow must be inside <Collection.Row>.

Collection.DeleteRow must be inside <Collection.Root>.

Props

2 documented props · Native <button> attributes supported

Collection.DeleteRow 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/collection/src/headless/delete-row.tsx

Collection.PaletteTriggeraction · <button>

A searchable dialog of field and value commands over the selection, written with one bulk update. WhenPalette renders nothing when the root has no palette or the provider cannot update many records at once.

Capability: bulkUpdate

Required scope

Collection.PaletteTrigger requires Collection.Root.

Props

2 documented props · Native <button> attributes supported

Collection.PaletteTrigger 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/collection/src/headless/palette-trigger.tsx

Collection.Palettescope

A searchable dialog of field and value commands over the selection, written with one bulk update. WhenPalette renders nothing when the root has no palette or the provider cannot update many records at once.

Capability: bulkUpdate

Required scope

Collection.Palette requires Collection.Root.

Props

4 documented props

Collection.Palette props
PropTypeDefault
labelRequired
string—
commandLabelRequired
BulkCommandLabel—
popup

The dialog the commands open in, which the pattern styles.

ReactElement<ComponentProps<typeof MotionDialog>>—
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/collection/src/headless/palette.tsx

Collection.WhenPalettegate

A searchable dialog of field and value commands over the selection, written with one bulk update. WhenPalette renders nothing when the root has no palette or the provider cannot update many records at once.

Capability: bulkUpdate

Required scope

Collection.WhenPalette requires Collection.Root.

Props

1 documented props

Collection.WhenPalette 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/collection/src/headless/when-palette.tsx

Collection.PaletteCountcontent · <span>

A searchable dialog of field and value commands over the selection, written with one bulk update. WhenPalette renders nothing when the root has no palette or the provider cannot update many records at once.

Capability: bulkUpdate

Required scope

Collection.PaletteCount requires Collection.Root.

Props

2 documented props · Native <span> attributes supported

Collection.PaletteCount props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { count: number | null; matching: 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/collection/src/headless/palette-count.tsx

Collection.PaletteCloseaction · <button>

A searchable dialog of field and value commands over the selection, written with one bulk update. WhenPalette renders nothing when the root has no palette or the provider cannot update many records at once.

Capability: bulkUpdate

Props

2 documented props · Native <button> attributes supported

Collection.PaletteClose 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/collection/src/headless/palette-close.tsx

Collection.PaletteSearchinput · <input>

A searchable dialog of field and value commands over the selection, written with one bulk update. WhenPalette renders nothing when the root has no palette or the provider cannot update many records at once.

Capability: bulkUpdate

Required scope

Collection.PaletteSearch requires Collection.Palette.

Props

2 documented props · Native <input> attributes supported

Collection.PaletteSearch 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/collection/src/headless/palette-search.tsx

Collection.PaletteItemscontent · <div>

A searchable dialog of field and value commands over the selection, written with one bulk update. WhenPalette renders nothing when the root has no palette or the provider cannot update many records at once.

Capability: bulkUpdate

Required scope

Collection.PaletteItems requires Collection.Palette.

Collection.PaletteItems requires Collection.Root.

Props

2 documented props · Native <div> attributes supported

Collection.PaletteItems props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { label: string; 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/collection/src/headless/palette-items.tsx

Collection.PaletteEmptycontent · <div>

A searchable dialog of field and value commands over the selection, written with one bulk update. WhenPalette renders nothing when the root has no palette or the provider cannot update many records at once.

Capability: bulkUpdate

Props

2 documented props · Native <div> attributes supported

Collection.PaletteEmpty 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/collection/src/headless/palette-empty.tsx

Collection.PaletteErrorcontent · <p>

A searchable dialog of field and value commands over the selection, written with one bulk update. WhenPalette renders nothing when the root has no palette or the provider cannot update many records at once.

Capability: bulkUpdate

Required scope

Collection.PaletteError requires Collection.Palette.

Props

2 documented props · Native <p> attributes supported

Collection.PaletteError props
PropTypeDefault
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/collection/src/headless/palette-error.tsx

Collection.ShortcutsTriggeraction · <button>

A modal sheet of the shortcuts this root answers to, also opened with ?, and its visible trigger.

Required scope

Collection.ShortcutsTrigger requires Collection.Root.

Props

2 documented props · Native <button> attributes supported

Collection.ShortcutsTrigger 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/collection/src/headless/shortcuts-trigger.tsx

Collection.Shortcutsscope

A modal sheet of the shortcuts this root answers to, also opened with ?, and its visible trigger.

Required scope

Collection.Shortcuts requires Collection.Root.

Props

11 documented props

Collection.Shortcuts props
PropTypeDefault
reparent
boolean—
palette
boolean—
selection
boolean—
search
boolean—
rowActions
boolean—
openRecord
boolean—
layout
"linear" | "grid" | "board" | "tree"—
titleRequired
string—
labels
Partial<Record<RowCommand, string>>—
popup

The dialog the shortcuts open in, which the pattern styles.

ComponentProps<typeof KeymapSheet>["popup"]—
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/collection/src/headless/shortcuts.tsx

Collection.BulkDelete.Rootscope

The root, the trigger that opens a native alert dialog, and the popup.

Required scope

BulkDelete.Root requires Collection.Root.

Props

1 documented props

Collection.BulkDelete.Root props
PropTypeDefault
children

Content rendered inside this part.

ReactNode—

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

Alternate public imports
  • BulkDelete.Root from @slices.sh/collection/headless/bulk-delete

Source: @slices.sh/collection/src/headless/bulk-delete/root.tsx

Collection.BulkDelete.Triggeraction · <button>

The root, the trigger that opens a native alert dialog, and the popup.

Required scope

BulkDelete.Trigger requires Collection.Root.

BulkDelete.Trigger requires BulkDelete.Root.

Props

2 documented props · Native <button> attributes supported

Collection.BulkDelete.Trigger 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.

Alternate public imports
  • BulkDelete.Trigger from @slices.sh/collection/headless/bulk-delete

Source: @slices.sh/collection/src/headless/bulk-delete/trigger.tsx

Collection.BulkDelete.Popupcontent · <div>

The root, the trigger that opens a native alert dialog, and the popup.

Required scope

BulkDelete.Popup requires BulkDelete.Root.

BulkDelete.Popup requires Collection.Root.

Props

3 documented props · Native <div> attributes supported

Collection.BulkDelete.Popup props
PropTypeDefault
popup

The alert dialog, its backdrop and the viewport that places it, which the pattern styles.

ReactElement<ComponentProps<typeof MotionAlertDialog>>—
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.

Alternate public imports
  • BulkDelete.Popup from @slices.sh/collection/headless/bulk-delete

Source: @slices.sh/collection/src/headless/bulk-delete/popup.tsx

Collection.BulkDelete.Titlecontent · <h2>

Title and description, given { count, matching } so they can name the scope. count is null when everything matching is selected and the provider did not count.

Required scope

BulkDelete.Title requires BulkDelete.Root.

Props

2 documented props · Native <h2> attributes supported

Collection.BulkDelete.Title props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { count: number | null; matching: 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.

Alternate public imports
  • BulkDelete.Title from @slices.sh/collection/headless/bulk-delete

Source: @slices.sh/collection/src/headless/bulk-delete/title.tsx

Collection.BulkDelete.Descriptioncontent · <p>

Title and description, given { count, matching } so they can name the scope. count is null when everything matching is selected and the provider did not count.

Required scope

BulkDelete.Description requires BulkDelete.Root.

Props

2 documented props · Native <p> attributes supported

Collection.BulkDelete.Description props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { count: number | null; matching: 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.

Alternate public imports
  • BulkDelete.Description from @slices.sh/collection/headless/bulk-delete

Source: @slices.sh/collection/src/headless/bulk-delete/description.tsx

Collection.BulkDelete.Cancelaction · <button>

Cancel (the first focus), Confirm with { count, pending }, and the refusal, which stays in the dialog.

Capability: bulkDelete

Required scope

BulkDelete.Cancel requires BulkDelete.Root.

Props

2 documented props · Native <button> attributes supported

Collection.BulkDelete.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.

Alternate public imports
  • BulkDelete.Cancel from @slices.sh/collection/headless/bulk-delete

Source: @slices.sh/collection/src/headless/bulk-delete/cancel.tsx

Collection.BulkDelete.Confirmaction · <button>

Cancel (the first focus), Confirm with { count, pending }, and the refusal, which stays in the dialog.

Capability: bulkDelete

Required scope

BulkDelete.Confirm requires BulkDelete.Root.

BulkDelete.Confirm requires Collection.Root.

Props

2 documented props · Native <button> attributes supported

Collection.BulkDelete.Confirm props
PropTypeDefault
children

Content rendered inside this part.

ReactNode | ((state: { count: number | null; 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.

Alternate public imports
  • BulkDelete.Confirm from @slices.sh/collection/headless/bulk-delete

Source: @slices.sh/collection/src/headless/bulk-delete/confirm.tsx

Collection.BulkDelete.Errorcontent · <p>

Cancel (the first focus), Confirm with { count, pending }, and the refusal, which stays in the dialog.

Capability: bulkDelete

Required scope

BulkDelete.Error requires BulkDelete.Root.

Props

2 documented props · Native <p> attributes supported

Collection.BulkDelete.Error props
PropTypeDefault
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.

Alternate public imports
  • BulkDelete.Error from @slices.sh/collection/headless/bulk-delete

Source: @slices.sh/collection/src/headless/bulk-delete/error.tsx

Collection.Rootscope

The root, and the parts that choose what is drawn under it: one of several views, the data a view needs, and one of two screens by width.

Props

25 documented props

Collection.Root props
PropTypeDefault
treeParent
string—
view
"table" | "list" | "grid" | "board" | "tree" | "detail"—
views
readonly CollectionViewValue[]—
cardSize
"small" | "medium" | "large"—
savedViews
readonly SavedView[]—
onSaveView
(view: SavedView) => void | Promise<void>—
groupBy
string | null—
onGroupByChange
(field: string | null) => void—
enabled

Left out or true: required, and a missing service throws. "optional": renders its children with no rows, and every part inside renders nothing. false: off. A capability name ("live") requires the service and that capability.

Enabled—
config

The collection config, "default" when left out. collection names one inside it.

string—
groupSumFields
readonly string[]—
cardSizing
booleanfalse
lanes
booleanfalse
collectionRequired
string—
schemaRequired
CollectionSchema—
density
"compact" | "comfortable" | "spacious"—
onDensityChange
(density: DensityValue) => void—
palette
booleanfalse
pageSize
number10
infinite
booleanfalse
live
booleanfalse
urlState

Whether the search, the sort and the filter travel in the address bar.

booleantrue
search

false when nothing on screen searches: no search applies, from the address or a saved view.

booleantrue
filters

false when nothing on screen filters: no filter applies, from the address or a saved view.

booleantrue
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/collection/src/headless/root.tsx

Collection.Viewgate

The root, and the parts that choose what is drawn under it: one of several views, the data a view needs, and one of two screens by width.

Required scope

Collection.View requires Collection.Root.

Props

2 documented props

Collection.View props
PropTypeDefault
nameRequired
CollectionViewValue | readonly CollectionViewValue[]—
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/collection/src/headless/view.tsx

Collection.Gridcontent · <table>

Row focus is the default. Cell mode preserves the existing APG grid keyboard.

Props

4 documented props · Native <table> attributes supported

Collection.Grid props
PropTypeDefault
focus
"row" | "cell""row"
selectable
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/collection/src/headless/grid.tsx

Collection.Rowcontent · <tr>

The row surface of a list, grid or board, the row repeated per record, the cell repeated per field (all, primary, media or details, or one field by name) and the value formatted by field type. Value renders nothing when the field is empty.

Required scope

Collection.Row must be inside <Collection.Root>.

Collection.Row requires Collection.Root.

Props

3 documented props · Native <tr> attributes supported

Collection.Row props
PropTypeDefault
openOnClick
booleanfalse
children

Content rendered inside this part.

ReactNode | ((state: { selected: boolean; dragging: 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/collection/src/headless/row.tsx

When something is missing

No service configuration
Install the collection 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 →