fix(desktop): toast polish — auto-dismiss, countdown bar, a11y#54
Merged
fix(desktop): toast polish — auto-dismiss, countdown bar, a11y#54
Conversation
Audit 27 §B2 — toast system polish: - Auto-dismiss success/info after 5s via useEffect timer keyed on toast id; error toasts persist until user dismiss. - Replace fixed `w-80` with `min-w-72 max-w-96`; long content wraps instead of truncating. - Per-toast `role`/`aria-live`: `status`/`polite` for success/info, `alert`/`assertive` for error. Replaces the misused `<output>` element. - Thin countdown progress bar at the bottom of auto-dismissing toasts, animated via CSS keyframe; honors `prefers-reduced-motion` (motion-safe variant only). - Move auto-dismiss out of `pushToast` (component-owned timer; cleaner than a fire-and-forget setTimeout). No new dependencies. Pure Tailwind + tokens + one CSS keyframe.
Contributor
There was a problem hiding this comment.
Findings
- No high-confidence issues found in added/modified lines.
Summary
- Review mode: initial
- No blocker/major/minor/nit issues identified in the current diff.
- Residual risk/testing gap: coverage was added for
scheduleAutoDismissbehavior, but there is still no component-level test forToastItem/ToastViewporta11y semantics and countdown-bar rendering lifecycle. - Context note:
docs/VISION.mdanddocs/PRINCIPLES.mdwere not found in this checkout (Not found in repo/docs).
Testing
- Not run (automation)
open-codesign Bot
hqhq1025
added a commit
that referenced
this pull request
Apr 19, 2026
Audit 27 §B2 — toast system polish: - Auto-dismiss success/info after 5s via useEffect timer keyed on toast id; error toasts persist until user dismiss. - Replace fixed `w-80` with `min-w-72 max-w-96`; long content wraps instead of truncating. - Per-toast `role`/`aria-live`: `status`/`polite` for success/info, `alert`/`assertive` for error. Replaces the misused `<output>` element. - Thin countdown progress bar at the bottom of auto-dismissing toasts, animated via CSS keyframe; honors `prefers-reduced-motion` (motion-safe variant only). - Move auto-dismiss out of `pushToast` (component-owned timer; cleaner than a fire-and-forget setTimeout). No new dependencies. Pure Tailwind + tokens + one CSS keyframe.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Implements audit 27 §B2 — Toast system polish.
§B2 checklist
success/info;errorpersists.useEffecttimer keyed on toast id, cleaned up on unmount. Removed the unconditional 4ssetTimeoutinpushToast.min-w-72 max-w-96instead of fixedw-80. Long titles/descriptions wrap (break-words) instead of getting truncated.role="status" aria-live="polite"(success/info) orrole="alert" aria-live="assertive"(error). The misused<output>element is replaced by<div>. Dismiss button keeps itsaria-label.h-0.5) bar at the bottom of auto-dismissing toasts, animated via a new@keyframes toast-countdown(linear scaleX 1 → 0). Uses--color-text-mutedat 30% alpha.motion-safe:variant meansprefers-reduced-motion: reduceusers see only a static bar — no animation.Files changed
apps/desktop/src/renderer/src/components/Toast.tsx— main rewrite (per-toast role/aria-live, useEffect timer, sizing, countdown bar). ExportsscheduleAutoDismiss+AUTO_DISMISS_MSfor unit testing.apps/desktop/src/renderer/src/store.ts— drop the 4s blanketsetTimeoutfrompushToast; the component owns the timer now.apps/desktop/src/renderer/src/index.css— add@keyframes toast-countdown.apps/desktop/src/renderer/src/components/__tests__/Toast.test.tsx— new Vitest unit test (5 cases) using fake timers: success/info dismiss after 5s, error never auto-dismisses, cleanup cancels the timer,AUTO_DISMISS_MSmap values.Net diff: ~106 LOC added (test included).
PRINCIPLES check
pushToast,dismissToast,useToastsignatures preserved). Only the internal timer location moved.Record<ToastVariant, number | null>map; adding a new variant or tweaking timing is a one-line change.prefers-reduced-motion; per-toast role/aria-live aligns with WAI-ARIA notification patterns; component owns its own lifecycle.Test plan
pnpm --filter @open-codesign/desktop test— 19 files / 143 tests pass (5 new Toast tests).pnpm lint— clean (only pre-existing warnings unrelated to this PR).pnpm typecheck— clean across the workspace.