fix(ui): show application links as a compact mobile badge

This commit is contained in:
Andras Bacsai
2026-08-15 14:04:09 +02:00
parent 2677e47138
commit 60f9fdd827
3 changed files with 42 additions and 27 deletions
@@ -1,4 +1,4 @@
@props(['application', 'fullWidth' => false])
@props(['application', 'fullWidth' => false, 'compact' => false])
@php
$hasLinks =
@@ -13,15 +13,22 @@
$linkItemClasses = 'listbox-option justify-start! gap-2.5!';
@endphp
<div @class(['relative', 'w-full' => $fullWidth]) x-data="{ open: false }"
<div @class([
'relative' => !$compact,
'static' => $compact,
'w-full' => $fullWidth,
]) x-data="{ open: false }"
x-effect="$dispatch('resource-actions-toggled', { open })" @keydown.escape.window="open = false">
<button type="button" @click="open = !open" @click.outside="open = false" title="Open application links"
@class([
'app-tab shrink-0 gap-1' => !$fullWidth,
'app-tab shrink-0 gap-1' => !$fullWidth && !$compact,
'button w-full justify-between' => $fullWidth,
'inline-flex h-6 shrink-0 items-center gap-1.5 rounded-full border border-neutral-200 bg-neutral-100 px-2 text-xs font-medium leading-none text-neutral-700 dark:border-white/[0.12] dark:bg-white/[0.07] dark:text-white' => $compact,
])>
<span class="inline-flex items-center gap-2">
<x-reicon name="external-link" class="size-3.5 shrink-0 opacity-70" />
@unless ($compact)
<x-reicon name="external-link" class="size-3.5 shrink-0 opacity-70" />
@endunless
Links
</span>
<span class="inline-flex transition-transform" :class="open && 'rotate-180'">
@@ -32,7 +39,8 @@
@class([
'listbox-panel top-full! mt-1!',
'left-0! right-0! w-full! min-w-0! max-w-none!' => $fullWidth,
'right-0! left-auto! min-w-60! max-w-96!' => !$fullWidth,
'left-1/2! right-auto! w-[calc(100vw-2rem)]! max-w-md! min-w-0! -translate-x-1/2' => $compact,
'right-0! left-auto! min-w-60! max-w-96!' => !$fullWidth && !$compact,
])>
@if ($hasLinks)
@if (data_get($application, 'gitBrancLocation'))
@@ -30,7 +30,10 @@
<h1 class="min-w-0 max-w-full truncate text-[24px]! leading-7! font-semibold! tracking-tight! text-black dark:text-fg">
{{ $application->name }}
</h1>
<x-status-summary :status="$application->status" />
<div class="relative flex w-full min-w-0 items-center gap-2">
<x-status-summary :status="$application->status" />
<x-applications.links :application="$application" compact />
</div>
</div>
</div>
@@ -147,9 +150,6 @@
</div>
</div>
@endif
<div class="resource-heading-menus w-full">
<x-applications.links :application="$application" full-width />
</div>
<div class="hidden" aria-hidden="true">
<x-modal-confirmation title="Confirm Application Stopping?" buttonTitle="Stop"
submitAction="stop" :checkboxes="$checkboxes" :actions="[
@@ -592,7 +592,7 @@ it('shows an icon in application and service Links controls', function () {
$serviceLinks = file_get_contents(resource_path('views/components/services/links.blade.php'));
$serviceLinksComponent = file_get_contents(app_path('View/Components/Services/Links.php'));
expect($applicationLinks)->toContain("@props(['application', 'fullWidth' => false])")
expect($applicationLinks)->toContain("@props(['application', 'fullWidth' => false, 'compact' => false])")
->toContain('<x-reicon name="external-link"')
->and($serviceLinksComponent)->toContain('public bool $fullWidth = false')
->and($serviceLinks)
@@ -610,25 +610,34 @@ it('visually distinguishes production and pull request application links', funct
->not->toContain("PR{{ data_get(\$preview, 'pull_request_id') }} |");
});
it('shows application and service Links on mobile headings', function () {
it('shows application Links as a compact badge beside the mobile status', function () {
$application = file_get_contents(resource_path('views/livewire/project/application/heading.blade.php'));
$service = file_get_contents(resource_path('views/livewire/project/service/heading.blade.php'));
$mobileApplicationSection = str($application)->between('class="w-full xl:hidden"', 'class="hidden w-full items-center xl:fixed')->toString();
$mobileServiceSection = str($service)->between('class="w-full md:hidden"', 'class="hidden w-full items-center md:flex')->toString();
expect($mobileApplicationSection)
->toContain('<x-applications.links')
->toContain('full-width')
->toContain('resource-heading-menus')
->not->toContain('<x-resource-heading-tabs')
->not->toContain("'label' => 'Settings'");
$applicationLinks = file_get_contents(resource_path('views/components/applications/links.blade.php'));
$mobileApplicationTitle = str($application)->between('class="mb-3 w-full xl:hidden"', '<div class="w-full xl:hidden">')->toString();
$mobileApplicationActions = str($application)->between('<div class="w-full xl:hidden">', '<div class="hidden" aria-hidden="true">')->toString();
expect($mobileApplicationTitle)
->toContain('<x-status-summary')
->toContain('<x-applications.links')
->toContain('relative flex w-full min-w-0 items-center gap-2')
->toContain('compact')
->not->toContain('full-width');
expect($mobileApplicationActions)
->not->toContain('<x-applications.links');
expect($applicationLinks)
->toContain("'button w-full justify-between' => \$fullWidth")
->toContain("'left-0! right-0! w-full! min-w-0! max-w-none!' => \$fullWidth")
->toContain("'compact' => false")
->toContain("'static' => \$compact")
->toContain("'inline-flex h-6 shrink-0 items-center gap-1.5 rounded-full border border-neutral-200 bg-neutral-100 px-2 text-xs font-medium leading-none text-neutral-700 dark:border-white/[0.12] dark:bg-white/[0.07] dark:text-white' => \$compact")
->toContain('@unless ($compact)')
->toContain("'left-1/2! right-auto! w-[calc(100vw-2rem)]! max-w-md! min-w-0! -translate-x-1/2' => \$compact")
->toContain('<x-reicon name="chevron-down"');
});
it('keeps service Links full width on mobile headings', function () {
$service = file_get_contents(resource_path('views/livewire/project/service/heading.blade.php'));
$mobileServiceSection = str($service)->between('class="w-full md:hidden"', 'class="hidden w-full items-center md:flex')->toString();
expect($mobileServiceSection)
->toContain('<x-services.links')
@@ -643,8 +652,6 @@ it('shows application and service Links on mobile headings', function () {
->toContain('<x-reicon name="chevron-down"')
->toContain('No links available');
// One mobile + one desktop instance.
expect(substr_count($application, '<x-applications.links'))->toBe(2);
expect(substr_count($service, '<x-services.links'))->toBe(2);
});