diff --git a/packages/framework-dashboard/components/EventList.test.tsx b/packages/framework-dashboard/components/EventList.test.tsx index 769dc786..75f2ed16 100644 --- a/packages/framework-dashboard/components/EventList.test.tsx +++ b/packages/framework-dashboard/components/EventList.test.tsx @@ -271,3 +271,34 @@ describe('EventList inline browser rows (#1455 item 6b)', () => { expect(screen.getByText('browser').className).toContain('text-primary') }) }) + +// The background wash (#1508): a tint across the whole line for the rows the eye hunts for — +// the reader's own turns, failures, the clean landing — while the bulk of the log stays plain. +describe('EventList row wash (#1508)', () => { + test("the reader's own turn gets the blue wash", () => { + const { container } = render( + , + ) + expect(container.querySelector('[class*="bg-info/10"]')).toBeTruthy() + }) + + test('a failure gets the red wash', () => { + const { container } = render() + expect(container.querySelector('[class*="bg-danger/10"]')).toBeTruthy() + }) + + test('a clean end gets the green wash; a stopped one gets none', () => { + const { container } = render() + expect(container.querySelector('[class*="bg-success/10"]')).toBeTruthy() + cleanup() + const { container: stopped } = render() + expect(stopped.querySelector('[class*="bg-info"], [class*="bg-danger"], [class*="bg-success"]')).toBeNull() + }) + + test("an agent reply stays plain canvas — the log's bulk must not shout", () => { + const { container } = render( + , + ) + expect(container.querySelector('[class*="bg-info"], [class*="bg-danger"], [class*="bg-success"]')).toBeNull() + }) +}) diff --git a/packages/framework-dashboard/components/EventList.tsx b/packages/framework-dashboard/components/EventList.tsx index 3597d695..3ce66677 100644 --- a/packages/framework-dashboard/components/EventList.tsx +++ b/packages/framework-dashboard/components/EventList.tsx @@ -118,6 +118,20 @@ function badgeTone(e: FrameworkEvent): string { return '' } +/** + * The row's BACKGROUND wash (#1508), the layer above {@link badgeTone}'s markers: a tint across + * the whole line, findable from the scrollbar's distance where a coloured badge word is not. + * Only the rows the eye actually hunts for get one — the reader's own turns (the log's natural + * chapter marks), failures, and the run landing cleanly — and at a whisper of alpha, so the + * text keeps the contrast and the bulk of the log stays plain canvas. + */ +function rowWash(e: FrameworkEvent): string { + if (isFailure(e)) return 'bg-danger/10' + if (e.kind === 'driver' && e.event.type === 'start') return 'bg-info/10' + if ((e.kind === 'end' && e.ok) || e.kind === 'ready-for-merge') return 'bg-success/10' + return '' +} + /** * Hoist the run's first prompt to the top of the log (#1170). * @@ -292,7 +306,9 @@ export function EventList({ const chunkHead = !prev || rowGroup(prev) !== rowGroup(e) const at = receivedAt(e) return ( - + // Every row carries the same -mx/px pair so a washed row's band and a plain row's + // text share the exact same columns; only the background differs. + {/* Fixed-width badge column so the text lines up whether or not this row repeats the badge. Wide enough for the longest common label ("system prompt") to sit on one line. */} {chunkHead && (