Skip to content

feat(web): redesign the topbar location strip as captioned segments - #659

Merged
danyaberezun merged 10 commits into
mainfrom
redesign-top-panel-breadcrumb
Oct 8, 2026
Merged

danyaberezun merged 10 commits into
mainfrom
redesign-top-panel-breadcrumb

Conversation

@danyaberezun

@danyaberezun danyaberezun commented Oct 6, 2026 •

Copy link
Copy Markdown
Collaborator

Problem

The strip after the ThinkRail mark — project › workspace ⑂ branch · from base · PR #N — was one line of plain, draggable text. Nothing in it could be clicked, project and git state had the same visual weight, the PR number carried no status, and the only ways to switch project or workspace or act on a workspace lived in the Projects tree. A survey of competitor agentic IDEs (Conductor, T3 Code, Vibe Kanban, JetBrains Air, Superset, plus Zed / GitHub Desktop as classic references) showed every one of them treating this bar as a control surface rather than a label.

Approach

Replace the text line with a row of captioned segments — PROJECT · WORKSPACE · BRANCH · from base · REMOTE · PULL REQUEST — whose values are controls. The direction was chosen from a mockup gallery (six directions + three hybrids, rendered in the real 40px bar with our palette, type and action cluster, across themes, widths and workspace states); the pick combines GitHub Desktop's labeled segments, JetBrains/Zed-style dropdown pills, and status chips, with the base branch folded into the BRANCH caption.

Decisions worth a reviewer's eye:

  • The strip is now the one deliberate exception to "buttons only in topbar-actions." Every pill, chip, link and the inline rename input is window-no-drag; captions and hairlines stay in the drag region, so the window can still be grabbed between controls. shell/SPEC.md records this; a unit test pins it.
  • No second implementation of workspace actions. Open in / Rename / Reveal / Remove, editor.list and the project workspace-list load move from ProjectTree into panels/workspaceActions.ts (Copy path stays a one-line copyText(worktreePath) at each call site) (plus a shared RemoveWorkspaceDialog); the tree and the topbar menu call the same functions. The branch card's Compare to is the Changes panel's BranchPicker bound to workspace.setDiffBase, so the two controls cannot disagree.
  • Type carries the hierarchy. Project tr-text-ui, workspace tr-title-section, branch tr-code-text (mono). A new ui.caption style (10px / 500 / compact / wide / uppercase) exists because eyebrow's 18px line cannot sit above a 22px value row inside 40px. Two colour tokens (feedback-warning-muted, feedback-info-muted) complete the chip hover set that success/error already had.
  • Deliberate scope limits. No "Open PR…" affordance in the no-PR state and no Push action: the host only exposes the plan-session pr.open (no session-less PR or push RPC), so the strip reports remote state and the plan pane keeps the action. The PULL REQUEST segment appears only with an open review; REMOTE only while something is unpushed or behind — and since the host attaches those counts to OpenBranchReview alone, REMOTE can only ever appear alongside an open PR/MR (a branch without one shows no remote state).
  • Explicit vertical rhythm. Each segment spends the 40px strip on the spacing scale — py-4, a 10px caption row, gap-2, a 20px value row — so there is a real margin above the caption and below the pill (the first cut let justify-center leave ~1px above the caption).
  • Responsive drop order (the old strip hid project/base on narrow widths): project and PR chip below sm, branch and remote below md; inside the row the branch shrinks first (shrink-[4]), then the project, then the workspace. The workspace segment never hides, which the existing topbar-chrome phone-with-insets geometry test enforces.

Changes

  • apps/web/src/shell/locationBar/ — new sub-module (SPEC.md, barrel exports LocationBar): Segment (caption/value grammar, pillClass, chipClass), ProjectSegment (project switcher: projects · Project home · Add project… via the shared useOpenProject), WorkspaceSegment (actions + inline rename + Switch to siblings with the running indicator + New workspace ⌘N, which opens the shell-owned dialog; subscribes to session state only while open), BranchSegment (branch card: copy, based-on, compare-to, remote + review rows; REMOTE chips open the same card) and ReviewSegment (PR/MR chip link), locationModel helpers.
  • shell/Shell.tsx — mounts LocationBar in place of the inline text; shell/SPEC.md gains the module entry and the rewritten Composition paragraph.
  • panels/workspaceActions.ts (+ RemoveWorkspaceDialog.tsx) — shared action/loader implementations; ProjectTree.tsx migrated to them (its inline request helpers and confirm copy removed); panels/SPEC.md notes the sharing.
  • Design tokens — typography.json ui.caption → tr-text-caption; colors.json feedback-warning-muted / feedback-info-muted; regenerated CSS; TYPOGRAPHY.md and the typography test counts (49 → 50 styles); colorUsage.test.ts learns border-l-0 is a width, not a colour.
  • Tests — locationBar.test.tsx (segment grammar per state, chip link vs static chip, no-drag coverage, no raw type/colour, model helpers); new e2e/topbar-location.spec.ts journey (switch via menu → rename in place → branch card copy + compare-to retarget mirrored in Changes → New workspace dialog → Project home and back → phone-width drop order → remove falls back to Default). e2e/history-search.spec.ts now clicks the header's left padding as its "outside" target because the strip's centre is a control.

Screenshots

Same scenario and viewport (fixture sample-project, worktree workspace-1, 1280×720, dark theme); captured with the e2e harness on origin/main and on this branch.

Topbar strip — before (origin/main)

topbar before

Topbar strip — after

topbar after

Full window — before / after

app before

app after

New surfaces (after only) — workspace menu, branch card, project switcher

workspace menu

branch card

project switcher

Related issues

None.

Checklist

  • Fast gates pass: bun run lint, bun run typecheck, bun run test
  • E2E suite passes for app-affecting changes (bun run e2e, or bun run e2e:full when touching agent behavior)
  • Before/after screenshots are included for frontend changes, or marked not applicable
  • Relevant SPEC.md / top-level specs updated to reflect any boundary, contract, or behavior change
  • I have read the Contributing guide and agree to the Code of Conduct

Testing

Run on the rebased head (origin/main = #666; re-run after the later rebase and the hairline fix):

  • bun run e2e → all 8 shards passed, 479 tests (174 s)
  • bun test in apps/web → 1338 pass (incl. the 8 new locationBar tests); bun test ./scripts/ → 91 pass; packages/ui → 9 pass
  • bunx turbo run typecheck --filter='!@thinkrail/desktop' → 20/20 successful. @thinkrail/desktop#typecheck could not run locally: its electrobun prepare step waits on the project build lock held by a running desktop dev process on this machine. The desktop package is untouched by this PR; CI runs it unblocked.
  • bun run lint → 1359 files, no issues
  • bun run check:deps, check:boundaries, check:seams, check:spec-surface (new spec enrolled), typography:check, colors:check, spacing:check, provider-glyphs:check → all OK
  • spec_validate → only the two pre-existing dangling task-* links (submodule-server-branch-review, submodule-server-pr)

@jetbrains-air jetbrains-air Bot 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.

Approved — ready to merge.

Comment thread apps/web/src/shell/locationBar/BranchSegment.tsx Outdated
Comment thread apps/web/src/shell/locationBar/WorkspaceSegment.tsx Outdated

@jetbrains-air jetbrains-air Bot 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.

Requesting changes — please address the blocking inline finding.

Comment thread apps/web/src/panels/workspaceActions.ts Outdated

@jetbrains-air jetbrains-air Bot 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.

Requesting changes — please address the blocking inline finding.

Comment thread apps/web/src/shell/locationBar/WorkspaceSegment.tsx Outdated

@jetbrains-air jetbrains-air Bot 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.

Requesting changes — please address the blocking inline finding.

Comment thread apps/web/src/panels/workspaceActions.ts Outdated

@jetbrains-air jetbrains-air Bot 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.

Approved — ready to merge.

@danyaberezun
danyaberezun added this pull request to stack #664 October 6, 2026 16:03

@jetbrains-air jetbrains-air Bot 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.

Approved — ready to merge.

@danyaberezun
danyaberezun force-pushed the redesign-top-panel-breadcrumb branch from 31af90e to cbfa9a2 Compare October 7, 2026 08:49

@jetbrains-air jetbrains-air Bot 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.

Approved — ready to merge.

@danyaberezun
danyaberezun force-pushed the redesign-top-panel-breadcrumb branch from cbfa9a2 to 334d466 Compare October 8, 2026 07:49

@jetbrains-air jetbrains-air Bot 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.

Approved — ready to merge.

@rsolmano Rinat S (rsolmano) left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Non-blocking. I've already approved, so this is your call. Feel free to ship as is.

I like the direction: a clickable topbar is the right idea, and the code reuses the tree's actions, dialog and picker well. My concern is scope. The topbar now copies almost everything from the Projects tree and the Changes panel. All 4 real bugs the bot found came from that: rename lost while offline, rename landing on the wrong workspace, delete targeting the wrong workspace, and the React Compiler bailout.

Suggestion: ship a smaller first version.

  • Keep: project switcher, the workspace Switch to list, New workspace ⌘N, the PR chip, and the captions.
  • Drop for now: Rename / Remove / Open in / Reveal / Copy path in the topbar (they stay in the tree), and the branch card (Compare to stays in Changes).

That's roughly 300 fewer lines (code + e2e), and no rename/delete race logic in the title bar. We can add more later if users ask for it.

Small things, whichever way you go (inline below):

  1. There's a divider between the logo and PROJECT. Both specs say there shouldn't be one.
  2. REMOTE only appears when an open PR/MR exists. Worth saying in the PR text and locationBar/SPEC.md.
  3. The description says Copy path moved into workspaceActions.ts, but it's still inline in ProjectTree and WorkspaceSegment. Fine to keep, just fix the text.

Comment thread apps/web/src/shell/locationBar/WorkspaceSegment.tsx
Comment thread apps/web/src/shell/locationBar/WorkspaceSegment.tsx
Comment thread apps/web/src/shell/locationBar/BranchSegment.tsx
Comment thread apps/web/src/shell/locationBar/BranchSegment.tsx
Comment thread apps/web/src/shell/locationBar/ProjectSegment.tsx
Comment thread apps/web/src/shell/locationBar/locationModel.ts

@jetbrains-air jetbrains-air Bot 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.

Approved — ready to merge.

@danyaberezun
danyaberezun force-pushed the redesign-top-panel-breadcrumb branch from 7a8a106 to 9e0d034 Compare October 8, 2026 12:57

@jetbrains-air jetbrains-air Bot 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.

Approved — ready to merge.

@danyaberezun
danyaberezun added this pull request to the merge queue Oct 8, 2026
Merged via the queue into main with commit f3efe79 Oct 8, 2026
17 checks passed
@danyaberezun
danyaberezun deleted the redesign-top-panel-breadcrumb branch October 8, 2026 13:24
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.

2 participants