Skip to content

Agentic UI: Simplify Sidebar with new Site-Centric Focus#3998

Closed
shaunandrews wants to merge 14 commits into
trunkfrom
extract-site-centric-sidebar
Closed

Agentic UI: Simplify Sidebar with new Site-Centric Focus#3998
shaunandrews wants to merge 14 commits into
trunkfrom
extract-site-centric-sidebar

Conversation

@shaunandrews

@shaunandrews shaunandrews commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Related issues

  • None

How AI was used in this PR

Codex helped extract and iterate on the site-centric Agentic UI sidebar, then verified the final branch with linting, typecheck, targeted tests, and a running local app session. Claude Code later ported the latest sidebar-relevant refinements from the exploration branch (explore-site-centric-conversation-chrome) and re-verified with lint, typecheck, and the targeted tests. The PR remains draft because it is a visual/navigation change that needs human review in the app.

Executive summary

This PR simplifies Agentic UI around sites as the primary object. The sidebar no longer behaves like a chat list; it focuses on local sites, their status, and their latest conversation. Chat creation and chat history moved into the chat panel footer so previous conversations remain reachable without making the sidebar carry two navigation models.

Site rows now open the latest chat, or start a new site chat when no chat exists. Site settings remain available through the existing settings route.

Proposed Changes

  • Makes the Agentic UI sidebar site-centric, with site rows focused on site names, run state, activity, and latest chat navigation.
  • Adds chat-panel footer controls for chat history and new chat, including tooltips and the New Chat keyboard shortcut.
  • Keeps the sidebar collapsed/open toggle aligned with the same footer control row and removes opacity/hover complexity from the sidebar footer account/toggle controls.
  • Keeps the preview panel governed by the user's preview toggle on preview-capable chat routes.
  • Replaces the site list's hand-rolled drag-reorder machinery with a shared, generic ReorderableList component (same behavior, less code, reusable for future sidebar groups).
  • Returns the user to their last visited chat or site on launch, instead of always landing on the first site in the list.
  • Wraps the delete-site dialog body in Dialog.Content for correct popup spacing, and gives the sidebar's create button a visible hover tint in both color schemes.

Review guide

  • Review the sidebar behavior first: selecting a site should open its latest active chat, stopped/running site controls should still work, and settings-context styling should not make the site row look like the active chat.
  • Review the new chat/history footer controls in narrow and wide chat panels, with the sidebar open and closed. The controls should align with nearby footer controls and should not collide with the composer.
  • Review keyboard and tooltip behavior for New Chat and Chat History.
  • Review light and dark appearances because this is primarily layout and visual polish.

Okay to skim

  • Mechanical cleanup of no-longer-used route, connector, query, and type plumbing.
  • CSS cleanup that only removes styles for deleted sidebar-row affordances.

Diff breakdown

  • Sidebar and site list: site-centric rows, row action cleanup, footer alignment updates.
  • Chat panel: footer actions for history and new chat, plus tests for ordering, labels, tooltips, timestamps, and shortcut behavior.
  • Routing/data: simplified site navigation and removed unused data paths.
  • Tests: updated site list and footer action coverage around the new navigation model.
  • Reorderable list: new shared apps/ui/src/components/reorderable-list component; the site list now consumes it. Existing drag-reorder tests cover the swap unchanged.
  • Last visited: new apps/ui/src/lib/last-visited.ts helper, recorded by the dashboard layout and read by the / index route.

Known tradeoffs and follow-ups

  • Any additional site-level actions should move into clear existing surfaces rather than adding another sidebar navigation mode.
  • The PR is still visual-heavy; reviewers should do a hands-on pass in both color schemes.
  • Existing local runtime noise was observed during app launch, including the known allowpopups warning. No new typecheck or targeted test failures were observed.

Safety checklist

  • Feature-flag/gating: limited to Agentic UI paths in apps/ui.
  • Data migrations or persistence changes: none.
  • API compatibility: only unused Agentic UI data plumbing was removed.
  • Default UI impact: changes Agentic UI navigation and footer controls only.
  • Performance: removes an unused site-details data path.
  • Security and privacy: no new data collection or credential handling.
  • Rollback plan: revert this PR or the final refinement commit to restore the previous sidebar/chat behavior.
  • Human visual review completed in light and dark mode.

Testing Instructions

  • Run npm run typecheck.
  • Run npm test -- apps/ui/src/components/site-list/index.test.tsx apps/ui/src/components/user-menu/index.test.tsx apps/ui/src/components/sidebar-layout/index.test.tsx apps/ui/src/ui-classic/components/session-view/session-chat-actions.test.tsx.
  • Run npm start and confirm Studio launches from this branch.
  • In the app, review the site-centric sidebar, site run controls, collapsed/open sidebar toggle, chat history control, New chat control, and composer/footer alignment in both light and dark appearances.

Pre-merge Checklist

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

@shaunandrews shaunandrews changed the title Extract site-centric sidebar changes Agentic UI: Simplify Sidebar with new Site-Centric Focus Jun 30, 2026
shaunandrews and others added 9 commits June 30, 2026 16:03
Removes the dead toggleSpacer markup and now-unused agent-run hooks, dedupes findActiveSiteKey via findSessionSiteKey, measures drag slot boundaries once at drag start instead of per pointermove, stabilizes the New chat shortcut handler, reverts the stray allowpopups cast, and simplifies the floating-toggle CSS.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Drops the local Tooltip.Provider delay={ 0 } wrappers on the chat footer, composer toolbar, and site dropdown so every tooltip inherits the app-wide provider's default hover delay and shares its hover group. Moves the zero delay into the composer test harness to keep those assertions deterministic.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@shaunandrews
shaunandrews marked this pull request as ready for review July 3, 2026 18:13
shaunandrews and others added 2 commits July 3, 2026 14:21
…-sidebar

# Conflicts:
#	apps/ui/src/components/sidebar-header/index.tsx
#	apps/ui/src/components/sidebar-layout/index.tsx
#	apps/ui/src/components/sidebar-layout/style.module.css
#	apps/ui/src/components/site-settings-view/index.tsx
#	apps/ui/src/components/site-settings-view/style.module.css
#	apps/ui/src/components/user-menu/index.tsx
#	apps/ui/src/ui-classic/components/session-view/index.tsx
#	apps/ui/src/ui-classic/components/session-view/style.module.css
…toggle

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@wpmobilebot

wpmobilebot commented Jul 3, 2026

Copy link
Copy Markdown
Collaborator

📊 Performance Test Results

Comparing f027d2d vs trunk

app-size

Metric trunk f027d2d Diff Change
App Size (Mac) 1412.01 MB 1344.91 MB 67.11 MB 🟢 -4.8%

site-editor

Metric trunk f027d2d Diff Change
load 749 ms 1119 ms +370 ms 🔴 49.4%

site-startup

Metric trunk f027d2d Diff Change
siteCreation 6499 ms 6502 ms +3 ms ⚪ 0.0%
siteStartup 2399 ms 1863 ms 536 ms 🟢 -22.3%

Results are median values from multiple test runs.

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

bcotrim added a commit that referenced this pull request Jul 13, 2026
…4129)

## Related issues

- Related to STU-1985 — piece 1 of splitting #3998 into small PRs

## How AI was used in this PR

Commit cherry-picked from #3998 (authored by @shaunandrews with AI
assistance); Claude Code handled the cherry-pick onto trunk and ran
lint/typecheck/tests.

## Proposed Changes

- The composer toolbar (add-attachment, model pill, stop, send) and the
site dropdown trigger each wrapped their tooltip in a local
`Tooltip.Provider delay={ 0 }`, so those tooltips popped instantly while
the rest of the app used the default hover delay.
- Drops the local overrides so every tooltip inherits the app-wide
provider (`AppProviders`) and its default delay/hover group — one
consistent tooltip feel across the app.
- The composer test harness keeps a zero delay locally so its assertions
stay deterministic.

## Testing Instructions

- Open the agentic UI and hover the composer buttons (attachment, model
pill, send/stop) and the site dropdown trigger.
- Tooltips should appear after the same default hover delay as other
tooltips in the app (no longer instantly), and still display correctly.

## 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 Opus 4.8 <noreply@anthropic.com>
bcotrim added a commit that referenced this pull request Jul 13, 2026
## Related issues

- Related to STU-1985 (follow-up: splitting the work around #3998 into
small PRs)

## How AI was used in this PR

Implemented with Claude Code from a detailed plan (target location,
migration hook point, race handling). Code, migration tests, and
verification steps reviewed by me.

## Proposed Changes

AI chat sessions were the last piece of Studio state still living in the
Electron `userData` dir (`~/Library/Application
Support/Studio/sessions`, `%APPDATA%\Studio\sessions`) — a historical
accident: sessions shipped (#2767) just before the `~/.studio` config
split (#2793), and only the config JSONs moved. This PR consolidates
sessions under `~/.studio/sessions`, resolved via a new
`getSessionsDirectory()` helper in `well-known-paths.ts` next to the
other config paths.

Existing sessions are migrated by a shared `Migration` registered in
**both** existing migration pipelines — the CLI's (runs as yargs
middleware on every invocation) and the desktop's (runs at boot, before
the main window exists) — so it covers CLI-only and desktop-only users
alike. A lockfile serializes concurrent desktop + CLI first runs.

After moving the files, the migration **leaves a symlink at the legacy
location** (a junction on Windows — no privileges needed) pointing at
`~/.studio/sessions`. That makes the move transparent to everything that
still resolves the old path: older Studio/CLI versions running next to a
newer one keep reading *and writing* the same store, and absolute paths
persisted inside session entries (e.g. screenshot artifacts from
`take_screenshot`) keep resolving — no session data rewriting needed. If
linking fails (e.g. network-redirected `%APPDATA%`), the migration
degrades to a self-healing merge that sweeps straggler files into the
new root on every run — destination wins on collisions, cross-volume
moves fall back to copy+remove. Failures are logged with
home-dir-sanitized paths; success is silent like the other CLI
migrations.

User impact: none visible — sessions and their screenshots keep working
in both the desktop app and the CLI, from the new location, across
version skew between surfaces. The E2E path overrides
(`E2E_APP_DATA_PATH`) keep their previous semantics, and the migration
is skipped under E2E/dev sandboxes so test runs can't touch real
sessions. The experimental hosted backend's session path was updated to
match so it keeps reading the same sessions desktop/CLI write.

## Testing Instructions

1. With existing sessions under the old location (`~/Library/Application
Support/Studio/sessions`), run `npm run cli:build && node
apps/cli/dist/cli/main.mjs code sessions list` — all sessions listed,
files now under `~/.studio/sessions`, old path is now a symlink to it
(`ls -l`).
2. Run it again — idempotent no-op, same list.
3. Old-version compatibility: with the link in place, sessions written
to the old path (simulating an outdated surface) land in
`~/.studio/sessions`, and old screenshot artifacts render in the desktop
conversation view (their persisted absolute paths resolve through the
link).
4. Start the desktop app, open Studio Code — session history intact, new
sessions land under `~/.studio/sessions/YYYY/MM/DD/`.
5. Fresh setup (no old dir): sessions are created directly under
`~/.studio/sessions`.

To revert the migration between scenarios (removes the link, then moves
the sessions back so the migration runs again — bare `rm` refuses to
delete a real directory, so it only ever removes the link):

```bash
# macOS
rm ~/Library/Application\ Support/Studio/sessions && mv ~/.studio/sessions ~/Library/Application\ Support/Studio/sessions
```

```powershell
# Windows (PowerShell)
(Get-Item $env:APPDATA\Studio\sessions).Delete(); Move-Item ~\.studio\sessions $env:APPDATA\Studio\sessions
```

## Pre-merge Checklist

- [x] Have you checked for TypeScript, React or other console errors?
bcotrim added a commit that referenced this pull request Jul 14, 2026
## Related issues

- Related to STU-1985 (splitting #3998 into reviewable pieces)
- Extracted from #3998 (`extract-site-centric-sidebar`)

## How AI was used in this PR

Claude Code ported the `ReorderableList` component verbatim from #3998
(Shaun's commit, preserved as author), adapted the order-persistence
wiring from the reference branch onto trunk's group-based sidebar, and
adapted/extended the tests. All changes reviewed and verified locally
(lint, typecheck, unit tests).

## Proposed Changes

Sites in the agentic UI sidebar can now be reordered by dragging, so
users can arrange their list to match how they work instead of being
stuck with an imposed order.

- Dragging a site's header row lifts it into a floating preview with a
drop placeholder and smooth FLIP animations (disabled under
`prefers-reduced-motion`); clicks, chat links, and action buttons keep
working as before.
- While a drag is active, every site's chat sublist collapses so rows
are uniform and long lists are easy to rearrange, and dragging near the
sidebar's top or bottom edge auto-scrolls the list.
- The order persists via the same per-site `sortOrder` appdata field the
legacy sidebar uses, so a custom order survives restarts and stays
consistent between both sidebars. The renderer owns the order for the
session — seeded once at startup, changed only by drags — so background
refetches can never reorder or flicker the list; the saved order is also
patched into the persisted query cache so a reload paints the right
order immediately (review feedback). In the browser (`studio ui` /
hosted), where there is no appdata, the order is kept in `localStorage`.
- Behavior change: the sidebar previously sorted sites by most-recent
chat activity; it now uses the stored `sortOrder` (falling back to
name), so the list stays stable and only changes when the user
rearranges it. Chats not assigned to a known site (the old "Unassigned"
group) are no longer shown; that logic gets cleaned up in a follow-up
PR.

The drag mechanics live in a generic `ReorderableList` component
(pointer-event based, 4px drag threshold, drop hit-testing against rects
captured at drag start, post-drag click suppression) that later pieces
of the #3998 split will reuse.

## Testing Instructions

1. `npm start`, open the agentic UI with a few sites created.
2. Drag a site by its header row: a floating preview follows the
pointer, a placeholder marks the drop slot, and other rows animate out
of the way. Drop it and confirm the new order.
3. Restart the app — the order should persist.
4. Confirm normal interactions still work: clicking a site header
toggles its chats, chat links navigate, the status/new-chat/menu buttons
work, and dragging from the chat sublist does **not** reorder.
5. Check the drag visuals in both light and dark mode.

## Pre-merge Checklist

- [x] Have you checked for TypeScript, React or other console errors?

---------

Co-authored-by: Shaun Andrews <shaun@automattic.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
bcotrim added a commit that referenced this pull request Jul 14, 2026
## Related issues

- Related to STU-1985 (chat-history-below-composer thread of the split;
does not close the issue)
- Split from #3998 (`extract-site-centric-sidebar`) — "add" half of the
add-before-remove sequencing: this PR adds the session chat controls
below the composer while the sidebar keeps its current chat sublists; a
follow-up PR makes the sidebar site-centric.

## How AI was used in this PR

Claude Code adapted the session-chrome portion of @shaunandrews'
`extract-site-centric-sidebar` branch onto trunk (his authorship is
preserved via `Co-authored-by`), and implemented the ⌘N accelerator fix.
All changes reviewed by @bcotrim.

## Proposed Changes

We want chat access to live with the conversation rather than in the
sidebar, and to discourage multiple concurrent chats per site. This PR
adds a footer row below the composer in the agentic UI (`apps/ui`) for
sessions that belong to a site:

- **Chat history menu**: opens upward, lists the site's chats
newest-first with first-prompt titles and relative timestamps, marks the
current chat, and offers a per-row archive action on hover. Empty state
shows "No chats yet".
- **Archived chats dialog**: reachable from the history menu (entry
shows the count); selecting an archived chat reopens it.
- **New chat button**: creates a fresh session for the current site and
navigates to it; disabled while creating; ⌘N/Ctrl+N shortcut shown in
the tooltip.
- **⌘N conflict fix**: the desktop menu bound `CommandOrControl+N` to
"File → Add Site…", which consumed the key before the renderer ever saw
it — so the New chat shortcut could never work in the desktop app. When
the agentic UI is active, the menu item no longer registers the
accelerator (the item itself remains). The classic UI keeps ⌘N for Add
Site unchanged.

## Testing Instructions

Enable the **Agentic UI** feature flag and open a chat session that
belongs to a site:

1. A footer row appears bottom-left below the composer with a history
button and a "New chat" button; while the session is loading, the layout
doesn't jump.
2. Open the chat history menu: it opens upward, lists only this site's
non-archived chats newest-first, titles from the first prompt
(truncating cleanly when long), relative timestamps, and the active chat
highlighted/marked as current.
3. Hover a history row: the timestamp swaps to an archive button;
archiving removes the chat from the menu and it appears in the "Archived
chats" dialog (menu entry shows the count). Reopening an archived chat
switches to it.
4. Click "New chat" (or press ⌘N/Ctrl+N): a fresh session for the site
is created and opened; the button is disabled while creating; the
tooltip shows the shortcut.
5. **Desktop ⌘N**: with the agentic UI active, File → Add Site… shows no
⌘N shortcut and ⌘N starts a new chat. With the flag off (classic UI), ⌘N
still opens Add Site. Toggling the flag from the dev Feature Flags menu
updates the menu after the renderer reloads.
6. A site with no other chats shows "No chats yet" in the menu.
7. Verify in both light and dark mode.

## Pre-merge Checklist

- [ ] Have you checked for TypeScript, React or other console errors?

---------

Co-authored-by: Shaun Andrews <191598+shaunandrews@users.noreply.github.com>
@bcotrim
bcotrim marked this pull request as draft July 14, 2026 16:21
bcotrim added a commit that referenced this pull request Jul 16, 2026
## Related issues

- Related to STU-1985
- Final extraction from #3998 (built on the already-landed #4131, #4133,
and #4134)

## 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 #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 #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

- [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 <191598+shaunandrews@users.noreply.github.com>
@bcotrim

bcotrim commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

@bcotrim bcotrim closed this Jul 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants