settings/SU-5: SettingsSaveBar primitive; convert Appearance Apply → sticky bar #836

Closed
opened 2026-05-04 20:03:30 +00:00 by claude-desktop · 0 comments
Collaborator

User story

As an operator, I want the same save UX on every multi-field settings page, so that I never have to guess whether changes auto-save, need an Apply, or need a Save click.

Context

Three different save patterns today:

  • Hub toggles (Billing, Caveman, Design pipeline) — autosave on change.
  • Service config — sticky-bar-ish per-section, plus confirm-dialog for destructive fields.
  • Voice input — local draft + Save/Discard buttons inline.
  • Appearance — staged state + "Apply" button (the odd one out).

Acceptance criteria

Save rule (codified)

  • Single boolean toggle → autosave + polite "Saved" toast (existing behaviour).
  • Multi-field form → sticky bottom bar [Discard] [Save changes] + dirty-field count.
  • Destructive field → confirm dialog before save (existing pattern).

Primitive

  • New apps/web/src/components/settings-save-bar.tsx exports <SettingsSaveBar dirtyCount onSave onDiscard saving />.
  • Sticky to bottom of editing surface (not viewport — must stay inside the side-nav layout's right pane).
  • Hidden when dirtyCount === 0.
  • Reduced-motion friendly enter/leave (per apps/web/CLAUDE.md).

Migrations

  • Appearance — drop "Apply" button; staged state still drives live preview, sticky bar commits via setMode / setDarkPack / setLightPack.
  • Voice input — inline Save/Discard replaced by sticky bar (page now hosts only one form).
  • Service config sub-pages — gradual; at minimum prove the primitive works on one (e.g. Forge tab) without regressing the destructive-field confirm dialog.

Tests

  • Save bar renders only when dirty.
  • Discard reverts to persisted state.
  • Save fires mutation; "Saving…" status visible during pending.

Out of scope

  • Server-side autosave debounce — out of scope.
  • Search palette — SU-6.

References

  • apps/web/src/routes/settings.appearance.tsx — Apply button to remove.
  • apps/web/src/routes/settings.index.tsx:1029-1051 — Voice Save/Discard pattern.
  • apps/web/src/routes/settings.service.tsx:248-263 — destructive confirm dialog (preserve).
## User story As an operator, I want the same save UX on every multi-field settings page, so that I never have to guess whether changes auto-save, need an Apply, or need a Save click. ## Context Three different save patterns today: - Hub toggles (Billing, Caveman, Design pipeline) — autosave on change. - Service config — sticky-bar-ish per-section, plus confirm-dialog for destructive fields. - Voice input — local draft + Save/Discard buttons inline. - Appearance — staged state + "Apply" button (the odd one out). ## Acceptance criteria ### Save rule (codified) - [ ] Single boolean toggle → autosave + polite "Saved" toast (existing behaviour). - [ ] Multi-field form → sticky bottom bar `[Discard] [Save changes]` + dirty-field count. - [ ] Destructive field → confirm dialog before save (existing pattern). ### Primitive - [ ] New `apps/web/src/components/settings-save-bar.tsx` exports `<SettingsSaveBar dirtyCount onSave onDiscard saving />`. - [ ] Sticky to bottom of editing surface (not viewport — must stay inside the side-nav layout's right pane). - [ ] Hidden when `dirtyCount === 0`. - [ ] Reduced-motion friendly enter/leave (per `apps/web/CLAUDE.md`). ### Migrations - [ ] Appearance — drop "Apply" button; staged state still drives live preview, sticky bar commits via `setMode` / `setDarkPack` / `setLightPack`. - [ ] Voice input — inline Save/Discard replaced by sticky bar (page now hosts only one form). - [ ] Service config sub-pages — gradual; at minimum prove the primitive works on one (e.g. Forge tab) without regressing the destructive-field confirm dialog. ### Tests - [ ] Save bar renders only when dirty. - [ ] Discard reverts to persisted state. - [ ] Save fires mutation; "Saving…" status visible during pending. ## Out of scope - Server-side autosave debounce — out of scope. - Search palette — SU-6. ## References - `apps/web/src/routes/settings.appearance.tsx` — Apply button to remove. - `apps/web/src/routes/settings.index.tsx:1029-1051` — Voice Save/Discard pattern. - `apps/web/src/routes/settings.service.tsx:248-263` — destructive confirm dialog (preserve).
dev closed this issue 2026-05-04 21:45:48 +00:00
Sign in to join this conversation.
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
charles/claude-hooks#836
No description provided.