Plan step 19, containment.md C-11. The full-screen layout was another horizontal row with a 28px corner and a mask, where M3's "shows one edge-to-edge large item at a time and scrolls vertically". It is now a vertical scroll-snap column: items fill the row with no corner and no mask, 16dp apart, no end padding, the previous/next buttons point up and down and the arrow keys are Up and Down. The row is capped at the 840px medium window, which with the portrait rule in the header comment is as far as CSS can hold M3's "compact and medium, portrait only". The ported FullScreenCarouselStrategy keylines go with it: nothing measures them any more. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qwx5USif3wFFmxtHg5U1g9
73 lines
3.3 KiB
PHP
73 lines
3.3 KiB
PHP
{{-- One item of an `<x-carousel>`: a slide of art — an `<img>`, which fills and crops to the
|
|
item, or any element sized `size-full`.
|
|
|
|
<x-carousel-item label="Lake Constance">
|
|
<img src="{{ $photo->url }}" alt="Lake Constance at dusk" />
|
|
</x-carousel-item>
|
|
|
|
`label` lays a short line of text over the bottom of the art, on a scrim, pinned to the
|
|
item's visible edge and fading out as the item narrows — Compose's carousel sample, which
|
|
fades its label chip in once the mask is wide enough to hold it. The scrim is what M3 asks
|
|
for under text on an image; the text itself is `inverse-on-surface`, a role a scheme and a
|
|
contrast profile follow, rather than a literal white.
|
|
|
|
A focusable `group` with `aria-roledescription="slide"`, named "n of m" by the carousel
|
|
around it. M3 puts the tab stop on the item, not on the row: Tab reaches the first item, the
|
|
arrow keys move between them and Space or Enter opens the focused one
|
|
(docs/reference/m3/components-actions-communication-containment.md § Carousel →
|
|
Accessibility). The item is laid out at the carousel's large size and masked:
|
|
the surface inside is clipped by `--material-carousel-inset` from both sides with M3's
|
|
extra-large corner (28px, CarouselDefaults' item shape) and moved by
|
|
`--material-carousel-shift`, both written by resources/js/carousel.js. Without script the
|
|
item shows unmasked, at its `item-width`. In a `full-screen` carousel it is none of that: the
|
|
item fills the row, edge to edge, with no corner and no mask. Only inside `<x-carousel>`. --}}
|
|
|
|
@props([
|
|
'label' => null,
|
|
])
|
|
|
|
{{-- The layout of the `<x-carousel>` around it: the full-screen one is a vertical row of
|
|
edge-to-edge items, which M3 gives no corner and no mask. --}}
|
|
@aware([
|
|
'layout' => 'multi-browse',
|
|
])
|
|
|
|
@php
|
|
$vertical = $layout === 'full-screen';
|
|
@endphp
|
|
|
|
<div {{ $attributes
|
|
->class([
|
|
'focus-ring relative h-full shrink-0 snap-start snap-always focus-visible:-outline-offset-3',
|
|
'w-full' => $vertical,
|
|
'w-(--material-carousel-slot) max-w-full rounded-corner-xl' => ! $vertical,
|
|
])
|
|
->merge([
|
|
'role' => 'group',
|
|
'aria-roledescription' => __('slide'),
|
|
'aria-label' => '[material-carousel-position]',
|
|
'data-material-carousel-item' => true,
|
|
'tabindex' => '0',
|
|
]) }}>
|
|
<div
|
|
data-material-carousel-surface
|
|
@class([
|
|
'relative size-full overflow-hidden bg-surface-container-highest text-on-surface',
|
|
'rounded-corner-xl translate-x-(--material-carousel-shift) [clip-path:inset(0_var(--material-carousel-inset,0px)_round_var(--md-sys-shape-corner-xl))]' => ! $vertical,
|
|
])
|
|
>
|
|
<div data-material-carousel-content class="size-full [&>img]:size-full [&>img]:object-cover">
|
|
{{ $slot }}
|
|
</div>
|
|
|
|
@if (filled($label))
|
|
<div
|
|
data-material-carousel-label
|
|
class="pointer-events-none absolute inset-x-0 bottom-0 flex bg-linear-to-t from-scrim/60 to-transparent px-4 pt-10 pb-4 opacity-(--material-carousel-label)"
|
|
>
|
|
<span class="truncate type-title-md text-inverse-on-surface translate-x-(--material-carousel-label-shift)">{{ $label }}</span>
|
|
</div>
|
|
@endif
|
|
</div>
|
|
</div>
|