feat(ui): expose app theme contract and public components
This commit is contained in:
@@ -0,0 +1,172 @@
|
||||
component PageHeader {
|
||||
props {
|
||||
class: string = ""
|
||||
eyebrow = ""
|
||||
title = ""
|
||||
description = ""
|
||||
|
||||
primaryLabel = ""
|
||||
primaryHref = ""
|
||||
|
||||
secondaryLabel = ""
|
||||
secondaryHref = ""
|
||||
|
||||
icon = "sparkles"
|
||||
|
||||
centered = false
|
||||
compact = false
|
||||
|
||||
showBreadcrumbs = false
|
||||
breadcrumbParent = ""
|
||||
breadcrumbParentHref = ""
|
||||
breadcrumbCurrent = ""
|
||||
|
||||
highlights = []
|
||||
}
|
||||
|
||||
view {
|
||||
<section
|
||||
aria-labelledby="public-page-title"
|
||||
class="relative overflow-hidden border-b border-slate-200 bg-white dark:border-white/10 dark:bg-slate-950 {class}"
|
||||
>
|
||||
<!-- Background decoration -->
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="pointer-events-none absolute inset-0 overflow-hidden"
|
||||
>
|
||||
<div class="absolute -right-40 -top-48 h-96 w-96 rounded-full bg-indigo-300/20 blur-3xl dark:bg-indigo-500/10" ></div>
|
||||
|
||||
<div class="absolute -left-40 top-20 h-80 w-80 rounded-full bg-violet-300/15 blur-3xl dark:bg-violet-500/5" ></div>
|
||||
|
||||
<div class="absolute left-1/2 top-0 h-px w-2/3 -translate-x-1/2 bg-linear-to-r from-transparent via-indigo-300/60 to-transparent dark:via-indigo-500/20" ></div>
|
||||
</div>
|
||||
|
||||
<div class="relative w-full px-5 sm:px-8 lg:px-10 xl:px-12">
|
||||
|
||||
<!-- Breadcrumbs -->
|
||||
<div
|
||||
class="border-b border-slate-200/80 py-3 dark:border-white/10"
|
||||
class:hidden="!showBreadcrumbs"
|
||||
>
|
||||
<Breadcrumbs
|
||||
centered="{centered}"
|
||||
compact="{false}"
|
||||
items="{[ ...(breadcrumbParent !== '' ? [{ label: breadcrumbParent, href: breadcrumbParentHref, current: false }] : []), ...(breadcrumbCurrent !== '' ? [{ label: breadcrumbCurrent, href: '', current: true }] : []) ]}"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- Header body -->
|
||||
<div
|
||||
class=" {compact ? 'py-9 sm:py-10 lg:py-12' : 'py-12 sm:py-14 lg:py-16' } {centered ? 'mx-auto flex max-w-5xl flex-col items-center text-center' : 'grid gap-8 lg:grid-cols-[minmax(0,1fr)_auto] lg:items-start lg:gap-12' } "
|
||||
>
|
||||
<!-- Content -->
|
||||
<div class=" min-w-0 {centered ? 'w-full max-w-4xl' : 'max-w-4xl'} " >
|
||||
<!-- Eyebrow -->
|
||||
<div
|
||||
class="flex"
|
||||
class:hidden="eyebrow === ''"
|
||||
class:justify-center="centered"
|
||||
class:justify-start="!centered"
|
||||
>
|
||||
<span
|
||||
class="inline-flex items-center gap-2 rounded-full border border-indigo-200 bg-indigo-50 px-3 py-1.5 text-xs font-semibold text-indigo-700 shadow-sm dark:border-indigo-500/20 dark:bg-indigo-500/10 dark:text-indigo-300"
|
||||
>
|
||||
<span class="grid h-5 w-5 place-items-center rounded-full bg-indigo-100 dark:bg-indigo-500/15" >
|
||||
<span class="icon-[lucide--{icon}] h-3 w-3" aria-hidden="true" ></span>
|
||||
</span>
|
||||
|
||||
{eyebrow}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- Title -->
|
||||
<h1
|
||||
id="public-page-title"
|
||||
class=" font-bold tracking-tight text-slate-950 dark:text-white {eyebrow !== '' ? 'mt-6' : ''} {compact ? 'text-3xl leading-tight sm:text-4xl lg:text-5xl' : 'text-4xl leading-[1.08] sm:text-5xl lg:text-[3.25rem]' } "
|
||||
>
|
||||
{title}
|
||||
</h1>
|
||||
|
||||
<!-- Description -->
|
||||
<p
|
||||
class=" mt-5 text-base text-slate-600 dark:text-slate-400 {compact ? 'leading-7' : 'leading-8 sm:text-lg'} {centered ? 'mx-auto max-w-3xl' : 'max-w-2xl'} "
|
||||
class:hidden="description === ''"
|
||||
>
|
||||
{description}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Single dynamic action group -->
|
||||
<div
|
||||
class=" flex flex-col gap-3 sm:flex-row {centered ? 'mt-8 justify-center' : 'lg:pt-1' } "
|
||||
class:hidden="primaryLabel === '' && secondaryLabel === ''"
|
||||
>
|
||||
<!-- Secondary action -->
|
||||
<a
|
||||
href="{secondaryHref}"
|
||||
class="h-12 items-center justify-center rounded-xl border border-slate-200 bg-white px-5 text-sm font-semibold text-slate-700 shadow-sm transition hover:-translate-y-0.5 hover:border-indigo-300 hover:bg-slate-50 hover:text-indigo-700 focus:outline-none focus-visible:ring-2 focus-visible:ring-indigo-500 dark:border-white/10 dark:bg-white/5 dark:text-slate-200 dark:hover:border-indigo-500/30 dark:hover:bg-white/10 dark:hover:text-indigo-300"
|
||||
class:hidden="secondaryLabel === ''"
|
||||
class:inline-flex="secondaryLabel !== ''"
|
||||
>
|
||||
{secondaryLabel}
|
||||
</a>
|
||||
|
||||
<!-- Primary action -->
|
||||
<a
|
||||
href="{primaryHref}"
|
||||
class="group h-12 items-center justify-center gap-2 rounded-xl bg-indigo-600 px-5 text-sm font-bold text-white shadow-lg shadow-indigo-600/20 transition hover:-translate-y-0.5 hover:bg-indigo-500 hover:shadow-xl focus:outline-none focus-visible:ring-2 focus-visible:ring-indigo-500 focus-visible:ring-offset-2 dark:focus-visible:ring-offset-slate-950"
|
||||
class:hidden="primaryLabel === ''"
|
||||
class:inline-flex="primaryLabel !== ''"
|
||||
>
|
||||
{primaryLabel}
|
||||
|
||||
<span class="icon-[lucide--arrow-right] h-4 w-4 transition-transform group-hover:translate-x-1" aria-hidden="true" ></span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Dynamic highlight strip -->
|
||||
<div
|
||||
class="border-t border-slate-200 py-5 dark:border-white/10"
|
||||
class:hidden="compact || highlights.length === 0"
|
||||
class:block="!compact && highlights.length > 0"
|
||||
>
|
||||
<div class="flex gap-y-5">
|
||||
{#each highlights as highlight}
|
||||
<div
|
||||
class="w-full min-w-0 pr-6"
|
||||
class:w-full="highlights.length === 1"
|
||||
class:sm:w-1/2="highlights.length >= 2"
|
||||
class:lg:w-1/2="highlights.length === 2"
|
||||
class:lg:w-1/3="highlights.length === 3"
|
||||
class:lg:w-1/4="highlights.length >= 4"
|
||||
>
|
||||
<div
|
||||
class="flex min-w-0 items-center gap-3"
|
||||
class:justify-center="centered"
|
||||
>
|
||||
<span class="grid h-10 w-10 shrink-0 place-items-center rounded-xl {highlight.iconBoxClass}" >
|
||||
<span class="{highlight.iconClass} h-5 w-5" aria-hidden="true" ></span>
|
||||
</span>
|
||||
|
||||
<div class="min-w-0">
|
||||
<p class="text-sm font-semibold text-slate-950 dark:text-white">
|
||||
{highlight.title}
|
||||
</p>
|
||||
|
||||
<p
|
||||
class="mt-0.5 text-xs leading-5 text-slate-500 dark:text-slate-400"
|
||||
class:hidden="highlight.description === ''"
|
||||
>
|
||||
{highlight.description}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user