feat(chat): quiet quote-reply chip, distinguish from threads (LC-461) #444

Merged
longjacksonle merged 1 commit from feat/quote-thread-clarity into main 2026-06-25 03:13:00 +02:00

What

Refines the room reply/thread rendering (LC-461, follow-up to LC-460). Ref data/ref-room-thread.png.

Data-model audit (done first)

Quote-reply and thread are two separate features:

Quote-reply Thread
Column quote_id (migration 0020) parent_id (migration 0011)
In main timeline? Yes (quoting message stays) No - excluded by WHERE parent_id IS NULL; lives in the side panel
Rendering inline "Replying to" chip "N replies" pill + Thread panel

They are mutually exclusive in code (insert_message_quoted omits parent_id; insert_reply omits quote_id). PR #443 had made the inline quote chip accent-tinted, so it dominated message bodies and looked like the thread pill - the source of the confusion.

Changes (rendering/CSS only)

  • Quote chip is now quiet: thin neutral left-border, no fill, small low-contrast text - subordinate to the message body. Content is louder than context.
  • Accent reserved for the thread pill (the door to the side panel), so quote vs thread read as visually distinct.
  • Thread panel header references the parent ("Replies to {author}"), making it clearly the expanded view of that message's pill.
  • Thread reply rows align to the redesigned timeline message (h-6 avatar, lc-caption time, pl-8 body). Kept as the lightweight partial - reusing the full message.html would emit a duplicate id="msg-{id}" (already in the timeline) and break OOB swaps.
  • Thread composer cue ("Replying in thread") so it is not confused with the main room composer.

Constraints honored

No change to storage, reply/thread server functions, WS events, or hx-swap-oob targets. Minimal CSS, inline SVG, light/dark tokens.

Verification

just build-css, just check (clippy + fmt clean), just test, just test-saas all green. just verify built the release binary clean; its server-up harness lacks the mandatory LETS_CHAT_BUNYIP_SSO_* startup vars, so the standalone server cannot boot to serve /login in this sandbox (environmental, not a regression).

🤖 Generated with Claude Code

## What Refines the room reply/thread rendering (LC-461, follow-up to LC-460). Ref `data/ref-room-thread.png`. ## Data-model audit (done first) Quote-reply and thread are **two separate features**: | | Quote-reply | Thread | |---|---|---| | Column | `quote_id` (migration 0020) | `parent_id` (migration 0011) | | In main timeline? | Yes (quoting message stays) | No - excluded by `WHERE parent_id IS NULL`; lives in the side panel | | Rendering | inline "Replying to" chip | "N replies" pill + Thread panel | They are mutually exclusive in code (`insert_message_quoted` omits `parent_id`; `insert_reply` omits `quote_id`). PR #443 had made the inline quote chip accent-tinted, so it dominated message bodies and looked like the thread pill - the source of the confusion. ## Changes (rendering/CSS only) - **Quote chip is now quiet**: thin neutral left-border, no fill, small low-contrast text - subordinate to the message body. Content is louder than context. - **Accent reserved for the thread pill** (the door to the side panel), so quote vs thread read as visually distinct. - **Thread panel header references the parent** ("Replies to {author}"), making it clearly the expanded view of that message's pill. - **Thread reply rows align to the redesigned timeline message** (h-6 avatar, `lc-caption` time, `pl-8` body). Kept as the lightweight partial - reusing the full `message.html` would emit a duplicate `id="msg-{id}"` (already in the timeline) and break OOB swaps. - **Thread composer cue** ("Replying in thread") so it is not confused with the main room composer. ## Constraints honored No change to storage, reply/thread server functions, WS events, or `hx-swap-oob` targets. Minimal CSS, inline SVG, light/dark tokens. ## Verification `just build-css`, `just check` (clippy + fmt clean), `just test`, `just test-saas` all green. `just verify` built the release binary clean; its `server-up` harness lacks the mandatory `LETS_CHAT_BUNYIP_SSO_*` startup vars, so the standalone server cannot boot to serve `/login` in this sandbox (environmental, not a regression). 🤖 Generated with [Claude Code](https://claude.com/claude-code)
feat(chat): quiet quote-reply chip, distinguish it from threads (LC-461)
All checks were successful
check-secrets / Nosey parker (push) Successful in 4s
check-secrets / Kingfisher (push) Successful in 4s
check-secrets / TruffleHog (push) Successful in 5s
check-secrets / Nosey parker (pull_request) Successful in 8s
check-secrets / TruffleHog (pull_request) Successful in 10s
check-secrets / Kingfisher (pull_request) Successful in 10s
Check / clippy + fmt + tests (pull_request) Successful in 5m38s
Create release / Create release from merged PR (pull_request) Has been skipped
e96918ac2f
Audited the data model first: quote-reply and thread are two separate features. A quote-reply sets `quote_id` (migration 0020) and the quoting message stays in the main timeline, rendering the inline "Replying to" chip; a thread reply sets `parent_id` (migration 0011), is excluded from the main timeline (WHERE parent_id IS NULL), and lives only in the side panel, with the "N replies" pill counting children. They are mutually exclusive in code (insert_message_quoted omits parent_id; insert_reply omits quote_id).

PR #443 had made the inline quote chip accent-tinted, so it dominated message bodies and looked like the thread pill. This separates the two treatments:

- Quote chip is now a quiet, muted reference line: thin neutral left-border, no fill, small low-contrast text - subordinate to the message body. The accent treatment is reserved for the thread-entry pill (the door to the side panel), so the two reply concepts read as visually distinct.
- Thread panel header references the parent ("Replies to {author}") so it is clearly the expanded view of that message's pill.
- Thread reply rows align to the redesigned timeline message (h-6 avatar, lc-caption time, pl-8 body); kept as the lightweight partial so no duplicate id="msg-{id}" is emitted.
- The thread composer gains a "Replying in thread" cue so it is not confused with the main room composer.

Rendering/CSS only: no change to storage, reply/thread server functions, WS events, or hx-swap-oob targets. Verified with just build-css, just check, just test, just test-saas. just verify built the release binary clean; its server-up harness lacks the mandatory LETS_CHAT_BUNYIP_SSO_* startup vars, so the standalone server cannot boot to serve /login in this sandbox (environmental).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
longjacksonle scheduled this pull request to auto merge when all checks succeed 2026-06-25 03:07:50 +02:00
longjacksonle deleted branch feat/quote-thread-clarity 2026-06-25 03:13:00 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
psa-systems/lets-chat!444
No description provided.