Files
Andreas Reinhold / reiniandClaude Opus 5 b4f1e005de Add the pane layout component
Plan step 35: <x-pane>, a content region with M3's margins (16px below
medium, 24px from it) drawn once however panes and layouts nest, a width
cap, and an optional pane app bar - <x-app-bar> as a direct child of the
pane with title, subtitle, actions, a back link or action, a leading
slot, and the section navigation under it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qwx5USif3wFFmxtHg5U1g9
2026-09-14 14:51:04 +02:00

89 lines
4.2 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{{-- A pane: a content region with M3's margins, and its own top app bar if it has a title.
<x-pane title="Settings" subtitle="Your account" width="narrow">
<x-slot:actions><x-button icon="help" tooltip="Help" /></x-slot:actions>
<x-slot:navigation><x-section-nav :items="$sections" /></x-slot:navigation>
</x-pane>
M3 puts every piece of content in a pane and lets each carry its own top app bar
(docs/reference/m3/foundations.md § Layout → Scaffold). The body is kept off the window's edge
by M3's margin, 16px below medium (600px) and 24px from it
(docs/reference/m3/foundations-supplement.md § Breakpoints); a pane inside something that
already keeps that margin — the scaffold's content region, a canonical layout, another pane's
body — draws none, so the margin is never doubled; on an `<x-surface>` it draws it again.
`width` caps the pane and centres it: `narrow` (40rem, M3's 4060 characters a line),
`medium` (60rem), `wide` (80rem) or `full` (the default, all the room it has).
The app bar is `<x-app-bar>`, drawn when there is a `title`, `actions`, a `leading` slot or
`back`: `title` and `subtitle`, `heading` (`h1` by default; the second pane of a canonical
layout passes `h2`), `sticky` (true: it holds to the top of the window for as long as the pane
is on screen), the `actions` slot at its end. Its leading icon button is the `leading` slot,
or `back`: a URL makes it a link back there, and `true` calls `back()` in the Alpine scope
around it, which `<x-list-detail>` provides and which it hides where both panes show, as M3
shows a back button only in a single-pane list-detail. The back arrow mirrors in a
right-to-left document.
`navigation` is the pane's section navigation (`<x-section-nav>`, `<x-tabs>`), under the bar
and above the body, with the body's margins; it is not the bar's leading button.
It takes `as` (`div` by default: `section`, `article`, `main` …), `hide-below` and `hide-from`
like every layout component, and the caller's `class` and `style` land on it untouched. Drawn
by resources/css/layout/pane.css. --}}
@props([
'as' => null,
'title' => null,
'subtitle' => null,
'heading' => 'h1',
'sticky' => true,
'back' => null,
'width' => null,
'hideBelow' => null,
'hideFrom' => null,
])
@php
$layout = \NoNameWeb\LivewireMaterial\Support\Layout::class;
$element = $layout::element($as);
$backLink = is_string($back) && $back !== '' ? $back : null;
$backAction = $back === true;
$bar = filled($title) || isset($actions) || isset($leading) || $backLink !== null || $backAction;
$attributes = $attributes->merge(array_filter([
'data-md-pane' => true,
'data-md-width' => $layout::choice($width, ['full', 'narrow', 'medium', 'wide']),
] + $layout::visibility($hideBelow, $hideFrom), fn ($value): bool => $value !== null));
@endphp
<{{ $element }} {{ $attributes }}>
@if ($bar)
<x-livewire-material::app-bar :title="$title" :subtitle="$subtitle" :heading="$heading" :sticky="$sticky" data-md-pane-bar>
@if (isset($leading))
<x-slot:navigation>{{ $leading }}</x-slot:navigation>
@elseif ($backLink !== null || $backAction)
<x-slot:navigation>
<span data-md-pane-back @if ($backAction) data-md-list-detail-back @endif>
@if ($backLink !== null)
<x-livewire-material::button icon="arrow_back" :tooltip="__('Back')" :link="$backLink" />
@else
<x-livewire-material::button icon="arrow_back" :tooltip="__('Back')" x-on:click="back()" />
@endif
</span>
</x-slot:navigation>
@endif
@isset($actions)
<x-slot:actions>{{ $actions }}</x-slot:actions>
@endisset
</x-livewire-material::app-bar>
@endif
@isset($navigation)
<div data-md-pane-navigation>{{ $navigation }}</div>
@endisset
<div data-md-pane-body>{{ $slot }}</div>
</{{ $element }}>