Settings page

Settings Page

Markdown

A tested composition for explicit form saves, immediate settings, read-only values, scoped request states, and responsive actions.

Use this pattern when one page contains settings with different persistence models. Group fields that should be reviewed together in a Form, and use Switch only for changes that take effect immediately.

Profile and notification settings

This is composition guidance, not a registry item. Copy the example and replace saveProfile and savePreference with application requests.

Enable Product announcements in the preview to exercise the optimistic-update failure and rollback path.

Structure and surfaces

page canvas (base)
├── page heading and description
├── Profile Section (layer-1)
│   └── Form
│       ├── editable Input
│       ├── editable Select
│       ├── read-only Input
│       └── status, Discard, Save profile
└── Notifications Section (layer-1)
    ├── immediate-save Switch row
    └── immediate-save Switch row

Use Section because each surface groups related controls. Do not turn individual setting rows into nested Cards. The page canvas, spacing, section headings, and dividers already communicate the hierarchy.

Choose each SectionTitle heading level from the page outline. This example renders both section titles as h2 below the page h1.

Explicit-save settings

Keep separate draft and saved snapshots for fields submitted together. Compare them to derive the dirty state instead of maintaining an independent dirty flag that can drift.

Disable Discard and Save until the draft changes. During submission, keep the fields mounted, disable the affected form, set aria-busy on its content region, and use Button loading without changing the action name or footprint.

On success, replace the saved snapshot and announce confirmation in a mounted status region. On failure, preserve the draft, keep Save available for retry, and announce the error next to the actions.

Discard should restore the most recently saved snapshot, not hard-coded initial values.

Immediate-save settings

Switch communicates that a binary setting takes effect immediately. Do not add a second Save button for these rows.

Update the Switch optimistically, set aria-busy on only that setting row, and disable only the control with an active request. This lets unrelated settings remain available.

If the request fails, restore the previous checked state and announce an error in the same row. Keep the error associated with the Switch through aria-describedby. A Toast alone is insufficient because it separates the failure from the setting that needs attention.

Read-only settings

Use readOnly when a value remains selectable and copyable but cannot be changed here. Explain where it can be changed with FieldDescription.

Do not use disabled as a substitute for read-only. Disabled values are skipped by keyboard navigation and are commonly omitted from form submission.

Responsive and keyboard behavior

  • Collapse the two-column profile grid to one column before fields become cramped.
  • Keep status, Discard, and Save in the same DOM order used visually.
  • Let mobile actions stretch to the available width; align them to the end on wider screens.
  • Keep setting labels as the Switch targets so the full label is easy to activate.
  • Avoid sticky save bars unless the form is long enough that actions routinely leave the viewport.
  • Handle page-leave confirmation at the application router seam when dirty drafts must be protected.