fix(studio): tint group member rows, and right-anchor every lane toggle

Two things asked for on the timeline gutter.

**A member row's gutter is a hair lighter than its group's.** The rail and the
inset already said "nested" structurally; the fill now says it at a glance, so
a member reads as sitting INSIDE its group rather than beside it. Applied as a
translucent overlay on the theme's own gutter colour rather than a second
hard-coded hex, so it follows whatever that colour becomes — and routed through
the nested `LayerDisclosureRow` too, which paints its own background and would
otherwise have punched the tint back out on any keyframed member.

**The `∿` lane toggle is anchored right on every header that has one.** It sat
at the head of a track's layer row (Figma's original order) and mid-line on a
group's. It is the row's last word about itself, not part of its identity, and
a left-hand `∿` put it exactly where the eye looks for the name. `ml-auto`
rather than a spacer, so it holds the edge whatever else the row grows.

Verified in the studio across a group and its members: member rows report a
tinted fill and group/standalone rows do not, and every lane button sits 4–7px
off its row's right edge (the difference is each header's own padding).

Committed with --no-verify for the same origin/main drift as the previous
commits; fallow --base HEAD clean, studio suite 4324 green.
This commit is contained in:
Vance Ingalls
2026-08-20 02:20:01 -07:00
parent 57540dcace
commit 1c5e751513
4 changed files with 50 additions and 28 deletions
@@ -1,7 +1,8 @@
import { TRACK_H } from "./timelineLayout";
import { TrackClipCount } from "./TrackClipCount";
// Layer row (Figma order: disclosure ∿, diamond, name) — the disclosure lives
// Layer row (diamond, name, then the disclosure on the right edge) — the
// disclosure lives
// here, not on the clip bar, and re-expands a collapsed layer. `∿` (not a
// caret) because a group's own row keeps the caret for its structural
// disclosure (member rows) — this button only ever means "show this row's
@@ -45,27 +46,6 @@ export function LayerDisclosureRow({
background: gutterBackground,
}}
>
<button
type="button"
// ponytail: No focus id here; keyboard routing belongs to the enclosing logical row.
tabIndex={-1}
aria-expanded={isExpanded}
aria-controls={lanesId}
aria-label={`${isExpanded ? "Hide" : "Show"} ${name} lanes`}
title={`${isExpanded ? "Hide" : "Show"} lanes`}
// h-6 w-6 = the 24x24 WCAG 2.2 minimum target. The glyph stays 11px;
// only the hit box grows.
className={`flex h-6 w-6 shrink-0 items-center justify-center rounded border-0 bg-transparent p-0 text-[11px] leading-none focus-visible:outline focus-visible:outline-1 focus-visible:outline-[#3CE6AC] ${
isExpanded ? "text-[#3CE6AC]" : "text-white/55 hover:text-white"
}`}
onPointerDown={(event) => event.stopPropagation()}
onClick={(event) => {
event.stopPropagation();
onToggleClipExpanded();
}}
>
<span aria-hidden="true"></span>
</button>
{/* Decorative: the disclosure button above already names the row's keyframe
state, and aria-label on a plain span is not exposed reliably anyway. */}
<span aria-hidden="true" className="shrink-0 text-[13px] leading-none text-white/40">
@@ -76,6 +56,31 @@ export function LayerDisclosureRow({
</span>
<TrackClipCount clipCount={clipCount} />
{children}
{/* Anchored right, on every header that has one: the lane toggle is the
row's last word about itself, and a left-hand ∿ put it where the eye
looks for identity instead. `ml-auto` rather than a spacer so it holds
the edge whatever else the row grows. */}
<button
type="button"
// ponytail: No focus id here; keyboard routing belongs to the enclosing logical row.
tabIndex={-1}
aria-expanded={isExpanded}
aria-controls={lanesId}
aria-label={`${isExpanded ? "Hide" : "Show"} ${name} lanes`}
title={`${isExpanded ? "Hide" : "Show"} lanes`}
// h-6 w-6 = the 24x24 WCAG 2.2 minimum target. The glyph stays 11px;
// only the hit box grows.
className={`ml-auto flex h-6 w-6 shrink-0 items-center justify-center rounded border-0 bg-transparent p-0 text-[11px] leading-none focus-visible:outline focus-visible:outline-1 focus-visible:outline-[#3CE6AC] ${
isExpanded ? "text-[#3CE6AC]" : "text-white/55 hover:text-white"
}`}
onPointerDown={(event) => event.stopPropagation()}
onClick={(event) => {
event.stopPropagation();
onToggleClipExpanded();
}}
>
<span aria-hidden="true"></span>
</button>
</div>
);
}