Ring a card of Your details that holds a change not yet saved (#927) #1078

Merged
tiagoagueda merged 1 commit from 927-unsaved-cards into main 2026-10-29 09:42:34 +00:00
Owner

Your details is one form of a dozen cards, and the guard of #258 knew only
that the form held something unsaved, not where. app.js now marks the card:
data-card-unsaved on it, which app.css draws as a soft amber outline
outside its border (amber 600 in the light theme, 3.06:1 against the page;
500 in the dark, 9.4:1), a "Not saved" badge in the amber tone in its title,
and a dot on its entry in the section menu with the same words for a screen
reader. The words come from a in the page, so they are translated
with it; nothing is announced, because the badge is text the card is read
with.

A card is changed while any named field in it differs from what the page was
loaded with (defaultValue, defaultChecked, the default option of a menu, a file
box holding a file), so undoing a change takes the mark off; saving is a new
page and takes every mark off. A refused save draws the page with what was
typed, so the view lists the fields it brought back changed (the form's and
each block's changed_data) and those cards are marked on load until saved.

The attribute is not data-unsaved, which settleGuard looks for anywhere in a
form (#656). The ring is an outline because forced colours keep an outline and
drop a box-shadow; the dot is painted CanvasText there. app.css names no
Basecoat class: the rules key on the attributes.

Closes #927

Notes for review

  • The mark: a card with unsaved changes gets data-card-unsaved, a 2px amber outline (an outline survives forced colours), a "Not saved" badge in its heading or legend, and an amber dot in the section menu, with "Not saved" as hidden text. There is no live announcement.
  • Why not data-unsaved: it is avoided on purpose, because settleGuard uses it for the save-as-you-go fields.
  • When it shows:
    • A card is marked while any field differs from its loaded value, so undoing the change clears the mark.
    • After a refused save, the cards with changed fields (from the form's changed_data) are marked refused and stay marked until a save.
  • Known gaps:
    • A row taken off with its bin doesn't re-check its card.
    • After a refused save, leaving the page still doesn't ask first, as before.

🤖 Generated with Claude Code

Your details is one form of a dozen cards, and the guard of #258 knew only that the form held something unsaved, not where. app.js now marks the card: `data-card-unsaved` on it, which app.css draws as a soft amber outline outside its border (amber 600 in the light theme, 3.06:1 against the page; 500 in the dark, 9.4:1), a "Not saved" badge in the amber tone in its title, and a dot on its entry in the section menu with the same words for a screen reader. The words come from a <template> in the page, so they are translated with it; nothing is announced, because the badge is text the card is read with. A card is changed while any named field in it differs from what the page was loaded with (defaultValue, defaultChecked, the default option of a menu, a file box holding a file), so undoing a change takes the mark off; saving is a new page and takes every mark off. A refused save draws the page with what was typed, so the view lists the fields it brought back changed (the form's and each block's changed_data) and those cards are marked on load until saved. The attribute is not `data-unsaved`, which settleGuard looks for anywhere in a form (#656). The ring is an outline because forced colours keep an outline and drop a box-shadow; the dot is painted CanvasText there. app.css names no Basecoat class: the rules key on the attributes. Closes #927 ## Notes for review - **The mark:** a card with unsaved changes gets `data-card-unsaved`, a 2px amber outline (an outline survives forced colours), a "Not saved" badge in its heading or legend, and an amber dot in the section menu, with "Not saved" as hidden text. There is no live announcement. - **Why not `data-unsaved`:** it is avoided on purpose, because `settleGuard` uses it for the save-as-you-go fields. - **When it shows:** - A card is marked while any field differs from its loaded value, so undoing the change clears the mark. - After a **refused** save, the cards with changed fields (from the form's `changed_data`) are marked `refused` and stay marked until a save. - **Known gaps:** - A row taken off with its bin doesn't re-check its card. - After a refused save, leaving the page still doesn't ask first, as before. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Ring a card of Your details that holds a change not yet saved (#927)
All checks were successful
CI / Unit tests and coverage (Python 3.14) (push) Successful in 12m59s
CI / Checks: lint, migrations, catalogues, settings, built files (push) Successful in 3m6s
CI / Database tests on PostgreSQL (push) Successful in 4m7s
CI / Security audit (push) Successful in 1m5s
CI / Browser tests (Chromium) (push) Successful in 31m46s
Every Python / Unit tests (Python 3.12) (push) Successful in 14m50s
Every Python / Unit tests (Python 3.13) (push) Successful in 16m26s
CI / Browser tests (Chromium) (pull_request) Successful in 31m44s
CI / Unit tests and coverage (Python 3.14) (pull_request) Successful in 13m8s
CI / Checks: lint, migrations, catalogues, settings, built files (pull_request) Successful in 3m8s
CI / Database tests on PostgreSQL (pull_request) Successful in 4m17s
CI / Security audit (pull_request) Successful in 1m6s
057ba9d03e
Your details is one form of a dozen cards, and the guard of #258 knew only
that the form held something unsaved, not where. app.js now marks the card:
`data-card-unsaved` on it, which app.css draws as a soft amber outline
outside its border (amber 600 in the light theme, 3.06:1 against the page;
500 in the dark, 9.4:1), a "Not saved" badge in the amber tone in its title,
and a dot on its entry in the section menu with the same words for a screen
reader. The words come from a <template> in the page, so they are translated
with it; nothing is announced, because the badge is text the card is read
with.

A card is changed while any named field in it differs from what the page was
loaded with (defaultValue, defaultChecked, the default option of a menu, a file
box holding a file), so undoing a change takes the mark off; saving is a new
page and takes every mark off. A refused save draws the page with what was
typed, so the view lists the fields it brought back changed (the form's and
each block's changed_data) and those cards are marked on load until saved.

The attribute is not `data-unsaved`, which settleGuard looks for anywhere in a
form (#656). The ring is an outline because forced colours keep an outline and
drop a box-shadow; the dot is painted CanvasText there. app.css names no
Basecoat class: the rules key on the attributes.

Closes #927

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
tiagoagueda force-pushed 927-unsaved-cards from 057ba9d03e
All checks were successful
CI / Unit tests and coverage (Python 3.14) (push) Successful in 12m59s
CI / Checks: lint, migrations, catalogues, settings, built files (push) Successful in 3m6s
CI / Database tests on PostgreSQL (push) Successful in 4m7s
CI / Security audit (push) Successful in 1m5s
CI / Browser tests (Chromium) (push) Successful in 31m46s
Every Python / Unit tests (Python 3.12) (push) Successful in 14m50s
Every Python / Unit tests (Python 3.13) (push) Successful in 16m26s
CI / Browser tests (Chromium) (pull_request) Successful in 31m44s
CI / Unit tests and coverage (Python 3.14) (pull_request) Successful in 13m8s
CI / Checks: lint, migrations, catalogues, settings, built files (pull_request) Successful in 3m8s
CI / Database tests on PostgreSQL (pull_request) Successful in 4m17s
CI / Security audit (pull_request) Successful in 1m6s
to d799d2cda7
All checks were successful
CI / Unit tests and coverage (Python 3.14) (pull_request) Successful in 13m46s
CI / Checks: lint, migrations, catalogues, settings, built files (pull_request) Successful in 2m47s
CI / Database tests on PostgreSQL (pull_request) Successful in 4m31s
CI / Security audit (pull_request) Successful in 1m28s
CI / Browser tests (Chromium) (pull_request) Successful in 32m37s
2026-10-29 09:39:54 +00:00
Compare
tiagoagueda deleted branch 927-unsaved-cards 2026-10-29 09:42:38 +00:00
Sign in to join this conversation.
No reviewers
No milestone
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
Postulo/postulo!1078
No description provided.