From 1d1a4cd87763915155bf2f837616fa829a87b932 Mon Sep 17 00:00:00 2001 From: isaacclad Date: Sat, 4 Jul 2026 00:53:55 +0000 Subject: [PATCH] Fix overlapping speaker cards in audio rooms with a proper grid layout. Use display grid for speaker tiles, show only host/co-host/panelist on stage, and re-layout when roles change so cards stay in separate cells. Co-authored-by: Cursor --- resources/css/app.css | 49 ++++++++++++++++++++-- resources/js/meet-room.js | 52 +++++++++++++++++++++++- resources/views/meet/room/show.blade.php | 2 +- 3 files changed, 98 insertions(+), 5 deletions(-) diff --git a/resources/css/app.css b/resources/css/app.css index fb50dba..8573dd9 100644 --- a/resources/css/app.css +++ b/resources/css/app.css @@ -336,10 +336,53 @@ html.meet-room-page { } .meet-room-page .meet-audio-grid { - place-content: center; - place-items: center; - grid-template-columns: repeat(auto-fill, minmax(7rem, 9rem)); + display: grid; + width: 100%; + min-height: 0; + overflow-x: hidden; + overflow-y: auto; + align-content: start; + justify-content: center; gap: 1rem; + padding: 0.75rem; + grid-template-columns: repeat(2, minmax(0, 9.5rem)); +} + +@media (min-width: 640px) { + .meet-room-page .meet-audio-grid { + gap: 1.25rem; + padding: 1rem; + grid-template-columns: repeat(auto-fill, minmax(8.5rem, 10rem)); + align-content: center; + } +} + +.meet-room-page .meet-audio-grid.meet-audio-grid--solo { + grid-template-columns: minmax(0, 10rem); + place-content: center; +} + +.meet-room-page .meet-audio-grid [data-participant-tile] { + position: relative; + width: 100%; + max-width: 10rem; + justify-self: center; + isolation: isolate; +} + +.meet-room-page .meet-audio-tile { + width: 100%; + min-width: 0; + box-shadow: 0 4px 14px rgb(0 0 0 / 0.25); +} + +.meet-room-page .meet-audio-tile [data-tile-body] { + flex: 1 1 auto; + min-height: 0; +} + +.meet-room-page .meet-audio-tile [data-tile-footer] { + flex-shrink: 0; } .meet-room-page .meet-audio-tile [data-tile-avatar-circle] { diff --git a/resources/js/meet-room.js b/resources/js/meet-room.js index 4104435..fd39a32 100644 --- a/resources/js/meet-room.js +++ b/resources/js/meet-room.js @@ -903,6 +903,13 @@ function meetRoom() { getTileContainerForIdentity(identity) { if (!this.usesStageLayout) { + if (this.isSpace) { + const person = this.sessionParticipants.find((entry) => entry.uuid === identity); + if (!person || !['host', 'co_host', 'panelist'].includes(person.role)) { + return null; + } + } + return document.getElementById('video-grid'); } @@ -980,6 +987,30 @@ function meetRoom() { if (!this.usesStageLayout) { document.getElementById('meet-stage-spotlight')?.replaceChildren(); document.getElementById('meet-audience-strip')?.replaceChildren(); + + if (room) { + const all = [room.localParticipant, ...room.remoteParticipants.values()]; + all.forEach((participant) => { + const target = this.getTileContainerForIdentity(participant.identity); + if (!target) { + this.removeParticipantTile(participant.identity); + return; + } + + const tile = this.getOrCreateParticipantTile(participant); + if (!tile) { + return; + } + + if (tile.parentElement !== target) { + target.appendChild(tile); + } + + this.updateParticipantTile(participant); + }); + } + + this.updateAudioGridLayout(); return; } @@ -1292,7 +1323,7 @@ function meetRoom() { tile = document.createElement('div'); tile.dataset.participantTile = identity; tile.className = this.audioOnly - ? 'meet-audio-tile relative flex aspect-square w-full max-w-[9rem] flex-col overflow-hidden rounded-2xl bg-slate-900' + ? 'meet-audio-tile relative flex aspect-square w-full flex-col overflow-hidden rounded-2xl bg-slate-900' : 'relative flex aspect-video w-full flex-col overflow-hidden rounded-xl bg-slate-900 min-h-0'; tile.innerHTML = `
@@ -2030,9 +2061,20 @@ function meetRoom() { this.applyStageLayout(); this.updateGalleryGridLayout(); + this.updateAudioGridLayout(); this.syncActiveSpeakers(room.activeSpeakers ?? []); }, + updateAudioGridLayout() { + const grid = document.getElementById('video-grid'); + if (!grid || !this.audioOnly || this.usesStageLayout) { + return; + } + + const count = grid.querySelectorAll('[data-participant-tile]').length; + grid.classList.toggle('meet-audio-grid--solo', count === 1); + }, + updateGalleryGridLayout() { const grid = document.getElementById('video-grid'); if (!grid || this.usesStageLayout || this.audioOnly) { @@ -2060,6 +2102,14 @@ function meetRoom() { } }); + if (room) { + [room.localParticipant, ...room.remoteParticipants.values()].forEach((participant) => { + if (!this.getTileContainerForIdentity(participant.identity)) { + this.removeParticipantTile(participant.identity); + } + }); + } + this.applyStageLayout(); }, diff --git a/resources/views/meet/room/show.blade.php b/resources/views/meet/room/show.blade.php index 213aa56..0f9a1a7 100644 --- a/resources/views/meet/room/show.blade.php +++ b/resources/views/meet/room/show.blade.php @@ -330,7 +330,7 @@
-
+