blade(""); preg_match('/]*>/', $html, $tag); expect($html) ->toMatch("/and($tag[0])->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, with M3\'s inner corners', function () { $css = ComponentStylesheet::read('button-group'); expect((string) $this->blade(''))->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('')) ->toContain('data-md-shape="square"') ->and((string) $this->blade('')) ->toContain('data-md-button-group="connected"') ->toContain('data-md-shape="square"') ->and((string) $this->blade('')) ->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(''); expect($html) ->toContain('data-md-selection="single"') ->toContain('data-md-selection-required') ->toContain('multiple: false') ->toContain('required: true') ->toContain('value: null') ->toContain('x-on:click="press($event)"') // No model: the group takes the state from the buttons' own aria-pressed and goes on. ->toContain('x-modelable="value"') ->and((string) $this->blade('')) ->toContain('multiple: true') ->toContain('required: false') ->toContain('value: []') ->and((string) $this->blade('')) ->not->toContain('data-md-selection') ->not->toContain('press($event)'); }); it('entangles a selection group with the property it binds, and keeps wire:model off the div', function () { $component = new class extends Component { public string $view = 'week'; public function render(): string { return <<<'BLADE'
BLADE; } }; $html = Livewire::test($component)->assertSet('view', 'week')->html(); expect($html) ->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(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 () { expect((string) $this->blade(''))->toContain('data-md-icon-button') ->and((string) $this->blade(''))->not->toContain('data-md-icon-button'); });