fix(ui): improve tooltip a11y and settings select layout

Make button and helper tooltips keyboard-focusable with ARIA roles,
close helper popups on outside pointer/focus leave, reserve select
chevron padding, rotate DNS chevron when open, and re-key the service
domain list after row changes.
This commit is contained in:
Andras Bacsai committed 2026-08-06 08:21:02 +02:00
1 parent 4f966e3759
commit 232b999cc9
8 files changed
+138 -26

No files matched your search

+33
View File
@@ -44,6 +44,39 @@ test('helper popup remains open while moving from the trigger into interactive c
->toContain('@mouseleave="hide()"');
});
test('helper popup supports focus dismissal and tooltip aria relationships', function () {
$helper = file_get_contents(resource_path('views/components/helper.blade.php'));
expect($helper)
->toContain('closeWhenFocusLeaves()')
->toContain('@focus="show(false)"')
->toContain('@blur="closeWhenFocusLeaves()"')
->toContain('role="tooltip"')
->toContain(':aria-describedby="open ? $id(\'helper-popup\') : null"')
->toContain(':id="$id(\'helper-popup\')"');
});
test('teleported helper popup closes from taps outside on mobile', function () {
$helper = file_get_contents(resource_path('views/components/helper.blade.php'));
expect($helper)
->toContain('@pointerdown.window="closeWhenPointerIsOutside($event)"')
->toContain('closeWhenPointerIsOutside(event)')
->toContain('this.$refs.popup?.contains(event.target)');
});
test('button tooltips are available to keyboard and assistive technology users', function () {
$button = file_get_contents(resource_path('views/components/forms/button.blade.php'));
expect($button)
->toContain('@focusin="showTooltip()"')
->toContain('@focusout="hideTooltip()"')
->toContain('@click.outside="hideTooltip()"')
->toContain('role="tooltip"')
->toContain(':aria-describedby="visible ? $id(\'button-tooltip\') : null"')
->toContain(':id="$id(\'button-tooltip\')"');
});
test('listbox keeps the helper outside the label association', function () {
$path = resource_path('views/components/forms/listbox.blade.php');
$contents = file_get_contents($path);
+9
View File
@@ -0,0 +1,9 @@
<?php
test('native select values stay clear of the dropdown icon on mobile', function () {
$styles = file_get_contents(resource_path('css/app.css'));
expect($styles)
->toMatch('/\.application-settings-workspace \.select,\s*\.application-settings-form \.select \{\s*padding-right: 2\.5rem;/')
->toMatch('/@media \(max-width: 767px\) \{\s*\.application-settings-workspace \.select,\s*\.application-settings-form \.select \{\s*font-size: 0\.75rem !important;/');
});
+17 -1
View File
@@ -105,6 +105,14 @@ it('shows dns entries control next to Add', function () {
->assertSee('Manual records');
});
it('rotates the dns entries chevron while its dropdown is open', function () {
$view = file_get_contents(resource_path('views/livewire/project/shared/cloudflare-autoconfigure.blade.php'));
expect($view)
->toContain('class="inline-flex transition-transform"')
->toContain(':class="dnsEntriesOpen && \'rotate-180\'"');
});
it('lists dns entries for service hosts that still need dns', function () {
$this->webApp->update([
'fqdn' => 'https://web.example.com',
@@ -199,7 +207,9 @@ it('adds a domain to a selected service application', function () {
->set('newDomain', 'https://web.example.com')
->call('addDomain')
->assertHasNoErrors()
->assertDispatched('success');
->assertDispatched('success')
->assertSet('domainRows', fn (array $rows): bool => collect($rows)->pluck('url')->contains('https://web.example.com'))
->assertSee('https://web.example.com');
$this->webApp->refresh();
expect(explode(',', (string) $this->webApp->fqdn))
@@ -216,6 +226,12 @@ it('adds a domain to a selected service application', function () {
->not->toBeNull();
});
it('replaces the rendered domain list when its rows change', function () {
$view = file_get_contents(resource_path('views/livewire/project/service/domains.blade.php'));
expect($view)->toContain('wire:key="service-domains-list-{{ md5(serialize($domainRows)) }}"');
});
it('does not duplicate the service name as a badge in the domain cell', function () {
$view = file_get_contents(resource_path('views/livewire/project/service/partials/domain-table.blade.php'));