Replace the notice banner with a queued toast system #30

Open
opened 2026-08-22 08:18:22 +00:00 by kayg · 0 comments
Owner

Current state

Transient notices currently flow through AppModel.notice and are rendered by the RootView notice banner. The state represents one message at a time: there is no queue, stack, or per-notice identity/dismissal policy.

Goal

Replace the single notice banner with a toast system. HermternalCore should own a platform-neutral, domain-typed queue policy; the macOS adapter should provide the presenter. Toasts should be queued, stackable, and swipe-dismissible while remaining usable from future platform adapters.

Acceptance criteria

  • Enqueuing multiple toasts preserves a deterministic ordering contract in both the Core queue and the macOS presenter; tests cover the ordering of visible and pending items.
  • Toast identity is explicit and deduplication by id prevents duplicate stack entries; tests cover repeated enqueue of the same id and the resulting retained/up-to-date item.
  • Expiring toasts disappear after their configured lifetime; the expiry clock pauses while the toast is hovered and while the app window is deactivated, then resumes with the remaining time.
  • The presenter enforces a documented maximum stack size and deterministically evicts the oldest eligible non-promoted toast when capacity is exceeded.
  • Errors can be promoted to non-expiring toasts; promoted errors remain until explicit dismissal or an associated recovery action and are not removed by expiry or ordinary capacity eviction.
  • A horizontal swipe dismisses a toast when its release velocity meets the dismissal rule; a below-threshold gesture returns it to the stack without losing or reordering it.
  • Reduce Motion uses a cross-fade/static transition instead of scale or spring motion while preserving state changes and input responsiveness.
  • VoiceOver announces newly presented toast content without stealing keyboard/VoiceOver focus from the current control or interrupting text entry.
  • The companion toast design spec governs exact motion values, thresholds, timing, spacing, and platform presentation details; those values are not redefined by this issue.

Issue #9 (native motion) is the motion contract for this work, not a blocker.

## Current state Transient notices currently flow through `AppModel.notice` and are rendered by the RootView notice banner. The state represents one message at a time: there is no queue, stack, or per-notice identity/dismissal policy. ## Goal Replace the single notice banner with a toast system. HermternalCore should own a platform-neutral, domain-typed queue policy; the macOS adapter should provide the presenter. Toasts should be queued, stackable, and swipe-dismissible while remaining usable from future platform adapters. ## Acceptance criteria - Enqueuing multiple toasts preserves a deterministic ordering contract in both the Core queue and the macOS presenter; tests cover the ordering of visible and pending items. - Toast identity is explicit and deduplication by id prevents duplicate stack entries; tests cover repeated enqueue of the same id and the resulting retained/up-to-date item. - Expiring toasts disappear after their configured lifetime; the expiry clock pauses while the toast is hovered and while the app window is deactivated, then resumes with the remaining time. - The presenter enforces a documented maximum stack size and deterministically evicts the oldest eligible non-promoted toast when capacity is exceeded. - Errors can be promoted to non-expiring toasts; promoted errors remain until explicit dismissal or an associated recovery action and are not removed by expiry or ordinary capacity eviction. - A horizontal swipe dismisses a toast when its release velocity meets the dismissal rule; a below-threshold gesture returns it to the stack without losing or reordering it. - Reduce Motion uses a cross-fade/static transition instead of scale or spring motion while preserving state changes and input responsiveness. - VoiceOver announces newly presented toast content without stealing keyboard/VoiceOver focus from the current control or interrupting text entry. - The companion toast design spec governs exact motion values, thresholds, timing, spacing, and platform presentation details; those values are not redefined by this issue. Issue #9 (native motion) is the motion contract for this work, not a blocker.
Sign in to join this conversation.
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
kayg/hermternal-apple#30
No description provided.