SettingsScreen
$ npx shadcn@latest add https://lacodda.github.io/dowel/r/settings-screen.jsonThe block lands in components/blocks/settings-screen.tsx, and what it is made
of - Frame,
SectionNav and
PageHeader - in components/ui.
A section per address. kilna’s settings sat on one page until a version
counted what was on it - a profile editor, a status check, export, backup,
import and a command to copy, in one scroll where nobody found the one thing
they came for. Each section is its own address now, so it can be linked to
and the back button walks between them. Pass sectionRender to draw a
section as the router’s link:
<SettingsScreen title="Settings" sections={sections} active={section ?? null} onSelect={(id) => navigate(id === null ? '/settings' : `/settings/${id}`)} sectionRender={(section) => <NavLink to={`/settings/${section.id}`} />} words={{ sections: 'Settings', back: 'All settings' }}/>The column says what is in each section. “Theme, language, start screen” under General, so a section is chosen by its contents rather than guessed from a word. The column is the rail’s width - it holds destinations, like the app’s own rail beside it - and it does not move while a long section scrolls.
Null is the column on a phone and the first section on a desktop. Where
there is room for both, something is always open, and the first section
stands in for none. Where there is not, active={null} is the column alone,
which is what /settings should be on a phone - one address, right at both
widths, with no width read in script.
A section can stand a bar at its foot. foot is outside the part that
scrolls, so a Save for a section that keeps a draft is in sight however far
down the edit was - and only while there is something to save, if the
product passes it only then.
SettingsGroup is the shape inside a section. A heading, a line under
it, and the fields one under another at the width of a field: side by side,
a segment and a select read as one control of two halves, and a field the
width of the pane asks the eye to cross a monitor between a label and what
it names.
<SettingsGroup title="Appearance"> <FieldGroup label="Theme"> <SegmentedControl aria-label="Theme" value={theme} onValueChange={setTheme}>…</SegmentedControl> </FieldGroup> <Switch checked={reopen} onCheckedChange={setReopen}>Open where I left off</Switch></SettingsGroup>Props
Read from the types in blocks/settings-screen.tsx, the file a product copies - so the description of each prop is also what an editor shows over it there.
SettingsScreen
| Prop | Type | Default | |
|---|---|---|---|
titlerequired | ReactNode | The screen's title. | |
description | ReactNode | One sentence under the title. | |
sectionsrequired | readonly SettingsSection[] | The sections, in the order the column lists them. | |
activerequired | string | null | The open section's id. Null opens the column on a narrow screen and the first section where there is room for both. | |
onSelectrequired | (id: string | null) => void | Told which section to open - or null, to go back to the column. | |
sectionRender | (item: SectionNavItem) => RenderProp<Record<string, unknown>> | A section drawn as the product's link, so it has an address: (section) => <Link to={/settings/${section.id}} />. A press is then the link's; onSelect is still told on the way back. | |
wordsrequired | SettingsScreenWords | The column's name and the way back, in the product's language. | |
className | string |
SettingsGroup
A group of settings inside a section.
| Prop | Type | Default | |
|---|---|---|---|
titlerequired | ReactNode | The group's caption: "Appearance", "Notifications". | |
description | ReactNode | A line under it, when the caption does not say enough. | |
childrenrequired | ReactNode | Its fields, one under another. | |
className | string |
Accessibility
The examples on the stand, through axe 4.14.0 in a browser, in both themes, against WCAG 2.2 A and AA and axe's best practices: 21 rules applied and passed, and none failed. The accessibility report has every item.
History
Each release that changed blocks/settings-screen.tsx - the file a product copies - newest first.