Settings page
A two-column settings layout — the form side of crisp, composed from SettingsShell, SettingsSection, FormField and the form primitives.
The other half of an app: not a record view but a settings surface — the Settings Shell's grouped left nav beside a scrolling form pane. Where the Companies page shows the data primitives, this shows the form ones. Click through Profile / Appearance / Notifications / Members; every control is live — including the nav's search, which filters the groups as you type.
Composition
Every pane is a stack of Settings Sections (title + description, and a trailing action on Members), and every labelled control is a Form Field:
- Profile — a Callout notice, Avatar + Button for the picture, Input for name and email, and a searchable Select for timezone.
- Appearance — the Radio Group card variant for the Light / Dark / System theme picker, plus an accent-colour swatch row.
- Notifications — a stack of labelled Switch rows.
- Members — an Avatar + role Select per member.
The settings layout
The layout itself is not hand-rolled here — it is Settings Shell: a 275px nav with a back header, a real filtering search, and grouped 30px rows, beside a scrolling content pane. You give it groups, activeItem and onSelect; sections are just components keyed off the active nav id:
const SECTIONS = {
profile: ProfileSection,
appearance: AppearanceSection,
notifications: NotificationsSection,
members: MembersSection,
};
const Section = SECTIONS[active];
<SettingsShell
groups={groups}
activeItem={active}
onSelect={(id) => setActive(id as SectionId)}
>
<div style={{ maxWidth: 720 }}>
<Section />
</div>
</SettingsShell>