Keep app pages light, move join actions to meeting details, fix join URL.
Deploy Ladill Meet / deploy (push) Successful in 1m31s

Force light color-scheme on app shells while scoping dark UI to the live room; remove join/restart from list cards and consolidate start/join/rejoin on the details action row; route Join meeting through /r/ so participants are registered before entering /room/.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
isaacclad
2026-07-01 18:44:32 +00:00
co-authored by Cursor
parent 5c1affcca5
commit 1705e6b435
16 changed files with 64 additions and 73 deletions
+38 -25
View File
@@ -15,37 +15,50 @@
display: none !important;
}
.meet-toolbar-icon {
/* App shell: always light (ignore OS dark mode). Live meeting keeps dark UI. */
html.app-shell {
color-scheme: light;
}
html.app-shell :is(input, select, textarea) {
color-scheme: light;
}
html.meet-room-page {
color-scheme: dark;
}
.meet-room-page .meet-toolbar-icon {
filter: brightness(0) invert(1);
opacity: 0.92;
}
.meet-chat-bubble {
.meet-room-page .meet-chat-bubble {
max-width: 85%;
}
.meet-chat-bubble--own {
.meet-room-page .meet-chat-bubble--own {
margin-left: auto;
}
.meet-tile-speaking {
.meet-room-page .meet-tile-speaking {
box-shadow: 0 0 0 2px rgb(52 211 153 / 0.9);
}
.meet-speaking-bar {
.meet-room-page .meet-speaking-bar {
transform-origin: center bottom;
animation: meet-speaking-pulse 0.9s ease-in-out infinite;
}
.meet-speaking-bar--1 {
.meet-room-page .meet-speaking-bar--1 {
animation-delay: 0s;
}
.meet-speaking-bar--2 {
.meet-room-page .meet-speaking-bar--2 {
animation-delay: 0.15s;
}
.meet-speaking-bar--3 {
.meet-room-page .meet-speaking-bar--3 {
animation-delay: 0.3s;
}
@@ -64,7 +77,7 @@
/* Meeting room footer */
@media (max-width: 639px) {
.meet-toolbar__track {
.meet-room-page .meet-toolbar__track {
display: flex;
align-items: center;
justify-content: space-between;
@@ -73,7 +86,7 @@
padding-bottom: max(0.25rem, env(safe-area-inset-bottom, 0px));
}
.meet-toolbar__primary {
.meet-room-page .meet-toolbar__primary {
display: flex;
min-width: 0;
flex: 1;
@@ -81,14 +94,14 @@
gap: 0.5rem;
}
.meet-toolbar__divider {
.meet-room-page .meet-toolbar__divider {
width: 1px;
height: 2rem;
flex-shrink: 0;
background-color: rgb(51 65 85);
}
.meet-toolbar__actions {
.meet-room-page .meet-toolbar__actions {
display: flex;
flex-shrink: 0;
align-items: center;
@@ -97,7 +110,7 @@
}
@media (min-width: 640px) {
.meet-toolbar__track {
.meet-room-page .meet-toolbar__track {
display: flex;
flex-wrap: wrap;
align-items: center;
@@ -107,7 +120,7 @@
}
/* Meeting room chat / participants: bottom sheet on mobile, sidebar on desktop */
.meet-room-panel {
.meet-room-page .meet-room-panel {
position: fixed;
inset: 0;
z-index: 50;
@@ -116,14 +129,14 @@
justify-content: flex-end;
}
.meet-room-panel__backdrop {
.meet-room-page .meet-room-panel__backdrop {
position: absolute;
inset: 0;
background-color: rgb(2 6 23 / 0.72);
backdrop-filter: blur(4px);
}
.meet-room-panel__sheet {
.meet-room-page .meet-room-panel__sheet {
position: relative;
z-index: 1;
display: flex;
@@ -135,13 +148,13 @@
padding: 0 0.75rem max(0.75rem, env(safe-area-inset-bottom, 0px));
}
.meet-room-panel__handle {
.meet-room-page .meet-room-panel__handle {
display: flex;
justify-content: center;
padding: 0.75rem 0 0.25rem;
}
.meet-room-panel__handle span {
.meet-room-page .meet-room-panel__handle span {
display: block;
height: 0.25rem;
width: 2.5rem;
@@ -149,7 +162,7 @@
background-color: rgb(51 65 85);
}
.meet-room-panel__header {
.meet-room-page .meet-room-panel__header {
display: flex;
flex-shrink: 0;
align-items: flex-start;
@@ -158,7 +171,7 @@
padding: 0 0.25rem 0.75rem;
}
.meet-room-panel__body {
.meet-room-page .meet-room-panel__body {
display: flex;
min-height: 0;
flex: 1;
@@ -170,7 +183,7 @@
}
@media (min-width: 640px) {
.meet-room-panel {
.meet-room-page .meet-room-panel {
position: relative;
inset: auto;
z-index: auto;
@@ -181,12 +194,12 @@
justify-content: flex-start;
}
.meet-room-panel__backdrop,
.meet-room-panel__handle {
.meet-room-page .meet-room-panel__backdrop,
.meet-room-page .meet-room-panel__handle {
display: none;
}
.meet-room-panel__sheet {
.meet-room-page .meet-room-panel__sheet {
display: flex;
height: 100%;
max-height: none;
@@ -196,7 +209,7 @@
padding: 0.75rem;
}
.meet-room-panel__body {
.meet-room-page .meet-room-panel__body {
border-radius: 1rem;
}
}
+1 -1
View File
@@ -4,7 +4,7 @@
$logoPath = public_path($logo);
@endphp
<!DOCTYPE html>
<html lang="en" class="h-full">
<html lang="en" class="h-full app-shell">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
+1 -1
View File
@@ -5,7 +5,7 @@
$logoPath = public_path($logo);
@endphp
<!DOCTYPE html>
<html lang="en">
<html lang="en" class="app-shell">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
@@ -1,5 +1,5 @@
<!DOCTYPE html>
<html lang="en">
<html lang="en" class="app-shell">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
@@ -1,6 +1,6 @@
@props(['title' => 'Ladill Meet', 'heading' => null])
<!DOCTYPE html>
<html lang="en" class="h-full">
<html lang="en" class="h-full app-shell">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
@@ -5,7 +5,7 @@
])
<!DOCTYPE html>
<html lang="en">
<html lang="en" class="app-shell">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
+1 -1
View File
@@ -101,7 +101,7 @@
<h2 class="text-lg font-semibold text-slate-900">Live meetings</h2>
<div class="mt-3 space-y-2">
@foreach ($active as $room)
@include('meet.partials.room-card', ['room' => $room, 'live' => true])
@include('meet.partials.room-card', ['room' => $room])
@endforeach
</div>
</section>
@@ -1,5 +1,5 @@
<!DOCTYPE html>
<html lang="en" class="h-full">
<html lang="en" class="h-full app-shell">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
@@ -1,5 +1,5 @@
<!DOCTYPE html>
<html lang="en" class="h-full">
<html lang="en" class="h-full app-shell">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
@@ -6,7 +6,6 @@
'cancelled' => 'bg-red-50 text-red-700',
];
$detailsRoute = $detailsRoute ?? route('meet.rooms.show', $room);
$startRoute = $startRoute ?? route('meet.rooms.start', $room);
@endphp
<div class="flex items-center justify-between rounded-2xl border border-slate-200 bg-white p-4">
<div class="min-w-0 flex-1">
@@ -27,17 +26,7 @@
@endif
</p>
</div>
<div class="ml-4 flex shrink-0 gap-2">
@if (($live ?? false) || $room->status === 'live')
@if ($room->activeSession())
<a href="{{ route('meet.room', $room->activeSession()) }}" class="btn-primary text-sm">Join</a>
@endif
@elseif ($room->canRestart())
<form method="POST" action="{{ $startRoute }}">
@csrf
<button type="submit" class="btn-primary text-sm">{{ $room->restartLabel() }}</button>
</form>
@endif
<div class="ml-4 shrink-0">
<a href="{{ $detailsRoute }}" class="rounded-lg border border-slate-300 px-3 py-2 text-sm text-slate-700 hover:bg-slate-50">Details</a>
</div>
</div>
+1 -1
View File
@@ -1,5 +1,5 @@
<!DOCTYPE html>
<html lang="en" class="h-full">
<html lang="en" class="h-full meet-room-page">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
+1 -1
View File
@@ -6,7 +6,7 @@
<div class="mt-4 space-y-2">
@forelse ($rooms as $room)
@include('meet.partials.room-card', ['room' => $room, 'live' => $room->status === 'live'])
@include('meet.partials.room-card', ['room' => $room])
@empty
<p class="rounded-2xl border border-dashed border-slate-200 bg-white p-8 text-center text-sm text-slate-500">No meetings yet.</p>
@endforelse
+15 -17
View File
@@ -5,17 +5,6 @@
<h1 class="text-2xl font-semibold text-slate-900">{{ $room->title }}</h1>
<p class="mt-1 text-sm text-slate-500">{{ config('meet.room_statuses')[$room->status] ?? $room->status }}</p>
</div>
@if ($room->canRestart())
<form method="POST" action="{{ route('meet.rooms.start', $room) }}">
@csrf
<button type="submit" class="btn-primary">{{ $room->restartLabel() }}</button>
</form>
@elseif ($room->status === 'scheduled')
<form method="POST" action="{{ route('meet.rooms.start', $room) }}">
@csrf
<button type="submit" class="btn-primary">Start meeting</button>
</form>
@endif
</div>
@if ($errors->any())
@@ -32,18 +21,27 @@
</div>
<div class="btn-group mt-4">
@if ($room->status === 'live' && $room->activeSession())
<a href="{{ route('meet.join', $room) }}" class="btn-primary btn-primary-sm">Join meeting</a>
@elseif ($room->status === 'scheduled')
<form method="POST" action="{{ route('meet.rooms.start', $room) }}" class="inline">
@csrf
<button type="submit" class="btn-primary btn-primary-sm">Start meeting</button>
</form>
@elseif ($room->canRestart())
<form method="POST" action="{{ route('meet.rooms.start', $room) }}" class="inline">
@csrf
<button type="submit" class="btn-primary btn-primary-sm">
{{ $room->status === 'ended' ? 'Rejoin meeting' : $room->restartLabel() }}
</button>
</form>
@endif
<a href="{{ route('meet.rooms.ical', $room) }}" class="btn-secondary btn-secondary-sm">Download iCal</a>
<a href="{{ route('meet.rooms.qr', $room) }}" target="_blank" class="btn-secondary btn-secondary-sm">QR code</a>
@if ($room->sessions->isNotEmpty())
<a href="{{ route('meet.rooms.attendance', $room) }}" class="btn-secondary btn-secondary-sm">Attendance CSV</a>
@endif
<a href="{{ route('meet.invitations.index', $room) }}" class="btn-secondary btn-secondary-sm">Manage invitations</a>
@if ($room->canRestart() && ($room->status === 'ended' || $room->type === 'personal' || $room->sessions->isNotEmpty()))
<form method="POST" action="{{ route('meet.rooms.start', $room) }}" class="inline">
@csrf
<button type="submit" class="btn-secondary btn-secondary-sm">{{ $room->restartLabel() }}</button>
</form>
@endif
</div>
@if ($room->passcode)
@@ -11,9 +11,7 @@
@forelse ($webinars as $room)
@include('meet.partials.room-card', [
'room' => $room,
'live' => $room->status === 'live',
'detailsRoute' => route('meet.webinars.show', $room),
'startRoute' => route('meet.webinars.start', $room),
])
@empty
<p class="rounded-2xl border border-dashed border-slate-200 bg-white p-8 text-center text-sm text-slate-500">No webinars yet.</p>
@@ -9,7 +9,6 @@
$mobileClass = match ($variant) {
'primary' => 'btn-fab h-10 w-10 lg:hidden',
'outline' => 'inline-flex h-10 w-10 items-center justify-center rounded-full border border-slate-200 bg-white text-slate-700 shadow-sm transition hover:border-slate-300 hover:bg-slate-50 lg:hidden',
'dark' => 'inline-flex h-10 w-10 items-center justify-center rounded-full bg-gray-900 text-white shadow-sm transition hover:bg-gray-800 lg:hidden',
'indigo' => 'inline-flex h-10 w-10 items-center justify-center rounded-full bg-indigo-600 text-white shadow-sm transition hover:bg-indigo-700 lg:hidden',
default => 'btn-fab h-10 w-10 lg:hidden',
};
@@ -17,7 +16,6 @@
$desktopClass = match ($variant) {
'primary' => 'btn-primary hidden items-center lg:inline-flex',
'outline' => 'hidden items-center rounded-lg border border-gray-200 bg-white px-4 py-2 text-sm font-medium text-gray-700 shadow-sm transition hover:bg-gray-50 lg:inline-flex',
'dark' => 'hidden items-center gap-1.5 rounded-lg bg-gray-900 px-3.5 py-2 text-sm font-medium text-white transition hover:bg-gray-800 lg:inline-flex',
'indigo' => 'hidden items-center justify-center rounded-xl bg-indigo-600 px-4 py-2.5 text-sm font-semibold text-white transition hover:bg-indigo-700 lg:inline-flex',
default => 'btn-primary hidden items-center lg:inline-flex',
};
@@ -8,30 +8,25 @@
@php
$linkClass = match ($variant) {
'dark' => 'block rounded-md px-3 py-2 text-sm text-slate-200 hover:bg-slate-800',
'sheet' => 'block rounded-xl px-4 py-3 text-sm font-medium text-slate-700 transition hover:bg-slate-100',
default => 'block rounded-lg px-3 py-2 text-sm text-slate-700 hover:bg-slate-100',
};
$logoutClass = match ($variant) {
'dark' => 'w-full rounded-md px-3 py-2 text-left text-sm text-rose-300 hover:bg-rose-950/40',
'sheet' => 'w-full rounded-xl px-4 py-3 text-left text-sm font-medium text-rose-600 transition hover:bg-rose-50',
default => 'w-full rounded-lg px-3 py-2 text-left text-sm text-rose-600 hover:bg-rose-50',
};
$logoutWrapperClass = match ($variant) {
'sheet' => 'border-t border-slate-100 pt-2',
'dark' => '',
default => '',
};
$dividerClass = match ($variant) {
'dark' => 'my-1 border-t border-slate-800',
default => 'my-1 border-t border-slate-100',
};
$containerClass = match ($variant) {
'dark' => 'mt-2 rounded-lg border border-slate-800 bg-slate-900 p-1',
'sheet' => 'space-y-1 p-2 pb-4',
default => 'p-1',
};