Skip to content

feat(sidebar): mark the active workspace with an accent rail and wash - #914

Merged
svenmalvik merged 4 commits into
mainfrom
highlight-active-workspace-sidebar
Aug 8, 2026
Merged

feat(sidebar): mark the active workspace with an accent rail and wash#914
svenmalvik merged 4 commits into
mainfrom
highlight-active-workspace-sidebar

Conversation

@svenmalvik

Copy link
Copy Markdown
Collaborator

Summary

The sidebar could not tell you which workspace you were actually in. The active
card carried three quiet signals — a brighter label, a 14px accent glyph
(WorkspaceGlyph.tsx:22), and a sticky header — and theme.css recorded the
decision explicitly: "The active row carries no fill — selection is shown by
label color alone."

Two things defeated that. The accent glyph is the same hue as the
status-dot--active dots on every working workspace, and those pulse — a
static 14px icon loses to three animated ones. And a --sidebar-active-bg token
already existed for exactly this purpose (theme.css:135, mapped from
list.inactiveSelectionBackground) with nothing in the sidebar using it.

The active card now reads as a region: a 2px accent rail down its full
height plus a wash on the workspace's own rows.

The rail and the wash have different extents on purpose. The rail runs past an
expanded file tree so the region still reads as one; the wash lands only on
direct .sidebar-item-row children, and an expanded tree renders into
.sidebar-project-files — not a row — so it stays on the plain sidebar surface.
The highlight therefore costs the same whether a folder is collapsed or a
thousand-line tree is open.

CSS only. No component changes: sidebar-project-group--active was already on
the card.

Three cascade traps, all recorded in renderer.md

None are catchable by the sidebar's unit tests, since jsdom never loads
theme.css.

  1. The sticky header needs the wash composited onto --bg-sidebar through
    a linear-gradient layer. It ties with the card's wash rule at (0,3,0) and
    comes later, so a flat opaque fill wins and leaves the header reading
    unhighlighted while its children stay washed.
  2. Its hover needs the same treatment — the card's hover rule scores
    (0,3,1) and would otherwise replace the opaque base with a translucent
    fill, letting rows scroll visibly through the header.
  3. The rail needs z-index: 3 to clear the header's 2. That header
    background is opaque by necessity and otherwise paints over the rail's top,
    so the rail appears to start at the first folder row instead of the top of
    the card. This one was not predicted — the screenshot caught it.

Rows inside the active card also need their own :hover: --list-hover-bg is
accent at 5% against the 7% wash and loses on specificity anyway, so without it
the active card stops responding to the pointer entirely.

Testing

  • Seen, not just asserted: npm run screenshot:component ProjectSidebar --theme royal-dark, before and after, confirms the rail spans the card, the
    wash stops above the file tree, and no label shifted horizontally.
  • Computed styles read from a driven browser (--emit-html + playwright):
    header 7%→12% over an opaque rgb(9,13,24) in both resting and hover states,
    repo row 7%→12%, inactive rows untouched at transparent→5%, rail 2px accent at
    z-index: 3 over the header's 2. Note these must be read after the row's
    background transition settles, or the value is a mid-flight interpolation —
    that misled me once and is now documented.
  • npx vitest run src/renderer/components/sidebar — 12 files, 118 tests, pass.
  • npm test — 2911 passed, 1 failed: src/main/app/debug-log.test.ts, a
    main-process timing test with a 40ms sleep. It passes in isolation (8/8) and
    has no reference to theme.css or the sidebar; it flakes under full-suite
    contention. Not caused by this change.
  • npm run typecheck — clean across web, node, plugins.
  • bash scripts/wiki-lint.shrenderer.md updated here and not stale.

Rebased onto latest main and re-verified after, since #912 (label shimmer)
and #911 both touch these files. The shimmer applies background-clip: text to
the label — a different element than the row wash — and the two render together
without conflict.

Design spec and implementation plan are included as the first two commits.

🤖 Generated with Claude Code

svenmalvik and others added 4 commits August 8, 2026 18:40
The active card carries only a brighter label and a 14px accent glyph today,
and that glyph is the same hue as the pulsing status dots on every working
workspace — so the static marker loses to the animated ones.

Adds an accent rail spanning the whole card plus a subtle wash that stops above
an expanded file tree, so the highlight costs the same whether a folder is
collapsed or a large tree is open.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The active card carried only a brighter label and a 14px accent glyph, both
losing to the pulsing status dots on every working workspace below it.

It now reads as a region: a 2px accent rail down the card's full height with a
wash on the workspace's own rows. The wash lands via a child combinator, so an
expanded file tree — which renders into .sidebar-project-files, not a row —
stays on the plain sidebar surface and the highlight costs the same at any tree
depth.

Three cascade traps, all verified in a real browser rather than by inspection:
the sticky header needs the wash composited onto an opaque base or it ties at
(0,3,0) and wins with a flat fill; its hover needs the same or it goes
translucent and lets rows scroll through it; and the rail needs z-index 3 to
clear that opaque header, which otherwise paints over its top.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Records the three cascade traps in these selectors — the sticky header's
composited background, its hover, and the rail's z-index — plus the transition
that makes a naive getComputedStyle read return a mid-flight value. None of them
are catchable by the sidebar's jsdom tests, which never load theme.css.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@svenmalvik
svenmalvik requested a review from a team August 8, 2026 16:42
@svenmalvik
svenmalvik merged commit 33dfa59 into main Aug 8, 2026
2 checks passed
@svenmalvik
svenmalvik deleted the highlight-active-workspace-sidebar branch August 8, 2026 16:43
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