Refine light-mode sidebar surfaces#4268
Conversation
- Improve light-mode contrast for rows, controls, and separators - Use neutral sidebar tokens and preserve dark-mode styling
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
ApprovabilityVerdict: Needs human review 1 blocking correctness issue found. This PR combines significant feature additions (project filtering, Thread List V2 sidebar support, command palette shortcuts) with styling refinements. Three unresolved medium-severity issues remain: keyboard focus visibility, CSS tokens not applying in mobile portals, and jump shortcuts mismatching filtered order. You can customize Macroscope's approvability policy. Learn more. |
… rings The previous light pass set the rail to near-white (oklch 0.992) with pure white borderless cards on top, so the surface hierarchy collapsed. Drop the rail to a light zinc (oklch 0.972) and lift every card/control off it as a white object with a hairline ring: resting cards get a faint ring + shadow, quiet (receded) cards go 70% white, hover deepens the ring, and the active row becomes a crisp white pill (ring-black/13 + shadow). Selected rows use a solid neutral tint. Scoped project chips get the same lifted-pill treatment while unscoped chips stay quiet outlines. Dark mode keeps the original graphite fills unchanged (verified against pre-change computed styles). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The translucent lower chrome lets the composer shadow taper into the message canvas, but over the terminal drawer it rendered as a dirty light-to-black gradient. Tag the chrome with data-terminal-open and switch it to the opaque workspace background so the drawer border defines the boundary instead. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The v2 cards used a black tint (2.5-4%) on the already-gray #f2f2f7 light screen, reading dingy — the same failure just fixed in the web sidebar. Follow the iOS grouped-list convention instead: cards are white surfaces on the gray screen (quiet ready rows at 70% opacity so active work pops), and the selected project-scope chip becomes a lifted white pill with a stronger border while unscoped chips stay quiet outlines. Dark mode keeps the original graphite tints via explicit dark: variants. Verified on the iOS Simulator (iPhone 16 Pro, light + dark) against a seeded local environment. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The rounded tonal cards read wrong on the phone in both schemes. Render active threads as edge-to-edge rows on the screen background with an inset hairline separator — colored status labels and text hierarchy carry state, matching the settled tail's flat style so the whole list is one surface. The opaque row background stays so swipe actions reveal behind it. Verified on the iOS Simulator in light and dark. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sidebar v1 and the mobile Live Activity/widgets established amber for approval, indigo for input, and sky for working — but sidebar v2 (web and the mobile thread list) collapsed input into approval's amber and shifted working to plain blue, so the same thread wore different colors across surfaces and the two waiting-on-you states were indistinguishable at a glance. Restore the convention in both v2 lists. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Desktop cards mark remote threads with a cloud icon and a "Running on ..." tooltip; mobile rows carried no environment signal at all. Phones have no hover, so render the environment label as quiet text in the row's meta line — and only when more than one environment is connected, since repeating a single machine's name on every row is noise. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The row already subscribed to the thread's PR (for merged/closed auto-settle) but never showed it, while desktop cards render a state-colored #number badge. Reuse the shared ThreadPrPresentation — the same label/color source as the v1 rows — in the meta line between the branch and the provider icon, mirroring the desktop order. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Branch + PR + provider + machine on one meta line truncated the branch on ordinary phone widths. Move the machine up beside the project title as "project · machine" — both answer where the thread lives — leaving the meta line to branch, PR, and provider. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The sidebar pane (ThreadNavigationSidebar) only knew the v1 grouped list, so the Thread List v2 beta silently did nothing on iPad. Reuse the shared v2 partition (buildThreadListV2Items) and row component: when the beta is on, the sidebar renders the flat creation-order card block and settled tail — with statuses, PR badges, provider logos, machine labels, swipe settle/un-settle, and Show more paging — scoped by the sidebar's existing environment filter and search. Split view needs to mark the thread open in the detail pane, so ThreadListV2Row gains a `selected` tint (compact Home never sets it) and a fullSwipeWidth override for narrow panes. The settled paging constants move to threadListV2.ts so both surfaces page identically. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The first iPad pass reused the compact-Home row shell verbatim, painting opaque bg-screen slabs with square-edged selection tints onto the sidebar's drawer surface — a visibly mismatched gray block. Give ThreadListV2Row a pane variant instead: "screen" keeps the flat edge-to-edge phone idiom, "sidebar" renders rounded rows that blend into the drawer with the accent-filled white-text selection the v1 sidebar rows use (every colored row fragment gains an on-accent variant), pane- scoped paddings, and a rounded swipe container. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Dismissing prior approval to re-evaluate ab492a5
…sidebar # Conflicts: # apps/web/src/components/SidebarV2.tsx
…e clock Four review findings on the Thread List v2 surfaces: - The filter menus (iPad sidebar, iOS and Android Home headers) kept offering Sort projects / Sort threads / Group projects while v2 silently ignored them — its layout is fixed creation order. Hide those submenus when the beta is on (the environment filter still applies) and key the "customized" icon state off the environment alone. - The sidebar v2 list dropped queued offline tasks entirely; render them above the thread rows with the sidebar row treatment, respecting the environment scope and search filter (mirrors the compact Home v2 list). - nowMinute was captured at mount but the tick only started once v2 was enabled, so flipping the beta on after a long v1 session partitioned with an hours-old clock until the first tick. Refresh it on enable, in both the sidebar and the compact Home list. - The compact Home v2 FlatList's extraData omitted savedConnectionsById, so connection changes didn't invalidate rows' machine labels. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Add project scope menus and filter state across home and sidebar views - Refresh dynamic native header menus as project data loads - Add coverage for project filter menu actions
Dismissing prior approval to re-evaluate ddc8c71
Co-authored-by: codex <codex@users.noreply.github.com>
Co-authored-by: codex <codex@users.noreply.github.com>
Co-authored-by: codex <codex@users.noreply.github.com>
The compact Home list carried a horizontal project-chip scroller above the v2 threads, duplicating the project filter that now lives in the header filter menu. Remove the chip row and its component — the menu entry is the single scoping mechanism on mobile; the chip idiom stays desktop-only. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
"project · machine" crowded the top line into truncation while non-git projects left the meta row empty with a lone provider icon. Pair the machine with the branch instead — "branch · machine" on one truncating line, machine last so a tight fit cuts the repetitive label rather than the branch, and machine-only filling the row when there is no branch. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: codex <codex@users.noreply.github.com>
Co-authored-by: codex <codex@users.noreply.github.com>
| ? "bg-muted text-foreground" | ||
| : shouldRecede | ||
| ? "text-muted-foreground/75 hover:bg-muted hover:text-foreground" | ||
| : "bg-transparent text-foreground hover:bg-muted", |
There was a problem hiding this comment.
Thread rows hide keyboard focus
Medium Severity
The rowSurfaceClassName applies outline-none to focusable sidebar rows, removing the visual focus indicator for keyboard users. This impacts both slim and card rows, as no focus-visible styling is present to compensate.
Reviewed by Cursor Bugbot for commit 10f29ef. Configure here.
- Align sidebar surfaces, controls, states, and contrast with theme tokens - Add thread detail tooltips and streamlined project scope controls
| global chrome background, or the fade shows a seam (same rule as the | ||
| light palette above). */ | ||
| --sidebar-stage-fade: var(--card); | ||
| [data-sidebar-version="v2"] { |
There was a problem hiding this comment.
🟡 Medium src/index.css:501
The Sidebar V2 token overrides on [data-sidebar-version="v2"] never apply on mobile because Sheet/Dialog.Root receives the data-sidebar-version attribute but SheetPopup is rendered through a portal that does not inherit it. The portaled popup falls back to the root sidebar tokens (--sidebar: var(--card), etc.), so V2 row colors, borders, and surfaces are lost on mobile. Apply data-sidebar-version="v2" (or the token overrides) to the portaled popup or an ancestor inside the portal.
🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file @apps/web/src/index.css around line 501:
The Sidebar V2 token overrides on `[data-sidebar-version="v2"]` never apply on mobile because `Sheet`/`Dialog.Root` receives the `data-sidebar-version` attribute but `SheetPopup` is rendered through a portal that does not inherit it. The portaled popup falls back to the root sidebar tokens (`--sidebar: var(--card)`, etc.), so V2 row colors, borders, and surfaces are lost on mobile. Apply `data-sidebar-version="v2"` (or the token overrides) to the portaled popup or an ancestor inside the portal.
- Normalize sidebar colors and surfaces across app and settings navigation - Restore positional command-palette shortcuts for project items
| return itemWithoutShortcut; | ||
| }); | ||
| } | ||
|
|
There was a problem hiding this comment.
Jump keys ignore filtered order
Medium Severity
enumerateCommandPaletteItems binds thread.jump.1–9 from the original project list index, but filterCommandPaletteGroups re-sorts and drops rows when the palette query is non-empty. Visible row order and shortcut badges no longer match, and handleKeyDown still resolves jumps by the stale shortcutCommand on each item.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 4168fec. Configure here.
- Add compact action sizing for slim mobile thread-list rows - Preserve full-row press targets while reducing action visuals
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.
There are 3 total unresolved issues (including 2 from previous reviews).
Bugbot Autofix is ON, but a cloud agent failed to start.
Reviewed by Cursor Bugbot for commit 89830a0. Configure here.
| { height: 14, justifyContent: "center", paddingTop: props.compact ? 0 : 2 }, | ||
| labelStyle, | ||
| ]} | ||
| > |
There was a problem hiding this comment.
Swipe label clipped non-compact
Low Severity
SwipeActionButton now fixes the label wrapper at 14px tall for every mode, but non-compact actions still apply 2px top padding while the label uses 14px line height. That leaves only 12px for the text, so action captions like Delete or Un-settle can clip on card rows and other non-compact swipe surfaces.
Reviewed by Cursor Bugbot for commit 89830a0. Configure here.
Merge resolves the SidebarV2 restyle (#4268) by re-applying snooze onto the new surface model (sidebar tokens, thread tooltips, restyled action buttons), and folds in serverSelfUpdate capability alongside threadSnooze. Review fixes: - Snooze classification now uses a precise clock instead of the minute-quantized partition time, plus a timeout armed at the earliest upcoming wake — the shelf empties the moment a snooze expires instead of up to a minute late (Cursor) - thread.snooze now rejects queued turn starts exactly like thread.settle, server-side (shared threadHasQueuedTurnStart helper) and client-side (canSnooze gains the hasQueuedTurnStart check) (Cursor) - threadWokeAt keeps an early hand-raise wake authoritative after the scheduled wake time passes, so a visited-and-cleared Woke pill cannot resurface when snoozedUntil elapses (Macroscope) - resolveSnoozePresets advances calendar days with setDate instead of DAY_MS offsets, fixing tomorrow/next-week presets across DST transitions (Macroscope) - Documented why hasOpenBlockingRequest's scan of the 500-capped activities array is sound for the snooze invariant (Macroscope) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com> Co-authored-by: codex <codex@users.noreply.github.com>


Summary
Testing
Note
Medium Risk
Touches primary navigation (mobile home/sidebar and web sidebar v2) and list filtering across v1/v2 code paths; behavior is mostly UI but incorrect scoping or header menu staleness would confuse users.
Overview
Mobile moves project scoping from inline chips into the home header filter menu (Android + iOS), wires that selection through
HomeRouteScreen/HomeScreen, and applies it to both the legacy grouped list and Thread List v2. When Thread List v2 is on, sort/group controls are hidden because the list ignores them; the filter “customized” state only reflects environment and project. The iPad navigation sidebar gains the same v2 flat list (pending tasks, settle/unsettle, paged settled tail) and project filter behavior as home. Thread List v2 rows shift to flat edge-to-edge styling on phone, sidebar-style rounded rows on iPad, optional environment labels on multi-connection setups, and compact swipe actions for slim rows.NativeStackScreenOptionsaddsoptionsVersionso native header menus refresh when async filter data loads.Web refines Sidebar v2: shared row hover/selection tokens, rich hover tooltips (project, env, branch, model, errors), project filter as a dropdown instead of horizontal chips, and aligned status colors with mobile. Command palette assigns
thread.jump.1–9to the first nine visible project actions and executes them from the search input. Sidebar chrome, command dialog, composer, and related components get light/dark surface and contrast tweaks (sidebar-row-*, inset rings in dark mode,data-sidebar-versionon the app sidebar).Reviewed by Cursor Bugbot for commit 89830a0. Bugbot is set up for automated code reviews on this repo. Configure here.
Note
Refine light-mode sidebar surfaces with zinc-based tokens and sidebar-specific color roles
--color-sidebar*,--color-surface-raised, sidebar row hover/active/selected colors).SidebarV2,AppSidebarLayout,SidebarChrome,SettingsSidebarNav,sidebar.tsx) to consume the new sidebar-scoped tokens for hover, active, and selected states instead of generic accent tokens.SidebarV2ThreadTooltip) to thread rows showing project, environment, branch, model, and last error details; replaces inline error text and separate chip tooltips.SidebarV2with a dropdown radio menu for project filtering.data-terminal-openattribute and CSS rule).Macroscope summarized 89830a0.