tests / browser (firefox, firefox) (push) Successful in 1m54s
tests / browser (safari, webkit) (push) Successful in 2m17s
tests / lint (push) Successful in 59s
tests / feature (8.4) (push) Successful in 1m7s
tests / feature (8.5) (push) Successful in 1m0s
tests / browser (chrome, chromium) (push) Successful in 1m49s
<x-button> (label buttons, icon buttons and toggles in five sizes, with filled, tonal, outlined, elevated and text variants in any colour role), <x-tooltip>, <x-menu> with items, groups and separators, <x-button-group>, <x-group> as a connected button group, <x-split-button>, <x-fab>, <x-fab-menu> and <x-loading>. Sizes, colours and shapes come from androidx Compose Material 3's tokens; the loading indicator ports its Morph into SVG + SMIL. Menus follow WAI-ARIA's menu button pattern on popovers placed by CSS anchor positioning. Browser tests run in Chromium, Firefox and WebKit. The showcase fetches the icon names on demand: inlined, they tripped Pest's test server into HTTP 431s under Firefox. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01V9NnLxnPp8vaaurb3Z1MFy
52 lines
2.3 KiB
PHP
52 lines
2.3 KiB
PHP
{{-- An M3 plain tooltip: a short label for a control, in the inverse surface.
|
|
|
|
Two ways in. Inside a component that already names its own anchor — `<x-button tooltip="…">`
|
|
passes `anchor` — it is a bare popover. Standalone, it wraps its trigger:
|
|
|
|
<x-tooltip text="Copy link"><button …>…</button></x-tooltip>
|
|
|
|
It shows after a short hover on a pointer that can hover, at once on keyboard focus, and
|
|
hides on leave, blur, press and Escape. A phone has no hover, so a control there carries its
|
|
words. The bubble is a `popover="manual"` in the top layer — never clipped by an
|
|
`overflow-hidden` parent, never widening a scroll container — placed by CSS anchor
|
|
positioning on `side` (`top`, `bottom`, `left`, `right`), flipping when there is no room.
|
|
|
|
It is aria-hidden: an icon button takes the same words as its aria-label, and a labelled
|
|
control would otherwise read them twice. --}}
|
|
|
|
@props([
|
|
'text',
|
|
'side' => 'top',
|
|
'anchor' => null,
|
|
])
|
|
|
|
@php
|
|
$side = in_array($side, ['top', 'bottom', 'left', 'right'], true) ? $side : 'top';
|
|
$standalone = $anchor === null;
|
|
$anchor ??= '--material-tooltip-'.\Illuminate\Support\Str::lower(\Illuminate\Support\Str::random(10));
|
|
@endphp
|
|
|
|
@if ($standalone)
|
|
<span class="inline-flex" style="anchor-name: {{ $anchor }}">
|
|
{{ $slot }}
|
|
@endif
|
|
|
|
<span
|
|
popover="manual"
|
|
aria-hidden="true"
|
|
x-data="materialTooltip"
|
|
style="position-anchor: {{ $anchor }}"
|
|
@class([
|
|
'pointer-events-none m-0 max-w-50 overflow-visible border-0 rounded-corner-xs bg-inverse-surface px-2 py-1 text-center whitespace-normal type-body-sm text-inverse-on-surface [inset:auto]',
|
|
'opacity-0 transition-[opacity,display,overlay] transition-discrete duration-(--md-sys-motion-effects-fast-duration) ease-effects-fast open:opacity-100 starting:open:opacity-0',
|
|
'my-1 [position-area:top] [position-try-fallbacks:flip-block]' => $side === 'top',
|
|
'my-1 [position-area:bottom] [position-try-fallbacks:flip-block]' => $side === 'bottom',
|
|
'mx-1 [position-area:left] [position-try-fallbacks:flip-inline]' => $side === 'left',
|
|
'mx-1 [position-area:right] [position-try-fallbacks:flip-inline]' => $side === 'right',
|
|
])
|
|
>{{ $text }}</span>
|
|
|
|
@if ($standalone)
|
|
</span>
|
|
@endif
|