fix(maestro): pin activity rail to left edge, drop active-state pulse
Rail now spans full row height flush to the left edge with square corners, instead of a depth-shifted inset bar. Active state stays solid green since colour alone already signals it; blink/flash stay for awaiting-input/error.
This commit is contained in:
+9
-7
@@ -51,13 +51,15 @@ command. `<duration>` follows in the rail's colour when shown. There is no
|
||||
state word and no second badge: the rail exists so the state is still legible
|
||||
when a row is dimmed or the terminal renders the duration in the default fg.
|
||||
|
||||
In the **web client** the rail is a 5px bar positioned inside the row's own
|
||||
indent gutter — it shifts outward with nesting depth exactly as the gutter
|
||||
does — spanning the full card height. It carries motion, reserved for states
|
||||
that need attention (DESIGN.md's "living signals" rule): a slow breathing
|
||||
opacity while `Active`, a hard blink while `AwaitingInput`, a fast flash while
|
||||
`Error`. `Idle` is solid and still, on purpose. `prefers-reduced-motion`
|
||||
leaves every state as a solid bar.
|
||||
In the **web client** the rail is a 5px bar pinned to the row's own left
|
||||
edge, square corners, spanning the full card height edge to edge — it
|
||||
shifts outward with nesting depth along with the row's own padding, since
|
||||
it is positioned relative to the row. It carries motion only for states that
|
||||
need attention (DESIGN.md's "living signals" rule): a hard blink while
|
||||
`AwaitingInput`, a fast flash while `Error`. `Active` and `Idle` are both
|
||||
solid and still — colour alone (green vs. the idle grey) is the signal for
|
||||
`Active`, so it does not also pulse. `prefers-reduced-motion` leaves every
|
||||
state as a solid bar.
|
||||
|
||||
In the **TUI** the rail is a one-column-wide block glyph (`▌`) in the state's
|
||||
palette role, leading the existing indent gutter (`INDENT`/`META_INDENT`) on
|
||||
|
||||
+6
-8
@@ -68,13 +68,11 @@ const STATE_WORDS: Record<string, string> = {
|
||||
error: "Error",
|
||||
};
|
||||
|
||||
/** docs/SIDEBAR.md: the activity rail sits inside the row's own indent
|
||||
* gutter, so it shifts outward with nesting depth exactly as that gutter
|
||||
* does. `depth * 16 + 8` is the same expression `renderNode` uses for the
|
||||
* row's own padding — the rail sits just inside it. */
|
||||
function activityRailMarkup(slug: string, stateWord: string, depth: number): string {
|
||||
const left = depth * 16 + 2;
|
||||
return `<span class="activity-rail" data-activity="${slug}" style="left:${left}px" role="img" title="${escapeHtml(stateWord)}" aria-label="${escapeHtml(stateWord)}"></span>`;
|
||||
/** docs/SIDEBAR.md: the activity rail is pinned to the row's own left edge,
|
||||
* full height. The row's own padding (`renderNode`) shifts outward with
|
||||
* nesting depth, carrying the rail with it. */
|
||||
function activityRailMarkup(slug: string, stateWord: string): string {
|
||||
return `<span class="activity-rail" data-activity="${slug}" role="img" title="${escapeHtml(stateWord)}" aria-label="${escapeHtml(stateWord)}"></span>`;
|
||||
}
|
||||
|
||||
function metaLine(s: Session, now: number): string {
|
||||
@@ -172,7 +170,7 @@ function renderNode(node: TreeNode, depth: number): HTMLElement {
|
||||
);
|
||||
// docs/SIDEBAR.md: line 1 reserves action width, and line 2 is unconditional.
|
||||
row.innerHTML = `
|
||||
${activityRailMarkup(slug, stateWord, depth)}
|
||||
${activityRailMarkup(slug, stateWord)}
|
||||
<span class="card-line1">
|
||||
<span class="leaf-name">${escapeHtml(name)}</span>
|
||||
<span class="leaf-actions">
|
||||
|
||||
+5
-7
@@ -1393,23 +1393,21 @@ input.leaf-rename:focus {
|
||||
color: var(--danger);
|
||||
}
|
||||
|
||||
/* docs/SIDEBAR.md: the activity rail replaces the old inline dot. It sits
|
||||
inside the row's own indent gutter (`.tree-leaf` is already positioned),
|
||||
at a `left` set inline per nesting depth — see `activityRailMarkup` in
|
||||
/* docs/SIDEBAR.md: the activity rail replaces the old inline dot. It is
|
||||
pinned to the row's own left edge, full height, square corners — see
|
||||
catalog.ts. Idle stays solid and still on purpose: motion is reserved for
|
||||
states that need attention (DESIGN.md's "living signals" rule). */
|
||||
.activity-rail {
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
bottom: 4px;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 5px;
|
||||
border-radius: 2px;
|
||||
background: currentColor;
|
||||
}
|
||||
|
||||
.activity-rail[data-activity="active"] {
|
||||
color: var(--live);
|
||||
animation: pulse 2.4s var(--ease-out) infinite;
|
||||
}
|
||||
.activity-rail[data-activity="idle"] {
|
||||
color: var(--border-strong);
|
||||
|
||||
Reference in New Issue
Block a user