Files
livewire-material/resources/views/showcase/sections/fields.blade.php
T
Andreas Reinhold / reiniandClaude Opus 5 3fb0a404db Write the showcase examples' layout tags as an application does
Plan step 38 review: nine sections' examples wrapped their components
in <x-livewire-material::stack>, ::row and ::grid (148 tags) beside an
unprefixed <x-button>, while bars, containment and the layout pages
wrote <x-stack>. The code sample is what an application copies, and
the example component rewrites only unprefixed tags to a configured
prefix, so the namespaced ones taught a second form and escaped it.
Every example now writes <x-stack>, <x-row> and <x-grid>; a test
rejects a namespaced tag inside an example heredoc.

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

236 lines
15 KiB
PHP

@php
$examples = [
'Outlined and filled text fields' => <<<'BLADE'
<x-grid :columns="['compact' => 1, 'medium' => 2]" gap="space300">
<x-stack gap="space200">
<x-input label="Share name" hint="Recipients see this name" />
<x-input label="Recipient" icon="mail" type="email" placeholder="name@example.com" clearable value="anna@example.com" />
<x-input label="Price" prefix="CHF" suffix="per month" type="number" value="12" />
<x-input label="Share link" value="https://sealshare.test/s/8f3k2" readonly copyable />
<x-password label="Password" hint="At least 12 characters" />
<x-input label="Disabled" value="Not editable" disabled />
</x-stack>
<x-stack gap="space200">
<x-input variant="filled" label="Share name" hint="Recipients see this name" />
<x-input variant="filled" label="Recipient" icon="mail" type="email" placeholder="name@example.com" clearable value="anna@example.com" />
<x-input variant="filled" label="Price" prefix="CHF" suffix="per month" type="number" value="12" />
<x-input variant="filled" label="Search" icon="search" icon-right="mic" />
<x-password variant="filled" label="Password" hint="At least 12 characters" />
<x-input variant="filled" label="Disabled" value="Not editable" disabled />
</x-stack>
</x-grid>
BLADE,
'Errors, required and sizes' => <<<'BLADE'
<x-grid :columns="['compact' => 1, 'medium' => 2]" gap="space300">
<x-stack gap="space200">
<x-input label="Email" required />
<x-field id="showcase-error" label="Expiry" :messages="['Choose a date in the future.']">
<input id="showcase-error" data-md-field-control value="2020-01-01" aria-invalid="true" />
</x-field>
</x-stack>
<x-stack gap="space200">
<x-field id="showcase-error-filled" variant="filled" label="Expiry" :messages="['Choose a date in the future.']">
<input id="showcase-error-filled" data-md-field-control value="2020-01-01" aria-invalid="true" />
</x-field>
<x-row gap="space125" wrap align="center">
<x-input size="sm" icon="search" placeholder="Filter" aria-label="Filter" class="showcase-w-sm" />
<x-input size="xs" placeholder="Find" aria-label="Find" class="showcase-w-xs" />
</x-row>
</x-stack>
</x-grid>
BLADE,
'Width at medium and above' => <<<'BLADE'
<x-stack gap="space200">
{{-- M3: never let a text field span the full width of a large screen. From medium it stops at 40rem. --}}
<x-input label="Bounded, the default" hint="No wider than 40rem from medium, however wide the pane is" />
<x-input label="Narrower" class="showcase-w-narrow" hint="An unlayered rule from the call site wins" />
<x-input label="The width of the pane" full icon="search" hint="`full` takes the bound off — for a search row or an editor" />
</x-stack>
BLADE,
'Character counter' => <<<'BLADE'
<x-grid :columns="['compact' => 1, 'medium' => 2]" gap="space300">
<x-stack gap="space200">
<x-input label="Share name" maxlength="40" counter hint="Recipients see this name" />
<x-input variant="filled" label="Subject" maxlength="60" counter />
</x-stack>
<x-textarea label="Message for recipients" maxlength="180" counter rows="3" hint="Sent with the link" />
</x-grid>
BLADE,
'Textarea and select' => <<<'BLADE'
<x-grid :columns="['compact' => 1, 'medium' => 2]" gap="space300">
<x-stack gap="space200">
<x-textarea label="Message" hint="Grows as you type, up to six lines" rows="2" max-rows="6" />
<x-select label="Expires after" :options="[['id' => 1, 'name' => '1 hour'], ['id' => 24, 'name' => '1 day'], ['id' => 168, 'name' => '7 days'], ['id' => 720, 'name' => '30 days', 'disabled' => true]]" />
<x-file label="Attachments" multiple hint="Up to 2 GB" />
</x-stack>
<x-stack gap="space200">
<x-textarea variant="filled" label="Message" hint="Grows as you type, up to six lines" rows="2" max-rows="6" />
<x-select variant="filled" label="Expires after" icon="schedule" placeholder="Choose…" :options="[['id' => 1, 'name' => '1 hour'], ['id' => 24, 'name' => '1 day'], ['id' => 168, 'name' => '7 days']]" />
<x-file variant="filled" label="Attachments" multiple />
</x-stack>
</x-grid>
BLADE,
'Checkboxes' => <<<'BLADE'
<x-grid :columns="['compact' => 1, 'expanded' => 3]" gap="space300">
<x-stack gap="space200">
<x-checkbox label="Notify me on download" checked />
<x-checkbox label="Select all files" indeterminate />
<x-checkbox label="Burn after reading" hint="The share is deleted after its first download" />
</x-stack>
<x-stack gap="space200">
<x-checkbox label="Disabled" disabled />
<x-checkbox label="Disabled and ticked" checked disabled />
<x-checkbox label="Disabled, partly ticked" indeterminate disabled />
</x-stack>
<x-stack gap="space200">
<x-checkbox label="Show in the dashboard" right />
<x-checkbox aria-label="Unlabelled" />
</x-stack>
</x-grid>
BLADE,
'A checkbox group at expanded' => <<<'BLADE'
{{-- M3: from expanded (840px), gather related checkboxes into a contained region instead of one long column. --}}
<x-card variant="outlined" data-md-showcase-demo-card data-md-showcase-size="lg">
<fieldset>
<legend class="md-type-title-sm md-ink" data-md-showcase-legend>Tell me about</legend>
<x-grid :columns="['compact' => 1, 'expanded' => 2]" gap="space200">
<x-checkbox label="Downloads" name="notify[]" value="downloads" checked />
<x-checkbox label="Comments" name="notify[]" value="comments" />
<x-checkbox label="Expiring shares" name="notify[]" value="expiring" checked />
<x-checkbox label="Failed uploads" name="notify[]" value="failed" />
<x-checkbox label="New team members" name="notify[]" value="members" />
<x-checkbox label="Weekly summary" name="notify[]" value="summary" />
</x-grid>
</fieldset>
</x-card>
BLADE,
'Radio buttons' => <<<'BLADE'
<x-grid :columns="['compact' => 1, 'medium' => 2]" gap="space300">
<x-radio label="Who can open the link" name="showcase-audience" value="password" :options="[['id' => 'anyone', 'name' => 'Anyone with the link'], ['id' => 'password', 'name' => 'Anyone with the password', 'hint' => 'Share the password separately'], ['id' => 'team', 'name' => 'My team only', 'disabled' => true]]" />
<x-radio label="Theme" name="showcase-radio-theme" value="system" inline :options="[['id' => 'light', 'name' => 'Light'], ['id' => 'dark', 'name' => 'Dark'], ['id' => 'system', 'name' => 'System']]" hint="Inline from sm" />
</x-grid>
BLADE,
'Switches' => <<<'BLADE'
<x-grid :columns="['compact' => 1, 'expanded' => 3]" gap="space300">
<x-stack gap="space200">
<x-toggle label="Email notifications" checked />
<x-toggle label="Weekly summary" />
</x-stack>
<x-stack gap="space200">
<x-toggle label="With icons" icons checked />
<x-toggle label="With icons, off" icons />
<x-toggle label="Only the check" icons="selected" checked />
</x-stack>
<x-stack gap="space200">
<x-toggle label="Disabled" disabled />
<x-toggle label="Disabled, on" checked disabled icons />
<x-toggle label="Public link" hint="Anyone with the link can open it" right />
</x-stack>
</x-grid>
BLADE,
'Choices' => <<<'BLADE'
<x-grid :columns="['compact' => 1, 'medium' => 2]" gap="space300">
<x-stack gap="space300">
<x-choices label="Days you are free" hint="Filter chips: any number" :value="[1, 3]" :options="[['id' => 1, 'name' => 'Mon'], ['id' => 2, 'name' => 'Tue'], ['id' => 3, 'name' => 'Wed'], ['id' => 4, 'name' => 'Thu'], ['id' => 5, 'name' => 'Fri'], ['id' => 6, 'name' => 'Sat', 'disabled' => true]]" />
<x-choices label="Expires after" single :value="24" :options="[['id' => 1, 'name' => '1 hour'], ['id' => 24, 'name' => '1 day'], ['id' => 168, 'name' => '7 days']]" />
</x-stack>
<x-stack gap="space200">
<x-choices label="Time zone" searchable icon="public" value="Europe/Zurich" :options="collect(timezone_identifiers_list())->map(fn ($zone) => ['id' => $zone, 'name' => str_replace('_', ' ', $zone)])->all()" />
<x-choices label="Language" searchable variant="filled" placeholder="Type a language" :options="[['id' => 'de', 'name' => 'Deutsch'], ['id' => 'en', 'name' => 'English'], ['id' => 'fr', 'name' => 'Français'], ['id' => 'it', 'name' => 'Italiano'], ['id' => 'rm', 'name' => 'Rumantsch', 'disabled' => true]]" />
</x-stack>
</x-grid>
BLADE,
'Search' => <<<'BLADE'
<x-grid :columns="['compact' => 1, 'medium' => 2]" gap="space300">
<div x-data="{ query: '' }">
<x-search x-model="query" placeholder="Search shares">
<x-list>
<x-list-item title="holiday-photos.zip" description="248 MB · 3 days left" icon="folder_zip" link="#fields" x-show="'holiday-photos.zip'.includes(query.toLowerCase())" />
<x-list-item title="contract.pdf" description="1.2 MB · 1 hour left" icon="picture_as_pdf" link="#fields" x-show="'contract.pdf'.includes(query.toLowerCase())" />
<x-list-item title="design-review.mp4" description="3.4 GB · 7 days left" icon="movie" link="#fields" x-show="'design-review.mp4'.includes(query.toLowerCase())" />
</x-list>
<x-slot:trailing>
<span class="md-type-label-lg" data-md-showcase-avatar>AR</span>
</x-slot:trailing>
</x-search>
</div>
{{-- M3's resting bar is 360px and grows to 720 while focused; --search-width sets the resting one. --}}
<div style="--search-width: 22.5rem">
<x-search placeholder="Search in settings" docked>
<x-slot:empty>Type to search your settings.</x-slot:empty>
</x-search>
</div>
</x-grid>
BLADE,
'Search entry points and suggestions' => <<<'BLADE'
<x-grid :columns="['compact' => 1, 'medium' => 2]" gap="space300">
<div x-data="{ query: '' }">
<x-search x-model="query" placeholder="Search shares">
<x-slot:suggestions>
<x-list>
<x-list-item title="Recent: holiday photos" icon="history" link="#fields" />
<x-list-item title="Recent: contract" icon="history" link="#fields" />
<x-list-item title="Shares expiring this week" icon="trending_up" link="#fields" />
</x-list>
</x-slot:suggestions>
<x-list>
<x-list-item title="holiday-photos.zip" description="248 MB" icon="folder_zip" link="#fields" x-show="'holiday-photos.zip'.includes(query.toLowerCase())" />
<x-list-item title="contract.pdf" description="1.2 MB" icon="picture_as_pdf" link="#fields" x-show="'contract.pdf'.includes(query.toLowerCase())" />
</x-list>
</x-search>
</div>
{{-- M3's search icon button: search as a secondary action, expanding into the full-screen view. --}}
<div data-md-showcase-search-bar>
<x-button icon="menu" aria-label="Open the menu" />
<span class="md-type-title-md md-ink" data-md-showcase-search-bar-title>Shares</span>
<x-search trigger="icon" label="Search shares">
<x-slot:suggestions>
<x-list>
<x-list-item title="Recent: design review" icon="history" link="#fields" />
</x-list>
</x-slot:suggestions>
<x-slot:empty>No shares match.</x-slot:empty>
</x-search>
</div>
</x-grid>
BLADE,
'A form' => <<<'BLADE'
<x-card variant="outlined" data-md-showcase-demo-card data-md-showcase-size="md">
<x-form x-on:submit.prevent="materialToast('Share created', { type: 'success' })" separator>
<x-input label="Share name" required />
<x-textarea label="Message for recipients" />
<x-select label="Expires after" :options="[['id' => 24, 'name' => '1 day'], ['id' => 168, 'name' => '7 days']]" />
<x-toggle label="Protect with a password" right />
<x-slot:actions>
<x-button label="Cancel" type="reset" />
<x-button label="Create share" variant="filled" type="submit" />
</x-slot:actions>
</x-form>
</x-card>
BLADE,
];
@endphp
<x-livewire-material::stack as="section" id="fields" gap="space300">
<h2 class="md-visually-hidden">Text fields and selection</h2>
<p class="md-type-body-md md-ink-variant">
<code>&lt;x-input&gt;</code>, <code>&lt;x-password&gt;</code>, <code>&lt;x-textarea&gt;</code>, <code>&lt;x-select&gt;</code>, <code>&lt;x-file&gt;</code>
(all on <code>&lt;x-field&gt;</code>, outlined or filled), <code>&lt;x-checkbox&gt;</code>, <code>&lt;x-radio&gt;</code>, <code>&lt;x-toggle&gt;</code>, <code>&lt;x-choices&gt;</code>, <code>&lt;x-search&gt;</code> and <code>&lt;x-form&gt;</code>.
</p>
@foreach ($examples as $title => $code)
<x-showcase::example :$title :$code />
@endforeach
</x-livewire-material::stack>