fix(client): decouple the turn strip from the category palette

The turn strip's per-turn palette was positionally identical to the six
category colors (turn 1 indigo = system, turn 2 amber = tools, ...).
Sitting 4px under the bars, the strip read as a detached full-width
bottom segment that never aligned with the bars above — the bars looked
broken, especially in multi-turn sessions.

The strip now uses a neutral two-tone zebra (adjacent turns still read
as separate ranges) with secondary-label text; the in-turn bar tint goes
neutral too. Verified against the live GUI: every composition bar's
segments measure pixel-aligned; the strip now clearly reads as an axis.
This commit is contained in:
Bowen Liang committed 2026-08-18 08:33:33 +08:00
1 parent cf286766bc
commit 01a8dfc3a6
2 files changed
+12 -6

No files matched your search

+6 -3
View File
@@ -83,8 +83,11 @@ export function makeTrendChart(kit: ViewKit): (props: TrendChartProps) => ReactN
// compressing. The turn strip below mirrors the same column grid.
const BAR_W = 14
const BAR_GAP = 2
// Turn strip palette: one color per turn, cycling for long histories.
const TURN_COLORS = ['#6366f1', '#f59e0b', '#22c55e', '#a855f7', '#3b82f6', '#14b8a6', '#ef4444', '#ec4899']
// Turn strip fills: a neutral zebra, deliberately DISJOINT from the
// category palette — the strip sits directly under the bars, and the old
// per-turn palette (identical to the six category colors) made it read as
// a detached, misaligned bottom segment of the composition bars.
const TURN_FILLS = ['rgba(128,128,128,0.12)', 'rgba(128,128,128,0.26)']
return function TrendChart(props: TrendChartProps): ReactNS.ReactElement {
const requests = props.requests
@@ -267,7 +270,7 @@ export function makeTrendChart(kit: ViewKit): (props: TrendChartProps) => ReactN
className={'lc-turn' + (on ? ' lc-turn-on' : '')}
style={{
width: blockW + 'px',
background: TURN_COLORS[gi % TURN_COLORS.length],
background: TURN_FILLS[gi % TURN_FILLS.length],
}}
title={'T' + grp.turn}
onMouseEnter={() => { props.onHoverTurn(grp.turn) }}
+6 -3
View File
@@ -73,13 +73,16 @@ export const STYLES = [
'.lc-bar:hover { background: var(--dsw-alias-bg-layer-2); }',
'.lc-bar-selected { outline: 2px solid var(--dsw-alias-brand-primary); outline-offset: 1px; }',
'.lc-bar-hovered { outline: 1px dashed var(--dsw-alias-brand-primary); outline-offset: 1px; }',
'.lc-bar-in-turn { background: rgba(99,102,241,0.14); }',
'.lc-bar-in-turn { background: rgba(128,128,128,0.14); }',
'.lc-bar-stack { display: flex; flex-direction: column-reverse; width: 100%; }',
'.lc-bar-stack > div { width: 100%; }',
'.lc-bar-marker { position: absolute; top: -16px; left: 50%; transform: translateX(-50%); font-size: 11px; color: var(--dsw-alias-state-warn-primary); }',
// Turn strip: NEUTRAL zebra fills (inline, see TURN_FILLS) with secondary
// text — never the category palette, or the strip reads as a detached
// bottom segment of the bars above it.
'.lc-turns { display: flex; gap: 2px; width: max-content; min-width: 100%; margin-top: 4px; }',
'.lc-turn { flex: none; box-sizing: border-box; text-align: center; font-size: 10px; line-height: 14px; font-weight: 600; color: #fff; border-radius: 3px; height: 14px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; cursor: default; transition: filter 120ms, opacity 120ms; }',
'.lc-turn-on { filter: brightness(1.35); box-shadow: 0 0 0 1px rgba(255,255,255,0.4); }',
'.lc-turn { flex: none; box-sizing: border-box; text-align: center; font-size: 10px; line-height: 14px; font-weight: 600; color: var(--dsw-alias-label-secondary); border-radius: 3px; height: 14px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; cursor: default; transition: filter 120ms, opacity 120ms; }',
'.lc-turn-on { filter: brightness(1.35); color: var(--dsw-alias-label-primary); }',
'.lc-detail { margin-top: 12px; border-top: 1px solid var(--dsw-alias-border-l1); padding-top: 12px; }',
'.lc-detail-head { display: flex; flex-wrap: wrap; gap: 6px 16px; margin-bottom: 8px; color: var(--dsw-alias-label-secondary); }',
'.lc-detail-head b { color: var(--dsw-alias-label-primary); }',