blade('Copy'); preg_match('/anchor-name: (--material-tooltip-[a-z0-9]+)/', $html, $anchor); expect($anchor)->not->toBeEmpty() ->and($html) ->toMatch('/\s*Copy<\/button>/') ->toMatch('/Copy link<\/span>/') ->not->toContain('class='); }); it('places the bubble on the side asked for, 4px out, flipping when there is no room', function (string $side, string $axis, string $margin, string $flip) { $css = ComponentStylesheet::read('tooltip'); expect((string) $this->blade("x"))->toContain("data-md-side=\"{$side}\"") ->and($css->declarations("[data-md-tooltip][data-md-side='{$side}']"))->toBe(['position-area' => $side]) ->and($css->declarations("[data-md-tooltip]:is({$axis})"))->toBe([$margin => 'var(--md-sys-measurement-space50)', 'position-try-fallbacks' => $flip]); })->with([ 'top' => ['top', "[data-md-side='top'], [data-md-side='bottom']", 'margin-block', 'flip-block'], 'bottom' => ['bottom', "[data-md-side='top'], [data-md-side='bottom']", 'margin-block', 'flip-block'], 'left' => ['left', "[data-md-side='left'], [data-md-side='right']", 'margin-inline', 'flip-inline'], 'right' => ['right', "[data-md-side='left'], [data-md-side='right']", 'margin-inline', 'flip-inline'], ]); it('falls back to the top for a side it does not know', function () { expect((string) $this->blade('x'))->toContain('data-md-side="top"'); }); it('draws M3\'s plain tooltip in the inverse surface, and fades on the effects spring', function () { $css = ComponentStylesheet::read('tooltip'); expect($css->declarations('[data-md-tooltip]'))->toMatchArray([ 'max-inline-size' => '200px', 'border-radius' => 'var(--md-sys-shape-corner-xs)', 'padding-block' => 'var(--md-sys-measurement-space50)', 'padding-inline' => 'var(--md-sys-measurement-space100)', 'background-color' => 'var(--md-sys-color-inverse-surface)', 'color' => 'var(--md-sys-color-inverse-on-surface)', 'font' => 'var(--md-sys-typescale-body-sm)', 'pointer-events' => 'none', 'opacity' => '0', 'transition-duration' => 'var(--md-sys-motion-effects-fast-duration)', 'transition-timing-function' => 'var(--md-sys-motion-effects-fast)', 'transition-behavior' => 'allow-discrete', ]) ->and($css->declarations('[data-md-tooltip]:popover-open'))->toBe(['opacity' => '1']) ->and($css->declarations('[data-md-tooltip]:popover-open', ['@starting-style']))->toBe(['opacity' => '0']); }); it('takes the caller\'s class and style on the standalone wrapper, its root', function () { $root = layoutRoot((string) $this->blade('Copy')); expect($root)->toMatchArray(['<' => 'span', 'data-md-tooltip-anchor' => '', 'class' => 'app-tooltip-wrapper']) ->and($root['style'])->toStartWith('anchor-name: --material-tooltip-')->toEndWith('; gap: 4px;'); }); it('escapes its text', function () { $this->blade('x') ->assertSee('<b>bold</b>', false); });