Skip to content

feat(agent): declutter the chat page - #12540

Merged
MarkusNeusinger merged 11 commits into
mainfrom
feat/agent-chat-declutter
Nov 2, 2026
Merged

MarkusNeusinger merged 11 commits into
mainfrom
feat/agent-chat-declutter

Conversation

@MarkusNeusinger

@MarkusNeusinger MarkusNeusinger commented Nov 2, 2026 •

Copy link
Copy Markdown
Owner

Summary

  • Notice: the public experimental notice is one line, # experimental AI · results can be wrong · stored only if you send feedback, and its ⓘ button (About the assistant) opens a popover with which AI and where, what not to paste, the daily limits and the link to /legal#assistant (ExperimentalNotice.tsx, texts in lane.ts).
  • Data card: the header is # your data ⓘ, and the ⓘ opens the how-to (formats, steps, a fix in plain words, changes afterwards). The long label, its hint line and the how-to paragraph under the card are gone. The data box and the composer name example data, a curve and a fix in short placeholders, and typing example data or a curve still works as before. Both ⓘ popovers share InfoPopover.tsx.
  • Result card: the image, its toolbar and the theme switch show as before. The rounds grid and the "what changed" list sit behind one status line at the end of the theme row (second try · 2 changes ⓘ). The code sits behind .show_code() / .hide_code(), while .copy() and the downloads stay in view. Each card keeps its choice for the session, also across a collapse of the whole card, and a new version's card starts folded. Residual notes stay in view.
  • Feedback and save: quick feedback shows only the four reactions until one is picked, which unfolds the message box, the data box, the public consent line and .send(). On the admin lane, .save() and its # include data.csv box leave the header row for a "⋯" menu (SessionMenu.tsx). The public lane has no .save() and no menu (owner decision of 2026-11-02): a visitor cannot resume a saved session, and the feedback form covers "something went wrong".
  • Missing parameters: the notice now names the plot page's .use_my_data() (feat(spec-detail): .use_my_data() beside the library carousel replaces the image icon #12539) instead of .adapt().
  • Wider column: the chat column grows with the window up to 1360 px (COLUMN_MAX_WIDTH, 960 before). The data card, the plot cards (bigger images) and the code use the full width. The thread's replies, turns and notices, and a card's text lists, keep a readable line of at most about 80 characters (CHAT_TEXT_MAX = '80ch' in styles.ts); user turns stay right-aligned. Below about 1100 px the window sets the width, as before. Both lanes share the layout. Measured at 1920 px with the BFF mock: before, column 960 and card 918 px; after, column 1360, card 1318 and reply 718 px.
  • Root prompt (agents/anyplot/prompts/root.md, "The page's controls"): the list now names .show_code() and .hide_code() for the code, .expand() and .collapse() for the whole card, the status line, and .cancel() in the feedback. It no longer names .save(): the prompt has no notion of the lane, and the public page has no .save(). This is a wording-only prompt change, so it got no harness or eval run. test_prompt_controls.py and all of tests/unit/agents pass (19,962 tests).

Decisions (decided and documented)

  • Popover, not tooltip, for the ⓘ buttons: it opens on a tap as on a click, holds a link, traps focus until Escape or a click outside, and returns the focus to the button. The data card's ⓘ sits beside its <label>, not inside it, so it never joins the data box's accessible name.
  • Collapsed layout: the tries moved from the card header into the status line, so ok is not said twice. The header keeps v2 · library · ● status for collapsed earlier versions. A run with neither rounds nor changes gets a plain status line without a toggle. .copy() became a text button in the code row, because the code block it used to sit on is folded now. The highlighter chunk loads only when the code opens.
  • .save() goes into a "⋯" menu on the admin lane, not the feedback area. A save downloads the session to the user's computer and stores nothing, while feedback stores a case for the operator; one data box for both would blur what goes where. The menu stays mounted, so the box keeps its choice; a successful save closes it, and a failure keeps it open with its line, which goes when the menu closes. The admin lane keeps its ticked default (checked in the browser on /debug/agent). On the public lane the page renders neither the menu nor .save().
  • Fresh feedback form gets .cancel(), which folds it back to the reactions and moves the focus to the first one; without it a mis-click could not be undone.
  • Placeholders wrap at phone width (::placeholder with pre-wrap), while a pasted table keeps its lines.

Finding for the API (not in this PR)

The public BFF route GET /agent/session/bundle still exists, but no page calls it now. Removing it is an API change for another PR; docs/reference/api.md says so for now.

Texts to read

New or changed user-facing texts:

  • Notice line: # experimental AI · results can be wrong · stored only if you send feedback
  • ⓘ button name: About the assistant
  • Popover heading: # about the assistant
  • Popover lines: Claude by Anthropic, through Google Cloud Vertex AI in the EU · don't paste data you may not share · daily limits apply · link how the assistant works (unchanged, now inside the popover)
  • Removed from the notice (the legal page covers them): an AI does the work here: … reads what you paste and writes the plot and its code and nobody checks them by hand. Say if either should come back into the popover.
  • Data card header: was # your data — paste or drop CSV, TSV, JSON, plain text, Excel, ODS, Parquet, Feather or NumPy, now # your data with an ⓘ (name How the data card works)
  • Data card how-to popover, heading # how it works, lines:
    • formats: CSV, TSV, JSON, plain text, Excel, ODS, Parquet, Feather or NumPy
    • paste or drop → check the preview and the bindings → .confirm() → .create_plot()
    • the assistant fixes your data in plain words: "sum per month"
    • afterwards, ask for changes: "log scale on y", "label the outliers"
  • Removed: the hint or type "example data" here, or ask for a curve in the chat: y = sin(x), x from -pi to pi, and the paragraph under the card (paste your data above, or ask here for example data or a curve … it sums your data up here … "read Anteil as numbers" or "sum per month". check the preview and the bindings, confirm, then .create_plot(), with a note first if the plot should do something differently. afterwards, ask for changes to the plot: "log scale on y", "dark version", "label the outliers".). The paragraph's "it sums your data up here", "read Anteil as numbers", "with a note first if the plot should do something differently" and "dark version" are not carried over.
  • Data box placeholder: was the sample month,revenue / 2026-01,120 / 2026-02,135, now three lines: paste a table or drop a file (csv, excel, json …) / or type: example data / or ask for a curve: y = sin(x), x from -pi to pi
  • Composer placeholder, step 1: was ask for example data or a curve: "y = sin(x), x from -pi to pi" (no data) and ask about your data, or for a fix: "sum per month" (data), now ask for example data, a curve, or a fix to your data for both
  • Composer placeholder after a plot: was ask about this plot, or ask for a change, now ask for a change, e.g. log scale on y
  • Missing-parameters notice: was open this page from a plot's .adapt() button: it needs a spec and a library, such as scatter-basic in matplotlib., now open it from a plot's .use_my_data(), or start with scatter-basic in matplotlib.
  • Card status line: <tries> · <n> change(s) with ⓘ, for example second try · 2 changes; screen-reader name Run details: …
  • Code toggle: .show_code() / .hide_code() (names Show code / Hide code); copy button .copy() / .copied
  • Feedback: .cancel() on a fresh form (name Cancel the feedback on version N)
  • Admin lane only: menu button ⋯ (name More actions, tooltip more · .save() the session as a json file); menu heading # save the session as a json file (the old .save() tooltip's words). Public lane: .save() and its # include data.csv box are gone.
  • Root prompt, "The page's controls" (read by the model, not shown to users):
    • page header: the clause `.save()`, which downloads the session is removed;
    • result card: `.expand()` and `.collapse()` for the code becomes the status line next to the light and dark switch (the tries and the number of changes), which opens the rounds and the list of what changed, `.show_code()` and `.hide_code()` for the code, `.expand()` and `.collapse()` for the whole card;
    • feedback: with `.send()` becomes a click on one of which opens the message box with `.send()` and `.cancel()`.

Screenshots (BFF mock, public lane, headless playwright-core)

All in /tmp/claude-1000/-home-meake-projects-anyplot/402df83f-568f-4063-805d-572b195b8887/scratchpad/chatui/shots/, named <before|after>-<width>-<theme>-<n>-<what>.png, each at 1440 and 390 in light and dark.

Wide screen at 1920 px, full page with two versions, a user turn and a reply, before and after:

  • /tmp/claude-1000/-home-meake-projects-anyplot/402df83f-568f-4063-805d-572b195b8887/scratchpad/chatui/shots/before-1920-light-wide.png → /tmp/claude-1000/-home-meake-projects-anyplot/402df83f-568f-4063-805d-572b195b8887/scratchpad/chatui/shots/after-1920-light-wide.png
  • /tmp/claude-1000/-home-meake-projects-anyplot/402df83f-568f-4063-805d-572b195b8887/scratchpad/chatui/shots/before-1920-dark-wide.png → /tmp/claude-1000/-home-meake-projects-anyplot/402df83f-568f-4063-805d-572b195b8887/scratchpad/chatui/shots/after-1920-dark-wide.png
  • also after: after-1440-*-wide.png, after-2560-*-wide.png and after-390-*-wide.png in the same folder (the masthead and the pinned data header appear mid-page in these full-page captures because they are sticky)

Data card, before and after:

  • /tmp/claude-1000/-home-meake-projects-anyplot/402df83f-568f-4063-805d-572b195b8887/scratchpad/chatui/shots/before-1440-light-8-datacard.png → /tmp/claude-1000/-home-meake-projects-anyplot/402df83f-568f-4063-805d-572b195b8887/scratchpad/chatui/shots/after-1440-light-8-datacard.png
  • /tmp/claude-1000/-home-meake-projects-anyplot/402df83f-568f-4063-805d-572b195b8887/scratchpad/chatui/shots/before-390-light-8-datacard.png → /tmp/claude-1000/-home-meake-projects-anyplot/402df83f-568f-4063-805d-572b195b8887/scratchpad/chatui/shots/after-390-light-8-datacard.png
  • /tmp/claude-1000/-home-meake-projects-anyplot/402df83f-568f-4063-805d-572b195b8887/scratchpad/chatui/shots/before-1440-dark-8-datacard.png → /tmp/claude-1000/-home-meake-projects-anyplot/402df83f-568f-4063-805d-572b195b8887/scratchpad/chatui/shots/after-1440-dark-8-datacard.png
  • /tmp/claude-1000/-home-meake-projects-anyplot/402df83f-568f-4063-805d-572b195b8887/scratchpad/chatui/shots/before-390-dark-8-datacard.png → /tmp/claude-1000/-home-meake-projects-anyplot/402df83f-568f-4063-805d-572b195b8887/scratchpad/chatui/shots/after-390-dark-8-datacard.png
  • How-to open: /tmp/claude-1000/-home-meake-projects-anyplot/402df83f-568f-4063-805d-572b195b8887/scratchpad/chatui/shots/after-1440-light-9-datacard-howto.png, /tmp/claude-1000/-home-meake-projects-anyplot/402df83f-568f-4063-805d-572b195b8887/scratchpad/chatui/shots/after-390-dark-9-datacard-howto.png

Notice, header, card and feedback, before:

  • /tmp/claude-1000/-home-meake-projects-anyplot/402df83f-568f-4063-805d-572b195b8887/scratchpad/chatui/shots/before-1440-light-1-top.png, /tmp/claude-1000/-home-meake-projects-anyplot/402df83f-568f-4063-805d-572b195b8887/scratchpad/chatui/shots/before-390-dark-1-top.png
  • /tmp/claude-1000/-home-meake-projects-anyplot/402df83f-568f-4063-805d-572b195b8887/scratchpad/chatui/shots/before-1440-light-4-card-folded.png (the whole card as it was), /tmp/claude-1000/-home-meake-projects-anyplot/402df83f-568f-4063-805d-572b195b8887/scratchpad/chatui/shots/before-390-dark-4-card-folded.png
  • /tmp/claude-1000/-home-meake-projects-anyplot/402df83f-568f-4063-805d-572b195b8887/scratchpad/chatui/shots/before-1440-light-6-feedback.png

After:

  • /tmp/claude-1000/-home-meake-projects-anyplot/402df83f-568f-4063-805d-572b195b8887/scratchpad/chatui/shots/after-1440-light-1-top.png: notice and header
  • /tmp/claude-1000/-home-meake-projects-anyplot/402df83f-568f-4063-805d-572b195b8887/scratchpad/chatui/shots/after-1440-light-2-notice-open.png, /tmp/claude-1000/-home-meake-projects-anyplot/402df83f-568f-4063-805d-572b195b8887/scratchpad/chatui/shots/after-390-dark-2-notice-open.png: notice popover open
  • /tmp/claude-1000/-home-meake-projects-anyplot/402df83f-568f-4063-805d-572b195b8887/scratchpad/chatui/shots/after-1440-light-admin-3-menu-open.png, /tmp/claude-1000/-home-meake-projects-anyplot/402df83f-568f-4063-805d-572b195b8887/scratchpad/chatui/shots/after-390-dark-admin-3-menu-open.png: the "⋯" menu on the admin lane (the public header in after-1440-light-1-top.png has none)
  • /tmp/claude-1000/-home-meake-projects-anyplot/402df83f-568f-4063-805d-572b195b8887/scratchpad/chatui/shots/after-1440-light-4-card-folded.png, /tmp/claude-1000/-home-meake-projects-anyplot/402df83f-568f-4063-805d-572b195b8887/scratchpad/chatui/shots/after-390-dark-4-card-folded.png: card folded
  • /tmp/claude-1000/-home-meake-projects-anyplot/402df83f-568f-4063-805d-572b195b8887/scratchpad/chatui/shots/after-1440-light-5-card-open.png, /tmp/claude-1000/-home-meake-projects-anyplot/402df83f-568f-4063-805d-572b195b8887/scratchpad/chatui/shots/after-1440-dark-5-card-open.png: card with details and code open
  • /tmp/claude-1000/-home-meake-projects-anyplot/402df83f-568f-4063-805d-572b195b8887/scratchpad/chatui/shots/after-1440-light-6-feedback.png / /tmp/claude-1000/-home-meake-projects-anyplot/402df83f-568f-4063-805d-572b195b8887/scratchpad/chatui/shots/after-1440-light-7-feedback-open.png, /tmp/claude-1000/-home-meake-projects-anyplot/402df83f-568f-4063-805d-572b195b8887/scratchpad/chatui/shots/after-390-light-7-feedback-open.png: feedback before and after a click

Plan

N/A (owner decisions of 2026-11-02, relayed by the lead)

Test plan

  • yarn lint, yarn fm:check, yarn type-check, yarn test (149 files, 1561 tests), yarn build, on the head after the merges of origin/main (feat(spec-detail): .use_my_data() beside the library carousel replaces the image icon #12539, docs(legal): cut the legal page by half, current state only #12538) and the width change
  • Width: 1440, 1920 and 2560 px, light and dark, plus 390 px: no sideways scroll; the column is 1248, 1360 and 1360 px wide, and 358 px at 390 as before; the reply is capped at 718 px; the card is full width
  • uv run --extra test --extra agents pytest tests/unit/agents (19,962 passed, 36 skipped) after the root.md change
  • New and updated tests: SessionMenu.test.tsx (new); ResultCard.test.tsx (status line, rounds, plain line, code fold, failed code, state across a collapse, new version folded); ResultFeedback.test.tsx (folded form, .cancel() focus, consent before send); SaveButton.test.tsx (onSaved); DataPanel.test.tsx (one-line label, placeholder, the how-to popover with Escape and focus return); page tests for the notice popover, the menu, the save flow, the placeholders and the .use_my_data() notice
  • uv run pytest tests/unit/agents/test_prompt_controls.py (3 passed)
  • Browser: public lane at 1440 and 390, light and dark, against the BFF mock: notice popover, menu, card folded and open, feedback before and after a click, the data card and its how-to popover, the placeholder wrapping in the box at 390, no "⋯" menu on the public lane, no sideways scroll, no console errors from the page (the only 403 is the masthead's GitHub release lookup, rate-limited); admin lane at 1440 light and 390 dark: no notice, box ticked, save downloads and closes the menu with focus back on the button
  • Gemini 3.8 Flash pre-PR check: 4 findings. Fixed: a stale failure line in the kept-mounted menu, and a missing Escape test. Skipped: a static name for the code toggle, which would break label-in-name for .show_code(); and a "missing" edit-cancel test that already exists.

https://claude.ai/code/session_01H7HSkGyea1k2v293XiAMo8

MarkusNeusinger and others added 3 commits November 2, 2026 23:36
…cards, compact feedback

The public notice is one line with an info popover for the details; a
result card folds its rounds and change list behind one status line and
its code behind .show_code(), with .copy() and the downloads in view;
quick feedback shows only the reactions until one is picked; .save()
and its data box move from the header row into a "⋯" menu.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H7HSkGyea1k2v293XiAMo8
…b in the save test

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H7HSkGyea1k2v293XiAMo8
…Escape test

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H7HSkGyea1k2v293XiAMo8
Copilot AI lite review requested due to automatic review settings November 2, 2026 22:48
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H7HSkGyea1k2v293XiAMo8

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

An active moderate accessibility issue remains because the code-toggle accessible names omit the visible .show_code()/.hide_code() labels, violating label-in-name and hindering voice-control targeting.

1 open issue
What changed in this PR

This pull request declutters the experimental agent chat while preserving access to result details, code, feedback, and session-saving controls.

Changes:

  • Adds a compact public-lane notice with an informational popover.
  • Folds result details, code, and feedback controls behind explicit interactions.
  • Moves session saving into a persistent overflow menu.
  • Updates related documentation, changelog content, and frontend tests.

This pull request requires changes.

File Description
docs/​reference/​plausible.md Documents the new session-save menu location.
docs/​concepts/​agent-network.md Updates agent-chat and public-lane behavior documentation.
changelog.d/​agent-chat-declutter.md Adds the changelog fragment for the UI decluttering work.
app/​src/​sections/​agent-chat/​SessionMenu.tsx Adds the persistent overflow menu for session saving.
app/​src/​sections/​agent-chat/​SessionMenu.test.tsx Tests menu opening, focus behavior, failures, persistence, and disabled states.
app/​src/​sections/​agent-chat/​SaveButton.tsx Supports save completion handling and menu integration.
app/​src/​sections/​agent-chat/​SaveButton.test.tsx Tests save success and failure behavior.
app/​src/​sections/​agent-chat/​ResultFeedback.tsx Folds feedback fields until a reaction is selected and adds cancellation.
app/​src/​sections/​agent-chat/​ResultFeedback.test.tsx Tests folded feedback, cancellation, consent, and sending.
app/​src/​sections/​agent-chat/​ResultCard.tsx Adds folded run details and code controls.
app/​src/​sections/​agent-chat/​ResultCard.test.tsx Tests summaries, detail/code folding, failure states, and state persistence.
app/​src/​sections/​agent-chat/​lane.ts Defines the revised public experimental notice text.
app/​src/​sections/​agent-chat/​ExperimentalNotice.tsx Adds the compact notice and informational popover.
app/​src/​sections/​agent-chat/​ChatFeedback.test.tsx Updates chat-feedback tests for folded forms.
app/​src/​pages/​AgentChatPage.tsx Integrates the session menu and experimental notice.
app/​src/​pages/​AgentChatPage.save.test.tsx Tests saving through the overflow menu.
app/​src/​pages/​AgentChatPage.public.test.tsx Tests the public notice popover and save defaults.
app/​src/​pages/​AgentChatPage.feedback.test.tsx Updates page-level feedback flow tests.

Review effort: Lite

…short placeholders

The data card's long label, its hint line and the how-to paragraph under
it go; '# your data ⓘ' opens the formats, the steps, a fix in plain words
and changes afterwards (InfoPopover, shared with the notice). The data
box and the composer name example data, a curve and a fix in short
placeholders. The missing-parameters notice names .use_my_data().

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H7HSkGyea1k2v293XiAMo8
@codecov

codecov Bot commented Nov 2, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 96.22642% with 4 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
app/src/sections/agent-chat/ResultCard.tsx 94.00% 3 Missing ⚠️
app/src/sections/agent-chat/ResultFeedback.tsx 94.73% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

MarkusNeusinger and others added 6 commits November 2, 2026 23:56
….md and the fragment

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H7HSkGyea1k2v293XiAMo8
…tter

# Conflicts:
#	docs/concepts/agent-network.md
… the new controls

Owner decision of 2026-11-02: a visitor cannot resume a saved session,
and the feedback form covers what went wrong, so the public lane offers
no .save() and renders no "⋯" menu; the admin lane keeps both. The root
prompt's control list names .show_code()/.hide_code() for the code,
.expand()/.collapse() for the card, the status line, .cancel() in the
feedback, and no longer names .save(), which the public page lacks.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H7HSkGyea1k2v293XiAMo8
… line

The data card, the plot cards and the code use the room of a wide
screen; the thread's replies, turns and notices and a card's text lists
stay at a readable line of about 80 characters. Below about 1100 px the
window sets the width, as before. Both lanes share the layout.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H7HSkGyea1k2v293XiAMo8
@MarkusNeusinger
MarkusNeusinger merged commit e1480c1 into main Nov 2, 2026
14 checks passed
@MarkusNeusinger
MarkusNeusinger deleted the feat/agent-chat-declutter branch November 2, 2026 23:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants