Skip to content

feat(console): bring the elicitation card back to its design - #1823

Merged
spacedragon merged 2 commits into
mainfrom
feat/elicitation-card-design
Sep 7, 2026
Merged

feat(console): bring the elicitation card back to its design#1823
spacedragon merged 2 commits into
mainfrom
feat/elicitation-card-design

Conversation

@spacedragon

Copy link
Copy Markdown
Contributor

The webchat elicitation card (#1816, #1817) had drifted from the design it was drawn from. Four things read wrong on a real AskUserQuestion form:

  • every question stood a labelled Other box open beneath its options, so a three-question form was mostly empty inputs
  • the description sat on its own line under the label instead of riding its baseline
  • the counter and the primary read as a bare 2/3 / Submit, with no clock
  • a long ask filled the head as a paragraph-long title

What changed

  • A question's box is behind its own Other… chip. Opening it discloses the input; closing it drops the draft, so a value the reader can no longer see is never part of the answer. A box the schema handed a default opens showing it.
  • Picking an option still leaves the box alone — a required question legitimately answers with both its pick and its custom text (fix(daemon): re-derive every elicitation answer against the card that offered it #1815, fix(console): fold a question's own "Other" box into that question #1817), and clearing on pick would cut that.
  • An option chip whose label is its value renders in mono, the way the design reads literals. Every option chip also names itself on hover, so one too long for the card is readable rather than just truncated.
  • The description rides the label's baseline; optional loses its parentheses; required keeps the brand color.
  • The head keeps one line and anything past it renders as the preamble it is, above the questions. The counter says 2/3 answered, and the row's own clock sits at the far edge.
  • The form's primary is Submit answers (a single-value card still says Submit).

Not adopted from the design

The design's footer reads Blank optional answers are sent as null, but the implementation omits an untouched optional field entirely rather than sending null — formAnswer builds the record that way and the daemon accepts it. The truthful Optional answers left blank are not sent stays; changing it would mean changing the answer semantics, not the copy.

Tests

SessionDetailView.elicitation.test.tsx follows the new interaction (it opens a question's box before typing) and gains one case: closing the box drops the draft, and the card then answers with the options alone. 74 passed across the SessionDetailView* files; typecheck, prettier and eslint clean.

🤖 Generated with Claude Code

The card drifted from the design in four places: every question stood a
labelled "Other" box open beneath its options, the description sat on its
own line under the label, the counter and the primary read as bare
"2/3"/"Submit", and a long ask filled the head as a paragraph-long title.

A question's box is now disclosed by its own "Other…" chip and closing it
drops the draft, so a hidden value is never part of the answer. Literal
option chips render in mono, the description rides the label's baseline,
"optional" loses its parentheses, the head keeps one line with the rest of
the ask as a preamble above the questions, and the row's clock sits at the
far edge.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

@agentconnect-md-test agentconnect-md-test Bot 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.

Reviewed revision 305ef8e. No blocking regressions found. The “Other…” toggle clears hidden drafts while preserving option selections, and the existing answer validation remains intact.

Validation: all 26 elicitation tests passed; web typecheck, ESLint, and Prettier checks passed.

sent by review-bot (Codex · gpt-6-astra) · open in session

Read from the canvas source (Webchat Elicitation.dc.html): a question whose
options are sentences is not a chip row there. One option past ~22 characters
turns the whole question into full-width rows — a radio-style indicator, the
label wrapping at 1.45 — so no answer is truncated away and the options stay
comparable by being shaped alike. A chip row that has to shrink its own options
is the failure this avoids.

Chips and rows are now one control: `ElicitOption` renders either shape, marks
a held pick only where the card actually holds one (a single-choice card
answers on the tap), and gives the "Other…" affordance the soft accent the
design uses for an option the agent never offered. A chips question's box is a
narrow mono literal, a row question's spans the list, and the head wears the
design's message-square-dot.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@spacedragon

Copy link
Copy Markdown
Contributor Author

Read the canvas source this was drawn from (Webchat Elicitation.dc.html, frames 1a/2a) and ported the parts the first pass had guessed at:

  • Long options. The design does not put sentences in chips: const long = d.opts.some(o => o.length > 22) switches the whole question to isList — full-width rows with a radio indicator, label wrapping at 1.45. Ported as asList() + one ElicitOption that renders either shape, for both the form rows and the single-question card.
  • Other… carries the soft accent (--brand-soft / --brand-soft-border), not the solid brand fill a real pick gets — it is an option the agent never offered.
  • A chips question's box is a narrow mono literal (~260px); a row question's box spans the list (~340px).
  • Head icon is message-square-dot, as in the source.
  • A held pick shows an indicator only where the card holds one: a single-choice card answers on the tap, so it has no staged state to report.

Two deliberate deviations from the canvas, both because the wire disagrees with it:

  1. Footer still reads Optional answers left blank are not sent. The canvas says "sent as null", but formAnswer omits an untouched optional field and the daemon accepts that shape.
  2. Picking an option does not clear a filled Other box. The canvas models one answer per question (answers[id] = '__other'), while our wire carries the question and its custom answer as two properties and fix(daemon): re-derive every elicitation answer against the card that offered it #1815/fix(console): fold a question's own "Other" box into that question #1817 deliberately send both for a required question.

@agentconnect-md-test agentconnect-md-test Bot 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.

Reviewed updated revision 54ddc45, including the long-option row layout and shared option component. No blocking regressions found; selection limits, submission behavior, and clearing hidden custom answers remain intact.

Validation: all 26 elicitation tests passed; web typecheck, ESLint, and Prettier checks passed.

sent by review-bot (Codex · gpt-6-astra) · open in session

@agentconnect-md-test

Copy link
Copy Markdown
Contributor

Both deviations preserve the existing answer contract: blank optional fields are omitted, and a required selection can accompany custom text. My approval of 54ddc45 already covers these changes, including the long-option row layout.

sent by review-bot (Codex · gpt-6-astra) · open in session

@spacedragon
spacedragon merged commit 032913e into main Sep 7, 2026
13 checks passed
@spacedragon
spacedragon deleted the feat/elicitation-card-design branch September 7, 2026 07:04
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.

1 participant