Skip to content

fix(frontend): tighten the app shell lines and the playground scrollbars - #5461

Merged
mmabrouk merged 8 commits into
release/v0.105.9from
ui-shell-rail-and-lines
Jul 23, 2026
Merged

fix(frontend): tighten the app shell lines and the playground scrollbars#5461
mmabrouk merged 8 commits into
release/v0.105.9from
ui-shell-rail-and-lines

Conversation

@mmabrouk

Copy link
Copy Markdown
Member

Context

The app shell and the agent playground had a set of small visual defects that added up. The collapsed navigation rail was 80px wide around 14px icons, and it painted in two different greys because the Ant Design menu drew its own background over the middle of it. The lines that frame the app were nearly invisible and never lined up: the rail's edge, the breadcrumb bar and the playground header each stopped where the next one started. Inside the playground, the configuration panel's scrollbar sat there permanently, eating 11px of width and cutting the sticky section headers short of the panel edge. The Model and harness row named the model by its stored id (sonnet) while the picker right next to it used the real name.

Changes

The navigation rail. It is 48px collapsed, sized to its icons the way Langfuse and Linear size theirs. The menu background is transparent so the rail is one flat colour, darker than the content in dark mode and white in light mode.

The frame lines. The theme gains a small shell group: a rail background, one line colour shared by every frame line, and the two scroll thumb colours. The rail edge, the breadcrumb bar and the playground header now use that one line colour. The workflow sidebar's two header rows are 45px tall, so the rail's lines land at exactly the same height as the content's and read as one line across the app. The agent picker loses its own border, since it sits inside a row the rail already frames.

The configuration panel's scrollbar. A native scrollbar reserves layout width, and the browser will not paint content into that reserved strip, so the sticky headers were always short by the scrollbar's width. Widening the content does not help, and Chrome ignores overflow-clip-margin once the other axis scrolls. So the panel keeps no native scrollbar at all, and a new OverlayScrollbar component draws the thumb on top of the content instead. It appears while the pointer is in the panel and for a moment after a scroll, it can be dragged, and it never affects layout. The chat panel keeps a native thin scrollbar that stays transparent until you hover it, since its header does not have the same problem.

A stuck second scrollbar. Ant Design styles every Splitter panel with overflow: auto, so each panel was itself a scroll container even though the section inside does the scrolling. While the configuration sections load, the content overflows the panel for a moment. Chrome painted the panel's own thin scrollbar for that moment and then left it on screen with a full-height thumb, because by then there was nothing left to scroll. Both panels are clipped now.

Model names. modelLabel reads the harness catalog the model picker already uses, so the summary line says Claude Code · Sonnet instead of Claude Code · sonnet. For Pi harness models the difference is larger, since their ids look like anthropic/claude-sonnet-4-5.

The divider. The channel between the configuration panel and the chat drops from 12px to 9px.

Tests / notes

  • Verified in the running EE dev stack, in dark and light modes, with the sidebar collapsed and expanded. Measured the geometry in the browser rather than eyeballing it: the rail's lines and the content's lines share the same y, and the configuration header's painted pixels reach the panel edge.
  • Confirmed the stuck splitter scrollbar with the panel's own numbers. After a wheel scroll its width minus its inner width went from 0 to 11px while its scroll height still equalled its visible height, which is a scrollbar with nothing to scroll.
  • Theme colours were added to palette.ts and the generated files were regenerated with pnpm generate:tailwind-tokens.
  • Not checked: the playground's comparison view, which needs a prompt app with several revisions selected. That view keeps its own scroll handling and the splitter change is inert there.

What to QA

  • Open an agent's playground in Build view. The left rail is narrow, one flat colour, and the line down its right edge runs from the top of the window to the bottom.
  • Look along the top. The line under the breadcrumbs and the line under the agent name each run straight across the rail and the content with no break or step.
  • Hover the configuration panel and scroll. One thumb appears on the right edge, it fades out shortly after you stop, and it can be dragged. There is no second bar and nothing shifts sideways.
  • Scroll the configuration panel down past the Triggers and Files headers. Each header spans the full panel width, edge to edge, with no notch on the right.
  • Check the Model and harness row. It names the model the way the picker does, for example Claude Code · Sonnet.
  • Collapse and expand the sidebar, then switch between light and dark. Nothing jumps and no line goes missing.
  • Regression: open a prompt app's playground (not an agent). The configuration panel and the divider behave as they did before.

mmabrouk added 7 commits July 23, 2026 01:15
…inuous

The collapsed sidebar was 80px wide around 14-16px icons, and the rail
painted two different greys because the antd menu drew its own
background over the middle. The frame lines were nearly invisible, so
the rail edge and the top bars never read as one frame.

- Rail is 48px collapsed, one flat colour, darker than the content in
  dark mode and white in light mode.
- New shell tokens (rail background, frame line, scroll thumb) so the
  rail edge, the breadcrumb bar and the playground header share one line.
- Workflow sidebar header rows are 45px, so the rail's lines land on the
  same y as the content's and carry straight across.
- The agent picker loses its own border inside the framed row.
- Configuration panel gets a quiet scrollbar: gutter always reserved, so
  no content shift, thumb only on hover or focus.
… cleanly

The config and chat panels were separated by a 12px dark channel, and
neither header reached it. The config panel's sticky headers also
stopped short of the panel edge once the scrollbar gutter was reserved.

- The Build/Chat divider is a hairline in the shell's frame colour, so
  both panels butt against it. The grab zone stays 11px wide and the
  grip only appears on hover or drag.
- Sticky headers stretch across the reserved scrollbar gutter, so they
  span the panel edge to edge. The gutter width is measured, since it is
  zero on overlay-scrollbar systems.
- The chat panel gets the same quiet scrollbar as the config panel.
- Below 320px the config panel drops what it can spare: Configuration
  becomes Config, Deploy and Commit become icon buttons, section rows
  keep their icon and summary, and list rows keep their name. It can now
  be dragged down to 240px.
…panel collapse

Keeps only the sticky-header fix from the previous commit: config panel
headers still span the panel edge to edge across the reserved scrollbar
gutter.

Restored: the 12px gutter divider with its persistent grip, the 20%
minimum config width, and the full labels on section rows, list rows and
the Deploy/Commit buttons.
Reserving a scrollbar gutter kept the sticky headers short by the
scrollbar's width, and the earlier attempt to stretch them across it did
not work: the browser clips painting at the content box, so the notch
stayed. The config panel now reserves nothing and shows no scrollbar, so
its headers span the panel edge to edge and the layout never shifts. The
panel still scrolls with the wheel and its section headers still pin.
…ivider

- The config panel gets a scrollbar drawn on top of the content instead
  of beside it, so the sticky headers keep the full panel width and the
  thumb still appears on hover, after a scroll, and while dragging.
- Model & harness names the model the way the picker does ("Sonnet"),
  from the harness catalog, instead of the stored id ("sonnet").
- The divider channel between config and chat drops from 12px to 9px.
Wires OverlayScrollbar into the playground config pane: the pane becomes
the positioned hover group, and the thumb is rendered as a sibling of
the scroller so it floats over the content.
antd styles every Splitter panel with overflow:auto. A transient overflow
while the config sections load left Chrome's thin panel scrollbar stuck
on screen with a full-height thumb, next to the panel's real overlay
scrollbar. The sections inside own all scrolling, so the panels are
clipped instead.
@dosubot dosubot Bot added the size:L This PR changes 100-499 lines, ignoring generated files. label Jul 23, 2026
@vercel

vercel Bot commented Jul 23, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
agenta-documentation Ready Ready Preview, Comment Jul 23, 2026 12:10pm

Request Review

@coderabbitai

coderabbitai Bot commented Jul 23, 2026

Copy link
Copy Markdown

Review Change Stack

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: a996855d-b36d-4cd0-81ea-102f60f980d8

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The PR adds a draggable overlay scrollbar for the playground config panel, introduces shell and scrollbar theme tokens, narrows and restyles the sidebar rail, updates scrollbar utilities, and uses harness catalog labels for model summaries.

Changes

Shell and scrollbar layout

Layer / File(s) Summary
Shell theme and scrollbar tokens
web/oss/src/styles/theme/palette.ts, web/oss/src/styles/theme-variables.css, web/scripts/generate-tailwind-tokens.ts, web/oss/src/components/Layout/assets/styles.ts, web/oss/src/components/Playground/Components/PlaygroundHeader/index.tsx, web/oss/src/components/ProtectedRoute/ProtectedRoute.tsx
Shell rail, border, and scrollbar colors are added to the theme palette, CSS variables, and generated tokens; shell borders now reference --ag-shell-line.
Sidebar rail geometry and framing
web/oss/src/components/Sidebar/engine/SidebarShell.tsx, web/oss/src/components/Sidebar/components/SidebarSkeletonLoader.tsx, web/oss/src/components/Sidebar/components/WorkflowPicker.tsx, web/oss/src/components/Sidebar/scopes/workflowScope.tsx
Collapsed sidebar width changes from 80px to 48px, menu and picker sizing are aligned to the narrower rail, and workflow header rows use explicit 45px heights without the divider.
Playground overlay scrolling
web/oss/src/components/OverlayScrollbar/index.tsx, web/oss/src/components/Playground/Components/MainLayout/index.tsx, web/oss/src/styles/globals.css
A measured, draggable OverlayScrollbar observes and tracks the config panel; playground overflow classes and global scrollbar utilities support hidden and quiet scrollbar states, and the agent splitter gutter is reduced to 9px.

Harness model labeling

Layer / File(s) Summary
Harness-aware model summary
web/packages/agenta-entity-ui/src/DrillInView/SchemaControls/connectionUtils.ts, web/packages/agenta-entity-ui/src/DrillInView/SchemaControls/agentTemplate/useModelHarness.tsx
modelLabel resolves catalog labels or names, and model summaries use that result before falling back to enumLabel.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant PlaygroundMainView
  participant OverlayScrollbar
  participant ConfigPanel
  PlaygroundMainView->>OverlayScrollbar: pass configPanelRef
  OverlayScrollbar->>ConfigPanel: measure scroll geometry
  ConfigPanel-->>OverlayScrollbar: report scroll, resize, and mutation events
  OverlayScrollbar->>ConfigPanel: update scrollTop while dragging
Loading

Possibly related PRs

  • Agenta-AI/agenta#5008: Modifies the playground layout and Splitter pane sizing in the same MainLayout area.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed Docstring coverage is 66.67% which is sufficient. The required threshold is 60.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly summarizes the main frontend visual and scrollbar changes in the app shell and playground.
Description check ✅ Passed The description is directly related and accurately outlines the shell, scrollbar, and model-label changes.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ui-shell-rail-and-lines

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
web/oss/src/components/Sidebar/components/SidebarSkeletonLoader.tsx (1)

14-20: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Skeleton loader still hardcodes border-gray-100, not the new shell-line token.

The collapsed width now matches the 48px rail, but this file's border classes (here and at line 29) still use border-gray-100 while SidebarShell.tsx and workflowScope.tsx were updated to use border-[var(--ag-shell-line)]. The skeleton's frame line will not match the real rail once mounted, particularly in dark mode.

♻️ Align skeleton border with the shell-line token
         <section
             className={clsx(
-                "flex flex-col justify-between h-screen border border-r border-solid border-gray-100",
+                "flex flex-col justify-between h-screen border border-r border-solid border-[var(--ag-shell-line)]",
                 {
                     "w-[48px] items-center": collapsed,
                     "w-[236px]": !collapsed,
                 },
             )}

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: b5e4d006-34fb-461a-8f27-85b2aa8e5b0e

📥 Commits

Reviewing files that changed from the base of the PR and between b5d4596 and f4f9499.

📒 Files selected for processing (15)
  • web/oss/src/components/Layout/assets/styles.ts
  • web/oss/src/components/OverlayScrollbar/index.tsx
  • web/oss/src/components/Playground/Components/MainLayout/index.tsx
  • web/oss/src/components/Playground/Components/PlaygroundHeader/index.tsx
  • web/oss/src/components/ProtectedRoute/ProtectedRoute.tsx
  • web/oss/src/components/Sidebar/components/SidebarSkeletonLoader.tsx
  • web/oss/src/components/Sidebar/components/WorkflowPicker.tsx
  • web/oss/src/components/Sidebar/engine/SidebarShell.tsx
  • web/oss/src/components/Sidebar/scopes/workflowScope.tsx
  • web/oss/src/styles/globals.css
  • web/oss/src/styles/theme-variables.css
  • web/oss/src/styles/theme/palette.ts
  • web/packages/agenta-entity-ui/src/DrillInView/SchemaControls/agentTemplate/useModelHarness.tsx
  • web/packages/agenta-entity-ui/src/DrillInView/SchemaControls/connectionUtils.ts
  • web/scripts/generate-tailwind-tokens.ts

Comment thread web/oss/src/components/OverlayScrollbar/index.tsx
@github-actions

github-actions Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Railway Preview Environment

Preview URL https://gateway-production-65ee.up.railway.app/w
Project agenta-oss-pr-5461
Image tag pr-5461-63f68ec
Status Deployed
Railway logs Open logs
Workflow logs View workflow run
Updated at 2026-07-23T12:20:58.443Z

@mmabrouk
mmabrouk changed the base branch from main to release/v0.105.9 July 23, 2026 12:07
A cancelled pointer stream (touch interruption, app switch) never fires
pointerup, so the drag state stayed on and the window listeners stayed
attached. The thumb also takes touch-action: none, so a touch drag moves
it instead of scrolling the page.

Also clarifies why modelLabel stops at the catalog's label and name: the
caller still has the schema's own title to try before the raw id.
@mmabrouk

Copy link
Copy Markdown
Member Author

Thanks, both looked at.

Pointer drag (OverlayScrollbar) — fixed in 3bd70de. You are right that a cancelled pointer stream never fires pointerup, so the drag state stayed on and the two window listeners stayed attached and stacked on the next drag. pointercancel now runs the same teardown, and the thumb takes touch-action: none so a touch drag moves it instead of scrolling the page.

modelLabel falling back to id — leaving this as it is, and here is why. The one caller reads modelLabel(...) ?? enumLabel(props.llm, modelId), and enumLabel already ends at the raw id. So the full precedence today is catalog label, then catalog name, then the schema's own title, then the id. Returning id from modelLabel would cut the schema title out of that chain and make the summary slightly worse for any model whose catalog entry has no label or name but whose schema does have a title. The picker stops at id because it has no schema to consult.

The docstring said "same precedence as the picker", which is what made this look like a bug. That was fair. It now spells out where the two differ and why.

@mmabrouk
mmabrouk merged commit 9da39b4 into release/v0.105.9 Jul 23, 2026
31 of 32 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Frontend size:L This PR changes 100-499 lines, ignoring generated files. UI UX

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant