Settings
Reach for this for a grouped-settings screen — a micro-label heading over the kit's framed list, repeated per group. No spec of its own; it is the design system's settings reference screen made portable. Switches for instant-effect toggles, never a hand-rolled rows list.
Live
Real widgets, built from the real kit. Turn a knob and it rebuilds; the theme bar above applies the design system's own tokens — including anything you changed under Customize — and the device selector uses the same sizes the golden baselines gate on, so what you see here is what CI holds the widget to.
Press Focus on any preview to take it to the full window — at a desktop width that renders most devices at 1:1, which is when the widget's own controls become clickable. The bar always states the device and the scale, so a shrunk preview says it is shrunk. Esc leaves.
Adds the global action to the drawer's footer — so, like every drawer action, it acts only below 600. This screen opens at an iPad, where the shell mounts a rail instead.
Which nav the compact posture mounts — the drawer behind the hamburger, or a bottom bar.
The primary tier, and on a records destination the ONLY loud action the bar's neighborhood has. The scaffold renders it in the thumb zone at every window class; a screen never places it itself.
Actions in the drawer's own footer. The drawer carries them at EVERY window class — at 960 and wider it exists only because they do, since the expanded shell otherwise mounts a standing inline rail instead.
Shows when you open the drawer — the hamburger below 960, an edge swipe at 960 and wider, where the rail head's menu button toggles the rail instead. The actions sit in the drawer's own footer; the resting frame is identical either way. — press Focus to make the preview interactive.
The app's identity mark, and nothing else — it never opens a picker. At 960 and wider it sits beside the menu button in the rail's head at the same place in both postures, overhanging the collapsed rail so the bar beside it steps in. Below 960 the drawer's header band states it.
The scope — one value of the app's own kind (here an Area) — as the FIRST item of the bar's subtitle, ahead of the meta. With a picker it is a quiet text button with a chevron; on a phone the whole title block opens the picker as a bottom sheet. A pushed record's bar shows it read-only.
Global commands with no page ("Send feedback", "Help") pinned in the rail's footer under the footer destinations — the same row as a destination, but never lit and never counted in the destination index.
An organization's or partner's logo at the very bottom of the rail and the drawer — identity, never a control. Collapsed it shows its compact square, or nothing when the host gives none.
Dart for these values
screen_settings() What it is made of
The widgets this screen assembles, with their full API below. They used to live on a second entry of their own; one thing you choose gets one page.
SettingsScreen widget
The FLOORPLAN for grouped settings (`design-system/components/floorplans/SettingsScreen.d.ts`): labeled rows in micro-labeled groups, label start and control end, taking effect instantly. What it always owns: * **The bar, on every state.** In a destinations-mode AppScaffold the chrome projects into…
Full dartdoc
The FLOORPLAN for grouped settings (`design-system/components/floorplans/SettingsScreen.d.ts`): labeled rows in micro-labeled groups, label start and control end, taking effect instantly. What it always owns: * **The bar, on every state.** In a destinations-mode AppScaffold the chrome projects into the shell's bar through the contributor tier (AppHeaderActions, via RecordsChrome) — search resting as a glyph below 960, as the field at >=960, and as a MODE in between. Pushed (no bar host) the floorplan stands up its own AppHeaderBar carrying title in a body-mode AppScaffold. * **The row grammar** — label + optional ink60 line at the start, the control at the end, `--ctl` minimum height, hairline-separated, under a micro-label on framed paper (SettingsGroup over AppList `framed`). * **The layout by window class** (layout). * **The faces** — error (error + onRetry), loading (structural skeleton rows, never a spinner — loading) and narrowed-to-zero ("No settings match."), each in the body under the chrome, and in the contract's RANK: ERROR > LOADING > NARROWED-TO-ZERO > the rows. There is NO empty face: a settings screen with no groups is an authoring mistake, not a state. * **The scroll** — the rows scroll; in `split` the category list and the rows scroll independently and never the page. ```dart SettingsScreen( title: 'Settings', layout: SettingsLayout.split, groups: [ SettingsGroupSpec.rows(label: 'Sync', rows: [ SettingsRow(key: 'auto', label: 'Auto-sync', sub: 'Every 15 min on Wi-Fi', control: autoSwitch), ]), ], footer: const AppVersionLine(), syncStatus: const SyncStatusButton(), // required; null = no channel ) ``` **Every prop here is the contract's own** since pin e04afca: syncStatus, loading, error and onRetry all landed upstream.
SettingsScreendefault constructor
| Knob | Type | Default | What it does |
|---|---|---|---|
| band | FloorplanBand? | null | The surface's ONE TRANSIENT BAND (`SettingsScreen.d.ts`, THE SCREEN CARRIES THE TRANSIENT BAND, 2026-10-03) — a confirmation that clears itself ("Cache cleared") or a refusal the surface must not swallow ("Could not save the setting"). Settings apply instantly with no Save, so a write that fails has… |
| error | FloorplanError? | null | The load failed: `title` is the cause, `detail` one quiet line under it. Non-null outranks every other face; null means no error. |
| footer | Widget? | null | Quiet content after the last group — the app version, the licenses link. Never an action slab. |
| groups * | List<SettingsGroupSpec> | — | The groups, in order; each becomes a micro-labeled group (and a category in SettingsLayout.split). |
| layout | SettingsLayout column · split | SettingsLayout.column | The layout. Default SettingsLayout.column. |
| loading | bool | false | The canonical — and here the ONLY — loading signal (THE LOAD FACES). There is no data prop to carry a shorthand: groups is required and an empty list is a legitimate authored value. Default false. |
| onBack | VoidCallback? | null | The leading back affordance of this floorplan's OWN bar — the pushed posture, which is how a settings screen usually arrives. Null renders NONE. Ignored as a scaffold destination (the shell owns that leading). |
| onRetry | VoidCallback? | null | The error face's Retry. Null renders the cause with no way out. |
| presence | Widget? | null | THE PRESENCE STACK (`SettingsScreen.d.ts` `presence`; `Presence.d.ts` EVERY FLOORPLAN CARRIES IT AS A KNOB, steady-core #1331): the `AppPresenceStack` of the scope this screen joins. The HOST builds it; the screen never joins a channel. As a scaffold DESTINATION it is CONTRIBUTED into the shell's… |
| searchable | bool | false | Whether the bar carries search, narrowing rows by label and sub. Default false. |
| syncStatus * | Widget? | — | The shell's sync control, last inline-end in THIS screen's own bar when it is PUSHED, which is how a settings screen usually arrives. IGNORED as a destination (the scaffold's own control is that bar's) and nested (`SettingsScreen.d.ts`, corrected 2026-10-20, #1639). REQUIRED BUT NULLABLE: null… |
| title * | String | — | The view's name, in the headline role — the bar's title in the pushed posture (a destination's title belongs to the shell). |
SettingsGroup widget
One grouped-settings section: a micro-label heading over the kit's framed AppList — the design system's settings reference screen's one repeating unit (the `SettingsScreen.jsx` Group anatomy; `List.d.ts` `framed` is the grouped-settings posture). Promoted 2026-08-27 from the two hand-copied…
Full dartdoc
One grouped-settings section: a micro-label heading over the kit's framed AppList — the design system's settings reference screen's one repeating unit (the `SettingsScreen.jsx` Group anatomy; `List.d.ts` `framed` is the grouped-settings posture). Promoted 2026-08-27 from the two hand-copied `_SettingsGroup` helpers (a product app's settings screen and the shell's — the registered harvest candidate); the settings engine's renderer is the third consumer. AppList.shrinkWrap is the sectioned-surface posture: the list sizes to its rows and defers scrolling to the surface's own scroll view.
SettingsGroupdefault constructor
| Knob | Type | Default | What it does |
|---|---|---|---|
| children * | List<Widget> | — | The section's rows (conventionally AppListItems). |
| label * | String | — | The section heading, rendered in the label role (sentence case). |
Types its knobs take
These are not things you choose — they are the shapes the knobs above expect. They live under this entry rather than in the navigation for exactly that reason.
FloorplanBand support
A floorplan's ONE TRANSIENT BAND — the contract's `ScaffoldHeaderBandProps` on both floorplans that declare one, stated once here rather than twice. `DetailScreen.d.ts` and `RecordsScreen.d.ts` each type their `band` member as that shared props type and forward it VERBATIM, so a Dart type per…
| Field | Type | Default | What it does |
|---|---|---|---|
| actionLabel | String? | null | Label for the ONE action beside message (the Undo pattern). |
| message | String? | null | The transient message. Null draws nothing. |
| onAction | VoidCallback? | null | Callback for that single action. |
SettingsGroupSpec support
One group of settings rows — a micro-labeled section, and a category in the `split` layout. Named `…Spec` because SettingsGroup is the kit PATTERN this floorplan renders it with: the value type and the widget cannot share one name.
| Field | Type | Default | What it does |
|---|---|---|---|
| content * | Widget | — | |
| label * | String | — | The section heading, in the label role — sentence case, rendered as written. The group's identity, unique across the screen's groups. |
| Field | Type | Default | What it does |
|---|---|---|---|
| label * | String | — | The section heading, in the label role — sentence case, rendered as written. The group's identity, unique across the screen's groups. |
| rows * | List<SettingsRow> | — |
Where it lives
| Class | File |
|---|---|
| SettingsScreen | packages/app_widgets/lib/src/floorplans/settings_screen.dart |
| SettingsGroup | packages/app_widgets/lib/src/patterns/settings_group.dart |