Settings page
Tabs of settings with one Save and Discard that only enable when something changed.
A settings page is one form split into sections with Tabs, built from Field, Input, Textarea and Switch. Change something to see Save, Discard and the unsaved-changes hint wake up.
How it works
- Two copies of the settings:
saved(what the server has) anddraft(what's on screen). The page is dirty when they differ, so typing a change and then undoing it by hand makes it clean again. - One form around every tab. Switching tabs keeps edits, and one Save sends them all. Base UI unmounts hidden tab panels, which is fine because the state lives above the tabs.
- Save and Discard are disabled until something changes. Discard resets
drafttosaved; no confirm, since nothing has been sent yet. - "Unsaved changes" sits next to the buttons with
role="status", so screen readers hear it once. - While dirty, a
beforeunloadlistener makes the browser warn before the tab closes or reloads. It's plain DOM, so it works in Next.js and Vite alike. In-app navigation needs your router's own blocker on top. - On success, a Toast confirms it and
savedbecomes the draft.
Guidelines
- Save is the page's primary action:
brand, last. Discard isoutline. - While saving, disable both buttons and change the label ("Saving changes").
- Switches act on their own only on pages without a Save button. Here they wait for Save like everything else; don't mix the two on one page.
- Put each setting's help in
FieldDescription, one line. If it needs a paragraph, it needs a docs link. - Dangerous settings (delete the workspace, transfer ownership) go in their own section at the end, outside the form, each with its own confirm.