Simplify mobile meeting toolbar into primary actions and More menu.
Deploy Ladill Meet / deploy (push) Successful in 47s

Show mic, camera, share, and More on mobile with Leave/End after a divider,
and move reactions, chat, and hand-raise into the More panel on small screens.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
isaacclad
2026-07-01 14:27:19 +00:00
co-authored by Cursor
parent 70d556799e
commit 9b4eab4848
2 changed files with 101 additions and 92 deletions
+20 -38
View File
@@ -28,55 +28,37 @@
margin-left: auto;
}
/* Meeting room footer: horizontal carousel on mobile */
/* Meeting room footer */
@media (max-width: 639px) {
.meet-toolbar {
position: relative;
overflow: hidden;
}
.meet-toolbar::before,
.meet-toolbar::after {
content: '';
position: absolute;
top: 0;
bottom: 0;
z-index: 1;
width: 1.25rem;
pointer-events: none;
}
.meet-toolbar::before {
left: 0;
background: linear-gradient(to right, rgb(2 6 23), transparent);
}
.meet-toolbar::after {
right: 0;
background: linear-gradient(to left, rgb(2 6 23), transparent);
}
.meet-toolbar__track {
display: flex;
flex-wrap: nowrap;
align-items: center;
gap: 0.5rem;
overflow-x: auto;
overscroll-behavior-x: contain;
-webkit-overflow-scrolling: touch;
scroll-snap-type: x proximity;
scrollbar-width: none;
justify-content: space-between;
gap: 0.75rem;
padding-inline: 1rem;
padding-bottom: max(0.25rem, env(safe-area-inset-bottom, 0px));
}
.meet-toolbar__track::-webkit-scrollbar {
display: none;
.meet-toolbar__primary {
display: flex;
min-width: 0;
flex: 1;
align-items: center;
gap: 0.5rem;
}
.meet-toolbar__track > * {
.meet-toolbar__divider {
width: 1px;
height: 2rem;
flex-shrink: 0;
scroll-snap-align: center;
background-color: rgb(51 65 85);
}
.meet-toolbar__actions {
display: flex;
flex-shrink: 0;
align-items: center;
gap: 0.5rem;
}
}
+81 -54
View File
@@ -182,60 +182,75 @@
<footer class="relative shrink-0 bg-slate-950 py-4 sm:px-4">
<div class="meet-toolbar mx-auto max-w-5xl">
<div class="meet-toolbar__track sm:px-0">
<button @click="toggleMute()" type="button"
class="rounded-full p-3 transition-colors"
:class="isMuted ? 'bg-red-600 hover:bg-red-500' : 'bg-slate-700 hover:bg-slate-600'"
:title="isMuted ? 'Unmute' : 'Mute'">
<svg x-show="!isMuted" class="h-5 w-5" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M12 18.75a6 6 0 0 0 6-6v-1.5m-6 7.5a6 6 0 0 1-6-6v-1.5m6 7.5v3.75m-3.75 0h7.5M12 15.75a3 3 0 0 1-3-3V4.5a3 3 0 0 1 6 0v8.25a3 3 0 0 1-3 3Z"/></svg>
<svg x-show="isMuted" x-cloak class="h-5 w-5" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M12 18.75a6 6 0 0 0 6-6v-1.5m-6 7.5a6 6 0 0 1-6-6v-1.5m6 7.5v3.75m-3.75 0h7.5M12 15.75a3 3 0 0 1-3-3V4.5a3 3 0 0 1 6 0v8.25a3 3 0 0 1-3 3Z"/><path stroke-linecap="round" stroke-linejoin="round" d="m3 3 18 18"/></svg>
</button>
<button @click="toggleVideo()" type="button"
class="rounded-full p-3 transition-colors"
:class="isVideoOff ? 'bg-red-600 hover:bg-red-500' : 'bg-slate-700 hover:bg-slate-600'"
:title="isVideoOff ? 'Turn camera on' : 'Turn camera off'">
<svg x-show="!isVideoOff" class="h-5 w-5" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="m15.75 10.5 4.72-4.72a.75.75 0 0 1 1.28.53v11.38a.75.75 0 0 1-1.28.53l-4.72-4.72M4.5 18.75h9a2.25 2.25 0 0 0 2.25-2.25v-9a2.25 2.25 0 0 0-2.25-2.25h-9A2.25 2.25 0 0 0 2.25 7.5v9a2.25 2.25 0 0 0 2.25 2.25Z"/></svg>
<svg x-show="isVideoOff" x-cloak class="h-5 w-5" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="m15.75 10.5 4.72-4.72a.75.75 0 0 1 1.28.53v11.38a.75.75 0 0 1-1.28.53l-4.72-4.72M4.5 18.75h9a2.25 2.25 0 0 0 2.25-2.25v-9a2.25 2.25 0 0 0-2.25-2.25h-9A2.25 2.25 0 0 0 2.25 7.5v9a2.25 2.25 0 0 0 2.25 2.25Z"/><path stroke-linecap="round" stroke-linejoin="round" d="m3 3 18 18"/></svg>
</button>
<button @click="toggleScreenShare()" type="button"
class="rounded-full p-3 transition-colors"
:class="isScreenSharing ? 'bg-indigo-600 hover:bg-indigo-500' : 'bg-slate-700 hover:bg-slate-600'"
title="Share screen">
@include('meet.room.partials.meet-icon', ['icon' => 'screen-share'])
</button>
<button @click="raiseHand()" type="button" class="rounded-full bg-slate-700 p-3 hover:bg-slate-600" title="Raise hand">
@include('meet.room.partials.meet-icon', ['icon' => 'raise-hand'])
</button>
<button @click="sendReaction('thumbs')" type="button" class="rounded-full bg-slate-700 p-3 hover:bg-slate-600" title="Applause">
@include('meet.room.partials.meet-icon', ['icon' => 'applause'])
</button>
<button @click="sendReaction('heart')" type="button" class="rounded-full bg-slate-700 p-3 hover:bg-slate-600" title="React">
@include('meet.room.partials.meet-icon', ['icon' => 'react'])
</button>
<button @click="toggleChat()" type="button"
class="rounded-full p-3 transition-colors"
:class="chatOpen ? 'bg-indigo-600 hover:bg-indigo-500' : 'bg-slate-700 hover:bg-slate-600'"
title="Chat">
@include('meet.room.partials.meet-icon', ['icon' => 'chat'])
</button>
<input type="file" id="meet-file-input" class="hidden" @change="uploadFile">
<button @click="toggleFeatures()" type="button"
class="inline-flex items-center gap-1.5 rounded-full px-3.5 py-3 text-xs font-medium transition-colors"
:class="featuresOpen ? 'bg-indigo-600 hover:bg-indigo-500' : 'bg-slate-700 hover:bg-slate-600'"
title="More options">
<svg class="h-4 w-4" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M6.75 12a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0ZM12.75 12a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0ZM18.75 12a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0Z"/></svg>
More
</button>
<form method="POST" action="{{ route('meet.room.leave', $session) }}" class="inline">
@csrf
<button type="submit" class="rounded-full bg-red-600 px-5 py-3 text-sm font-medium hover:bg-red-500">Leave</button>
</form>
@if ($participant->isHost())
<button @click="openEndMeetingConfirm()" type="button"
class="rounded-full bg-red-950 px-4 py-3 text-sm text-red-400 hover:bg-red-900">End</button>
<form id="meet-end-form" method="POST" action="{{ route('meet.room.end', $session) }}" class="hidden">
@csrf
</form>
@endif
<div class="meet-toolbar__primary sm:contents">
<button @click="toggleMute()" type="button"
class="rounded-full p-3 transition-colors"
:class="isMuted ? 'bg-red-600 hover:bg-red-500' : 'bg-slate-700 hover:bg-slate-600'"
:title="isMuted ? 'Unmute' : 'Mute'">
<svg x-show="!isMuted" class="h-5 w-5" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M12 18.75a6 6 0 0 0 6-6v-1.5m-6 7.5a6 6 0 0 1-6-6v-1.5m6 7.5v3.75m-3.75 0h7.5M12 15.75a3 3 0 0 1-3-3V4.5a3 3 0 0 1 6 0v8.25a3 3 0 0 1-3 3Z"/></svg>
<svg x-show="isMuted" x-cloak class="h-5 w-5" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M12 18.75a6 6 0 0 0 6-6v-1.5m-6 7.5a6 6 0 0 1-6-6v-1.5m6 7.5v3.75m-3.75 0h7.5M12 15.75a3 3 0 0 1-3-3V4.5a3 3 0 0 1 6 0v8.25a3 3 0 0 1-3 3Z"/><path stroke-linecap="round" stroke-linejoin="round" d="m3 3 18 18"/></svg>
</button>
<button @click="toggleVideo()" type="button"
class="rounded-full p-3 transition-colors"
:class="isVideoOff ? 'bg-red-600 hover:bg-red-500' : 'bg-slate-700 hover:bg-slate-600'"
:title="isVideoOff ? 'Turn camera on' : 'Turn camera off'">
<svg x-show="!isVideoOff" class="h-5 w-5" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="m15.75 10.5 4.72-4.72a.75.75 0 0 1 1.28.53v11.38a.75.75 0 0 1-1.28.53l-4.72-4.72M4.5 18.75h9a2.25 2.25 0 0 0 2.25-2.25v-9a2.25 2.25 0 0 0-2.25-2.25h-9A2.25 2.25 0 0 0 2.25 7.5v9a2.25 2.25 0 0 0 2.25 2.25Z"/></svg>
<svg x-show="isVideoOff" x-cloak class="h-5 w-5" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="m15.75 10.5 4.72-4.72a.75.75 0 0 1 1.28.53v11.38a.75.75 0 0 1-1.28.53l-4.72-4.72M4.5 18.75h9a2.25 2.25 0 0 0 2.25-2.25v-9a2.25 2.25 0 0 0-2.25-2.25h-9A2.25 2.25 0 0 0 2.25 7.5v9a2.25 2.25 0 0 0 2.25 2.25Z"/><path stroke-linecap="round" stroke-linejoin="round" d="m3 3 18 18"/></svg>
</button>
<button @click="toggleScreenShare()" type="button"
class="rounded-full p-3 transition-colors"
:class="isScreenSharing ? 'bg-indigo-600 hover:bg-indigo-500' : 'bg-slate-700 hover:bg-slate-600'"
title="Share screen">
@include('meet.room.partials.meet-icon', ['icon' => 'screen-share'])
</button>
<button @click="toggleFeatures()" type="button"
class="inline-flex items-center gap-1.5 rounded-full px-3.5 py-3 text-xs font-medium transition-colors sm:hidden"
:class="featuresOpen ? 'bg-indigo-600 hover:bg-indigo-500' : 'bg-slate-700 hover:bg-slate-600'"
title="More options">
<svg class="h-4 w-4" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M6.75 12a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0ZM12.75 12a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0ZM18.75 12a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0Z"/></svg>
More
</button>
</div>
<button @click="raiseHand()" type="button" class="hidden rounded-full bg-slate-700 p-3 hover:bg-slate-600 sm:inline-flex" title="Raise hand">
@include('meet.room.partials.meet-icon', ['icon' => 'raise-hand'])
</button>
<button @click="sendReaction('thumbs')" type="button" class="hidden rounded-full bg-slate-700 p-3 hover:bg-slate-600 sm:inline-flex" title="Applause">
@include('meet.room.partials.meet-icon', ['icon' => 'applause'])
</button>
<button @click="sendReaction('heart')" type="button" class="hidden rounded-full bg-slate-700 p-3 hover:bg-slate-600 sm:inline-flex" title="React">
@include('meet.room.partials.meet-icon', ['icon' => 'react'])
</button>
<button @click="toggleChat()" type="button"
class="hidden rounded-full p-3 transition-colors sm:inline-flex"
:class="chatOpen ? 'bg-indigo-600 hover:bg-indigo-500' : 'bg-slate-700 hover:bg-slate-600'"
title="Chat">
@include('meet.room.partials.meet-icon', ['icon' => 'chat'])
</button>
<input type="file" id="meet-file-input" class="hidden" @change="uploadFile">
<button @click="toggleFeatures()" type="button"
class="hidden items-center gap-1.5 rounded-full px-3.5 py-3 text-xs font-medium transition-colors sm:inline-flex"
:class="featuresOpen ? 'bg-indigo-600 hover:bg-indigo-500' : 'bg-slate-700 hover:bg-slate-600'"
title="More options">
<svg class="h-4 w-4" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M6.75 12a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0ZM12.75 12a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0ZM18.75 12a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0Z"/></svg>
More
</button>
<div class="meet-toolbar__divider sm:hidden" aria-hidden="true"></div>
<div class="meet-toolbar__actions sm:contents">
<form method="POST" action="{{ route('meet.room.leave', $session) }}" class="inline">
@csrf
<button type="submit" class="rounded-full bg-red-600 px-5 py-3 text-sm font-medium hover:bg-red-500">Leave</button>
</form>
@if ($participant->isHost())
<button @click="openEndMeetingConfirm()" type="button"
class="rounded-full bg-red-950 px-4 py-3 text-sm text-red-400 hover:bg-red-900">End</button>
<form id="meet-end-form" method="POST" action="{{ route('meet.room.end', $session) }}" class="hidden">
@csrf
</form>
@endif
</div>
</div>
</div>
@@ -258,6 +273,18 @@
</div>
<div class="space-y-1 p-2">
<div class="space-y-1 sm:hidden">
<x-meet.room.menu-item icon="raise-hand" title="Raise hand" subtitle="Let the host know you have a question"
@click="raiseHand(); featuresOpen = false" />
<x-meet.room.menu-item icon="applause" title="Applause" subtitle="Send a quick reaction to everyone"
@click="sendReaction('thumbs'); featuresOpen = false" />
<x-meet.room.menu-item icon="react" title="React" subtitle="Send a heart to the room"
@click="sendReaction('heart'); featuresOpen = false" />
<x-meet.room.menu-item icon="chat" title="Chat" subtitle="Open the meeting chat"
@click="toggleChat(); featuresOpen = false" />
<div class="my-1 border-t border-slate-800"></div>
</div>
<button @click="openUploadPicker()" type="button"
class="flex w-full items-center gap-3 rounded-xl px-3 py-2.5 text-left text-sm text-slate-200 transition-colors hover:bg-slate-800">
<span class="flex h-9 w-9 shrink-0 items-center justify-center rounded-lg bg-slate-800/80">