Skip to content

Render inline code in decision question text - #276

Open
MaggieAppleton wants to merge 2 commits into
mainfrom
design/question-inline-code
Open

MaggieAppleton wants to merge 2 commits into
mainfrom
design/question-inline-code

Conversation

@MaggieAppleton

@MaggieAppleton MaggieAppleton commented Oct 5, 2026 •

Copy link
Copy Markdown
Collaborator

Why

The Planner writes inline code with backticks in decision prompts, option labels and descriptions. The card showed them literally, e.g. "the current single .bak behavior".

What changed

  • New pure tokenizer inlineSegments() / plainInlineText() (single-backtick pairs only; empty or unmatched backticks stay literal) with unit tests.
  • New InlineCode component renders matched spans as <code class="inline-code">. No markdown renderer, no dangerouslySetInnerHTML. Stored text is unchanged.
  • Applied to the decision card (prompt, option label, description, resolved / discarded / expired summaries), the chat decision prompt entry, and the resolved-decision popover.
  • Accessible names and "Previously: …" use plainInlineText, so no stray backticks are read out.
  • .inline-code in apps/web/src/theme.css uses the same tokens as inline code in the document (inset, radius-sm, mono, inherited size) with font-weight: 400 so code in the bold prompt is not heavy.

Screenshots

Before (desktop):

before

After (desktop):

after

After (phone 390x844):

after phone

Needs a design-contract review

bun run ci fails ONLY on two reviewed dynamic-owner source hashes. Everything else (dprint, oxlint, tokens) passes. The exceptions were not edited.

  • packages/question/src/react/question-view.tsx -> scripts/design-contract/exceptions/dynamic-packages.json: new hash 5db9f37e2663a774eeb11cfde3a2fcf93dd06dc0ed6f077af42b5f8bc9e9b431 (old 6ffb7d6d...).
  • packages/editor/src/resolved-layer.tsx -> scripts/design-contract/exceptions/dynamic-editor.json: new hash d6976f81401b6563b3b68c38364b94bab169b30eed0038ed1f788f4025488260.

Why it is safe: the change only wraps existing text children in <InlineCode> and passes plain text to aria labels. There is no new class or style logic, and the dynamic className/style owners are untouched.

Testing

  • bun test packages/question: 134 pass, 0 fail
  • bun run types: clean
  • bun run fix: clean
  • bun run ci: fails only on the two hashes above
  • Browser: checked on a fake-GitHub server with a temporary backtick fixture (not committed). E2E not run. No phone "before" shot.

🤖 Generated with Claude Code

@coolify-githubnext-app

coolify-githubnext-app Bot commented Oct 5, 2026 •

Copy link
Copy Markdown

The preview deployment for chopin is ready. 🟢

Open app | Open Build Logs | Open Application Logs

Last updated at: 2026-10-05 09:34:38 CET

@MaggieAppleton

Copy link
Copy Markdown
Collaborator Author

Review: Changes needed (minor; visuals look good)

Checked in a browser (desktop 1440x900, phone 390x844) with a backtick fixture. Spans render as inset-chip mono at the inherited size, prompt/option/description wrap cleanly, and the card design is otherwise unchanged. Tokens only (--color-inset, --radius-sm, --font-mono). The two design-contract hashes are the only CI failure and the change is safe.

Findings

  1. Uncovered place: apps/web/src/conversation-plan/evidence-popover.tsx:48 renders row.label (option text, or thread.question per evidence.ts:90) as plain text, so backticks show literally in the evidence hover on the same decision. Wrap in <InlineCode>. excerpt-correction.tsx:88,162 (thread.question in a status message and a native <option>) cannot render elements; use plainInlineText there so stray backticks are not shown.
  2. Tokenizer, multi-backtick runs (inline-segments.ts:11-24): "a`b" gives "a" + code(b) + "`" and "```x```" gives "" + code(x) + "``", leaving stray backticks around a chip. Either match equal-length runs (CommonMark) or treat runs of 2+ as literal and skip the whole run. Add tests for both.
  3. Escapes: \x`renders` plus code "x" (backslash inside the chip). Either honour ``` or document it as unsupported with a test.
  4. Whitespace: "a" renders a padded chip with leading/trailing spaces. CommonMark trims one space; consider trimming, and treat whitespace-only as literal like the empty case.
  5. Joined strings tokenise across items: question-view.tsx:499/505 (chosen = choices.join(", ")) and :812 (labels.join(", ")) run the tokenizer over the joined string, so a lone backtick in one label can pair with one in the next and swallow the separator. Map plainInlineText per label, then join. For the resolved line, render each choice with <InlineCode> separately.
  6. Tests: only 5 cases, none for the items above (multiple backticks, escapes, whitespace, adjacent spans). No component-level coverage that aria-labels are backtick-free; consider a pure test on the label builders.

Accessible names otherwise look right: the Related button labels, Decision prompt: group label and "Previously:" use plain text; the radio option names come from content and exclude backticks.

@MaggieAppleton

Copy link
Copy Markdown
Collaborator Author

Addressed in 23270f4:

  1. evidence-popover.tsx row label now uses InlineCode; excerpt-correction.tsx status message and <option> use plainInlineText.
    2-4. Tokenizer follows CommonMark: N-length runs close at the next run of exactly N, unmatched runs stay literal, one space trimmed per side when both present, whitespace-only stays literal, ``` outside a span is a literal backtick, backslashes inside a span are literal.
  2. question-view.tsx now tokenizes each choice/label separately (InlineCodeList, plainInlineList); never the joined string.
  3. Tests cover every case above plus adjacent spans, per-item list reading, and backtick-free label builders (142 pass in packages/question).

question-view.tsx hash for the design-contract exception is now 5db9f37e2663a774eeb11cfde3a2fcf93dd06dc0ed6f077af42b5f8bc9e9b431 (PR body updated). bun run ci still fails only on the two hashes. Visuals are unchanged, so screenshots were not retaken.

lavaman131 added a commit that referenced this pull request Oct 6, 2026
Fixes that only exist because several open PRs now share one tree:

- Drop #290's duplicate ImageIcon and its LineIcon titles, which #287 removed.
- Remove the import #302 left unused after #276's inline code.
- Renew design-contract pins for files more than one PR edited, and record
  #290's new icons and #295's face colours as reviewed exceptions.
- Find icons by path rather than the titles #287 removed, and faces by the
  label #295 gives them.
- A tool that returns after its turn was stopped ends as failed, so #314's
  early completion keeps #272's stopped-question outcome.

Assistant-model: Claude Opus 5.5
Assistant-workflow: inline
Assistant-verification: typecheck passed: bun run types
Assistant-verification: dprint/oxlint/design checks passed: bun run ci
Assistant-verification: bun test passed: 3860 pass, 0 fail
Co-authored-by: Alex Lavaee <lavaman131@github.com>
@MaggieAppleton
MaggieAppleton force-pushed the design/question-inline-code branch 2 times, most recently from 8c33f74 to 833557b Compare October 7, 2026 12:01
@MaggieAppleton

This comment has been minimized.

@MaggieAppleton
MaggieAppleton force-pushed the design/question-inline-code branch 2 times, most recently from 16baac5 to e554b37 Compare October 7, 2026 13:45
MaggieAppleton and others added 2 commits October 7, 2026 14:55
Planner prompts, option labels and descriptions use backticks for inline code. Render matched single-backtick pairs as code elements; display only, stored text unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@MaggieAppleton
MaggieAppleton force-pushed the design/question-inline-code branch from e554b37 to 1bd9558 Compare October 7, 2026 13:55
@MaggieAppleton

Copy link
Copy Markdown
Collaborator Author

I rechecked the latest failed ci run for 1bd9558c583e51efdfdb1b3e4f5ea4bd9f69d3ec. The head still matches the recorded candidate, container and e2e are green, and the only failing job is format, lint, types, tests, stopping in Format, lint, and enforce design tokens. The blocker is still the reviewed design-contract exception renewal for packages/question/src/react/question-view.tsx and packages/editor/src/resolved-layer.tsx, which would require changing scripts/design-contract/exceptions/ entries that this workflow is not allowed to edit. I did not queue a [ci-fix] commit. Local reproduction and verification are also blocked in this runner because bun and mise are not installed, so I could not run bun install --frozen-lockfile, bun run fix, or bun run ci here. Next human action: review and renew the exact design-contract exception if the ownership change is approved, or push a new head that avoids needing the exception update.

babysit-head:1bd9558c583e51efdfdb1b3e4f5ea4bd9f69d3ec

Generated by PR CI fixer · gpt54 · 43.1 AIC · ⌖ 3.21 AIC · ⊞ 15.1K · ◷

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