fix(ui): reserve scrollbar space and animate event multiselect

Always reserve vertical scrollbar space on base and v5 body
layouts to prevent content shift. Match notification event
multiselect panel open/close transitions to other listboxes.
This commit is contained in:
Andras Bacsai
2026-08-13 09:17:37 +02:00
parent 009b298520
commit 882e25e072
5 changed files with 38 additions and 3 deletions
@@ -34,7 +34,14 @@
</svg>
</button>
<div class="listbox-panel" x-show="open" x-cloak role="listbox" aria-multiselectable="true">
<div class="listbox-panel" x-show="open" x-cloak
x-transition:enter="transition ease-out duration-100"
x-transition:enter-start="opacity-0 -translate-y-1 scale-[0.98]"
x-transition:enter-end="opacity-100 translate-y-0 scale-100"
x-transition:leave="transition ease-in duration-75"
x-transition:leave-start="opacity-100 translate-y-0 scale-100"
x-transition:leave-end="opacity-0 -translate-y-1 scale-[0.98]"
role="listbox" aria-multiselectable="true">
@foreach ($events as $event)
<button wire:key="{{ $id }}-{{ $event['property'] }}" type="button" class="listbox-option"
role="option" aria-selected="{{ $event['enabled'] ? 'true' : 'false' }}"
+1 -1
View File
@@ -95,7 +95,7 @@
</head>
@section('body')
<body class="dark:text-inherit text-black">
<body class="overflow-y-scroll dark:text-inherit text-black">
<x-toast />
<x-icon-tooltip />
<script data-navigate-once>
+1 -1
View File
@@ -63,7 +63,7 @@
<x-inertia::head />
</head>
<body>
<body class="overflow-y-scroll">
<x-inertia::app id="v5-app" />
</body>
@@ -132,3 +132,21 @@ test('notification event multiselect truncates long selected summaries', functio
->toContain('title="Docker cleanup failure, Disk usage warning, Server unreachable, Server patching"')
->toContain('4/4');
});
test('notification event multiselect uses the same panel animation as listboxes', function () {
$html = Blade::render(<<<'BLADE'
<x-notification.event-multiselect id="deployment-email-events" label="Deployments" :events="[
['property' => 'deploymentSuccessEmailNotifications', 'label' => 'Deployment success', 'enabled' => false],
['property' => 'deploymentFailureEmailNotifications', 'label' => 'Deployment failure', 'enabled' => true],
['property' => 'statusChangeEmailNotifications', 'label' => 'Container status changes', 'enabled' => false],
]" />
BLADE);
expect($html)
->toContain('x-transition:enter="transition ease-out duration-100"')
->toContain('x-transition:enter-start="opacity-0 -translate-y-1 scale-[0.98]"')
->toContain('x-transition:enter-end="opacity-100 translate-y-0 scale-100"')
->toContain('x-transition:leave="transition ease-in duration-75"')
->toContain('x-transition:leave-start="opacity-100 translate-y-0 scale-100"')
->toContain('x-transition:leave-end="opacity-0 -translate-y-1 scale-[0.98]"');
});
+10
View File
@@ -0,0 +1,10 @@
<?php
test('app layouts always reserve space for the vertical scrollbar', function (string $layout) {
$contents = file_get_contents(dirname(__DIR__, 2).'/'.$layout);
expect($contents)->toMatch('/<body(?:\s+[^>]*)?class="[^"]*overflow-y-scroll[^"]*"[^>]*>/');
})->with([
'current interface' => 'resources/views/layouts/base.blade.php',
'v5 interface' => 'resources/views/v5/app.blade.php',
]);