feat(ui): restyle unsaved-changes bar as a compact inverted card (#893)

* feat(ui): restyle unsaved-changes bar as a compact inverted card

Show Page.SettingsActions only when the form is dirty, as a centered
dark card with a secondary Discard button and a primary Save button.

Co-authored-by: best <best@classroomio.com>

* fix(ui): announce settings actions from a persistent live region

Keep role=status mounted outside the dirty-state card so screen readers
still hear the status when the bar appears, without live-region wrapping
the Discard/Save buttons.

Co-authored-by: best <best@classroomio.com>

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
This commit is contained in:
Rotimi Best
2026-08-14 10:53:28 +01:00
committed by GitHub
co-authored by Cursor Agent
parent 7ba551aa43
commit 41d810d4f7
4 changed files with 56 additions and 54 deletions
+3 -2
View File
@@ -481,8 +481,9 @@ Use `@cio/ui/base/page` for dashboard page shells. See `packages/ui/README.md`
**Every settings page with save/discard** must use `Page.SettingsActions` as the last child of `Page.Root` (after `Page.Body`). Do not put Save in `Page.Header` or inline at the bottom of form sections.
- Sticky at the viewport bottom while scrolling; docks naturally at the end of the page content
- Save and Discard are disabled when `hasChanges` is false
- Compact centered card (not full width), sticky at the viewport bottom while scrolling; docks naturally at the end of the page content
- Only appears when `hasChanges` is true
- Save is a primary button (not a split/combo control); Discard is secondary
- Labels come from dashboard translations: `common.unsaved_changes.label`, `common.discard`, `common.save_changes`
- Pair with `UnsavedChanges` for navigation guards where appropriate