fix(ui): cap helper popup width and share destination status

Limit helper info popups to 320px with normal text wrapping so
content stacks vertically. Use the shared status-summary on the
application destination card instead of custom status badges.
This commit is contained in:
Andras Bacsai
2026-08-07 13:02:54 +02:00
parent 4539d1442e
commit 7c6d00c8de
4 changed files with 27 additions and 21 deletions
+4 -2
View File
@@ -73,8 +73,10 @@
const viewportBottom = viewportTop + viewportHeight;
const availableWidth = Math.max(0, viewportWidth - padding * 2);
const availableHeight = Math.max(0, viewportHeight - padding * 2);
const maxPopupWidth = 320;
const popupWidth = Math.min(maxPopupWidth, availableWidth);
this.style = `max-width: ${availableWidth}px; max-height: ${availableHeight}px; overflow-y: auto;`;
this.style = `max-width: ${popupWidth}px; max-height: ${availableHeight}px; overflow-y: auto;`;
const triggerRect = trigger.getBoundingClientRect();
const popupRect = popup.getBoundingClientRect();
@@ -120,7 +122,7 @@
x-transition:leave-start="opacity-100"
x-transition:leave-end="opacity-0"
:style="style"
class="info-helper-popup fixed z-[9999] w-max max-w-[min(20rem,calc(100vw-2rem))]"
class="info-helper-popup fixed z-[9999] w-max max-w-[min(20rem,calc(100vw-2rem))] whitespace-normal"
@mouseenter="cancelHide()" @mouseleave="hide()" @focusout="closeWhenFocusLeaves()" @click.stop>
<div class="px-3 py-2.5 text-[13px] leading-5">
{!! $helper !!}
@@ -1,14 +1,6 @@
<div>
@if ($resource->getMorphClass() === 'App\Models\Application')
@php
$primaryStatus = str($resource->realStatus());
$primaryStatusType = match (true) {
$primaryStatus->startsWith('running') => 'success',
$primaryStatus->startsWith('exited') => 'error',
$primaryStatus->startsWith(['starting', 'restarting']) => 'warning',
default => 'neutral',
};
$primaryStatusLabel = $primaryStatus->before(':')->headline()->value() ?: 'Unknown';
$additionalDestinations = $resource->additional_networks;
$hasAdditionalDestinations = $additionalDestinations->isNotEmpty();
@endphp
@@ -41,21 +33,13 @@
</div>
<div class="flex flex-wrap items-center gap-2 sm:justify-end">
@if ($primaryStatus->startsWith('running'))
<x-status.running :status="$primaryStatus->value()" />
@elseif ($primaryStatus->startsWith(['starting', 'restarting']))
<x-status.restarting :status="$primaryStatus->value()" />
@elseif ($primaryStatus->startsWith('exited'))
<x-status.stopped :status="$primaryStatus->value()" />
@else
<x-status-badge :status="$primaryStatusLabel" :type="$primaryStatusType" />
@endif
<x-status-summary :status="$resource->status" />
@if ($hasAdditionalDestinations)
<x-forms.button canGate="deploy" :canResource="$resource"
wire:click="redeploy('{{ data_get($resource, 'destination.id') }}','{{ data_get($resource, 'destination.server.id') }}')">
Deploy
</x-forms.button>
@if ($primaryStatus->startsWith('running'))
@if (str($resource->status)->startsWith('running'))
<x-forms.button isError canGate="deploy" :canResource="$resource"
wire:click="stop('{{ data_get($resource, 'destination.server.id') }}')">
Stop
@@ -0,0 +1,10 @@
<?php
it('uses the shared status summary in the primary application server card', function () {
$view = file_get_contents(resource_path('views/livewire/project/shared/destination.blade.php'));
$applicationSection = str($view)->before('@else')->value();
expect($applicationSection)
->toContain('<x-status-summary :status="$resource->status" />')
->not->toContain('<x-status :resource="$resource"');
});
+11 -1
View File
@@ -86,11 +86,21 @@ test('helper popup stays within the visual viewport on mobile', function () {
->toContain('window.visualViewport')
->toContain('viewport?.offsetLeft')
->toContain('viewport?.offsetTop')
->toContain('max-width: ${availableWidth}px;')
->toContain('max-width: ${popupWidth}px;')
->toContain('max-height: ${availableHeight}px;')
->toContain('overflow-y: auto;');
});
test('helper popup width is capped while allowing content to wrap vertically', function () {
$helper = file_get_contents(resource_path('views/components/helper.blade.php'));
expect($helper)
->toContain('const maxPopupWidth = 320;')
->toContain('const popupWidth = Math.min(maxPopupWidth, availableWidth);')
->toContain('max-width: ${popupWidth}px;')
->toContain('whitespace-normal');
});
test('helper popup supports focus dismissal and tooltip aria relationships', function () {
$helper = file_get_contents(resource_path('views/components/helper.blade.php'));