Highlight saving, not discarding, on the unsaved-changes guard #219

Closed
opened 2026-09-02 14:05:37 +00:00 by jcoffey-dev · 0 comments
Owner

Reported on #175 after the guard shipped: "Discard changes" was the only choice carrying a colour — a filled red button, against a plain outlined "Save changes" — which made losing the work the loudest thing in a dialog whose entire purpose is to stop that. The reporter's colleague is right that the non-destructive action is the one that normally gets the highlight.

What changed

A dialog choice can now be marked primary, and Save is. Discard keeps its danger flag, but a danger choice is drawn the way .menu-item.danger already is: a red label on the ordinary surface. In a list of answers a filled red button does not read as "this one is destructive", it reads as "this one is the default" — the opposite of what it meant here.

The other dialog this reaches

The calendar's "this occurrence or the whole series" also uses choiceDialog, and marks both answers danger because both delete something. Two filled red buttons become two red labels, and nothing is highlighted. That is right for that dialog: neither answer is the safe one, so neither should look like the default. Calling it out because it is a visible change nobody asked for.

Verified

Driven in a real browser against the mock — new rule, navigate away, guard appears — in both themes:

  • Light: Save is white on the accent; Discard is #dc2626 on white, 4.8:1.
  • Dark: Discard uses the theme's own --danger, which every palette already tunes for contrast on this surface.

Tests

unsavedChanges.test.tsx, eight cases. One pins the fix (Save is primary, Discard is not) and fails on main; the other seven are regression guards on behaviour that already worked and had no test at all — dismissing keeps you put and loses nothing, a failed save holds you on the page, discard calls discard and not save.

npm run typecheck, npm test, npm run build pass.

Merged 2026-09-02 as coffey-labs/ihasmail@3f33b61369

Rebuilt from: git history, session transcript.

Reported on #175 after the guard shipped: "Discard changes" was the only choice carrying a colour — a filled red button, against a plain outlined "Save changes" — which made losing the work the loudest thing in a dialog whose entire purpose is to stop that. The reporter's colleague is right that the non-destructive action is the one that normally gets the highlight. ## What changed A dialog choice can now be marked `primary`, and Save is. Discard keeps its `danger` flag, but a danger *choice* is drawn the way `.menu-item.danger` already is: a red label on the ordinary surface. In a list of answers a filled red button does not read as "this one is destructive", it reads as "this one is the default" — the opposite of what it meant here. ## The other dialog this reaches The calendar's "this occurrence or the whole series" also uses `choiceDialog`, and marks **both** answers `danger` because both delete something. Two filled red buttons become two red labels, and nothing is highlighted. That is right for that dialog: neither answer is the safe one, so neither should look like the default. Calling it out because it is a visible change nobody asked for. ## Verified Driven in a real browser against the mock — new rule, navigate away, guard appears — in both themes: - **Light:** Save is white on the accent; Discard is `#dc2626` on white, 4.8:1. - **Dark:** Discard uses the theme's own `--danger`, which every palette already tunes for contrast on this surface. ## Tests `unsavedChanges.test.tsx`, eight cases. One pins the fix (Save is `primary`, Discard is not) and fails on `main`; the other seven are regression guards on behaviour that already worked and had no test at all — dismissing keeps you put and loses nothing, a failed save holds you on the page, discard calls discard and not save. `npm run typecheck`, `npm test`, `npm run build` pass. **Merged** 2026-09-02 as coffey-labs/ihasmail@3f33b61369d0 <sub>Rebuilt from: git history, session transcript.</sub>
This repo is archived. You cannot comment on issues.