Polish in-meeting UI with custom icons and dismissible chat.
Deploy Ladill Meet / deploy (push) Successful in 2m24s

Use meet-icons assets for raise hand, applause, upload, and screen share; move More after lock, redesign the more menu and chat panel with bubbles and close controls.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
isaacclad
2026-07-01 08:14:13 +00:00
co-authored by Cursor
parent eed5853c2f
commit a546d2f0c0
8 changed files with 183 additions and 54 deletions
+2
View File
@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" id="Layer_1" data-name="Layer 1" viewBox="0 0 24 24" width="512" height="512"><path d="M19,8.99c0-.88-.39-1.71-1.06-2.29-.67-.57-1.56-.82-2.44-.67-1.22,.2-2.18,1.19-2.44,2.42l-2.68-2.68c-.55-.55-1.32-.84-2.09-.77-.78,.06-1.49,.47-1.95,1.11-.05,.07-.09,.14-.13,.21-.52-.41-1.18-.61-1.85-.55-.78,.06-1.49,.47-1.95,1.11-.41,.57-.55,1.28-.44,1.96-.52,.18-.99,.51-1.32,.98-.75,1.04-.6,2.54,.35,3.49l.29,.29c-.31,.19-.59,.44-.81,.74-.75,1.04-.6,2.54,.35,3.49l4.13,4.13c1.38,1.38,3.19,2.07,5.01,2.07s3.63-.69,5.01-2.07l1.98-1.98c1.32-1.32,2.05-3.08,2.05-4.95v-6.01Zm-2,6.01c0,1.32-.53,2.6-1.46,3.54l-1.98,1.98c-1.98,1.98-5.2,1.98-7.18,0l-4.13-4.13c-.26-.26-.32-.65-.14-.9,.16-.22,.38-.27,.49-.28,.19,0,.38,.05,.52,.19l2.1,2.1c.39,.39,1.02,.39,1.41,0s.39-1.02,0-1.41L2.42,11.86c-.26-.26-.32-.65-.14-.9,.16-.22,.38-.27,.49-.28,.19-.02,.38,.05,.52,.19l4.28,4.28c.39,.39,1.02,.39,1.41,0s.39-1.02,0-1.41l-4.8-4.8c-.26-.26-.32-.65-.14-.9,.16-.22,.38-.27,.49-.28,.19-.02,.38,.05,.52,.19l4.86,4.86c.2,.2,.45,.29,.71,.29s.51-.1,.71-.29c.39-.39,.39-1.02,0-1.41l-3.2-3.2s-.01-.01-.02-.02c-.26-.26-.32-.65-.14-.9,.16-.22,.38-.27,.49-.28,.19-.02,.38,.05,.52,.19l4.32,4.32c.29,.29,.71,.37,1.09,.22,.37-.15,.62-.52,.62-.92v-1.7c0-.54,.36-1.02,.82-1.09,.3-.05,.6,.03,.82,.22,.22,.19,.35,.47,.35,.76v6.01Zm7-6.01v6.3c0,1.66-.59,3.26-1.66,4.53l-2.51,2.96c-.45,.45-.88,.79-1.34,1.08-.16,.1-.35,.15-.52,.15-.34,0-.66-.17-.85-.47-.29-.47-.15-1.09,.33-1.38,.33-.2,.64-.45,.92-.73l2.46-2.9c.77-.9,1.19-2.05,1.19-3.23v-6.3c0-.29-.13-.57-.35-.76-.23-.19-.52-.27-.82-.22-.55,.1-1.06-.28-1.15-.83-.09-.55,.28-1.06,.83-1.15,.88-.15,1.77,.1,2.44,.67,.67,.57,1.06,1.4,1.06,2.29ZM10.29,3.71c-.39-.39-.39-1.02,0-1.41l1-1c.39-.39,1.02-.39,1.41,0s.39,1.02,0,1.41l-1,1c-.2,.2-.45,.29-.71,.29s-.51-.1-.71-.29ZM3.29,2.71c-.39-.39-.39-1.02,0-1.41s1.02-.39,1.41,0l1,1c.39,.39,.39,1.02,0,1.41-.2,.2-.45,.29-.71,.29s-.51-.1-.71-.29l-1-1Zm3.71-.71V1c0-.55,.45-1,1-1s1,.45,1,1v1c0,.55-.45,1-1,1s-1-.45-1-1Z"/></svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

+4
View File
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" id="Layer_1" data-name="Layer 1" viewBox="0 0 24 24">
<path d="m22.943,3.714c-.671-.571-1.56-.817-2.439-.674-.212.034-.416.093-.609.172-.347-1.273-1.513-2.213-2.894-2.213-.535,0-1.037.141-1.472.388-.534-.833-1.467-1.388-2.528-1.388-1.382,0-2.548.939-2.895,2.213-.194-.079-.397-.138-.609-.173-.879-.142-1.768.103-2.439.674-.672.571-1.057,1.404-1.057,2.286v8.698l-.956-.893c-1.208-1.125-3.107-1.061-4.234.145-1.129,1.208-1.066,3.11.13,4.231l3.294,3.176c2.436,2.349,5.64,3.642,9.023,3.642h1.743c4.962,0,9-4.038,9-9V6c0-.881-.385-1.714-1.057-2.286Zm-.943,11.286c0,3.86-3.14,7-7,7h-1.743c-2.862,0-5.574-1.094-7.635-3.081l-3.304-3.186c-.403-.378-.424-1.013-.047-1.417.376-.401,1.008-.422,1.409-.048l2.638,2.463c.292.272.717.344,1.081.186.365-.159.602-.519.602-.917V5c0-.294.128-.572.353-.762.228-.193.519-.272.823-.224.462.076.825.556.825,1.093v4.893c0,.552.448,1,1,1s1-.448,1-1V3c0-.551.449-1,1-1s1,.449,1,1v7c0,.552.448,1,1,1s1-.448,1-1v-6c0-.551.449-1,1-1s1,.449,1,1v6c0,.552.448,1,1,1s1-.448,1-1v-3.893c0-.538.362-1.018.825-1.093.303-.047.595.03.823.224.224.19.353.468.353.762v9Z"/>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" id="Layer_1" data-name="Layer 1" viewBox="0 0 24 24">
<path d="M22,15.184v-7.184c0-2.757-2.243-5-5-5H7c-2.757,0-5,2.243-5,5v7.184c-1.161,.414-2,1.514-2,2.816,0,1.654,1.346,3,3,3H21c1.654,0,3-1.346,3-3,0-1.302-.839-2.402-2-2.816ZM7,5h10c1.654,0,3,1.346,3,3v7h-4.5c-.265,0-.52,.105-.707,.293l-.707,.707h-4.172l-.707-.707c-.188-.188-.442-.293-.707-.293H4v-7c0-1.654,1.346-3,3-3Zm14,14H3c-.551,0-1-.449-1-1s.449-1,1-1h5.086l.707,.707c.188,.188,.442,.293,.707,.293h5c.265,0,.52-.105,.707-.293l.707-.707h5.086c.551,0,1,.449,1,1s-.449,1-1,1ZM8.337,10.751c-.391-.391-.391-1.023,0-1.414l2.256-2.256c.775-.775,2.038-.775,2.812,0l2.257,2.257c.391,.391,.391,1.023,0,1.414-.195,.195-.451,.293-.707,.293s-.512-.098-.707-.293l-1.249-1.249v3.497c0,.552-.448,1-1,1s-1-.448-1-1v-3.506l-1.249,1.257c-.391,.391-1.023,.391-1.414,0Z"/>
</svg>

After

Width:  |  Height:  |  Size: 902 B

+4
View File
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" id="Layer_1" data-name="Layer 1" viewBox="0 0 24 24">
<path d="M10,22.5c0,.829-.671,1.5-1.5,1.5h-3c-3.033,0-5.5-2.467-5.5-5.5V5.5C0,2.467,2.467,0,5.5,0h6.343c1.469,0,2.85,.572,3.889,1.611l2.657,2.657c.815,.815,1.347,1.848,1.536,2.985,.136,.817-.425,1.739-1.425,1.739s-5.5,.008-5.5,.008c-1.105,0-2-.895-2-2V3H5.5c-1.378,0-2.5,1.122-2.5,2.5v13c0,1.378,1.122,2.5,2.5,2.5h3c.829,0,1.5,.671,1.5,1.5Zm14-5c0,3.59-2.91,6.5-6.5,6.5s-6.5-2.91-6.5-6.5,2.91-6.5,6.5-6.5,6.5,2.91,6.5,6.5Zm-2.752-1.154l-3.063-3.063c-.378-.378-.991-.378-1.369,0l-3.063,3.063c-.61,.61-.178,1.653,.685,1.653h1.563v2.501c0,.828,.671,1.5,1.5,1.5s1.5-.672,1.5-1.5v-2.501h1.563c.863,0,1.295-1.043,.685-1.653Z"/>
</svg>

After

Width:  |  Height:  |  Size: 764 B

+13
View File
@@ -15,6 +15,19 @@
display: none !important;
}
.meet-toolbar-icon {
filter: brightness(0) invert(1);
opacity: 0.92;
}
.meet-chat-bubble {
max-width: 85%;
}
.meet-chat-bubble--own {
margin-left: auto;
}
/* QR create/show: flush mobile action bar to the physical screen bottom (mobile only) */
@media (max-width: 1023px) {
.mobile-action-bar {
+31 -3
View File
@@ -550,6 +550,22 @@ function meetRoom() {
});
},
toggleChat() {
this.chatOpen = !this.chatOpen;
if (this.chatOpen) {
this.featuresOpen = false;
this.shareOpen = false;
}
},
toggleFeatures() {
this.featuresOpen = !this.featuresOpen;
if (this.featuresOpen) {
this.chatOpen = false;
this.shareOpen = false;
}
},
async openShare() {
if (navigator.share && this.joinUrl) {
try {
@@ -632,11 +648,23 @@ function meetRoom() {
appendChatMessage(message) {
const container = document.getElementById('chat-messages');
if (!container) return;
const isOwn = message.sender_name === this.displayName;
const div = document.createElement('div');
div.className = 'text-sm';
div.className = `meet-chat-bubble${isOwn ? ' meet-chat-bubble--own' : ''}`;
div.dataset.uuid = message.uuid;
div.innerHTML = `<span class="font-medium text-sky-400">${this.escape(message.sender_name)}</span>
<p class="mt-0.5 text-slate-200">${this.escape(message.body)}</p>`;
const time = message.created_at
? new Date(message.created_at).toLocaleTimeString([], { hour: 'numeric', minute: '2-digit' })
: '';
div.innerHTML = `
<div class="rounded-2xl px-3 py-2 ${isOwn ? 'bg-indigo-600 text-white' : 'bg-slate-800 text-slate-100'}">
${isOwn ? '' : `<p class="mb-0.5 text-xs font-medium text-sky-300">${this.escape(message.sender_name)}</p>`}
<p class="text-sm leading-relaxed">${this.escape(message.body)}</p>
</div>
<p class="mt-1 text-[10px] text-slate-500 ${isOwn ? 'text-right' : ''}">${this.escape(time)}</p>`;
container.appendChild(div);
container.scrollTop = container.scrollHeight;
},
@@ -0,0 +1,3 @@
@props(['icon', 'class' => 'h-5 w-5'])
<img src="{{ asset('images/meet-icons/'.$icon.'.svg') }}" alt="" {{ $attributes->merge(['class' => 'meet-toolbar-icon '.$class]) }}>
+122 -51
View File
@@ -54,12 +54,12 @@
@endif
<div class="relative flex h-full flex-col">
<header class="flex shrink-0 items-center justify-between border-b border-slate-800 px-4 py-3">
<div>
<h1 class="text-sm font-semibold">{{ $room->title }}</h1>
<header class="flex shrink-0 items-center justify-between border-b border-slate-800/80 bg-slate-950/90 px-4 py-3 backdrop-blur">
<div class="min-w-0">
<h1 class="truncate text-sm font-semibold">{{ $room->title }}</h1>
<p class="text-xs text-slate-400" x-text="connectionStatus"></p>
</div>
<div class="flex items-center gap-2 text-xs text-slate-400">
<div class="flex shrink-0 items-center gap-2 text-xs text-slate-400">
<button @click="openShare()" type="button"
class="inline-flex items-center gap-1.5 rounded-lg border border-slate-700 bg-slate-900 px-2.5 py-1.5 text-xs font-medium text-slate-200 transition-colors hover:bg-slate-800"
title="Share meeting link">
@@ -68,7 +68,7 @@
</button>
<span x-show="isRecording" class="rounded bg-red-600 px-2 py-0.5 font-medium text-white">REC</span>
<span x-show="isLocked" class="rounded bg-amber-600 px-2 py-0.5 font-medium text-white">Locked</span>
<span x-text="participants.length + ' participants'"></span>
<span x-text="participants.length + ' in call'"></span>
</div>
</header>
@@ -95,8 +95,8 @@
</p>
</div>
<div class="flex min-h-0 flex-1">
<main class="relative min-w-0 flex-1 p-4">
<div class="relative min-h-0 flex-1">
<main class="relative h-full p-4">
<div id="video-grid" class="grid h-full gap-2 sm:grid-cols-2 lg:grid-cols-3"></div>
<div id="screen-share" class="absolute inset-4 hidden rounded-xl bg-black"></div>
@@ -108,37 +108,62 @@
<div class="pointer-events-none absolute inset-x-0 bottom-4 flex justify-center gap-2">
<template x-for="reaction in floatingReactions" :key="reaction.id">
<span class="flex h-10 w-10 animate-bounce items-center justify-center rounded-full bg-slate-800/90 text-sky-300 ring-1 ring-white/20">
<svg x-show="reaction.kind === 'thumbs'" 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="M6.633 10.25c.806 0 1.533-.278 2.118-.764.585-.486.96-1.15 1.05-1.875.09-.725-.03-1.46-.34-2.115-.31-.655-.8-1.2-1.41-1.56-.61-.36-1.31-.52-2.02-.46-.71.06-1.38.36-1.92.86-.54.5-.92 1.18-1.08 1.92h-.01A4.5 4.5 0 0 0 2.25 12c0 1.59.83 2.99 2.08 3.79.63.4 1.35.61 2.08.61h8.34c.98 0 1.93-.32 2.71-.91.78-.59 1.32-1.42 1.52-2.34l1.14-5.7c.1-.5-.02-1.02-.33-1.42-.31-.4-.78-.63-1.28-.63H9.75"/></svg>
<svg x-show="reaction.kind === 'heart'" class="h-5 w-5" fill="currentColor" viewBox="0 0 24 24"><path d="M11.645 20.91l-.007-.003-.022-.012a15.247 15.247 0 0 1-.383-.218 25.18 25.18 0 0 1-4.244-3.17C4.688 15.36 2.25 12.174 2.25 8.25 2.25 5.322 4.714 3 7.688 3A5.5 5.5 0 0 1 12 5.052 5.5 5.5 0 0 1 16.313 3c2.973 0 5.437 2.322 5.437 5.25 0 3.925-2.438 7.111-4.739 9.256a25.175 25.175 0 0 1-4.244 3.17 15.247 15.247 0 0 1-.383.219l-.022.012-.007.004-.003.001a.752.752 0 0 1-.704 0l-.003-.001Z"/></svg>
<span class="flex h-10 w-10 animate-bounce items-center justify-center rounded-full bg-slate-800/90 ring-1 ring-white/20">
<img x-show="reaction.kind === 'thumbs'" src="{{ asset('images/meet-icons/applause.svg') }}" alt="" class="meet-toolbar-icon h-5 w-5">
<svg x-show="reaction.kind === 'heart'" class="h-5 w-5 text-rose-400" fill="currentColor" viewBox="0 0 24 24"><path d="M11.645 20.91l-.007-.003-.022-.012a15.247 15.247 0 0 1-.383-.218 25.18 25.18 0 0 1-4.244-3.17C4.688 15.36 2.25 12.174 2.25 8.25 2.25 5.322 4.714 3 7.688 3A5.5 5.5 0 0 1 12 5.052 5.5 5.5 0 0 1 16.313 3c2.973 0 5.437 2.322 5.437 5.25 0 3.925-2.438 7.111-4.739 9.256a25.175 25.175 0 0 1-4.244 3.17 15.247 15.247 0 0 1-.383.219l-.022.012-.007.004-.003.001a.752.752 0 0 1-.704 0l-.003-.001Z"/></svg>
</span>
</template>
</div>
</main>
<aside class="hidden w-80 shrink-0 flex-col border-l border-slate-800 lg:flex" :class="{ '!flex': chatOpen }">
<div class="border-b border-slate-800 px-4 py-3 text-sm font-medium">Chat</div>
<div class="flex-1 space-y-3 overflow-y-auto p-4" id="chat-messages">
<aside x-show="chatOpen" x-cloak
x-transition:enter="transition ease-out duration-200"
x-transition:enter-start="translate-x-full opacity-0"
x-transition:enter-end="translate-x-0 opacity-100"
x-transition:leave="transition ease-in duration-150"
x-transition:leave-start="translate-x-0 opacity-100"
x-transition:leave-end="translate-x-full opacity-0"
@click.outside="chatOpen = false"
class="absolute inset-y-0 right-0 z-30 flex w-full max-w-sm flex-col border-l border-slate-700/80 bg-slate-950/95 shadow-2xl backdrop-blur-md">
<div class="flex items-center justify-between border-b border-slate-800 px-4 py-3">
<div>
<h2 class="text-sm font-semibold text-white">Meeting chat</h2>
<p class="text-xs text-slate-400">Messages are visible to everyone in the call</p>
</div>
<button @click="chatOpen = false" type="button"
class="rounded-lg p-2 text-slate-400 transition-colors hover:bg-slate-800 hover:text-white"
title="Close chat">
<svg 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="M6 18 18 6M6 6l12 12"/></svg>
</button>
</div>
<div class="flex-1 space-y-3 overflow-y-auto px-4 py-4" id="chat-messages">
@foreach ($messages as $message)
<div class="text-sm">
<span class="font-medium text-sky-400">{{ $message->sender_name }}</span>
<span class="text-slate-400">{{ $message->created_at->format('g:i A') }}</span>
<p class="mt-0.5 text-slate-200">{{ $message->body }}</p>
@php $isOwn = $message->sender_name === $participant->display_name; @endphp
<div class="meet-chat-bubble {{ $isOwn ? 'meet-chat-bubble--own' : '' }}">
<div class="rounded-2xl px-3 py-2 {{ $isOwn ? 'bg-indigo-600 text-white' : 'bg-slate-800 text-slate-100' }}">
@unless ($isOwn)
<p class="mb-0.5 text-xs font-medium text-sky-300">{{ $message->sender_name }}</p>
@endunless
<p class="text-sm leading-relaxed">{{ $message->body }}</p>
</div>
<p class="mt-1 text-[10px] text-slate-500 {{ $isOwn ? 'text-right' : '' }}">{{ $message->created_at->format('g:i A') }}</p>
</div>
@endforeach
</div>
<form @submit.prevent="sendChat" class="border-t border-slate-800 p-3">
<div class="flex gap-2">
<input type="text" x-model="chatInput" placeholder="Message everyone…"
class="flex-1 rounded-lg border-slate-700 bg-slate-900 px-3 py-2 text-sm text-white">
<button type="submit" class="rounded-lg bg-indigo-600 px-3 py-2 text-sm font-medium hover:bg-indigo-500">Send</button>
<form @submit.prevent="sendChat" class="border-t border-slate-800 bg-slate-950/80 p-3">
<div class="flex items-end gap-2">
<input type="text" x-model="chatInput" placeholder="Write a message…"
class="flex-1 rounded-xl border-slate-700 bg-slate-900 px-3 py-2.5 text-sm text-white placeholder:text-slate-500 focus:border-indigo-500 focus:ring-indigo-500">
<button type="submit"
class="rounded-xl bg-indigo-600 px-4 py-2.5 text-sm font-medium text-white transition-colors hover:bg-indigo-500 disabled:opacity-50"
:disabled="!chatInput.trim()">Send</button>
</div>
</form>
</aside>
</div>
<footer class="shrink-0 border-t border-slate-800 px-4 py-4">
<div class="mx-auto flex max-w-4xl flex-wrap items-center justify-center gap-2 sm:gap-3">
<footer class="relative shrink-0 border-t border-slate-800/80 bg-slate-950/95 px-4 py-4 backdrop-blur">
<div class="mx-auto flex max-w-5xl flex-wrap items-center justify-center gap-2 sm:gap-3">
<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'"
@@ -157,7 +182,7 @@
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">
<svg 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="M9 17.25v1.007a3 3 0 0 1-.879 2.122L7.5 21h9l-.621-.621A3 3 0 0 1 15 18.257V17.25m6-12V15a2.25 2.25 0 0 1-2.25 2.25H5.25A2.25 2.25 0 0 1 3 15V5.25m18 0A2.25 2.25 0 0 0 18.75 3H5.25A2.25 2.25 0 0 0 3 5.25m18 0V12a2.25 2.25 0 0 1-2.25 2.25H5.25A2.25 2.25 0 0 1 3 12V5.25"/></svg>
@include('meet.room.partials.meet-icon', ['icon' => 'screen-share'])
</button>
<button @click="openShare()" type="button"
class="rounded-full bg-slate-700 p-3 hover:bg-slate-600"
@@ -165,24 +190,23 @@
<svg 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="M7.217 10.907a2.25 2.25 0 1 0 0 2.186m0-2.186c.18.324.283.696.283 1.093s-.103.77-.283 1.093m0-2.186 9.566-5.314m-9.566 7.5 9.566 5.314m0 0a2.25 2.25 0 1 0 3.935 2.186 2.25 2.25 0 0 0-3.935-2.186Zm0-12.814a2.25 2.25 0 1 0 3.935-2.186 2.25 2.25 0 0 0-3.935 2.186Z"/></svg>
</button>
<button @click="raiseHand()" type="button" class="rounded-full bg-slate-700 p-3 hover:bg-slate-600" title="Raise hand">
<svg 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="M10.05 4.575a1.575 1.575 0 1 0-3.15 0v3m3.15-3v-1.5a1.575 1.575 0 0 1 3.15 0v1.5m-3.15 3v6.75a1.575 1.575 0 0 0 3.15 0V10.5m-6.3 0H4.875A1.125 1.125 0 0 0 3.75 11.625v4.125c0 .621.504 1.125 1.125 1.125h2.25m8.25-9.75V6.75a1.575 1.575 0 0 1 3.15 0v2.25m-3.15 3v6.75a1.575 1.575 0 0 0 3.15 0V10.5"/></svg>
@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">
<svg 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="M6.633 10.25c.806 0 1.533-.278 2.118-.764.585-.486.96-1.15 1.05-1.875.09-.725-.03-1.46-.34-2.115-.31-.655-.8-1.2-1.41-1.56-.61-.36-1.31-.52-2.02-.46-.71.06-1.38.36-1.92.86-.54.5-.92 1.18-1.08 1.92h-.01A4.5 4.5 0 0 0 2.25 12c0 1.59.83 2.99 2.08 3.79.63.4 1.35.61 2.08.61h8.34c.98 0 1.93-.32 2.71-.91.78-.59 1.32-1.42 1.52-2.34l1.14-5.7c.1-.5-.02-1.02-.33-1.42-.31-.4-.78-.63-1.28-.63H9.75"/></svg>
@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">
<svg 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="M21 8.25c0-2.485-2.099-4.5-4.688-4.5-1.935 0-3.597 1.126-4.312 2.733-.715-1.607-2.377-2.733-4.313-2.733C5.1 3.75 3 5.765 3 8.25c0 7.22 9 12 9 12s9-4.78 9-12Z"/></svg>
</button>
<button @click="chatOpen = !chatOpen" type="button" class="rounded-full bg-slate-700 p-3 hover:bg-slate-600 lg:hidden" title="Chat">
<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">
<svg 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="M8.625 9.75a.375.375 0 1 1-.75 0 .375.375 0 0 1 .75 0Zm3.75 0a.375.375 0 1 1-.75 0 .375.375 0 0 1 .75 0Zm3.75 0a.375.375 0 1 1-.75 0 .375.375 0 0 1 .75 0Zm-8.25 3.75a.375.375 0 1 1-.75 0 .375.375 0 0 1 .75 0Zm3.75 0a.375.375 0 1 1-.75 0 .375.375 0 0 1 .75 0Zm3.75 0a.375.375 0 1 1-.75 0 .375.375 0 0 1 .75 0Z"/><path stroke-linecap="round" stroke-linejoin="round" d="M2.25 12.76c0 1.6 1.123 2.994 2.707 3.227 1.087.16 2.185.283 3.293.369V21l4.184-4.183a1.14 1.14 0 0 1 .778-.332 48.294 48.294 0 0 0 5.83-.498c1.585-.233 2.708-1.626 2.708-3.228V6.741c0-1.602-1.123-2.995-2.707-3.228A48.394 48.394 0 0 0 12 3c-2.392 0-4.744.175-7.043.513C3.373 3.746 2.25 5.14 2.25 6.741v6.018Z"/></svg>
</button>
<button @click="featuresOpen = !featuresOpen" type="button"
class="rounded-full bg-slate-700 px-3 py-3 text-xs font-medium hover:bg-slate-600"
:class="featuresOpen ? 'ring-2 ring-indigo-400' : ''"
title="More options">More</button>
<input type="file" id="meet-file-input" class="hidden" @change="uploadFile">
<button @click="document.getElementById('meet-file-input').click()" type="button" class="rounded-full bg-slate-700 p-3 hover:bg-slate-600" title="Upload file">
<svg 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="m18.375 12.739-7.693 7.693a4.5 4.5 0 0 1-6.364-6.364l10.94-10.94A3 3 0 1 1 19.5 7.372L8.552 18.32m.009-.01-.01.01m5.114-8.962a1.875 1.875 0 1 1-2.652 2.652L8.552 18.32"/></svg>
@include('meet.room.partials.meet-icon', ['icon' => 'upload-file'])
</button>
@if ($participant->isHost())
<button @click="toggleRecording()" type="button"
@@ -199,6 +223,13 @@
<svg x-show="isLocked" 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="M16.5 10.5V6.75a4.5 4.5 0 1 0-9 0v3.75M3.75 21h16.5A2.25 2.25 0 0 0 22.5 18.75v-6.75A2.25 2.25 0 0 0 20.25 9.75H3.75A2.25 2.25 0 0 0 1.5 12.75v6.75A2.25 2.25 0 0 0 3.75 21Z"/></svg>
</button>
@endif
<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>
@@ -210,33 +241,73 @@
</form>
@endif
</div>
</footer>
<div x-show="featuresOpen" x-cloak class="absolute inset-x-4 bottom-24 z-40 rounded-xl border border-slate-700 bg-slate-900/95 p-4 shadow-xl">
<div class="flex gap-4">
<div x-show="featuresOpen" x-cloak @click.outside="featuresOpen = false"
x-transition:enter="transition ease-out duration-150"
x-transition:enter-start="translate-y-2 opacity-0"
x-transition:enter-end="translate-y-0 opacity-100"
x-transition:leave="transition ease-in duration-100"
x-transition:leave-start="translate-y-0 opacity-100"
x-transition:leave-end="translate-y-2 opacity-0"
class="absolute bottom-full left-1/2 z-40 mb-3 w-[min(24rem,calc(100vw-2rem))] -translate-x-1/2 overflow-hidden rounded-2xl border border-slate-700/80 bg-slate-900/98 shadow-2xl backdrop-blur-md">
<div class="flex items-center justify-between border-b border-slate-800 px-4 py-3">
<div>
<p class="text-sm font-semibold text-white">More options</p>
<p class="text-xs text-slate-400">Meeting tools and extras</p>
</div>
<button @click="featuresOpen = false" type="button" class="rounded-lg p-1.5 text-slate-400 hover:bg-slate-800 hover:text-white" title="Close">
<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 18 18 6M6 6l12 12"/></svg>
</button>
</div>
<div class="space-y-1 p-2">
@if ($participant->isHost())
<button @click="createBreakouts(); featuresOpen = false" 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 items-center justify-center rounded-lg bg-indigo-500/15 text-indigo-300">
<svg 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="M3.75 6A2.25 2.25 0 0 1 6 3.75h2.25A2.25 2.25 0 0 1 10.5 6v2.25a2.25 2.25 0 0 1-2.25 2.25H6a2.25 2.25 0 0 1-2.25-2.25V6ZM3.75 15.75A2.25 2.25 0 0 1 6 13.5h2.25a2.25 2.25 0 0 1 2.25 2.25V18a2.25 2.25 0 0 1-2.25 2.25H6A2.25 2.25 0 0 1 3.75 18v-2.25ZM13.5 6a2.25 2.25 0 0 1 2.25-2.25H18A2.25 2.25 0 0 1 20.25 6v2.25A2.25 2.25 0 0 1 18 10.5h-2.25a2.25 2.25 0 0 1-2.25-2.25V6ZM13.5 15.75a2.25 2.25 0 0 1 2.25-2.25H18a2.25 2.25 0 0 1 2.25 2.25V18A2.25 2.25 0 0 1 18 20.25h-2.25A2.25 2.25 0 0 1 13.5 18v-2.25Z"/></svg>
</span>
<span>
<span class="block font-medium">Start breakouts</span>
<span class="block text-xs text-slate-400">Split participants into smaller rooms</span>
</span>
</button>
<button @click="closeBreakouts(); featuresOpen = false" 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 items-center justify-center rounded-lg bg-slate-700 text-slate-300">
<svg 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="M9 9V4.5M9 9H4.5M9 9 3.75M9 15v4.5M9 15H4.5M9 15l-5.25 5.25M15 9h4.5M15 9V4.5M15 9l5.25-5.25M15 15h4.5M15 15v4.5m0-4.5 5.25 5.25"/></svg>
</span>
<span>
<span class="block font-medium">Close breakouts</span>
<span class="block text-xs text-slate-400">Bring everyone back to the main room</span>
</span>
</button>
@endif
</div>
@if ($isWebinar ?? false)
<div class="flex-1">
<p class="text-xs font-medium text-slate-400">Q&A</p>
<ul class="mt-2 max-h-32 space-y-1 overflow-y-auto text-sm">
<div class="border-t border-slate-800 px-4 py-3">
<p class="text-xs font-semibold uppercase tracking-wide text-slate-500">Q&amp;A</p>
<ul class="mt-2 max-h-36 space-y-2 overflow-y-auto">
<template x-for="item in qaItems" :key="item.uuid">
<li><span class="text-sky-400" x-text="item.asker_name"></span>: <span x-text="item.question"></span></li>
<li class="rounded-lg bg-slate-800/80 px-3 py-2 text-sm">
<span class="font-medium text-sky-300" x-text="item.asker_name"></span>
<span class="text-slate-300" x-text="': ' + item.question"></span>
</li>
</template>
<li x-show="qaItems.length === 0" class="text-xs text-slate-500">No questions yet.</li>
</ul>
<form @submit.prevent="submitQuestion" class="mt-2 flex gap-2">
<input type="text" x-model="qaInput" placeholder="Ask a question…" class="flex-1 rounded border-slate-700 bg-slate-800 px-2 py-1 text-sm">
<button type="submit" class="rounded bg-indigo-600 px-2 py-1 text-xs">Send</button>
<form @submit.prevent="submitQuestion" class="mt-3 flex gap-2">
<input type="text" x-model="qaInput" placeholder="Ask a question…"
class="flex-1 rounded-lg border-slate-700 bg-slate-950 px-3 py-2 text-sm text-white placeholder:text-slate-500">
<button type="submit" class="rounded-lg bg-indigo-600 px-3 py-2 text-xs font-medium hover:bg-indigo-500">Send</button>
</form>
</div>
@endif
@if ($participant->isHost())
<div class="space-y-2 text-sm">
<button @click="createBreakouts()" type="button" class="block w-full rounded bg-slate-700 px-3 py-2 hover:bg-slate-600">Start breakouts</button>
<button @click="closeBreakouts()" type="button" class="block w-full rounded bg-slate-700 px-3 py-2 hover:bg-slate-600">Close breakouts</button>
</div>
@endif
</div>
<p x-show="breakoutBroadcast" class="mt-3 rounded bg-amber-900/50 px-3 py-2 text-sm text-amber-100" x-text="breakoutBroadcast"></p>
<p x-show="breakoutBroadcast" class="border-t border-slate-800 bg-amber-950/40 px-4 py-3 text-sm text-amber-100" x-text="breakoutBroadcast"></p>
</div>
</footer>
</div>
</body>
</html>