Skip to content

fix(sidebar): align every row on shared glyph and label lanes - #3116

Merged
benjaminshafii merged 1 commit into
devfrom
task/sidebar-lane-primitives
Jul 25, 2026
Merged

fix(sidebar): align every row on shared glyph and label lanes#3116
benjaminshafii merged 1 commit into
devfrom
task/sidebar-lane-primitives

Conversation

@benjaminshafii

Copy link
Copy Markdown
Member

Problem

The sidebar had five different left edges, which is the misalignment reported:

row label started at
WORKSPACES section label 16px
workspace titles 20px
session titles 36px (glyph poking out at 12px, left of the parent title)
group labels (TO DO, UNGROUPED) 37px
placeholders (No tasks yet.) 44px

A workspace title also jumped 24px to the right whenever its loading
dot-matrix appeared, because the glyph was only rendered while loading.

Fix

apps/app/src/react-app/domains/session/sidebar/sidebar-lanes.tsx is the new
single source for the sidebar's two rails:

  • glyph lane, 20px — activity dot-matrix, chevrons, row icons, and the
    top-level WORKSPACES label.
  • label lane, 44px — every title: workspace names, session titles, group
    labels, pinned/archived headers, placeholders, and the account name.
  • nesting steps right by 12px per depth level.

Workspace headers, group separators, session rows, the pinned and archived
sections, the loading placeholder and the footer account chip now compose from
SIDEBAR_ROW_LANE / SidebarGlyphSlot instead of ad-hoc ps-* values, and the
glyph slot is always rendered so titles never shift when an indicator appears.

Guideline + guardrail

  • apps/app/src/react-app/ARCHITECTURE.md documents the rails and the three
    rules for adding a sidebar row.
  • evals/flows/sidebar-lanes.flow.mjs measures every rendered row in the real
    app and fails if one lands off the rails, so a new row with its own padding
    cannot regress this silently.

Before / after

before after
before after

Tests

  • pnpm fraimz --flow sidebar-lanes --cdp-url http://127.0.0.1:9834PASSED
    (1 passed, 0 failed) against a real Electron app; measured rows report label
    lanes 20, 44 only.
  • Same flow against the pre-fix app-sidebar.tsxFAILED as intended,
    listing the off-lane rows (WORKSPACES 16, TO DO 37, sessions 36), which
    proves the guardrail catches the regression.
  • npx tsc --noEmit -p apps/app/tsconfig.json — clean.
  • bun test tests/managed-brand-header.test.ts — 1 pass (only unit test that
    renders the sidebar).

Made with Cursor

The sidebar had five different left edges: the WORKSPACES label at 16px,
workspace titles at 20px, group labels at 37px, session titles at 36px and
placeholders at 44px, and a workspace title jumped 24px right whenever its
loading dot-matrix appeared.

Introduce `sidebar-lanes.tsx` as the single source for the two rails every
row uses — a 20px glyph lane and a 44px label lane (+12px per nesting step) —
and compose workspace headers, group separators, session rows, pinned and
archived sections, placeholders and the account chip from it. The glyph slot
is always rendered, so titles never shift when an indicator appears.

`evals/flows/sidebar-lanes.flow.mjs` measures every rendered row and fails if
one lands off the rails; ARCHITECTURE.md documents the rule for new rows.

Co-authored-by: Cursor <cursoragent@cursor.com>
@vercel

vercel Bot commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

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

Project Deployment Actions Updated (UTC)
openwork-app Ready Ready Preview, Comment Jul 25, 2026 1:08pm
openwork-den Ready Ready Preview, Comment Jul 25, 2026 1:08pm
openwork-den-worker-proxy Ready Ready Preview, Comment Jul 25, 2026 1:08pm
openwork-diagnostics Ready Ready Preview, Comment Jul 25, 2026 1:08pm
openwork-landing Ready Ready Preview, Comment, Open in v0 Jul 25, 2026 1:08pm

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant