{{-- One item of an ``: a slide of art — an ``, which fills and crops to the item, or any element sized to fill it. Lake Constance at dusk `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, and the scrim is `--md-sys-color-scrim` — black in every scheme, theme and contrast level — so its ink is the one absolute the theme keeps, `white`; a role (`inverse-on-surface`) is dark ink in a dark scheme and fails on the scrim there (docs/audits/m3-alignment/containment.md, C-25, deliberately kept). 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). It renders the shared `md-focus-ring` class (foundation/interaction.css) rather than a hand-rolled ring — the box the class draws is the item's own whole hit area — which resources/css/components/carousel-item.css refines to an inset ring: an outward offset would draw under the next item, since items sit edge to edge in the row. 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. In a `multi-aspect` carousel the item is as wide as its own `aspect` makes it at the row's height, and nothing masks it: M3's uncontained multi-aspect-ratio layout is for items whose widths "vary… ranging from a 9:16 minimum to a 16:9 maximum aspect ratio", so `aspect` is held inside that range (`16/9`, `16:9` or a plain number; a square by default, and ignored in every other layout, where the keylines size the items) (docs/reference/m3/components-actions-communication-containment.md § Carousel → Variants, Specs). Only inside ``. --}} @props([ 'label' => null, 'aspect' => null, ]) {{-- The layout of the `` around it: the full-screen one is a vertical row of edge-to-edge items, which M3 gives no corner and no mask, and the multi-aspect one sizes each item by its own aspect ratio and masks none of them. --}} @aware([ 'layout' => 'multi-browse', ]) @php $multiAspect = $layout === 'multi-aspect'; // M3's 9:16 minimum and 16:9 maximum. `16/9`, `16:9` and `1.78` all say the same thing. $ratio = null; if ($multiAspect) { $value = $aspect ?? 1; if (is_string($value) && preg_match('/^\s*([\d.]+)\s*[\/:]\s*([\d.]+)\s*$/', $value, $parts) && (float) $parts[2] > 0) { $value = (float) $parts[1] / (float) $parts[2]; } $ratio = round(min(max((float) $value, 9 / 16), 16 / 9), 4); } @endphp
class('md-focus-ring') ->merge(array_filter([ 'role' => 'group', 'aria-roledescription' => __('slide'), 'aria-label' => '[material-carousel-position]', 'data-md-carousel-item' => true, 'tabindex' => '0', 'style' => $ratio === null ? null : "aspect-ratio: {$ratio}", ], fn ($value): bool => $value !== null)) }}>
{{ $slot }}
@if (filled($label))
{{ $label }}
@endif