General
Spectral Showcase code
Copy the implementation or inspect every file that belongs to this component unit.
resources/views/components/ui/spectral-showcase.blade.php
@props([
'defaultTheme' => 'flame',
])
@php
$themes = [
['value' => 'flame', 'label' => 'Flame', 'image' => '/images/spectral-showcase/flame.webp', 'width' => 1536, 'height' => 1024, 'position' => 'object-top'],
['value' => 'prism-light', 'label' => 'Prism Light', 'image' => '/images/spectral-showcase/prism-light.webp', 'width' => 1536, 'height' => 1024, 'position' => 'object-top'],
['value' => 'prism-dark', 'label' => 'Prism Dark', 'image' => '/images/spectral-showcase/prism-dark.webp', 'width' => 1536, 'height' => 1024, 'position' => 'object-top'],
['value' => 'ember', 'label' => 'Ember', 'image' => '/images/spectral-showcase/ember-hero.jpg', 'width' => 1999, 'height' => 1125, 'position' => 'object-center', 'closingImage' => '/images/spectral-showcase/ember-closing.jpg', 'closingWidth' => 1999, 'closingHeight' => 965],
];
@endphp
<section
x-data="spectralShowcase(@js($defaultTheme))"
:data-spectral-theme="theme"
{{ $attributes->class(['spectral-showcase relative isolate min-h-svh overflow-hidden']) }}
aria-label="Spectral component library showcase"
>
<div class="spectral-backdrop-layer pointer-events-none absolute inset-x-0 top-0 -z-20 overflow-hidden" aria-hidden="true">
@foreach ($themes as $themeOption)
<img
src="{{ $themeOption['image'] }}"
alt=""
width="{{ $themeOption['width'] }}"
height="{{ $themeOption['height'] }}"
class="spectral-backdrop absolute inset-0 h-full w-full object-cover {{ $themeOption['position'] }}"
x-show="theme === @js($themeOption['value'])"
@unless ($loop->first) x-cloak @endunless
x-transition:enter="transition-opacity duration-700 ease-out"
x-transition:enter-start="opacity-0"
x-transition:enter-end="opacity-100"
x-transition:leave="transition-opacity duration-500 ease-in"
x-transition:leave-start="opacity-100"
x-transition:leave-end="opacity-0"
>
@endforeach
</div>
<div class="spectral-vignette pointer-events-none absolute inset-0 -z-10" aria-hidden="true"></div>
<header class="spectral-header relative z-20 border-b">
<div class="mx-auto grid min-h-20 max-w-[96rem] grid-cols-[auto_1fr_auto] items-center gap-5 px-5 sm:px-8 lg:px-12">
<a href="{{ route('home') }}" class="spectral-ink text-lg font-extrabold tracking-[-0.04em] sm:text-xl">
HARBOUR
</a>
<nav class="hidden items-center justify-center gap-8 lg:flex" aria-label="Primary navigation">
<a href="{{ route('foundations.index') }}" class="spectral-nav-link">Foundations</a>
<a href="{{ route('components.index') }}" class="spectral-nav-link">Components</a>
<a href="{{ route('patterns.index') }}" class="spectral-nav-link">Patterns</a>
<a href="{{ route('examples.index') }}" class="spectral-nav-link">Examples</a>
</nav>
<div
class="spectral-theme-switcher flex items-center gap-1 rounded-full p-1"
role="group"
aria-label="Spectral theme"
@keydown.right.prevent="cycleTheme(1)"
@keydown.left.prevent="cycleTheme(-1)"
>
@foreach ($themes as $themeOption)
<button
type="button"
class="spectral-theme-button rounded-full px-3 py-2 text-xs font-semibold transition sm:px-3.5"
data-spectral-theme-button="{{ $themeOption['value'] }}"
:class="{ 'spectral-theme-button--active': theme === @js($themeOption['value']) }"
:aria-pressed="theme === @js($themeOption['value'])"
@click="setTheme(@js($themeOption['value']))"
>
<span class="hidden sm:inline">{{ $themeOption['label'] }}</span>
<span class="sm:hidden">{{ $loop->iteration }}</span>
</button>
@endforeach
</div>
</div>
<nav class="spectral-mobile-nav grid grid-cols-4 items-center border-t px-5 py-3 text-center text-xs sm:text-sm lg:hidden" aria-label="Mobile navigation">
<a href="{{ route('foundations.index') }}" class="spectral-nav-link">Foundations</a>
<a href="{{ route('components.index') }}" class="spectral-nav-link">Components</a>
<a href="{{ route('patterns.index') }}" class="spectral-nav-link">Patterns</a>
<a href="{{ route('examples.index') }}" class="spectral-nav-link">Examples</a>
</nav>
</header>
<main id="top" class="spectral-main relative z-10 mx-auto flex min-h-[calc(100svh-5rem)] max-w-[96rem] flex-col px-5 pb-16 pt-12 sm:px-8 sm:pb-20 sm:pt-16 lg:px-12 lg:pb-24 lg:pt-36">
<div class="spectral-hero grid flex-1 items-start gap-12 lg:grid-cols-[minmax(0,0.98fr)_minmax(38rem,1.02fr)] xl:gap-16">
<section class="spectral-copy max-w-4xl" aria-labelledby="spectral-title">
<p class="spectral-eyebrow text-xs font-bold uppercase tracking-[0.24em] sm:text-sm">Blade component library</p>
<h1 id="spectral-title" class="spectral-display-heading spectral-heading mt-7 text-[clamp(3.4rem,6vw,6rem)] font-medium leading-[0.94] tracking-[-0.06em]">
<span class="spectral-heading-flame block" x-show="theme === 'flame'">Components with<br class="hidden lg:block"> a point of view.</span>
<span class="spectral-heading-prism-light block" x-show="theme === 'prism-light'" x-cloak>Components<br class="hidden lg:block"> with a point of view.</span>
<span class="spectral-heading-dark block" x-show="theme === 'prism-dark'" x-cloak>Components<br class="hidden lg:block"> with a point<br class="hidden lg:block"> of view.</span>
<span class="spectral-heading-ember block" x-show="theme === 'ember'" x-cloak>Components<br class="hidden lg:block"> forged for<br class="hidden lg:block"> momentum.</span>
</h1>
<p class="spectral-muted mt-7 max-w-xl text-base leading-7 sm:text-lg sm:leading-8 lg:max-w-lg">
Production-ready Blade components for Laravel. Accessible, themeable, and built to move.
</p>
<div class="spectral-actions mt-8 flex flex-col gap-3 sm:flex-row sm:flex-wrap">
<a href="#collection" class="spectral-primary-action inline-flex min-h-12 items-center justify-center gap-3 px-6 py-3.5 text-sm font-semibold transition focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 sm:text-base">
Explore components
<x-ui.icon name="arrow-right" weight="bold" />
</a>
<a href="{{ route('patterns.index') }}" class="spectral-secondary-action inline-flex min-h-12 items-center justify-center gap-3 border px-6 py-3.5 text-sm font-semibold transition focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 sm:text-base">
View patterns
<x-ui.icon name="arrow-up-right" weight="bold" />
</a>
</div>
</section>
<aside class="spectral-panel overflow-hidden border lg:mt-56" aria-label="Interactive component example">
<div class="spectral-panel-tabs flex items-center gap-7 border-b px-5 sm:px-7" role="tablist" aria-label="Component example view">
<button
type="button"
class="spectral-panel-tab relative py-4 text-sm font-semibold"
:class="{ 'spectral-panel-tab--active': panel === 'preview' }"
:aria-selected="panel === 'preview'"
@click="panel = 'preview'"
role="tab"
>
Preview
</button>
<button
type="button"
class="spectral-panel-tab relative py-4 text-sm font-semibold"
:class="{ 'spectral-panel-tab--active': panel === 'code' }"
:aria-selected="panel === 'code'"
@click="panel = 'code'"
role="tab"
>
Code
</button>
</div>
<div x-show="panel === 'preview'" x-transition.opacity role="tabpanel" class="spectral-panel-body min-h-80 p-5 sm:p-7">
<div class="spectral-preview flex min-h-64 flex-col justify-between border p-6 sm:p-8">
<div>
<span class="spectral-kicker inline-flex items-center gap-2 rounded-full px-3 py-1.5 text-xs font-semibold">
<x-ui.icon name="sparkle" size="sm" />
New in Harbour
</span>
<h2 class="spectral-ink mt-7 max-w-md text-3xl font-medium leading-tight tracking-[-0.045em] sm:text-4xl">Build faster.<br>Ship beautiful interfaces.</h2>
<p class="spectral-muted mt-4 max-w-md text-sm leading-6">A collection of thoughtfully crafted Blade components that help you build consistent, accessible products.</p>
</div>
<div class="mt-8 flex flex-wrap gap-3">
<a href="{{ route('components.index') }}" class="spectral-mini-primary px-4 py-2.5 text-sm font-semibold">Get started</a>
<a href="{{ route('components.index') }}" class="spectral-mini-secondary border px-4 py-2.5 text-sm font-semibold">Browse components</a>
</div>
</div>
</div>
<div x-show="panel === 'code'" x-cloak x-transition.opacity role="tabpanel" class="spectral-panel-body min-h-80 overflow-x-auto p-5 sm:p-7">
<ol class="spectral-code min-w-[34rem] font-mono text-xs leading-7 sm:text-sm">
<li><span class="spectral-line-number">01</span><span><span class="spectral-code-tag"><x-button</span> <span class="spectral-code-key">variant</span>=<span class="spectral-code-string">"primary"</span> <span class="spectral-code-key">size</span>=<span class="spectral-code-string">"md"</span><span class="spectral-code-tag">></span></span></li>
<li><span class="spectral-line-number">02</span><span class="spectral-code-copy">Save changes</span></li>
<li><span class="spectral-line-number">03</span><span class="spectral-code-tag"></x-button></span></li>
<li><span class="spectral-line-number">04</span><span><span class="spectral-code-tag"><x-input</span> <span class="spectral-code-key">label</span>=<span class="spectral-code-string">"Email address"</span> <span class="spectral-code-key">type</span>=<span class="spectral-code-string">"email"</span> <span class="spectral-code-tag">/></span></span></li>
<li><span class="spectral-line-number">05</span><span><span class="spectral-code-tag"><x-checkbox</span> <span class="spectral-code-key">name</span>=<span class="spectral-code-string">"notifications"</span> <span class="spectral-code-key">checked</span> <span class="spectral-code-tag">/></span></span></li>
<li><span class="spectral-line-number">06</span><span><span class="spectral-code-tag"><x-alert</span> <span class="spectral-code-key">variant</span>=<span class="spectral-code-string">"success"</span> <span class="spectral-code-key">icon</span>=<span class="spectral-code-string">"check"</span> <span class="spectral-code-tag">/></span></span></li>
</ol>
</div>
</aside>
</div>
<div class="spectral-flame-footer mt-12 grid gap-8 border-t pt-8 lg:grid-cols-[0.56fr_1fr]" x-show="theme === 'flame'" aria-label="Featured atmosphere backgrounds">
<a href="{{ route('patterns.atmosphere-backgrounds') }}" class="spectral-featured group flex items-start justify-between gap-6 pr-6">
<span>
<span class="spectral-eyebrow block text-[0.65rem] font-bold uppercase tracking-[0.24em]">Featured pattern</span>
<span class="spectral-ink mt-5 block text-2xl font-medium tracking-[-0.035em] sm:text-3xl">Atmosphere backgrounds</span>
<span class="spectral-muted mt-5 block max-w-sm text-sm leading-6">Bring depth and energy to your layouts with expressive, production-ready texture.</span>
</span>
<x-ui.icon name="arrow-right" size="xl" class="spectral-ink mt-9 shrink-0 transition-transform group-hover:translate-x-1" />
</a>
<div class="grid grid-cols-3 overflow-hidden rounded-3xl border">
@foreach (['flame-coral.webp', 'flame-violet.webp', 'flame-cloud.webp'] as $flameAsset)
<img src="/images/spectral-showcase/{{ $flameAsset }}" alt="Flame atmosphere texture variation" width="420" height="240" class="aspect-[1.75] h-full w-full object-cover">
@endforeach
</div>
</div>
<div class="spectral-light-footer mt-14" x-show="theme === 'prism-light'" x-cloak aria-label="Featured pattern and component categories">
<a href="{{ route('patterns.atmosphere-backgrounds') }}" class="spectral-featured group flex max-w-lg items-end justify-between gap-6 py-6">
<span>
<span class="spectral-eyebrow block text-[0.65rem] font-bold uppercase tracking-[0.24em]">Featured pattern</span>
<span class="spectral-ink mt-3 block text-2xl font-medium tracking-[-0.035em]">Atmosphere backgrounds</span>
</span>
<x-ui.icon name="arrow-right" size="xl" class="spectral-ink shrink-0 transition-transform group-hover:translate-x-1" />
</a>
<div class="spectral-footer mt-10 grid grid-cols-2 gap-x-6 gap-y-4 border-t py-6 text-sm sm:grid-cols-4 lg:grid-cols-8">
@foreach (['Layout', 'Forms', 'Data display', 'Feedback', 'Navigation', 'Overlays', 'Media', 'Utilities'] as $category)
<a href="{{ route('components.index') }}" class="spectral-category-link">{{ $category }}</a>
@endforeach
</div>
</div>
<div class="spectral-dark-footer mt-16 grid border-t lg:grid-cols-[1.1fr_0.9fr]" x-show="theme === 'prism-dark'" x-cloak aria-label="Code sample and featured pattern">
<ol class="spectral-code min-w-0 overflow-x-auto py-5 pr-8 font-mono text-xs leading-6 sm:text-sm">
<li><span class="spectral-line-number">01</span><span><span class="spectral-code-tag"><x-button</span> <span class="spectral-code-key">variant</span>=<span class="spectral-code-string">"primary"</span> <span class="spectral-code-key">icon</span>=<span class="spectral-code-string">"arrow-right"</span><span class="spectral-code-tag">></span></span></li>
<li><span class="spectral-line-number">02</span><span class="spectral-code-copy">Explore components</span></li>
<li><span class="spectral-line-number">03</span><span class="spectral-code-tag"></x-button></span></li>
<li><span class="spectral-line-number">04</span><span> </span></li>
<li><span class="spectral-line-number">05</span><span><span class="spectral-code-tag"><x-input-label</span> <span class="spectral-code-key">for</span>=<span class="spectral-code-string">"email"</span><span class="spectral-code-tag">></span>Email address<span class="spectral-code-tag"></x-input-label></span></span></li>
<li><span class="spectral-line-number">06</span><span><span class="spectral-code-tag"><x-text-input</span> <span class="spectral-code-key">id</span>=<span class="spectral-code-string">"email"</span> <span class="spectral-code-key">type</span>=<span class="spectral-code-string">"email"</span> <span class="spectral-code-tag">/></span></span></li>
</ol>
<a href="{{ route('patterns.atmosphere-backgrounds') }}" class="spectral-featured group flex items-center justify-between gap-6 border-t py-7 lg:border-l lg:border-t-0 lg:pl-12">
<span>
<span class="spectral-eyebrow block text-xs font-bold uppercase tracking-[0.24em]">Featured pattern</span>
<span class="spectral-ink mt-3 block text-4xl font-medium leading-none tracking-[-0.05em] sm:text-[3.5rem]">Atmosphere<br>backgrounds</span>
</span>
<x-ui.icon name="arrow-right" size="2xl" class="spectral-ink shrink-0 transition-transform group-hover:translate-x-1" />
</a>
</div>
<div class="spectral-ember-footer mt-16 grid gap-3 sm:grid-cols-3 sm:gap-4" x-show="theme === 'ember'" x-cloak aria-label="Ember library principles">
@foreach ([
['Blade', 'Native composition'],
['Four', 'Art directions'],
['AA', 'Contrast focused'],
] as [$value, $label])
<div class="spectral-ember-stat relative overflow-hidden px-5 py-6 sm:px-7 sm:py-8">
<strong class="spectral-ink relative z-10 block text-3xl font-medium tracking-[-0.05em] sm:text-4xl">{{ $value }}</strong>
<span class="spectral-muted relative z-10 mt-2 block text-xs font-bold uppercase tracking-[0.18em]">{{ $label }}</span>
</div>
@endforeach
</div>
</main>
<div class="spectral-page-content relative z-10">
<section id="collection" class="spectral-section mx-auto max-w-[96rem] scroll-mt-24 px-5 py-24 sm:px-8 sm:py-32 lg:px-12 lg:py-40" aria-labelledby="spectral-collection-title">
<div class="grid items-end gap-10 lg:grid-cols-[1.2fr_0.8fr]">
<div>
<p class="spectral-eyebrow text-xs font-bold uppercase tracking-[0.24em]">The collection</p>
<h2 id="spectral-collection-title" class="spectral-display-heading spectral-section-heading spectral-ink mt-6 max-w-4xl text-[clamp(2.8rem,6vw,6.5rem)] font-medium leading-[0.94] tracking-[-0.06em]">
Built for the moments that make a product.
</h2>
</div>
<p class="spectral-muted max-w-xl text-base leading-7 sm:text-lg sm:leading-8 lg:justify-self-end">
Start with the pieces users touch every day. Every component carries the same accessibility, responsive behaviour, and exacting finish.
</p>
</div>
<div class="spectral-filter-bar mt-14 flex flex-wrap gap-2 border-y py-4" role="group" aria-label="Filter component collection">
@foreach ([
['value' => 'all', 'label' => 'All'],
['value' => 'navigation', 'label' => 'Navigation'],
['value' => 'inputs', 'label' => 'Inputs'],
['value' => 'feedback', 'label' => 'Feedback'],
['value' => 'data', 'label' => 'Data'],
] as $filter)
<button
type="button"
class="spectral-filter-button px-4 py-2 text-sm font-semibold transition"
:class="{ 'spectral-filter-button--active': collectionFilter === @js($filter['value']) }"
:aria-pressed="collectionFilter === @js($filter['value'])"
@click="collectionFilter = @js($filter['value'])"
>
{{ $filter['label'] }}
</button>
@endforeach
</div>
<div class="mt-8 grid gap-px sm:grid-cols-2 xl:grid-cols-3" aria-live="polite">
<x-ui.spectral-component-card
id="spectral-card-command-palette"
title="Command palette"
category="Navigation"
icon="command"
description="Fast, keyboard-first navigation that scales with the complexity of your product."
x-show="collectionFilter === 'all' || collectionFilter === 'navigation'"
x-transition.opacity
>
<x-slot:preview>
<div class="spectral-demo-window w-full max-w-sm border p-3 shadow-xl">
<div class="spectral-demo-field flex items-center gap-3 border px-3 py-2.5">
<x-ui.icon name="magnifying-glass" class="spectral-muted" />
<span class="spectral-muted text-sm">Jump to…</span>
<span class="spectral-key ml-auto border px-1.5 py-0.5 font-mono text-[0.65rem]">⌘ K</span>
</div>
<div class="mt-2 grid gap-1">
@foreach ([['house', 'Overview'], ['stack', 'Components'], ['sparkle', 'Patterns']] as [$icon, $label])
<div @class(['spectral-demo-row flex items-center gap-3 px-3 py-2 text-sm', 'spectral-demo-row--active' => $loop->first])>
<x-ui.icon :name="$icon" size="sm" />
<span>{{ $label }}</span>
@if ($loop->first)
<x-ui.icon name="arrow-right" size="sm" class="ml-auto" />
@endif
</div>
@endforeach
</div>
</div>
</x-slot:preview>
</x-ui.spectral-component-card>
<x-ui.spectral-component-card
id="spectral-card-form"
title="Form controls"
category="Inputs"
icon="text-t"
description="Clear, forgiving controls with labels, hints, validation, and focus states built in."
x-show="collectionFilter === 'all' || collectionFilter === 'inputs'"
x-transition.opacity
>
<x-slot:preview>
<div class="w-full max-w-sm space-y-4">
<label class="block">
<span class="spectral-ink text-xs font-semibold">Project name</span>
<span class="spectral-demo-field spectral-muted mt-2 block border px-3 py-3 text-sm">Harbour dashboard</span>
</label>
<label class="block">
<span class="spectral-ink text-xs font-semibold">Environment</span>
<span class="spectral-demo-field mt-2 flex items-center justify-between border px-3 py-3 text-sm">
Production
<x-ui.icon name="caret-down" size="sm" />
</span>
</label>
<button type="button" class="spectral-mini-primary w-full px-4 py-3 text-sm font-semibold">Create project</button>
</div>
</x-slot:preview>
</x-ui.spectral-component-card>
<x-ui.spectral-component-card
id="spectral-card-notifications"
title="Notification centre"
category="Feedback"
icon="bell"
description="A composed home for updates, progress, success, and the occasional useful interruption."
x-show="collectionFilter === 'all' || collectionFilter === 'feedback'"
x-transition.opacity
>
<x-slot:preview>
<div class="w-full max-w-sm space-y-2">
@foreach ([
['check-circle', 'Deployment complete', '2m ago'],
['user-plus', 'Maya joined the project', '18m ago'],
['chat-circle-text', 'New review comment', '1h ago'],
] as [$icon, $label, $time])
<div class="spectral-demo-row flex items-center gap-3 border px-3 py-3">
<span class="spectral-demo-icon grid size-9 shrink-0 place-items-center rounded-full"><x-ui.icon :name="$icon" size="sm" /></span>
<span class="min-w-0">
<span class="spectral-ink block truncate text-sm font-semibold">{{ $label }}</span>
<span class="spectral-muted block text-xs">{{ $time }}</span>
</span>
</div>
@endforeach
</div>
</x-slot:preview>
</x-ui.spectral-component-card>
<x-ui.spectral-component-card
id="spectral-card-table"
title="Data table"
category="Data"
icon="table"
description="Dense information made calm with precise alignment, useful states, and responsive detail."
x-show="collectionFilter === 'all' || collectionFilter === 'data'"
x-transition.opacity
>
<x-slot:preview>
<div class="spectral-demo-window w-full max-w-md overflow-hidden border">
<div class="spectral-demo-row grid grid-cols-[1fr_auto] border-b px-3 py-2 text-[0.65rem] font-bold uppercase tracking-[0.16em]">
<span>Component</span><span>Status</span>
</div>
@foreach ([['Button', 'Stable'], ['Dialog', 'Stable'], ['Date picker', 'Beta'], ['Data grid', 'New']] as [$name, $status])
<div class="spectral-demo-row grid grid-cols-[1fr_auto] items-center border-b px-3 py-3 text-sm last:border-b-0">
<span class="spectral-ink font-medium">{{ $name }}</span>
<span class="spectral-status px-2 py-1 text-xs">{{ $status }}</span>
</div>
@endforeach
</div>
</x-slot:preview>
</x-ui.spectral-component-card>
<x-ui.spectral-component-card
id="spectral-card-toggle"
title="Preference controls"
category="Inputs"
icon="sliders-horizontal"
description="Settings that remain readable at a glance and feel obvious the first time around."
x-show="collectionFilter === 'all' || collectionFilter === 'inputs'"
x-transition.opacity
>
<x-slot:preview>
<div class="spectral-demo-window w-full max-w-sm border p-4">
<div class="flex items-center justify-between gap-5 border-b pb-4">
<span><span class="spectral-ink block text-sm font-semibold">Weekly digest</span><span class="spectral-muted mt-1 block text-xs">Product updates every Friday</span></span>
<span class="spectral-toggle spectral-toggle--active flex h-6 w-11 items-center justify-end rounded-full p-1"><span class="size-4 rounded-full"></span></span>
</div>
<div class="flex items-center justify-between gap-5 pt-4">
<span><span class="spectral-ink block text-sm font-semibold">Usage alerts</span><span class="spectral-muted mt-1 block text-xs">Notify at 80% of quota</span></span>
<span class="spectral-toggle flex h-6 w-11 items-center rounded-full p-1"><span class="size-4 rounded-full"></span></span>
</div>
</div>
</x-slot:preview>
</x-ui.spectral-component-card>
<x-ui.spectral-component-card
id="spectral-card-empty-state"
title="Empty states"
category="Feedback"
icon="sparkle"
description="Useful next steps for the quiet moments, without burying people in explanation."
x-show="collectionFilter === 'all' || collectionFilter === 'feedback'"
x-transition.opacity
>
<x-slot:preview>
<div class="max-w-xs text-center">
<span class="spectral-demo-icon mx-auto grid size-12 place-items-center rounded-full"><x-ui.icon name="folder-open" size="lg" /></span>
<p class="spectral-ink mt-5 text-base font-semibold">No saved views yet</p>
<p class="spectral-muted mt-2 text-sm leading-6">Save your current filters to return to this view in one click.</p>
<button type="button" class="spectral-mini-primary mt-5 px-4 py-2.5 text-sm font-semibold">Save this view</button>
</div>
</x-slot:preview>
</x-ui.spectral-component-card>
</div>
<div class="mt-10 flex justify-end">
<a href="{{ route('components.index') }}" class="spectral-text-link group inline-flex items-center gap-3 border-b pb-2 text-sm font-semibold">
Browse the full collection
<x-ui.icon name="arrow-right" class="transition-transform group-hover:translate-x-1" />
</a>
</div>
</section>
<section id="principles" class="spectral-section spectral-principles border-y" aria-labelledby="spectral-principles-title">
<div class="mx-auto grid max-w-[96rem] lg:grid-cols-2">
<div class="border-b px-5 py-24 sm:px-8 sm:py-32 lg:border-b-0 lg:border-r lg:px-12 lg:py-40">
<p class="spectral-eyebrow text-xs font-bold uppercase tracking-[0.24em]">A better baseline</p>
<h2 id="spectral-principles-title" class="spectral-display-heading spectral-section-heading spectral-ink mt-6 max-w-2xl text-[clamp(2.8rem,5.3vw,5.8rem)] font-medium leading-[0.94] tracking-[-0.06em]">The details are already decided.</h2>
<p class="spectral-muted mt-8 max-w-xl text-base leading-7 sm:text-lg sm:leading-8">Harbour gives teams an opinionated starting point, then gets out of the way. Spend time on the product—not re-solving focus rings.</p>
</div>
<div class="grid">
@foreach ([
['Accessible by default', 'Keyboard paths, clear focus, useful labels, and reduced-motion support are part of the component—not an afterthought.'],
['Theme without rewrites', 'Swap the atmosphere while your component structure, states, and semantics stay exactly where they belong.'],
['Made for Laravel', 'Blade-first composition, predictable props, named slots, and conventions that feel at home in the framework.'],
] as [$heading, $copy])
<article class="spectral-principle-row border-b px-5 py-9 last:border-b-0 sm:px-8 lg:px-12 lg:py-11">
<h3 class="spectral-ink text-2xl font-medium tracking-[-0.04em]">{{ $heading }}</h3>
<p class="spectral-muted mt-3 max-w-lg text-sm leading-6 sm:text-base sm:leading-7">{{ $copy }}</p>
</article>
@endforeach
</div>
</div>
</section>
<section id="workflow" class="spectral-section mx-auto max-w-[96rem] scroll-mt-24 px-5 py-24 sm:px-8 sm:py-32 lg:px-12 lg:py-40" aria-labelledby="spectral-workflow-title">
<div class="grid gap-12 lg:grid-cols-[0.72fr_1.28fr] lg:gap-20">
<div>
<p class="spectral-eyebrow text-xs font-bold uppercase tracking-[0.24em]">From install to interface</p>
<h2 id="spectral-workflow-title" class="spectral-display-heading spectral-section-heading spectral-ink mt-6 text-[clamp(2.8rem,5vw,5.4rem)] font-medium leading-[0.94] tracking-[-0.06em]">Three steps. One point of view.</h2>
<p class="spectral-muted mt-7 max-w-lg text-base leading-7">Move from a blank Laravel view to a composed product surface without giving up the control that makes it yours.</p>
<div class="mt-10 grid gap-px border" role="tablist" aria-label="Harbour workflow">
@foreach ([['install', 'Install'], ['compose', 'Compose'], ['ship', 'Ship']] as [$value, $label])
<button
type="button"
role="tab"
class="spectral-workflow-tab flex items-center gap-5 px-5 py-4 text-left transition"
:class="{ 'spectral-workflow-tab--active': workflowStep === @js($value) }"
:aria-selected="workflowStep === @js($value)"
@click="workflowStep = @js($value)"
>
<span class="font-semibold">{{ $label }}</span>
<x-ui.icon name="arrow-right" class="ml-auto" />
</button>
@endforeach
</div>
</div>
<div class="spectral-workflow-stage min-w-0 border p-4 sm:p-7 lg:p-10" aria-live="polite">
<div x-show="workflowStep === 'install'" role="tabpanel" class="flex min-h-[30rem] flex-col justify-between">
<div>
<h3 class="spectral-ink text-3xl font-medium tracking-[-0.045em] sm:text-4xl">Add Harbour to the project you already have.</h3>
<p class="spectral-muted mt-4 max-w-xl text-sm leading-6 sm:text-base sm:leading-7">No starter rewrite. No foreign runtime. Install the package and keep your Laravel application recognisably yours.</p>
</div>
<div class="spectral-install-command mt-12 flex flex-col gap-4 border p-4 sm:flex-row sm:items-center">
<code class="spectral-ink min-w-0 flex-1 overflow-x-auto font-mono text-sm">composer require harbour/ui</code>
<button type="button" class="spectral-copy-button inline-flex items-center justify-center gap-2 border px-4 py-2.5 text-sm font-semibold" @click="copyInstallCommand()">
<x-ui.icon name="copy" />
<span x-text="copiedSnippet ? 'Copied' : 'Copy command'">Copy command</span>
</button>
</div>
</div>
<div x-show="workflowStep === 'compose'" x-cloak role="tabpanel" class="flex min-h-[30rem] flex-col">
<h3 class="spectral-ink text-3xl font-medium tracking-[-0.045em] sm:text-4xl">Readable Blade. Thoughtful defaults.</h3>
<ol class="spectral-code mt-10 min-w-[34rem] overflow-x-auto font-mono text-xs leading-8 sm:text-sm">
<li><span class="spectral-line-number">01</span><span><span class="spectral-code-tag"><x-ui.card</span> <span class="spectral-code-key">title</span>=<span class="spectral-code-string">"Project health"</span><span class="spectral-code-tag">></span></span></li>
<li><span class="spectral-line-number">02</span><span> <span class="spectral-code-tag"><x-ui.metric</span> <span class="spectral-code-key">label</span>=<span class="spectral-code-string">"Deployments"</span> <span class="spectral-code-key">value</span>=<span class="spectral-code-string">"42"</span> <span class="spectral-code-tag">/></span></span></li>
<li><span class="spectral-line-number">03</span><span> <span class="spectral-code-tag"><x-ui.progress</span> <span class="spectral-code-key">:value</span>=<span class="spectral-code-string">"86"</span> <span class="spectral-code-tag">/></span></span></li>
<li><span class="spectral-line-number">04</span><span><span class="spectral-code-tag"></x-ui.card></span></span></li>
</ol>
</div>
<div x-show="workflowStep === 'ship'" x-cloak role="tabpanel" class="flex min-h-[30rem] flex-col">
<h3 class="spectral-ink text-3xl font-medium tracking-[-0.045em] sm:text-4xl">A product surface, ready to meet people.</h3>
<div class="spectral-ship-preview mt-10 grid flex-1 gap-px border sm:grid-cols-[0.7fr_1.3fr]">
<div class="border-b p-5 sm:border-b-0 sm:border-r">
<span class="spectral-muted text-xs font-bold uppercase tracking-[0.18em]">Project health</span>
<strong class="spectral-ink mt-5 block text-5xl font-medium tracking-[-0.06em]">86%</strong>
<span class="spectral-status mt-4 inline-flex px-2 py-1 text-xs">All systems normal</span>
</div>
<div class="p-5">
<div class="flex items-center justify-between gap-4"><span class="spectral-ink text-sm font-semibold">Deployments</span><span class="spectral-muted text-sm">42 this month</span></div>
<div class="spectral-progress mt-4 h-2 overflow-hidden"><span class="block h-full w-[86%]"></span></div>
<div class="mt-8 grid grid-cols-3 gap-px border">
@foreach ([['12m', 'Build'], ['99.9%', 'Uptime'], ['0', 'Errors']] as [$value, $label])
<span class="p-3 text-center"><strong class="spectral-ink block text-lg">{{ $value }}</strong><span class="spectral-muted mt-1 block text-[0.65rem] uppercase tracking-[0.14em]">{{ $label }}</span></span>
@endforeach
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<section id="get-started" class="spectral-closing relative isolate overflow-hidden border-y" aria-labelledby="spectral-closing-title">
<div class="pointer-events-none absolute inset-0 -z-20" aria-hidden="true">
@foreach ($themes as $themeOption)
<img
src="{{ $themeOption['closingImage'] ?? $themeOption['image'] }}"
alt=""
width="{{ $themeOption['closingWidth'] ?? $themeOption['width'] }}"
height="{{ $themeOption['closingHeight'] ?? $themeOption['height'] }}"
class="absolute inset-0 h-full w-full object-cover {{ $themeOption['position'] }}"
x-show="theme === @js($themeOption['value'])"
@unless ($loop->first) x-cloak @endunless
x-transition.opacity.duration.500ms
>
@endforeach
</div>
<div class="spectral-closing-scrim pointer-events-none absolute inset-0 -z-10" aria-hidden="true"></div>
<div class="mx-auto max-w-[96rem] px-5 py-28 sm:px-8 sm:py-36 lg:px-12 lg:py-44">
<p class="spectral-eyebrow text-xs font-bold uppercase tracking-[0.24em]">Ready when you are</p>
<h2 id="spectral-closing-title" class="spectral-display-heading spectral-ink mt-6 max-w-5xl text-[clamp(3.2rem,7vw,7.5rem)] font-medium leading-[0.9] tracking-[-0.065em]">Choose a point of view. Keep the system.</h2>
<div class="mt-10 flex flex-col gap-3 sm:flex-row">
<a href="{{ route('components.index') }}" class="spectral-primary-action inline-flex min-h-12 items-center justify-center gap-3 px-6 py-3.5 text-sm font-semibold transition sm:text-base">Explore components <x-ui.icon name="arrow-right" weight="bold" /></a>
<a href="{{ route('patterns.index') }}" class="spectral-secondary-action inline-flex min-h-12 items-center justify-center gap-3 border px-6 py-3.5 text-sm font-semibold transition sm:text-base">View patterns <x-ui.icon name="arrow-up-right" weight="bold" /></a>
</div>
</div>
</section>
<footer class="spectral-site-footer mx-auto grid max-w-[96rem] gap-10 px-5 py-12 sm:px-8 lg:grid-cols-[1fr_auto] lg:px-12" aria-label="Spectral showcase footer">
<div>
<a href="#top" class="spectral-ink text-lg font-extrabold tracking-[-0.04em]">HARBOUR</a>
<p class="spectral-muted mt-3 max-w-md text-sm leading-6">A production-ready Blade component library for Laravel teams with a point of view.</p>
</div>
<nav class="grid grid-cols-2 gap-x-10 gap-y-3 text-sm sm:grid-cols-4" aria-label="Footer navigation">
<a href="{{ route('foundations.index') }}" class="spectral-nav-link">Foundations</a>
<a href="{{ route('components.index') }}" class="spectral-nav-link">Components</a>
<a href="{{ route('patterns.index') }}" class="spectral-nav-link">Patterns</a>
<a href="{{ route('examples.index') }}" class="spectral-nav-link">Examples</a>
</nav>
</footer>
</div>
<p class="sr-only" aria-live="polite" x-text="`Theme changed to ${themeLabel}`"></p>
</section>