feat(huddle): compact stay-in-chat dock, grows for video, collapsible (LC-700) #666

Merged
longjacksonle merged 1 commit from feat/LC-700-huddle-dock into main 2026-08-10 20:22:57 +02:00

Redesigns the active-huddle layout (LC-700) so it reads as a lightweight, docked, stay-in-chat mode rather than a co-equal split that squeezes the timeline and wastes space on one avatar in a big box. Presentation only: no change to the WebRTC mesh/SFU signaling, the join/leave/mute/camera/screen logic, or transcription controls.

What changed

  • Audio-first compact dock: scoped to .lc-huddle, when nobody has a live camera or screen-share the in-call grid becomes a wrapping row of compact chips (avatar + name + speaking equalizer + mute badge + YOU pill), capped short, so the message timeline stays primary. Driven by one new data-media="audio|video" attribute voice.js sets in updateTileMedia; the rest is pure CSS :has() reusing the live tile DOM, so speaking/mute/YOU state stays wired.
  • Grows for media: any camera or screen-share flips the same tiles back to the full 16/9 gallery. Mixed huddles (one on video, others audio) show the gallery.
  • Collapse / expand: a chevron toggle drops the huddle to a minimal control bar and back. Pure UI in live.js (no RTC), remembered per room in localStorage; chevron rotates.
  • Consistent responsive controls: the controls row is now a .lc-callbar-controls inside a lc-callbar query container, reusing the call view's rule so labels collapse to icons when the dock is narrow. Leave stays destructive.
  • Motion: dock growth + chevron transition are behind prefers-reduced-motion: no-preference; collapse is a deterministic display toggle (no layout jump).

Safety / scope

The full-screen voice-channel view has no .lc-huddle root, so every new rule is scoped away from it. The only JS change to the RTC file is a single read-only setAttribute line; the collapse handler lives in live.js. No Rust, no signaling changes, no DB migration.

Drag-to-resize was the stated alternative to a collapse toggle in the ticket; the toggle path is implemented, drag-resize is out of scope.

Tests

just test green (195 binaries, 1634 tests), en/es locale parity holds, both JS files pass node --check. Template compiles. Huddle integration tests exercise signaling only and are unaffected.

🤖 Generated with Claude Code

https://claude.ai/code/session_016ufqbuN7mjyt4ms5NEygMy

Redesigns the active-huddle layout (LC-700) so it reads as a lightweight, docked, stay-in-chat mode rather than a co-equal split that squeezes the timeline and wastes space on one avatar in a big box. Presentation only: no change to the WebRTC mesh/SFU signaling, the join/leave/mute/camera/screen logic, or transcription controls. ## What changed - Audio-first compact dock: scoped to `.lc-huddle`, when nobody has a live camera or screen-share the in-call grid becomes a wrapping row of compact chips (avatar + name + speaking equalizer + mute badge + YOU pill), capped short, so the message timeline stays primary. Driven by one new `data-media="audio|video"` attribute voice.js sets in `updateTileMedia`; the rest is pure CSS `:has()` reusing the live tile DOM, so speaking/mute/YOU state stays wired. - Grows for media: any camera or screen-share flips the same tiles back to the full 16/9 gallery. Mixed huddles (one on video, others audio) show the gallery. - Collapse / expand: a chevron toggle drops the huddle to a minimal control bar and back. Pure UI in live.js (no RTC), remembered per room in localStorage; chevron rotates. - Consistent responsive controls: the controls row is now a `.lc-callbar-controls` inside a `lc-callbar` query container, reusing the call view's rule so labels collapse to icons when the dock is narrow. Leave stays destructive. - Motion: dock growth + chevron transition are behind `prefers-reduced-motion: no-preference`; collapse is a deterministic display toggle (no layout jump). ## Safety / scope The full-screen voice-channel view has no `.lc-huddle` root, so every new rule is scoped away from it. The only JS change to the RTC file is a single read-only `setAttribute` line; the collapse handler lives in live.js. No Rust, no signaling changes, no DB migration. Drag-to-resize was the stated alternative to a collapse toggle in the ticket; the toggle path is implemented, drag-resize is out of scope. ## Tests `just test` green (195 binaries, 1634 tests), en/es locale parity holds, both JS files pass `node --check`. Template compiles. Huddle integration tests exercise signaling only and are unaffected. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_016ufqbuN7mjyt4ms5NEygMy
feat(huddle): compact stay-in-chat dock, grows for video, collapsible (LC-700)
All checks were successful
check-secrets / TruffleHog (push) Successful in 4s
check-secrets / Nosey parker (push) Successful in 4s
check-secrets / Kingfisher (push) Successful in 5s
check-secrets / TruffleHog (pull_request) Successful in 10s
check-secrets / Nosey parker (pull_request) Successful in 11s
check-secrets / Kingfisher (pull_request) Successful in 12s
Check / clippy + fmt + tests (pull_request) Successful in 12m58s
Create release / Create release from merged PR (pull_request) Has been skipped
53450aabcf
Redesigns the active-huddle layout so it reads as a lightweight docked mode instead of a co-equal split that squeezes the timeline. Presentation only: no change to the WebRTC mesh/SFU signaling, the join/leave/mute/camera/screen logic, or transcription.

Audio-first compact dock: scoped to .lc-huddle, when no participant has a live camera or screen-share the in-call grid lays out as a wrapping row of compact chips (avatar + name + speaking equalizer + mute badge + YOU pill) capped to a short height, so the message timeline stays the primary area. The switch is driven by a single new data-media="audio|video" attribute that voice.js sets in updateTileMedia (one line); the layout is then pure CSS :has() on the root and reuses the live tile DOM, so the speaking ring, mute state, and YOU pill stay wired.

Grows for media: as soon as anyone turns on a camera or shares a screen, the same tiles revert to the full 16/9 gallery (existing behavior). Mixed huddles (one on video, others audio) show the full gallery.

Collapse / expand: a chevron toggle in the bar collapses the huddle to a minimal control bar and expands it again. Handled in live.js (pure UI, no RTC), remembered per room in localStorage, chevron rotates to show state.

Consistent responsive controls: the controls row becomes a .lc-callbar-controls inside a lc-callbar query container, reusing the call view's rule so labelled buttons collapse to icons when the dock is narrow. Leave keeps its destructive styling.

Motion: dock growth and the chevron transition are guarded behind prefers-reduced-motion: no-preference; collapse itself is a deterministic display toggle so the timeline reflows without a jump. The full-screen voice-channel view is untouched (no .lc-huddle root).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016ufqbuN7mjyt4ms5NEygMy
longjacksonle scheduled this pull request to auto merge when all checks succeed 2026-08-10 20:17:22 +02:00
longjacksonle deleted branch feat/LC-700-huddle-dock 2026-08-10 20:22:57 +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!666
No description provided.