Skip to main content

Box components

Boxes are the layout of a view. Everything between the view's title and its toolbar is a tree of boxes, and the backend decides its shape — which is why arranging a form is a backend change, not a frontend one.

SchemaBox receives one node of that tree and asks the box provider which container renders it. The pages below document the containers it can pick.

ComponenttypeRenders
SchemaSimpleBoxsimpleA labelled stack of fields — also the fallback for an unknown type
SchemaTabBoxtabTabbed sections, with the open tab kept in the URL
SchemaWizardBoxwizardA stepped form that validates each step before advancing
SchemaGridBoxgrid / grid-itemA responsive 12-column grid
SchemaListBoxlistAn embedded list of a related resource
SchemaArrayBoxarrayA repeatable group of fields; an array with array.listed renders as SchemaChoicesArrayBox — one checkbox row per enum value
SchemaObjectBoxobjectThe properties of a nested object
SchemaGalleryBoxgalleryAn image grid built from a related resource

Two more pages cover what the containers are built from:

PageWhat it covers
SchemaBoxThe dispatcher every box goes through, and conditional rendering
Layout primitivesPanel, PanelGrid and Section — the schema-free containers underneath

Common schema fields​

Every box type reads these from its BoxSchema, whatever the type:

FieldTypeDescription
namestringIdentifies the box; tab and wizard state is keyed by the path of names
labelstringSection heading. On its own it turns the card frame on; together with card: false it renders as a plain heading — see Card frame
cardboolean | nullThree-state card frame — see Card frame
collapsible'open' | 'closed'Makes the box collapsible and sets its initial state
boxesBoxItem[]Children: nested boxes, field descriptors, or both
readOnlybooleanRenders every field inside as a display field
toolbarActionsActionDescriptor[]Buttons in the box header, next to the label
bottomActionsActionDescriptor[]Buttons below the box's fields, e.g. a section-level save
options.dynamicRenderDynamicRenderOptionsshowQuery / requiredQuery — see SchemaBox

Card frame​

card has three states, and an absent key means the same as null:

ValueBehaviour
trueAlways renders the card (Panel)
falseNever renders the card (Section), even with a label or toolbar actions — the label becomes a plain section heading over the page background
null / absentThe component decides

Left unset, the card comes from the box's own signals: a simple or grid box takes it from a label, toolbarActions or collapsible; the collection boxes (list, array, object, gallery) take it from the label alone. On top of that, the view's first box gets the card by default on a page, so page content never floats on the background.

That default is handed down through layout. A first box that holds no fields of its own — a grid, a tab or a wizard, a bare simple wrapper — draws no card and passes the default to its children, so the card lands on the first box that actually holds content. A tab box and a wizard never hold fields (field children are filtered out), so they always pass it on — unless the schema asks them for a card, which they then draw like any other box, with the tab strip or stepper, its toolbar and the footer inside it. A box that draws a card for any other reason (a label, card: true) is that surface, and the hand-down stops there.

A "page" here means there is no card above the box. Every surface that is a card says so through InsidePanelContext: Panel does it for each box and each dashboard widget, and ViewDialog / ViewSidePanel declare it for their own overlay surface. A view rendered on any of them — a dialog, the docked side panel, or a widget — therefore keeps its first box card-less, and no card ends up inside a card.

Common props​

Every box component takes the same props (SchemaBoxProps); the generated views pass them for you.

NameTypeDefaultDescription
schema (required)BoxSchema—The box to render
labelstring | ReactElement | falseschema.labelfalse renders the box without a heading
excludeFieldsstring[]—Field names rendered elsewhere and to be skipped here
isRequiredboolean—Marks the box as required, used by the conditional rendering wrapper
isRootbooleanfalseMarks the view's first box; only a root box takes the card default on a page

See also​