fix: don't grey out streaming output in grid and slides layouts#10094
Conversation
The grid and slides renderers marked a cell's output as stale for the entire time the cell was running by deriving `stale` from outputIsLoading(status). That greys out output even when it is actively streaming (e.g. a spinner via mo.status.spinner / mo.output.replace), which is exactly the run/app-view symptom reported. The vertical layout avoids this by using outputIsStale, whose `outputReceivedWhileRunning` exemption keeps freshly-streamed output un-greyed — the grid and slide renderers never adopted it. Use outputIsStale (matching vertical-layout, edited=false) in GridCell and the Slide output component, threading interrupted/staleInputs/runStartTimestamp through all call sites (three GridCell sites; five Slide sites across minimap, slide-cell-view, and reveal-component). Add a render test asserting streaming output is not greyed while a queued cell's output still is. Fixes #1587
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
Pull request overview
This PR fixes a UI regression in non-vertical layouts (grid + slides) where cell output was being marked stale (greyed out) for the entire time a cell was running, even when the output was actively streaming updates. It aligns grid/slides behavior with the vertical layout by using outputIsStale() (which exempts “output received while running”) instead of deriving stale directly from outputIsLoading().
Changes:
- Switch stale computation in slides and grid layouts from
outputIsLoading(status)tooutputIsStale({ ...runtimeFields }, edited=false). - Thread
interrupted,staleInputs, andrunStartTimestampthrough allSlideandGridCellcall sites that need accurate staleness. - Add a slides render test asserting streaming output is not greyed while running, while queued output remains greyed.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| frontend/src/components/slides/slide.tsx | Compute stale via outputIsStale() so streaming output isn’t greyed during runs. |
| frontend/src/components/slides/slide-cell-view.tsx | Pass interrupted, staleInputs, runStartTimestamp into Slide. |
| frontend/src/components/slides/reveal-component.tsx | Thread the additional runtime fields through Slide usage in reveal views. |
| frontend/src/components/slides/minimap.tsx | Thread the additional runtime fields through thumbnail Slide rendering. |
| frontend/src/components/slides/tests/slide.test.tsx | Add regression tests for issue #1587 stale/streaming behavior. |
| frontend/src/components/editor/renderers/grid-layout/grid-layout.tsx | Update GridCell to use outputIsStale() and plumb required fields through call sites. |
There was a problem hiding this comment.
No issues found across 6 files
Architecture diagram
sequenceDiagram
participant User as User
participant Renderer as Grid/Slide Renderer
participant CellState as Cell Runtime State
participant StaleFunc as outputIsStale()
participant OutputArea as OutputArea Component
participant DOM as DOM (CSS class)
Note over Renderer, StaleFunc: CHANGED: In GridCell & Slide, replace outputIsLoading with outputIsStale
Renderer->>CellState: read status, output, interrupted, staleInputs, runStartTimestamp
Renderer->>StaleFunc: call(state, edited=false)
Note over StaleFunc: logic: check if status is "running" or "queued", then apply<br/>outputReceivedWhileRunning exemption
alt Cell running with streaming output (output.timestamp > runStartTimestamp)
StaleFunc-->>Renderer: stale = false
Renderer->>OutputArea: stale={false}
OutputArea->>DOM: no "marimo-output-stale" class
Note over DOM: Output remains bright, not greyed out
else Cell queued (no exemption)
StaleFunc-->>Renderer: stale = true
Renderer->>OutputArea: stale={true}
OutputArea->>DOM: adds "marimo-output-stale" class
Note over DOM: Output greyed out (old queued behavior preserved)
end
Note over Renderer, OutputArea: Previously: outputIsLoading(status) always returned true for "running",<br/>so streaming output was incorrectly greyed out. Now matches vertical layout.
Per review, compute outputIsStale(cell, false) at the call sites and pass a single stale boolean into GridCell and Slide instead of threading interrupted, staleInputs, and runStartTimestamp into each. Pure refactor — same computed value, no behavior change.
There was a problem hiding this comment.
1 issue found across 6 files (changes from recent commits).
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="frontend/src/components/slides/__tests__/slide.test.tsx">
<violation number="1" location="frontend/src/components/slides/__tests__/slide.test.tsx:22">
P3: The streaming-output regression can reappear in the slides renderers without this test failing, because the test now bypasses the stale calculation by passing `stale={false}`/`stale={true}` directly into the leaf `Slide`. Consider adding or restoring a render-level case through a slides caller (or otherwise computing `stale` from a runtime cell with `output.timestamp > runStartTimestamp`) so the test fails if a call site goes back to `outputIsLoading(status)`.
(Based on your team's feedback about preserving targeted regression coverage for bug fixes.) [FEEDBACK_USED]</violation>
</file>
Tip: Review your code locally with the cubic CLI to iterate faster.
Re-trigger cubic
| describe("Slide", () => { | ||
| it("does not grey out the output when stale is false", () => { | ||
| const { container } = render( | ||
| <Slide cellId={cellId} status="running" output={output} stale={false} />, |
There was a problem hiding this comment.
P3: The streaming-output regression can reappear in the slides renderers without this test failing, because the test now bypasses the stale calculation by passing stale={false}/stale={true} directly into the leaf Slide. Consider adding or restoring a render-level case through a slides caller (or otherwise computing stale from a runtime cell with output.timestamp > runStartTimestamp) so the test fails if a call site goes back to outputIsLoading(status).
(Based on your team's feedback about preserving targeted regression coverage for bug fixes.)
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At frontend/src/components/slides/__tests__/slide.test.tsx, line 22:
<comment>The streaming-output regression can reappear in the slides renderers without this test failing, because the test now bypasses the stale calculation by passing `stale={false}`/`stale={true}` directly into the leaf `Slide`. Consider adding or restoring a render-level case through a slides caller (or otherwise computing `stale` from a runtime cell with `output.timestamp > runStartTimestamp`) so the test fails if a call site goes back to `outputIsLoading(status)`.
(Based on your team's feedback about preserving targeted regression coverage for bug fixes.) </comment>
<file context>
@@ -3,52 +3,31 @@
-
+ it("does not grey out the output when stale is false", () => {
+ const { container } = render(
+ <Slide cellId={cellId} status="running" output={output} stale={false} />,
+ );
expect(container.querySelector(".marimo-output-stale")).toBeNull();
</file context>
The grid and slides renderers marked a cell's output as stale for the entire
time the cell was running by deriving
stalefrom outputIsLoading(status).That greys out output even when it is actively streaming (e.g. a spinner via
mo.status.spinner / mo.output.replace), which is exactly the run/app-view
symptom reported. The vertical layout avoids this by using outputIsStale,
whose
outputReceivedWhileRunningexemption keeps freshly-streamed outputun-greyed — the grid and slide renderers never adopted it.
Use outputIsStale (matching vertical-layout, edited=false) in GridCell and the
Slide output component, threading interrupted/staleInputs/runStartTimestamp
through all call sites (three GridCell sites; five Slide sites across minimap,
slide-cell-view, and reveal-component). Add a render test asserting streaming
output is not greyed while a queued cell's output still is.
Fixes #1587