tests / lint (push) Has been cancelled
tests / feature (8.4) (push) Has been cancelled
tests / feature (8.5) (push) Has been cancelled
tests / browser (chrome, chromium) (push) Has been cancelled
tests / browser (firefox, firefox) (push) Has been cancelled
tests / browser (safari, webkit) (push) Has been cancelled
The showcase is now an overview and one page per section behind a grouped navigation rail, moved between with wire:navigate, instead of one long page under a scrolling top bar. The switch exposed a WebKit bug in the menu: inside a focusable region, WebKit moves focus out of the closing popover before its toggle event, so Escape no longer returned focus to the trigger. The menu now reads it on beforetoggle. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01V9NnLxnPp8vaaurb3Z1MFy
88 lines
4.5 KiB
PHP
88 lines
4.5 KiB
PHP
{{-- The app shell, as a whole page: /material/shell and its sibling pages, so the rail, the bar, the
|
|
modal rail and wire:navigate between pages can be tried at any window width. --}}
|
|
|
|
@php
|
|
$page ??= 'inbox';
|
|
|
|
$pages = [
|
|
'inbox' => ['title' => 'Inbox', 'icon' => 'inbox', 'badge' => 12],
|
|
'starred' => ['title' => 'Starred', 'icon' => 'star'],
|
|
'sent' => ['title' => 'Sent', 'icon' => 'send'],
|
|
'drafts' => ['title' => 'Drafts', 'icon' => 'draft', 'badge' => true],
|
|
'travel' => ['title' => 'Travel', 'icon' => 'flight', 'section' => 'Labels', 'bar' => false],
|
|
'receipts' => ['title' => 'Receipts', 'icon' => 'receipt_long', 'section' => 'Labels', 'bar' => false],
|
|
];
|
|
|
|
$destinations = collect($pages)
|
|
->map(fn (array $destination, string $key): array => $destination + [
|
|
'url' => route('livewire-material.shell', $key === 'inbox' ? [] : ['page' => $key]),
|
|
'active' => $key === $page,
|
|
])
|
|
->values()
|
|
->all();
|
|
|
|
$current = $pages[$page];
|
|
@endphp
|
|
|
|
<!DOCTYPE html>
|
|
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
|
|
<head>
|
|
<meta charset="utf-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
|
|
<meta name="robots" content="noindex" />
|
|
|
|
<title>{{ $current['title'] }} · App shell · Livewire Material</title>
|
|
|
|
<x-livewire-material::theme-script />
|
|
|
|
@vite(config('livewire-material.showcase.vite'))
|
|
@livewireStyles
|
|
</head>
|
|
<body class="bg-surface font-sans text-on-surface antialiased">
|
|
<x-livewire-material::app-shell :destinations="$destinations">
|
|
<x-slot:brand>
|
|
<a href="{{ route('livewire-material.showcase') }}" class="block truncate rounded-corner-xs type-title-lg focus-ring">Livewire Material</a>
|
|
</x-slot:brand>
|
|
|
|
<x-slot:rail-header>
|
|
<span class="rail-collapsed:hidden"><x-livewire-material::fab label="Compose" icon="edit" x-on:click="materialToast('Compose opens here')" /></span>
|
|
<span class="hidden rail-collapsed:inline-flex"><x-livewire-material::fab icon="edit" tooltip-right="Compose" x-on:click="materialToast('Compose opens here')" /></span>
|
|
</x-slot:rail-header>
|
|
|
|
<x-slot:rail-footer>
|
|
<x-livewire-material::navigation-rail-item label="Settings" icon="settings" link="#settings" no-wire-navigate />
|
|
</x-slot:rail-footer>
|
|
|
|
<x-slot:actions>
|
|
<x-livewire-material::button icon="dark_mode" tooltip-right="Switch theme" x-data x-on:click="$store.theme.toggle()" />
|
|
<x-livewire-material::button icon="help" tooltip-right="Help" x-on:click="materialToast('Help opens here')" />
|
|
</x-slot:actions>
|
|
|
|
<x-slot:top>
|
|
<header class="sticky top-0 z-20 flex h-16 items-center gap-1 bg-surface px-1 pt-[env(safe-area-inset-top)] sm:px-4">
|
|
<span class="sm:hidden"><x-livewire-material::button icon="menu" tooltip="Open navigation" x-data x-on:click="$store.rail.show()" data-test="shell-menu" /></span>
|
|
<h1 class="min-w-0 flex-1 truncate px-3 type-title-lg sm:px-0">{{ $current['title'] }}</h1>
|
|
<x-livewire-material::button icon="search" tooltip="Search" />
|
|
</header>
|
|
</x-slot:top>
|
|
|
|
<div class="mx-auto w-full max-w-5xl space-y-4 px-4 pb-6 sm:px-6">
|
|
<p class="type-body-md text-on-surface-variant" data-test="shell-page">This is the {{ strtolower($current['title']) }} page.</p>
|
|
|
|
<x-livewire-material::list segmented>
|
|
@foreach (range(1, 14) as $index)
|
|
<x-livewire-material::list-item :title="$current['title'].' item '.$index" description="A line of supporting text for this item" :icon="$current['icon']" trailing="{{ $index }}h" wire:key="item-{{ $index }}" />
|
|
@endforeach
|
|
</x-livewire-material::list>
|
|
|
|
<div class="flex flex-wrap gap-2">
|
|
<x-livewire-material::button label="Show a toast" variant="tonal" x-data x-on:click="materialToast('Moved to archive', { action: { label: 'Undo', handler: () => {} } })" />
|
|
<x-livewire-material::button label="Back to the showcase" link="{{ route('livewire-material.section', 'navigation') }}" no-wire-navigate />
|
|
</div>
|
|
</div>
|
|
</x-livewire-material::app-shell>
|
|
|
|
@livewireScripts
|
|
</body>
|
|
</html>
|