Draw the button group without Tailwind
Plan step 36. <x-button-group> renders data-md-button-group (standard or connected), data-md-size, data-md-shape and, with a selection, data-md-selection and data-md-selection-required. button-group.css now also draws the standard group: its gaps per size, the square corner scale it hands its buttons, and the press expansion that widens a pressed label button while its neighbours give way. groups.css keeps only the split button until that is rewritten too. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qwx5USif3wFFmxtHg5U1g9
This commit is contained in:
co-authored by
Claude Opus 5
parent
b8c6d411db
commit
8dd0a7ef9d
@@ -2,42 +2,73 @@
|
||||
|
||||
use Livewire\Component;
|
||||
use Livewire\Livewire;
|
||||
use NoNameWeb\LivewireMaterial\Tests\Support\ComponentStylesheet;
|
||||
|
||||
it('groups buttons with the spacing of their size', function () {
|
||||
expect((string) $this->blade('<x-button-group label="Views" size="md"><x-button label="Day" /></x-button-group>'))
|
||||
->toContain('role="group"')
|
||||
->toContain('aria-label="Views"')
|
||||
->toContain('data-button-group="standard"')
|
||||
->toContain('data-size="md"')
|
||||
->toContain('gap-2')
|
||||
->and((string) $this->blade('<x-button-group><x-button label="Day" /></x-button-group>'))
|
||||
->toContain('gap-3');
|
||||
});
|
||||
it('groups buttons with the spacing of their size', function (string $size, string $gap) {
|
||||
expect((string) $this->blade("<x-button-group label=\"Views\" size=\"{$size}\"><x-button label=\"Day\" /></x-button-group>"))
|
||||
->toMatch("/<div\\s+role=\"group\"\\s+aria-label=\"Views\"\\s+data-md-button-group=\"standard\"\\s+data-md-size=\"{$size}\"\\s+data-md-shape=\"round\"/")
|
||||
->not->toContain('class=')
|
||||
->and(ComponentStylesheet::read('button-group')->declarations(in_array($size, ['xs', 'sm'], true)
|
||||
? "[data-md-button-group='standard'][data-md-size='{$size}']"
|
||||
: "[data-md-button-group='standard']"))->toBe(['gap' => $gap]);
|
||||
})->with([
|
||||
'xs' => ['xs', '18px'],
|
||||
'sm' => ['sm', '12px'],
|
||||
'md' => ['md', 'var(--md-sys-measurement-space100)'],
|
||||
'lg' => ['lg', 'var(--md-sys-measurement-space100)'],
|
||||
'xl' => ['xl', 'var(--md-sys-measurement-space100)'],
|
||||
]);
|
||||
|
||||
it('connects buttons 2px apart', function () {
|
||||
expect((string) $this->blade('<x-button-group connected><x-button label="Day" /></x-button-group>'))
|
||||
->toContain('data-button-group="connected"')
|
||||
->toContain('gap-0.5');
|
||||
it('connects buttons 2px apart, with M3\'s inner corners', function () {
|
||||
$css = ComponentStylesheet::read('button-group');
|
||||
|
||||
expect((string) $this->blade('<x-button-group connected><x-button label="Day" /></x-button-group>'))->toContain('data-md-button-group="connected"')
|
||||
->and($css->declarations("[data-md-button-group='connected']"))->toBe(['gap' => 'var(--md-sys-measurement-space25)'])
|
||||
->and($css->declarations("[data-md-button-group='connected'] > *"))->toMatchArray([
|
||||
'--md-button-group-corner' => 'var(--md-button-group-inner)',
|
||||
'border-start-start-radius' => 'var(--md-button-group-corner)',
|
||||
])
|
||||
->and($css->declarations("[data-md-button-group='connected'] > :active"))->toBe(['--md-button-group-corner' => 'var(--md-button-group-inner-pressed)'])
|
||||
->and($css->declarations("[data-md-button-group='connected'] > :first-child"))->toBe([
|
||||
'border-start-start-radius' => 'var(--md-button-group-outer)',
|
||||
'border-end-start-radius' => 'var(--md-button-group-outer)',
|
||||
])
|
||||
// Half the height, never 9999px, which would scale the small inner corners away.
|
||||
->and($css->declarations("[data-md-button-group][data-md-size='xl']"))->toMatchArray(['--md-button-group-full' => '68px', '--md-button-group-inner' => 'var(--md-sys-shape-corner-lg-increased)']);
|
||||
});
|
||||
|
||||
it('squares a group', function () {
|
||||
// M3 lists "Default shape | Round, square" as a button-group configuration; the shape covers
|
||||
// every button in the group, so it need not be written on each one.
|
||||
$css = ComponentStylesheet::read('button-group');
|
||||
|
||||
expect((string) $this->blade('<x-button-group shape="square"><x-button label="Day" /></x-button-group>'))
|
||||
->toContain('data-shape="square"')
|
||||
->toContain('data-md-shape="square"')
|
||||
->and((string) $this->blade('<x-button-group connected shape="square"><x-button label="Day" /></x-button-group>'))
|
||||
->toContain('data-button-group="connected"')
|
||||
->toContain('data-shape="square"')
|
||||
->and((string) $this->blade('<x-button-group><x-button label="Day" /></x-button-group>'))
|
||||
->toContain('data-shape="round"');
|
||||
->toContain('data-md-button-group="connected"')
|
||||
->toContain('data-md-shape="square"')
|
||||
->and((string) $this->blade('<x-button-group shape="oval"><x-button label="Day" /></x-button-group>'))
|
||||
->toContain('data-md-shape="round"')
|
||||
->and($css->declarations("[data-md-button-group='standard'][data-md-shape='square'] > *"))->toBe(['border-radius' => 'var(--md-button-group-square)'])
|
||||
->and($css->declarations("[data-md-button-group='standard'][data-md-shape='square'] > [aria-pressed='true']"))->toBe(['border-radius' => 'var(--md-button-group-full)']);
|
||||
});
|
||||
|
||||
it('widens a pressed label button while its neighbours give way', function () {
|
||||
$css = ComponentStylesheet::read('button-group');
|
||||
|
||||
expect($css->declarations("[data-md-button-group='standard'] > :not([data-md-icon-button]):active:not(:disabled, [aria-disabled='true'])"))
|
||||
->toBe(['padding-inline' => 'calc(var(--md-button-group-pad) + var(--md-button-group-grow))'])
|
||||
->and($css->declarations("[data-md-button-group='standard'] > :not([data-md-icon-button]):active:not(:disabled, [aria-disabled='true']) + :not([data-md-icon-button])"))
|
||||
->toBe(['padding-inline-start' => 'calc(var(--md-button-group-pad) - var(--md-button-group-grow))'])
|
||||
->and($css->declarations("[data-md-button-group][data-md-size='lg']"))->toMatchArray(['--md-button-group-pad' => 'var(--md-sys-measurement-space600)', '--md-button-group-grow' => '16px']);
|
||||
});
|
||||
|
||||
it('takes over aria-pressed for a group that carries a selection', function () {
|
||||
$html = (string) $this->blade('<x-button-group connected selection="single" required label="View"><x-button label="Day" value="day" :selected="true" /></x-button-group>');
|
||||
|
||||
expect($html)
|
||||
->toContain('data-selection="single"')
|
||||
->toContain('data-selection-required')
|
||||
->toContain('data-md-selection="single"')
|
||||
->toContain('data-md-selection-required')
|
||||
->toContain('multiple: false')
|
||||
->toContain('required: true')
|
||||
->toContain('value: null')
|
||||
@@ -49,7 +80,7 @@ it('takes over aria-pressed for a group that carries a selection', function () {
|
||||
->toContain('required: false')
|
||||
->toContain('value: []')
|
||||
->and((string) $this->blade('<x-button-group connected><x-button label="Day" /></x-button-group>'))
|
||||
->not->toContain('data-selection')
|
||||
->not->toContain('data-md-selection')
|
||||
->not->toContain('press($event)');
|
||||
});
|
||||
|
||||
@@ -74,14 +105,14 @@ it('entangles a selection group with the property it binds, and keeps wire:model
|
||||
$html = Livewire::test($component)->assertSet('view', 'week')->html();
|
||||
|
||||
expect($html)
|
||||
->toContain('data-selection="single"')
|
||||
->toContain('data-md-selection="single"')
|
||||
->toMatch('/value: window\.Livewire\.find\(/')
|
||||
->and(substr_count($html, 'wire:model.live="view"'))->toBe(0);
|
||||
});
|
||||
|
||||
it('never wraps a group onto a second line', function () {
|
||||
expect((string) $this->blade('<x-button-group><x-button label="Day" /></x-button-group>'))
|
||||
->not->toContain('flex-wrap');
|
||||
expect(ComponentStylesheet::read('button-group')->declarations('[data-md-button-group]'))->toMatchArray(['display' => 'inline-flex'])
|
||||
->not->toHaveKey('flex-wrap');
|
||||
});
|
||||
|
||||
it('marks icon buttons, which keep their width when a group is pressed', function () {
|
||||
|
||||
Reference in New Issue
Block a user