Agentic UI: Add toasts for notifications - #4203
Conversation
There was a problem hiding this comment.
Pull request overview
This PR adds an app-wide toast notification system to the Agentic UI (apps/ui) and wires it into key site lifecycle and sync flows, rendering the toasts in the sidebar footer (expanded) or as a floating shelf (collapsed).
Changes:
- Introduces a module-level toast store (
app-messages.ts) with queuing, timed expiry, and pause-on-hover behavior, plus unit tests. - Adds a new
<AppToasts />renderer component and mounts it viaSidebarLayoutfor both expanded and collapsed sidebar modes. - Emits success/error toasts from react-query mutations for start/stop, settings save, preview publish, push/pull, and import completion.
Reviewed changes
Copilot reviewed 10 out of 11 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| package-lock.json | Updates a package bin path entry (lockfile-only change). |
| apps/ui/src/data/queries/use-sync-site.ts | Adds push/pull success and error toasts. |
| apps/ui/src/data/queries/use-sites.ts | Adds toasts for copy/start/stop and settings save success. |
| apps/ui/src/data/queries/use-preview-site.ts | Adds preview publish success/error toasts. |
| apps/ui/src/data/queries/use-import-site.ts | Adds an “Import finished” success toast after import completes. |
| apps/ui/src/data/app-messages.ts | Implements the toast store (visibility cap, queueing, timers, hover pause/resume). |
| apps/ui/src/data/app-messages.test.ts | Adds vitest coverage for toast lifecycle, queue promotion, and timer behavior. |
| apps/ui/src/components/sidebar-layout/style.module.css | Adds layout styles for sidebar and floating toast placement. |
| apps/ui/src/components/sidebar-layout/index.tsx | Mounts <AppToasts /> in expanded footer and collapsed floating position. |
| apps/ui/src/components/app-toasts/style.module.css | Adds toast stack/animation styling and theming overrides for Notice/Button. |
| apps/ui/src/components/app-toasts/index.tsx | Adds the toast renderer component (Notice-based UI, dismiss + optional action). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
📊 Performance Test ResultsComparing d09b9f3 vs trunk app-size
site-editor
site-startup
Results are median values from multiple test runs. Legend: 🟢 Improvement (faster) | 🔴 Regression (slower) | ⚪ No change (<50ms diff) |
bcotrim
left a comment
There was a problem hiding this comment.
Great work on this! 👍
Something I think we could improve, noticed during testing — while the "create a site" screen is open, the toast timers keep ticking, so users will likely miss them. I'm not sure the toasts should appear over that screen (my feeling is probably not), so the timers could pause while the toasts aren't rendered. If this requires a complex change, maybe we can skip it, but let's explore.
It did not seem too complex so I added this suggestion, let me know what you think |
bcotrim
left a comment
There was a problem hiding this comment.
Nice and simple solution, thanks for looking into it!
LGTM 👍
## Related issues Related to STU-1984 Builds on #4203 (toast notifications), which landed separately. ## How AI was used in this PR The initial implementation is @katinthehatsite's work from the original branch. The follow-up work — addressing review findings, simplifying the dismissal plumbing, and merging trunk — was done with Claude Code and reviewed before pushing. ## Proposed Changes Adds **persistent message cards** to the Agentic UI sidebar. Unlike the toasts from #4203, which fade on their own, these stay until the user acts on them or dismisses them — for things the user needs to see even if they looked away. The first (and currently only) card tells the user when an **app update has been downloaded and is ready to install**: - The card appears in the sidebar footer with a **Restart now** button that installs the update immediately, instead of waiting for the user to happen to quit. - With the sidebar collapsed, a small dot on the sidebar toggle signals that a message is waiting. - Dismissing hides the card for the current session only. Persisting the dismissal isn't needed: restarting Studio installs the pending update, so the card's reason to exist is gone after any restart. If Studio stays open long enough for a *newer* version to download, the card comes back — dismissals are version-scoped. - Card content is derived at render time from the current update status, so nothing user-facing is stored and a locale change re-renders it translated. The card layer is deliberately generic (a list of messages filtered by dismissed ids), so future messages — onboarding checklists, announcements — can plug into it. If one of those ever needs a dismissal that outlives a restart, that's the point to add persisted storage for it. ## Testing Instructions The update card only appears when the auto-updater has actually downloaded an update, so fake it locally: 1. Run with the Agentic UI enabled: `ENABLE_AGENTIC_UI=true npm start` 2. At the top of `setupUpdates()` in `apps/studio/src/updates.ts`, add: ```ts updaterState = 'waiting-for-restart'; downloadedVersion = '99.9.9'; setTimeout( () => { downloadedVersion = '99.9.10'; void sendIpcEventToRenderer( 'app-update-status', buildAppUpdateStatus() ); }, 20_000 ); return; ``` Restart the app fully — this is main-process code, so hot reload won't pick it up. 3. Confirm the card **"Studio 99.9.9 is ready to install"** appears in the sidebar footer. 4. Dismiss it → it animates out and stays hidden. 5. Wait for the 20s mark → the `99.9.10` card appears, confirming both the live IPC push and that dismissals are version-scoped. 6. Collapse the sidebar while a card is active → a dot appears on the sidebar toggle button. 7. Click **Restart now** → the app quits (with a real update it relaunches into the new version). 8. Check the card in **both light and dark mode**. 9. Remove the fake before merging. ## Pre-merge Checklist - [ ] Have you checked for TypeScript, React or other console errors? - [ ] Verified in both light and dark mode --------- Co-authored-by: Kateryna Kodonenko <kateryna@automattic.com> Co-authored-by: bcotrim <bernardo.cotrim@a8c.com> Co-authored-by: Bernardo Cotrim <bmmcotrim@gmail.com>
Related issues
Related to STU-1984
How AI was used in this PR
It was used to analyse the proposal in
explore-site-centric-conversation-chromebranch (commit1d0b08c04) and adapt it as the first step for adding system notifications.Proposed Changes
This PR introduces the toast notifications for when:
Dark mode
Light mode
Sidebar collapsed
Testing Instructions
npm startAgentic UIfeature flag fromStudio -> Feature flagsfrom the topbarPre-merge Checklist