PageHeader
Reusable page header component.
Usage
Components are auto-discovered. Use the component directly in any .wrn view:
<PageHeader
eyebrow="eyebrow"
title="title"
description="description"
primaryLabel="primaryLabel"
primaryHref="primaryHref"
/>Legacy mount name: data-component="PageHeader".
Props and attributes
| Prop | Type | Requirement | Default |
|---|---|---|---|
class | string | Optional | "" |
eyebrow | string | Optional | "" |
title | string | Optional | "" |
description | string | Optional | "" |
primaryLabel | string | Optional | "" |
primaryHref | string | Optional | "" |
secondaryLabel | string | Optional | "" |
secondaryHref | string | Optional | "" |
icon | string | Optional | "sparkles" |
centered | boolean | Optional | false |
compact | boolean | Optional | false |
showBreadcrumbs | boolean | Optional | false |
breadcrumbParent | string | Optional | "" |
breadcrumbParentHref | string | Optional | "" |
breadcrumbCurrent | string | Optional | "" |
highlights | string | Optional | [] |
Slots
This component does not declare a slot.
Events
This component does not declare a custom event.
Source contract
Installed source: components/PageHeader.wrn
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>
}
}