Skip to content

feat: BrainDump completion toast — close button + display-duration preference (#109)#119

Merged
ryota-murakami merged 4 commits into
mainfrom
feat/109-braindump-toast-controls
Jun 25, 2026
Merged

feat: BrainDump completion toast — close button + display-duration preference (#109)#119
ryota-murakami merged 4 commits into
mainfrom
feat/109-braindump-toast-controls

Conversation

@ryota-murakami

@ryota-murakami ryota-murakami commented Jun 25, 2026

Copy link
Copy Markdown
Collaborator

Summary

Adds the two things issue #109 asked for on the BrainDump completion toast:

Close button (✕)

  • The completion toast now renders a close (✕) button (sonner closeButton: true per-toast → top-left placement; Toaster-level closeButtonAriaLabel: 'Dismiss').
  • Clicking it dismisses the toast immediately; the existing Undo action is untouched and keeps working. Site B (clear-on-complete path) disambiguates an Undo-click-via-onDismiss from a real ✕/auto close with a wasUndoCalled guard, so a restored line survives a ✕ click.

Display-duration preference (ms)

  • New braindumpToastDurationMs preference, expressed in milliseconds, following Users can set how long a completed BrainDump task stays before it clears (delay in ms) #108's braindumpClearDelayMs 11-file pattern exactly: constant (src/lib/constants/braindump.ts, bounded [2000, 10000] ms, default 5000, step 500), Zod field, slice state/selector/action, cross-window sync allowlist, and an appearance slider.
  • The editor reads it at completion time and passes it as the toast duration, so the next completion toast stays for the configured time. scheduleDeferredClear clamps the effective clear delay to min(clearDelayMs, braindumpToastDurationMs) so a cleared line can never outlast its own Undo toast.
  • Persists across restarts via the existing preferences persistence middleware (localStorage) + cross-window BroadcastChannel sync, identical to every other braindump* field.

Design refinements folded in (FINDING-001 regret-safe Math.floor Undo-window copy + quiet-companion voice; FINDING-002 softened helper copy). The spec's open question — whether to offer an infinite "stay until I close it" duration — was resolved by autoplan as no: a bounded slider, deliberately (the ✕ already covers manual dismissal).

Commits (git log origin/main..HEAD):

Test Coverage

All six acceptance criteria are unit-covered; pnpm validate green on CI Node 24.13.0 — 709 passed | 33 skipped, build/typecheck/lint exit 0.

  • Close button: toast options assert closeButton: true + closeButtonAriaLabel: 'Dismiss'; Undo-survives-✕ guarded by the wasUndoCalled test.
  • Duration pref: constant bounds, Zod clamp/finite-guard/catch-default, slice setter clamp + selector default-fallback, sync-channel allowlist, slider dispatch, and editor-consumes-at-completion all covered.
  • Coverage audit (ship Step 7): code-path 17/17 after closing GAP-1 — the regret-safe Math.floor half-step branch (reachable via the 500 ms slider step) was previously untested; fc556d9 adds a discriminating 2500 ms → "2 s" (never "3 s") regression test.

Live UI note: BrainDumpEditor/BrainDumpAppearance are isBrainDumpEnvironment()-gated and the slider sits behind auth, so the interactive path is auth + Electron-gated and not locally drivable; CI E2E is the regression gate and the renderer ships via Vercel on merge (same precedent as #92/#95/#104).

Pre-Landing Review

/review (Standards + Spec, parallel sub-agents, fixed point origin/main...HEAD) — clean on both axes at HEAD. No any, functional components, @/ imports, constants as SCREAMING_SNAKE_CASE with _MS suffix, JSDoc present; spec ACs 1-6 all satisfied; the bounded-range resolution of the infinite-duration open question confirmed as deliberate, not a missing requirement. React Compiler is enabled, so manual-memo findings were correctly treated as false positives.

Design Review

/design-review ran (cross-model Codex + web-designer lens): 2 findings, both auto-fixed, clean after. FINDING-001 (regret-safe Math.floor so the Undo-window copy never over-promises remaining time + warmer copy) and FINDING-002 (softened the duration-helper voice to DESIGN.md's quiet self-affirmation register). No AI-slop; copy uses curly quotes and the quiet-companion voice.

Adversarial Review

Cross-model Codex adversarial pass raised 2 High findings; both were verified against primary source and judged non-blocking, pre-existing, and non-data-loss:

  1. A malformed/hand-edited persisted braindumpToastDurationMs blob bypasses the Zod clamp on the localStorage hydrate path (it feeds the sonner duration/copy/timer). Pre-existing & deliberate: store.ts:52-62 documents the deepMerge-not-Zod-reparse design ("preserve beats reject"), and Users can set how long a completed BrainDump task stays before it clears (delay in ms) #108's shipped selectBraindumpClearDelayMs uses the identical ?? DEFAULT no-clamp read — this property applies to all numeric prefs equally, is corrupt-blob-only (normal writes always go through the clamping setter), and is cosmetic, not data-loss. BrainDump completion toast: add a close button + a setting for how long it stays #109's min(clearDelayMs, braindumpToastDurationMs) actually caps the clear timer more tightly than Users can set how long a completed BrainDump task stays before it clears (delay in ms) #108, and the new ✕ improves the stuck-toast case. Recorded as a follow-up candidate, not changed here — clamping Users can set how long a completed BrainDump task stays before it clears (delay in ms) #108's shipped read path is out of BrainDump completion toast: add a close button + a setting for how long it stays #109's scope.
  2. The ✕ on the deferred-clear path removes the Undo affordance after the user explicitly dismissed it; the "Completed row + edited source line" outcome is the pre-existing edit-during-linger self-suppress behavior (BrainDumpEditor.tsx:931-951, "the win is already recorded"), present with or without the ✕. Intended behavior, no data loss.

Plan Completion

Plan: ~/.gstack/projects/laststance-corelive/feat-109-braindump-toast-controls-plan.md12 DONE, 1 CHANGED (design copy refinement, intentional), 1 DEFERRED (E1 infinite-duration — plan-blessed: bounded slider chosen), 2 UNVERIFIABLE locally (CI E2E gate, native QA). Scope check: CLEAN — no #108 clear-delay behavior change, no AI/auto-label work.

Closes #109

TODOS

No TODO items completed in this PR.

Test plan

  • pnpm validate green on CI Node 24.13.0 — 709 passed | 33 skipped; build, typecheck, lint exit 0
  • Coverage audit 17/17 code paths (GAP-1 closed by fc556d9)
  • /review Standards + Spec clean; /design-review clean (2 findings auto-fixed); Codex adversarial findings verified pre-existing/non-blocking
  • CI E2E (BrainDump paths) — gated on CI run for this PR
  • Native/live BrainDump UI — auth + Electron-gated, ships via Vercel on merge

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added a configurable Brain Dump confirmation duration setting.
    • Completion toasts now include a close button and a clearer Undo window message.
    • Toast duration changes sync across open windows.
  • Bug Fixes

    • Undo now reliably restores cleared lines even after toast dismissal.
    • Cleared lines no longer disappear after the Undo window ends.
    • Saved duration values are clamped to the supported range and recover safely from invalid values.

…erence (#109)

Add a sonner close (✕) button to the BrainDump completion toast and a
persisted, configurable display duration (braindumpToastDurationMs) that
controls how long the toast lingers before it auto-dismisses.

- New preference braindumpToastDurationMs (default 5000ms, clamped [2000,10000])
  mirrors the #108 11-file preference pattern: constant, Zod schema field
  (.finite().transform(clamp).catch(default)), slice reducer+selector+action,
  cross-window sync allowlist, BrainDumpAppearance slider, BrainDumpEditor consume.
- showCompletionToast helper centralizes toast.success with closeButton:true,
  duration, action(Undo), and onAutoClose/onDismiss callbacks for both the
  complete-only (site A) and clear-on-complete (site B) paths.
- Site B disambiguates Undo-via-onDismiss from a real dismiss with a
  wasUndoCalled guard so the restored line survives a close click.
- scheduleDeferredClear clamps the effective clear delay to the toast duration
  (min) so a line never outlives its own Undo toast.
- Toaster sets closeButtonAriaLabel: 'Dismiss' (Toaster-level per sonner 2.x).

Tests: schema defaults/clamp/NaN-heal, slice reducer+selector, cross-window
propagation, appearance slider (track/readout/always-enabled/step), and editor
toast (closeButton+duration, description copy, Undo-restore, min clamp).

Closes #109
… toast copy

Cross-model design-review on #109: the dynamic Undo-window copy read as a
system instruction ("Tap Undo within N s to revert.") and rounded the
seconds with Math.round, which over-promises the Undo window at half-step
slider settings (2500ms -> "3 s" while the toast closes at 2.5s) — the
regret-UNSAFE direction, against the feature's own regret-safe framing.

- Reword to the DESIGN.md quiet-companion voice: "Undo stays here for N s
  if you need it." (offer, not command).
- Math.round -> Math.floor so the stated window is never longer than the
  real one (under-promise, never over-promise).
- Update the one DAMP assertion that pins the exact copy (8s case).
…t-companion voice

Cross-model design-review on #109: the appearance helper ended on an
imperative UI command ("Press the ✕ to dismiss it sooner."), which slips out
of the DESIGN.md quiet-companion voice the rest of the BrainDump copy holds
(the #108 sibling helper reads as a gentle soft-exit). Reword to a calm,
declarative line: "The ✕ lets it fade early." — keeps the close affordance
explicit without barking an instruction.
…tion (#109)

The existing copy spec used 8000ms where floor==round, so FINDING-001's
regret-safe floor (never over-promise the Undo window) was untested at the
discriminating input. The slider's 500ms step makes 2500ms reachable; this
asserts it reads "2 s" (floor), never "3 s" (round).
@vercel

vercel Bot commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
corelive Ready Ready Preview, Comment Jun 25, 2026 12:13am

Request Review

@coderabbitai

coderabbitai Bot commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 7fde39cb-42c6-44a6-898a-f6fef856fcee

📥 Commits

Reviewing files that changed from the base of the PR and between 7118f52 and fc556d9.

📒 Files selected for processing (12)
  • src/components/braindump/BrainDumpEditor.test.tsx
  • src/components/braindump/BrainDumpEditor.tsx
  • src/components/electron/BrainDumpAppearance.test.tsx
  • src/components/electron/BrainDumpAppearance.tsx
  • src/components/ui/sonner.tsx
  • src/lib/constants/braindump.ts
  • src/lib/preferences-sync-channel.test.ts
  • src/lib/preferences-sync-channel.ts
  • src/lib/redux/slices/preferencesSlice.test.ts
  • src/lib/redux/slices/preferencesSlice.ts
  • src/lib/schemas/preferences.test.ts
  • src/lib/schemas/preferences.ts

📝 Walkthrough

Walkthrough

BrainDump adds a configurable completion-toast duration preference, persists and syncs it, exposes it in appearance settings, and uses it in completion-toast rendering and deferred clearing.

Changes

BrainDump completion toast duration

Layer / File(s) Summary
Toast duration contract
src/lib/constants/braindump.ts, src/lib/schemas/preferences.ts, src/lib/schemas/preferences.test.ts
The new braindumpToastDurationMs preference, its bounds, default, and schema parsing rules are added and tested.
Toast duration state
src/lib/redux/slices/preferencesSlice.ts, src/lib/redux/slices/preferencesSlice.test.ts
The preferences slice stores, selects, and snapshots braindumpToastDurationMs, and tests cover reducer, selector, and legacy-default behavior.
Toast duration sync
src/lib/preferences-sync-channel.ts, src/lib/preferences-sync-channel.test.ts
The toast-duration action is added to the cross-window broadcast allowlist and verified in sync tests.
Toast duration setting
src/components/electron/BrainDumpAppearance.tsx, src/components/electron/BrainDumpAppearance.test.tsx
BrainDumpAppearance adds the confirmation-duration slider and tests cover its saved value, range, display, enablement, and stepping.
Completion toast flow
src/components/braindump/BrainDumpEditor.tsx, src/components/braindump/BrainDumpEditor.test.tsx, src/components/ui/sonner.tsx
BrainDumpEditor uses the stored duration for completion toasts and deferred clearing, Sonner gets the close-button label, and tests cover close, undo, and timing cases.

Sequence Diagram(s)

sequenceDiagram
  participant BrainDumpEditor
  participant showCompletionToast
  participant Toaster
  participant Sonner
  BrainDumpEditor->>showCompletionToast: pass title, durationMs, onUndo, onAutoClose, onDismiss
  showCompletionToast->>Toaster: render toastOptions with closeButtonAriaLabel
  Toaster->>Sonner: open completion toast
  Sonner-->>showCompletionToast: onUndo / onAutoClose / onDismiss
  showCompletionToast-->>BrainDumpEditor: undoCompleted or confirmClearedCompletion
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related issues

  • issue 108 — changes adjust BrainDump completion timing and the clear/undo window, matching the request for configurable toast duration and dismiss behavior.

Possibly related PRs

  • laststance/corelive#118: Both changes touch BrainDumpEditor timing logic for completion and clear behavior, including undo/linger and deferred removal paths.
  • laststance/corelive#88: Both changes modify BrainDumpEditor’s completion toast and onAutoClose wiring around clear-on-complete behavior.
  • laststance/corelive#84: Both PRs modify src/lib/preferences-sync-channel.ts to register preference actions for cross-window broadcast.

Poem

A bunny tuned the toast just right,
With a close button glinting bright.
“Undo,” it said, “can stay awhile,”
While seconds hopped in measured style.
Thump-thump—completion feels just right 🐇

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: a BrainDump completion toast close button and duration preference.
Linked Issues check ✅ Passed The PR adds the close button, keeps Undo working, adds a persisted millisecond duration preference, and applies it to the next toast.
Out of Scope Changes check ✅ Passed The changes are all supporting pieces for the requested toast and preference feature, with no unrelated scope added.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/109-braindump-toast-controls

Comment @coderabbitai help to get the list of available commands.

@codecov-commenter

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 95.12195% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 67.81%. Comparing base (7118f52) to head (fc556d9).

Files with missing lines Patch % Lines
src/components/braindump/BrainDumpEditor.tsx 90.47% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #119      +/-   ##
==========================================
+ Coverage   67.57%   67.81%   +0.23%     
==========================================
  Files         139      139              
  Lines        4420     4449      +29     
  Branches     1210     1216       +6     
==========================================
+ Hits         2987     3017      +30     
+ Misses       1215     1214       -1     
  Partials      218      218              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@ryota-murakami ryota-murakami merged commit 1dac619 into main Jun 25, 2026
25 checks passed
@ryota-murakami ryota-murakami deleted the feat/109-braindump-toast-controls branch June 25, 2026 00:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

BrainDump completion toast: add a close button + a setting for how long it stays

2 participants