M3 Expressive's flexible navigation bar, the collapsed, expanded and modal navigation rail with its state applied before the first paint, and an adaptive app shell composing them. The head script now restores the theme and rail attributes that wire:navigate strips from <html>. Completes Phase 8. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01V9NnLxnPp8vaaurb3Z1MFy
88 lines
4.2 KiB
PHP
88 lines
4.2 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-theme-script />
|
|
|
|
@vite(config('livewire-material.showcase.vite'))
|
|
@livewireStyles
|
|
</head>
|
|
<body class="bg-surface font-sans text-on-surface antialiased">
|
|
<x-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-fab label="Compose" icon="edit" x-on:click="materialToast('Compose opens here')" /></span>
|
|
<span class="hidden rail-collapsed:inline-flex"><x-fab icon="edit" tooltip-right="Compose" x-on:click="materialToast('Compose opens here')" /></span>
|
|
</x-slot:rail-header>
|
|
|
|
<x-slot:rail-footer>
|
|
<x-navigation-rail-item label="Settings" icon="settings" link="#settings" no-wire-navigate />
|
|
</x-slot:rail-footer>
|
|
|
|
<x-slot:actions>
|
|
<x-button icon="dark_mode" tooltip-right="Switch theme" x-data x-on:click="$store.theme.toggle()" />
|
|
<x-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-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-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-list segmented>
|
|
@foreach (range(1, 14) as $index)
|
|
<x-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-list>
|
|
|
|
<div class="flex flex-wrap gap-2">
|
|
<x-button label="Show a toast" variant="tonal" x-data x-on:click="materialToast('Moved to archive', { action: { label: 'Undo', handler: () => {} } })" />
|
|
<x-button label="Back to the showcase" link="{{ route('livewire-material.showcase') }}#navigation" no-wire-navigate />
|
|
</div>
|
|
</div>
|
|
</x-app-shell>
|
|
|
|
@livewireScripts
|
|
</body>
|
|
</html>
|