Plan step 36. <x-split-button> renders data-md-split-button and data-md-size on the pair and data-md-split on its halves. split-button.css draws SplitButton*Tokens' shape — full outer corners, inner corners that grow under the finger, the trailing half round while its menu is open — the narrower leading padding and 48px trailing half at xs and sm, and the chevron's own size, nudge and turn on the standard scheme. groups.css is empty and leaves tailwind.css. The actions browser test follows data-md-split and data-md-button-group, and gains the owed tests for a connected segment's 48px edge and a button group's single-required and multi selection. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qwx5USif3wFFmxtHg5U1g9
69 lines
4.4 KiB
PHP
69 lines
4.4 KiB
PHP
<?php
|
|
|
|
use NoNameWeb\LivewireMaterial\Tests\Support\ComponentStylesheet;
|
|
|
|
it('puts the action on the leading button and the menu on the trailing one', function () {
|
|
$html = (string) $this->blade(<<<'BLADE'
|
|
<x-split-button label="Download all" icon="download" wire:click="downloadZip" menu-label="Download options" class="mt-4">
|
|
<x-menu-item label="As a ZIP" />
|
|
</x-split-button>
|
|
BLADE);
|
|
|
|
expect($html)
|
|
->toStartWith('<div data-md-split-button data-md-size="sm" class="mt-4">')
|
|
->toMatch('/<button data-md-button="data-md-button"[^>]*data-md-split="leading" wire:click="downloadZip">/')
|
|
->toMatch('/<button data-md-button="data-md-button"[^>]*data-md-icon-button="data-md-icon-button"[^>]*aria-label="Download options"[^>]*data-md-split="trailing">/')
|
|
->toContain('role="menu"')
|
|
->toContain('As a ZIP')
|
|
->and(substr_count($html, 'wire:click="downloadZip"'))->toBe(1);
|
|
});
|
|
|
|
it('leaves the corners to the pair, growing the inner ones under the finger', function () {
|
|
$css = ComponentStylesheet::read('split-button');
|
|
|
|
expect($css->declarations('[data-md-split-button] [data-md-split]'))->toBe([
|
|
'--md-split-button-corner' => 'var(--md-split-button-inner)',
|
|
'border-start-start-radius' => 'var(--md-split-button-corner)',
|
|
'border-end-start-radius' => 'var(--md-split-button-corner)',
|
|
'border-start-end-radius' => 'var(--md-split-button-corner)',
|
|
'border-end-end-radius' => 'var(--md-split-button-corner)',
|
|
])
|
|
->and($css->declarations('[data-md-split-button] [data-md-split]:active'))->toBe(['--md-split-button-corner' => 'var(--md-split-button-inner-pressed)'])
|
|
->and($css->declarations("[data-md-split-button] [data-md-split='trailing'][aria-expanded='true']"))->toBe(['--md-split-button-corner' => 'var(--md-split-button-full)'])
|
|
->and($css->declarations("[data-md-split-button][data-md-size='xl']"))->toBe([
|
|
'--md-split-button-inner' => 'var(--md-sys-shape-corner-md)',
|
|
'--md-split-button-inner-pressed' => 'var(--md-sys-shape-corner-lg-increased)',
|
|
'--md-split-button-full' => '68px',
|
|
'--md-split-button-icon' => '50px',
|
|
'--md-split-button-nudge' => '6px',
|
|
])
|
|
->and($css->imports())->toBe(['./button.css']);
|
|
});
|
|
|
|
it('is filled unless another container variant is asked for', function () {
|
|
expect((string) $this->blade('<x-split-button label="Save" variant="text"><x-menu-item label="Draft" /></x-split-button>'))->toContain('data-md-variant="filled"')->not->toContain('data-md-variant="text"')
|
|
->and((string) $this->blade('<x-split-button label="Save" variant="tonal"><x-menu-item label="Draft" /></x-split-button>'))->toContain('data-md-variant="tonal"');
|
|
});
|
|
|
|
it('gives the two smallest sizes their narrower inner padding and 48px trailing button', function () {
|
|
$css = ComponentStylesheet::read('split-button');
|
|
|
|
expect((string) $this->blade('<x-split-button label="Save" size="xs"><x-menu-item label="Draft" /></x-split-button>'))->toContain('data-md-split-button data-md-size="xs"')
|
|
->and($css->declarations("[data-md-split-button][data-md-size='xs'] [data-md-split='leading']"))->toBe(['padding-inline-end' => 'var(--md-sys-measurement-space125)'])
|
|
->and($css->declarations("[data-md-split-button][data-md-size='sm'] [data-md-split='leading']"))->toBe(['padding-inline-end' => '12px'])
|
|
->and($css->declarations("[data-md-split-button]:is([data-md-size='xs'], [data-md-size='sm']) [data-md-split='trailing']"))->toBe(['inline-size' => 'var(--md-sys-measurement-space600)']);
|
|
});
|
|
|
|
it('nudges its chevron towards the leading half and turns it over on the standard scheme', function () {
|
|
$css = ComponentStylesheet::read('split-button');
|
|
|
|
expect($css->declarations("[data-md-split-button] [data-md-split='trailing'] [data-md-icon]"))->toBe([
|
|
'inline-size' => 'var(--md-split-button-icon)',
|
|
'block-size' => 'var(--md-split-button-icon)',
|
|
'margin-inline-start' => 'calc(-1 * var(--md-split-button-nudge))',
|
|
'margin-inline-end' => 'var(--md-split-button-nudge)',
|
|
'transition' => 'rotate var(--md-sys-motion-duration-short) var(--md-sys-motion-easing-standard)',
|
|
])
|
|
->and($css->declarations("[data-md-split-button] [data-md-split='trailing'][aria-expanded='true'] [data-md-icon]"))->toBe(['rotate' => '180deg']);
|
|
});
|