Agentic UI: Make the sidebar site-centric - #4191
Conversation
Replace the sidebar's site+chat sublists with a flat list of site rows. Clicking a row opens the site's latest non-archived chat (or a new-chat route when it has none); chats no longer render in the sidebar. Each row aggregates its sessions' agent activity into one indicator with priority sync > pending question > working > new message. Extracts DeleteSiteDialog into its own component with an onDeleted callback, and forwards onClick/onPointerDown through Menu.Popup so menu clicks don't bubble into row navigation. Co-authored-by: Shaun Andrews <191598+shaunandrews@users.noreply.github.com>
Full-bleed 44px site icon with overlaid status badge in the site dropdown, flattened site-icon (no border/inner shadow), visible hover tint on the sidebar create button, floating sidebar toggle moved to the bottom-left of the main area, and settings-header padding aligned with the new layout. Co-authored-by: Shaun Andrews <191598+shaunandrews@users.noreply.github.com>
Brings over the exploration's AgentWorkingIndicator — a 2×3 grid of brand-blue pixels breathing out of phase — and uses it instead of the generic spinner for a site row's working state, matching the design exploration. Co-authored-by: Shaun Andrews <191598+shaunandrews@users.noreply.github.com>
Inline the UUID-safe settings-path check and single-caller helpers, require hasUnreadUpdate at the call site, drop the unused presentational prop from AgentWorkingIndicator, and collapse the four row-background aliases into one --sidebar-row-background var.
…ntric # Conflicts: # apps/ui/src/components/site-list/style.module.css
The seen/unread bookkeeping keyed off the siteId route param, so sitting on a site's settings page suppressed its unread badge even though the chat wasn't visible. Key it off the open session's site instead, and derive the settings-route outline directly from the route param.
|
I think this mostly looks good but one bit that I am finding strange is that the Screen.Recording.2026-07-15.at.8.32.05.PM.movWhen you click it at the bottom, it restarts the chat and opens a new one whivh makes sense but the |
That button is going away with #4177 |
Behavior when deleting site will be addressed by #4132 |
katinthehatsite
left a comment
There was a problem hiding this comment.
If the issues that I mentioned will be addressed in separate PRs, then the changes look good to me 👍 I did not spot any regressions
Maybe some styling comments could be cleaned up but I think overall, it looks fine 👍
…ntric # Conflicts: # apps/ui/src/components/sidebar-header/index.test.tsx
Could you share those in a Linear issue to ensure we don't miss that cleanup as a follow-up, please? 🙇 |
📊 Performance Test ResultsComparing 83d0e3b 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) |
## Related issues - Fixes [STU-1989](https://linear.app/a8c/issue/STU-1989/improve-site-menu-button-contrast-and-consistency) - Design reference: #3975 (`explore-site-centric-conversation-chrome`) ## How AI was used in this PR Implemented with Claude Code: ported the site-menu trigger/dropdown styling from the design-preview branch onto trunk (resolving overlap with #4191), and verified light/dark rendering in a browser harness before manual review. All changes were reviewed and visually tested by the author. ## Proposed Changes The site menu trigger (the button showing the site name/status that opens publish/preview/settings) sat on a near-transparent background, so it was easy to miss and didn't read as clickable. Its content also changed with sidebar state, since the site icon only appeared when the sidebar was collapsed. - **The trigger now uses an inverted, solid fill** that always contrasts with the surrounding panel — dark-on-light in light mode, light-on-dark in dark mode — using theme-adaptive `--wpds-color-*-interactive-neutral-strong` tokens. - **The dropdown opens on the same inverted surface**, so the button and its menu read as one connected control. The menu's wpds tokens are remapped locally, letting the existing row styles (labels, dividers, hover/disabled states) adapt without per-element overrides. - **The site icon is always visible**, so the button looks the same whether the sidebar is expanded or collapsed. The running/stopped status dot overlays the icon's corner and only shows when the sidebar is collapsed — the expanded sidebar already shows status. - **The start/stop toggle now follows the menu surface.** It previously keyed some colors off the OS color scheme, which landed backwards on the inverted surface (invisible thumb in dark mode). - New `floating` prop on the trigger controls the drop shadow: on for overlay placements (chat header), available to turn off for in-flow header rows. **Note**: The actions from the menu are out of scope for this PR, my goal is to address the layout of the menu only. | Light | Dark | |--------|--------| | <img width="2424" height="1864" alt="image" src="https://github.com/user-attachments/assets/c593bef9-5b8d-4ae6-bc12-b9eecdaa5dcd" /> | <img width="2424" height="1864" alt="image" src="https://github.com/user-attachments/assets/1650aa3d-6545-4bab-8c24-2e5720b3c122" /> | ## Testing Instructions 1. Enable the Agentic UI beta and open a site. 2. Check the site menu button in the chat header and in site settings: solid fill, site icon always visible, status dot on the icon corner only when the sidebar is collapsed. 3. Open the dropdown: it should share the button's surface, with legible rows and a working start/stop toggle (running/stopped/stopping states). 4. Repeat all of the above in **light and dark** mode. ## Pre-merge Checklist - [x] Have you checked for TypeScript, React or other console errors?
) ## Related issues - Fixes STU-1986 ## How AI was used in this PR Implemented with Claude Code using the #3975 design preview as reference: it cherry-picked the frame treatment onto trunk, adapted it to the site-centric sidebar (#4191), and updated the tests. Code reviewed and visually verified by me. ## Proposed Changes The Agentic UI currently renders as a single flat surface — the sidebar and main content sit side by side with no visual hierarchy between app chrome and content, which makes it feel like a different app rather than an evolution of Studio. This brings back "the frame" from the classic Studio UI: - A dark chrome surface fills the app window, including the titlebar/traffic-light region. - The sidebar (sites, user account) sits directly on the dark chrome — no card or panel behind it — in **both** color schemes, with its controls resolving against a dark theme scope. In dark mode the chrome goes a step deeper so it still contrasts with content surfaces. - The main content area (chat + preview) floats within the frame as a lighter, elevated canvas with rounded corners — the same dark-frame-around-a-light-canvas pattern as wp-admin and the site editor. - The exposed chrome doubles as a window drag region; everything inside the content card stays interactive. - Hiding the sidebar sends the content full-bleed, so the collapsed state looks the same as today. | Light | Dark | |--------|--------| | <img width="1832" height="1522" alt="image" src="https://github.com/user-attachments/assets/23e53c2e-a71f-46d3-a5a0-4df40cf254c1" /> | <img width="1832" height="1522" alt="image" src="https://github.com/user-attachments/assets/17298730-aba6-4d8c-a376-8fae6cb346d5" /> | ## Testing Instructions 1. Enable the Agentic UI beta feature flag and launch Studio (`npm start`). 2. Verify the frame: dark surface fills the window including the titlebar region; the content area reads as a lighter rounded card inset within it. 3. Sidebar: site rows' hover/active/selected highlights are visible on the dark chrome; status indicators and popup menus (create menu, user menu, site context menu) render legibly. 4. Drag the window from the chrome gaps around the content card and from the sidebar header; buttons and resize handles must not drag the window. 5. Toggle the sidebar: the card animates to full-bleed and back. Resize the sidebar and the preview split. 6. Open a site preview and verify it stays contained within the rounded card. 7. Repeat the pass in **both light and dark** appearance. 8. Regression: with the feature flag off, the classic UI is unaffected. ## Pre-merge Checklist - [x] Have you checked for TypeScript, React or other console errors?
## Related issues - Fixes STU-2061 ## How AI was used in this PR Claude traced every reference to the `starred` session flag across the codebase, removed the dead plumbing, updated the tests, and ran lint/typecheck/tests. Changes were reviewed and the archive flow was manually tested. ## Proposed Changes The star/unstar UI for chat conversations was removed in #4191, which left the `starred` session-metadata flag as dead plumbing: nothing could set it and nothing displayed it. This PR retires the flag end-to-end — from the shared-config schema, session types and hydration, the IPC handler, the hosted/local PATCH endpoints, and the UI data layer. - Starring was already unreachable, so removing it has no user-visible impact. - No config migration needed: the shared-config schema is loose, so existing `shared.json` files with leftover `starred` entries still parse fine; the stale keys are simply ignored and go away when the chat is deleted. - Based on review feedback: archiving the chat you're currently viewing now opens a new chat instead of leaving you inside the archived conversation. ## Testing Instructions - Search the codebase for `starred` — no references to the removed feature remain. - In the agentic UI, open a chat for a site, archive another chat from the Chat history menu, and confirm it moves to the "Archived chats" dialog. - Archive the chat you're currently on — a new chat should open instead of staying on the archived one. - If your `~/.studio/shared.json` has old `"starred"` entries, everything keeps working; they're just ignored. ## Pre-merge Checklist - [x] Have you checked for TypeScript, React or other console errors? 🤖 Generated with [Claude Code](https://claude.com/claude-code)
…#4130) ## Related issues - Related to STU-1985 — extracted from #3998 as part of splitting it into smaller PRs. ## How AI was used in this PR The core change was cherry-picked from #3998 (authored there with AI assistance). Claude Code ported it onto trunk, resolved merge conflicts (including the moves to id-based session↔site matching from #4131 and the signed-out gates from #4183), addressed review feedback, and wrote the unit tests for the redirect logic. All code was reviewed and verified locally (lint, typecheck, apps/ui test suite). ## Proposed Changes Studio's agentic UI always lands on the first site (in raw fetch order) at launch, regardless of where the user was working. This PR makes the app reopen on the site the user last worked with: - The dashboard remembers the last visited site in `localStorage`. - On launch, the `/` index route opens that site's newest active chat (or a new chat if it has none) — matching exactly what clicking the site in the site-centric sidebar (#4191) does. - If the remembered site no longer exists (deleted) or nothing is stored yet, it falls back to the **top site in sidebar order**, respecting the manual ordering from #4134 instead of raw fetch order. - The sidebar auto-scrolls to keep the restored site's row visible when it sits below the fold (thanks @sejas for catching this!). An earlier revision restored the exact last-visited *session*. We simplified to site-level restore to stay consistent with the site-centric sidebar model: sites are the primary navigation unit, and a site always opens its newest active chat. No launch-time cost: the index route already fetched sites and sessions before redirecting; this adds only a synchronous `localStorage` read. ## Testing Instructions 1. Launch Studio with the agentic UI and open a chat on a site other than the top one in the sidebar. 2. Quit and relaunch — you should land on that same site (its newest active chat). 3. With enough sites to make the sidebar scroll, work on a site near the bottom, relaunch — the sidebar should scroll so the selected site's row is visible. 4. Archive the chat you were on, relaunch — you should land on that site's newest remaining active chat, or a new chat if none are left. 5. Delete the site you were on, relaunch — you should land on your sidebar's top site, with no errors. 6. Drag a different site to the top of the sidebar, clear the app's localStorage, relaunch — the fallback should follow your sidebar order. ## Pre-merge Checklist - [x] Have you checked for TypeScript, React or other console errors? 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Shaun Andrews <shaun@automattic.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com>


Related issues
How AI was used in this PR
Claude (Fable 5) extracted and adapted this change from the #3998 reference branch under close direction, preserving Shaun Andrews' original work via co-authored commits, and re-verified the result (typecheck, unit tests, light/dark visual pass in the browser UI). Code was human-reviewed throughout.
Proposed Changes
This is the capstone of the site-centric sidebar work: the sidebar becomes a flat list of sites, with no per-site chat sublists.
--studio-color-status-*tokens: the wpds palette has no vivid status colors (--wpds-color-fg-content-successresolves to near-black at dot size), which also fixes the session header's running dot rendering almost black.Two product decisions to be aware of (intentional for now):
aria-current+ active-row styling, not the literal "Current chat" label from the mockups.Testing Instructions
npm startand enable theAgentic UIfeature flag.Pre-merge Checklist
🤖 Generated with Claude Code