feat(ui): section-heading component, dashboard spacing, sidebar-toggle icon

- Add reusable <x-section-heading> (title, muted subtitle, optional action)
  with a compact contained "View all" button; migrate dashboard Projects/
  Servers/Deployments and shared-variables environment headers to it.
- Dashboard: hide the empty active-deployments node so it no longer adds a
  gap above the first section; align section actions with the title row.
- Mobile: use the panel-left sidebar-toggle icon (matching desktop) as the
  drawer trigger instead of a hamburger.
This commit is contained in:
Aditya Tripathi 2026-09-07 02:55:58 +00:00 committed by Andras Bacsai
parent d91d2fa35d
commit 28fe3384ed
5 changed files with 44 additions and 48 deletions

View file

@ -0,0 +1,34 @@
@props([
'title',
'subtitle' => null,
'href' => null,
'actionLabel' => 'View all',
'icon' => 'arrow-right',
])
{{--
Shared section heading: a 14px title, an optional 11px muted subtitle, and an
optional right-aligned action. Pass `href` for the default ghost "View all"
button, or an `<x-slot:actions>` for a custom control.
--}}
<div {{ $attributes->merge(['class' => 'mb-3 min-w-0']) }}>
<div class="flex items-center justify-between gap-4">
<h2 class="min-w-0 truncate text-[14px]! leading-5! font-semibold! text-black dark:text-fg">
{{ $title }}
</h2>
@isset($actions)
<div class="shrink-0">{{ $actions }}</div>
@elseif (filled($href))
<a href="{{ $href }}" {{ wireNavigate() }}
class="group inline-flex h-7 shrink-0 items-center gap-1.5 rounded-md border border-neutral-200 bg-white px-2.5 text-[12px] font-medium text-neutral-600 transition-[color,background-color,transform] duration-100 ease-out hover:bg-neutral-100 hover:text-black active:scale-[0.97] dark:border-white/[0.08] dark:bg-white/[0.06] dark:text-fg-dim dark:hover:bg-white/[0.1] dark:hover:text-fg">
{{ $actionLabel }}
@if ($icon)
<x-reicon :name="$icon" class="size-3 opacity-70 transition-transform duration-150 ease-out group-hover:translate-x-0.5" />
@endif
</a>
@endisset
</div>
@if (filled($subtitle))
<p class="mt-0.5 text-[11px] text-neutral-500 dark:text-fg-faint">{{ $subtitle }}</p>
@endif
</div>

View file

@ -144,9 +144,9 @@ class="hidden shrink-0 items-center"></div>
<button type="button" x-on:click="open = !open"
class="-mr-1 flex size-9 items-center justify-center rounded-md text-neutral-500 transition-transform duration-100 ease-out hover:bg-neutral-100 hover:text-black active:scale-90 dark:text-fg-dim dark:hover:bg-white/[0.06] dark:hover:text-fg">
<span class="sr-only">Open sidebar</span>
<svg class="w-6 h-6" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
<svg class="size-5" viewBox="0 0 24 24" fill="none" aria-hidden="true">
<rect x="3" y="4" width="18" height="16" rx="2" stroke="currentColor" stroke-width="1.6" />
<path d="M9 4v16" stroke="currentColor" stroke-width="1.6" />
</svg>
</button>
</div>

View file

@ -17,21 +17,8 @@
<livewire:dashboard.active-deployments />
<section class="mb-0! min-w-0">
<div class="mb-3 flex items-end justify-between gap-4">
<div>
<h2 class="text-[14px]! leading-5! font-semibold! text-black dark:text-fg">
Projects
</h2>
<p class="mt-0.5 text-[11px] text-neutral-500 dark:text-fg-faint">
Your deployment workspaces
</p>
</div>
<a href="{{ route('project.index') }}" {{ wireNavigate() }}
class="inline-flex shrink-0 items-center gap-1 text-[12px] font-medium text-neutral-500 transition-colors hover:text-black dark:text-fg-dim dark:hover:text-fg">
View all
<x-reicon name="arrow-right" class="size-3" />
</a>
</div>
<x-section-heading title="Projects" subtitle="Your deployment workspaces"
:href="route('project.index')" />
@if ($dashboardProjects->isEmpty())
<x-empty title="No projects yet"
@ -125,21 +112,8 @@ class="flex size-6.5 items-center justify-center rounded-md text-neutral-400 tra
</section>
<section class="mb-0! min-w-0">
<div class="mb-3 flex items-end justify-between gap-4">
<div>
<h2 class="text-[14px]! leading-5! font-semibold! text-black dark:text-fg">
Servers
</h2>
<p class="mt-0.5 text-[11px] text-neutral-500 dark:text-fg-faint">
Infrastructure available for deployments
</p>
</div>
<a href="{{ route('server.index') }}" {{ wireNavigate() }}
class="inline-flex shrink-0 items-center gap-1 text-[12px] font-medium text-neutral-500 transition-colors hover:text-black dark:text-fg-dim dark:hover:text-fg">
View all
<x-reicon name="arrow-right" class="size-3" />
</a>
</div>
<x-section-heading title="Servers" subtitle="Infrastructure available for deployments"
:href="route('server.index')" />
@if ($dashboardServers->isEmpty())
@if ($privateKeys->isEmpty())

View file

@ -24,19 +24,10 @@
$hasAnyDeployments = $hasActiveDeployments || $hasRecentDeployments;
@endphp
<div wire:poll.3000ms="refreshDeployments" @class(['mb-0! min-w-0' => $hasAnyDeployments])>
<div wire:poll.3000ms="refreshDeployments" @class(['mb-0! min-w-0' => $hasAnyDeployments, 'hidden' => ! $hasAnyDeployments])>
@if ($hasAnyDeployments)
<section class="mb-0! min-w-0">
<div class="mb-3">
<div>
<h2 class="text-[14px]! leading-5! font-semibold! text-black dark:text-fg">
Deployments
</h2>
<p class="mt-0.5 text-[11px] text-neutral-500 dark:text-fg-faint">
Active and recent deployment activity
</p>
</div>
</div>
<x-section-heading title="Deployments" subtitle="Active and recent deployment activity" />
<div class="flex min-w-0 flex-col gap-4">
@if ($hasActiveDeployments)

View file

@ -22,10 +22,7 @@
$project->description,
...$project->environments->flatMap(fn ($environment) => [$environment->name, $environment->description])->all(),
]))">
<div class="mb-3">
<h2 class="text-[14px]! leading-5! font-semibold! text-black dark:text-fg">{{ $project->name }}</h2>
<p class="mt-0.5 text-[11px] text-neutral-500 dark:text-fg-faint">{{ $project->description ?: 'Project environments' }}</p>
</div>
<x-section-heading :title="$project->name" :subtitle="$project->description ?: 'Project environments'" />
@if ($project->environments->isEmpty())
<x-empty title="No environments in this project." size="sm" />
@else