Skip to content

Agentic UI: Make the sidebar site-centric - #4191

Merged
bcotrim merged 8 commits into
trunkfrom
make-sidebar-site-centric
Jul 16, 2026
Merged

Agentic UI: Make the sidebar site-centric#4191
bcotrim merged 8 commits into
trunkfrom
make-sidebar-site-centric

Conversation

@bcotrim

@bcotrim bcotrim commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

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.

  • Clicking a site opens its most recent (non-archived) chat, or starts a new chat when the site has none. Chat history is no longer browsed from the sidebar — that moved below the composer in Add chat history and New chat controls below the composer #4133.
  • Each site row carries a single activity indicator that aggregates all of the site's sessions, with priority: live-site sync > needs an answer > working > new message. This keeps long site lists calm while still surfacing what needs attention.
  • Row quick actions (site actions menu + start/stop status button) appear on hover/focus; drag-to-reorder from Add drag-to-reorder for sites in the agentic UI sidebar #4134 keeps working on the flat rows.
  • Status colors move to shared --studio-color-status-* tokens: the wpds palette has no vivid status colors (--wpds-color-fg-content-success resolves to near-black at dot size), which also fixes the session header's running dot rendering almost black.
  • Chrome polish: full-bleed 44px site icon with overlaid status badge in the site dropdown, flattened site icons, a visible hover tint on the sidebar create button, the floating sidebar toggle moved to the bottom-left, and aligned settings-header padding.

Two product decisions to be aware of (intentional for now):

  • Unread "new message" badges are in-memory only — they reset (seed as all-seen) on every launch.
  • The current chat is indicated via aria-current + active-row styling, not the literal "Current chat" label from the mockups.

Testing Instructions

  • Start Studio with npm start and enable the Agentic UI feature flag.
  • Confirm the sidebar shows a flat list of sites (no chat sublists): clicking a site with chats opens its latest chat; a site without chats opens the new-chat view.
  • Hover a row: the site actions menu and start/stop button appear; right side shows a green dot for running sites, a play affordance for stopped ones.
  • Send a prompt on one site, switch to another: the first row shows a working spinner, then a "New message" badge when the turn completes; answering a pending question clears the "Needs an answer" indicator.
  • Drag a site row to reorder; the order persists across restarts.
  • Delete a site you're currently viewing and confirm you land back on the home view.
  • Check the sidebar and site dropdown in both light and dark mode.

Pre-merge Checklist

  • Have you checked for TypeScript, React or other console errors?

🤖 Generated with Claude Code

bcotrim and others added 3 commits July 14, 2026 11:47
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>
bcotrim and others added 4 commits July 14, 2026 17:46
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.
@bcotrim
bcotrim requested review from a team and katinthehatsite July 15, 2026 10:26
@bcotrim
bcotrim marked this pull request as ready for review July 15, 2026 10:26
@katinthehatsite

Copy link
Copy Markdown
Contributor

I think this mostly looks good but one bit that I am finding strange is that the New chat button essentially seems to do nothing when you already have a chat:

Screen.Recording.2026-07-15.at.8.32.05.PM.mov

When you click it at the bottom, it restarts the chat and opens a new one whivh makes sense but the New chat from the dropdown does not seem to do much. What do you think?

@katinthehatsite katinthehatsite left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Additionally, when I select a site and delete it, I remain on its chat view and can keep on sending messages:

Image
@bcotrim

bcotrim commented Jul 15, 2026

Copy link
Copy Markdown
Contributor Author

I think this mostly looks good but one bit that I am finding strange is that the New chat button essentially seems to do nothing when you already have a chat:
Screen.Recording.2026-07-15.at.8.32.05.PM.mov

When you click it at the bottom, it restarts the chat and opens a new one whivh makes sense but the New chat from the dropdown does not seem to do much. What do you think?

That button is going away with #4177

@bcotrim

bcotrim commented Jul 15, 2026

Copy link
Copy Markdown
Contributor Author

Additionally, when I select a site and delete it, I remain on its chat view and can keep on sending messages:
Image

Behavior when deleting site will be addressed by #4132

@bcotrim
bcotrim requested a review from katinthehatsite July 16, 2026 08:21

@katinthehatsite katinthehatsite left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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
@bcotrim

bcotrim commented Jul 16, 2026

Copy link
Copy Markdown
Contributor Author

Maybe some styling comments could be cleaned up but I think overall, it looks fine 👍

Could you share those in a Linear issue to ensure we don't miss that cleanup as a follow-up, please? 🙇

@bcotrim
bcotrim enabled auto-merge (squash) July 16, 2026 09:21
@wpmobilebot

Copy link
Copy Markdown
Collaborator

📊 Performance Test Results

Comparing 83d0e3b vs trunk

app-size

Metric trunk 83d0e3b Diff Change
App Size (Mac) 1352.92 MB 1352.92 MB 0.00 MB ⚪ 0.0%

site-editor

Metric trunk 83d0e3b Diff Change
load 1041 ms 1086 ms +45 ms ⚪ 0.0%

site-startup

Metric trunk 83d0e3b Diff Change
siteCreation 6991 ms 6986 ms 5 ms ⚪ 0.0%
siteStartup 2353 ms 2355 ms +2 ms ⚪ 0.0%

Results are median values from multiple test runs.

Legend: 🟢 Improvement (faster) | 🔴 Regression (slower) | ⚪ No change (<50ms diff)

@bcotrim
bcotrim merged commit 69fcc1a into trunk Jul 16, 2026
12 checks passed
@bcotrim
bcotrim deleted the make-sidebar-site-centric branch July 16, 2026 09:49
bcotrim added a commit that referenced this pull request Jul 17, 2026
## 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?
bcotrim added a commit that referenced this pull request Jul 17, 2026
)

## 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?
bcotrim added a commit that referenced this pull request Jul 20, 2026
## 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)
bcotrim added a commit that referenced this pull request Jul 21, 2026
…#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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

3 participants