ui: chat HTML rework — quiet mode + smaller fonts + contextual ASCII flourishes - #22
Conversation
…flourishes
Three asks from live testing:
1. The aA font-size toggle felt out of place / weird scaling — remove.
2. The chat is too busy reading every tool call. Want a toggle that
hides tool detail and shows just user prompts + assistant text.
3. Make the fonts a bit smaller everywhere, and add some little
contextual ASCII art that fits the existing retro CRT aesthetic.
## Removed: aA font-size toggle (ex-PR-27)
- Deleted `<button id="font-toggle">` HTML
- Deleted `#font-toggle`, `.fs-a`, `.fs-A`, `:root.fs-small`,
`:root.fs-large` CSS (~50 lines)
- Deleted `$fontToggle`, `FONT_KEY`, `applyFontMode`, click handler,
Cmd/Ctrl + +/- keyboard shortcut
- Deleted `tests/test_chat_html_font_toggle.py` (23 tests)
## Added: quiet-mode toggle
Same far-right slot in the status bar. Single button with a hollow
(○) / filled (●) circle glyph indicating off / on. State persists
per browser via `localStorage["tdpilot.quietMode"]`.
When active, three CSS rules hide every tool-call surface:
```css
:root.quiet-mode .msg.tool_call,
:root.quiet-mode .msg.tool_result,
:root.quiet-mode details.tool-pair { display: none; }
```
User prompts, assistant text, errors, and hints stay visible. The
status bar at the top still shows the agent's per-turn working
state ("thinking" / "calling td_create_node ...") so progress is
never blacked out — quiet mode hides DETAIL, not signal.
Keyboard shortcut: Cmd/Ctrl + . (period). Replaces the v2.0.0
font-zoom shortcuts.
## Smaller default fonts
| Element | Was | Now |
|---|---|---|
| body / chat content | 13px | 12px |
| status bar | 11px | 10px |
| input textarea | 13px | 12px |
Status-bar letter-spacing also softened from 0.1em → 0.08em so the
slightly-smaller text doesn't look too wide. line-height bumped
from 1.5 → 1.55 to compensate for the tighter base size.
## Contextual ASCII flourishes
On agent turn-end (state transitions from working → idle),
`attachFlourishToLastAssistant()` walks back through #history,
finds the most recent assistant message that doesn't already carry
a flourish, and appends a `.msg-flourish` div with a topic-matched
glyph from a 9-bucket pool:
default ▰▰▰ ∴ ◇ ◇ ◇ ═══ · · · ──◆── ·:·:· ▱▰▱
light ✺ ✸ ✺ \●/ ─ ✷ ─ ※ ✺ ※
camera [◉] ▤ ▥ ▤ ▣ ─ ▣ ┌─◎─┐
particle · ∴ · ∴ · ⋆ ✦ ⋆ ·:·∴·:· ∗ ⋆ ∗
material ▓▒░ ░▒▓ ░▒▓▒░ ▓ ─ ▓
audio ~~~ ∿ ~~~ ∿∿∿∿ · ∿ · ∿ ·
geom ◆ ─ ◇ ─ ◆ △ ▽ △ □ ▣ □ ◯ ◉ ◯
error × × × !? ─ ?! × ─ ✗ ─ ×
success ✓ ✓ ✓ ✦ ─ ▰ ─ ✦ ── ✓ ── · · ✦ · ·
Topic detection runs the last user message + assistant body
through 8 keyword regexes (light/camera/particle/material/audio/
geom/error/success). If any non-default topic matches, 75% chance
to draw from that bucket; 25% fallback to default for variety. The
chosen topic name appears in tiny uppercase under the glyph — gives
the reader a one-word post-context ("CAMERA", "PARTICLE", etc.).
CSS keeps it visually quiet:
- accent-dim color (purple-grey, not the bright primary accent)
- centered with 0.5em letter-spacing (reads as punctuation)
- 0.55 opacity
- 1px dashed top border separating from the message body
- no animation, no emoji, no extra weight
## Tests
`tests/test_chat_html_v210_ui.py` — 18 structural assertions:
- Font toggle is GONE (HTML, CSS, JS all clean)
- Quiet toggle exists with correct DOM structure + a11y attrs
- Status bar still has lhs / rhs / quiet-toggle in that order
- :root.quiet-mode hides ONLY tool blocks (NOT user / assistant /
error / hint)
- Cmd/Ctrl + . shortcut wired to applyQuietMode
- localStorage key namespaced + try/catch guarded
- All 9 flourish topic buckets defined
- 7 topic-detection regex literals present
- attachFlourishToLastAssistant idempotent (won't double-attach)
- Trigger fires on agent working → idle transition
- .msg-flourish styling matches the quiet-aesthetic spec
## Results
- 1635 tests pass / 12 deselected
(was 1640 in v2.0.1: −23 font-toggle tests, +18 v2.1.0 tests)
- ruff check + format clean
## Tox rebuild
Required (chat HTML is in standalone tox `_SOURCE_FILES`). Pairs
with the v2.0.1 release rebuild — same TD Textport recipe covers
both this UI rework AND the v2.0.1 source-side fixes.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 830bf1819e
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if (wasWorking && newState === 'idle') { | ||
| try { attachFlourishToLastAssistant(); } catch (_) { /* defensive */ } |
There was a problem hiding this comment.
Gate flourish insertion on actual assistant output
Only checking wasWorking && newState === 'idle' means a flourish is appended even when the just-finished transition produced no new assistant message (for example, a stop/cancel path). Because chat history rehydration (fullSync) rebuilds plain assistant messages without prior flourish DOM, this can decorate an older reply and make it look like a fresh completion happened. Please tie flourish insertion to whether a new assistant message was appended in the current turn, not just the status transition.
Useful? React with 👍 / 👎.
ui: chat HTML rework — quiet mode + smaller fonts + contextual ASCII flourishes
Path B per the user: bundle the would-be v2.0.1 patch (12 audit fixes from PRs #19 #20 + 1 live-tier propagation fix) and the chat UI rework (PR #22 — quiet mode, smaller fonts, contextual ASCII flourishes) into a single 2.1.0 minor release. Avoids a redundant .tox rebuild + npm publish cycle for what's effectively one batch of changes. Version bumps 2.0.0 → 2.1.0 across 13 canonical + cosmetic banner files. Live-tier fix re-applied to runtime.py (was on the closed PR #21 branch). uv.lock auto-refreshed in PR #20. CHANGELOG entry covers all 13 audit findings + the 4 UI rework items (font toggle removal, quiet mode toggle, smaller fonts, contextual ASCII flourishes), with migration notes for the two user-visible shifts (font-toggle → quiet-toggle and EXEC_MODE default flip). Tests: 1635 pass / 12 deselected (no regressions). Tox-freshness FAILS as expected — API_VERSION bump, runtime.py edit, chat HTML rework all need the .tox rebuilt. Mirror the v2.0.0 release pattern: merge → rebuild .tox → tag → release → npm OIDC publish. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Summary
Three asks from live testing on v2.0.1:
aAfont-size toggle felt out of place / weird scaling — remove.All three, in one branch.
Removed:
aAfont-size toggle (ex-PR-27)#font-toggle,.fs-a,.fs-A,:root.fs-small,:root.fs-large)$fontToggle,FONT_KEY,applyFontMode, click, keyboard shortcut)tests/test_chat_html_font_toggle.py(23 tests)Added: quiet-mode toggle
Same far-right slot in the status bar. Hollow ○ (off) / filled ● (on) glyph. State persists per browser via
localStorage["tdpilot.quietMode"]. Three CSS rules hide tool surfaces:User prompts, assistant text, errors, hints stay visible. The status bar at the top still shows the agent's per-turn state ("thinking" / "calling td_create_node…") so progress is never blacked out — quiet mode hides detail, not signal.
Keyboard shortcut:
Cmd/Ctrl + .(replaces the v2.0.0 font-zoom shortcuts).Smaller default fonts
Status-bar letter-spacing softened 0.1em → 0.08em (compensates for the tighter base). line-height bumped 1.5 → 1.55.
Contextual ASCII flourishes
On agent turn-end (state transitions from working → idle),
attachFlourishToLastAssistant()walks back through#history, finds the most recent assistant message that doesn't already carry a flourish, and appends a.msg-flourishdiv with a topic-matched glyph from a 9-bucket pool:8 topic-detection regexes against the last user message + assistant body. If any non-default matches, 75% chance to draw from that bucket; 25% fallback to default for variety. Chosen topic name appears in tiny uppercase under the glyph as one-word post-context.
CSS aesthetic:
--accent-dimcolor (purple-grey, not the bright primary accent)Test plan
uv run --extra dev pytest tests/test_chat_html_v210_ui.py -v→ 18 passuv run --extra dev pytest tests/ -q→ 1635 pass / 12 deselected (was 1640: −23 font-toggle tests, +18 v2.1.0 tests)uv run --extra dev ruff check .→ cleanuv run --extra dev ruff format --check .→ 298 files OKbash scripts/check_no_personal_paths.sh→ cleanpython scripts/check_versions.py→ in sync at v2.0.0 (no version bump in this PR — v2.1.0 bump happens in the release commit).tox rebuild
Required (chat HTML is in standalone tox
_SOURCE_FILES). Pairs with the v2.0.1 release rebuild that's already pending in PR #21 — single TD Textport rebuild covers both.Versioning
This is a new minor release (
2.1.0— feature additions: quiet mode + flourishes). Suggest sequencing:OR collapse: bump straight to v2.1.0, ship everything together. Your call.
🤖 Generated with Claude Code