705 lines
19 KiB
Plaintext
705 lines
19 KiB
Plaintext
import Breadcrumb from "./Breadcrumb.wrn"
|
|
import Button from "./button.wrn"
|
|
|
|
component PageHeader {
|
|
props {
|
|
eyebrow: string = ""
|
|
title: string = ""
|
|
description: string = ""
|
|
icon: string = ""
|
|
id: string = "page-title"
|
|
align: string = "left"
|
|
centered: boolean = false
|
|
compact: boolean = false
|
|
size: string = "default"
|
|
maxWidth: string = "xl"
|
|
showBreadcrumbs: boolean = false
|
|
breadcrumbs: unknown[] = []
|
|
breadcrumbParent: string = ""
|
|
breadcrumbParentHref: string = ""
|
|
breadcrumbCurrent: string = ""
|
|
primaryLabel: string = ""
|
|
primaryHref: string = ""
|
|
primaryIcon: string = ""
|
|
secondaryLabel: string = ""
|
|
secondaryHref: string = ""
|
|
secondaryIcon: string = ""
|
|
color: string = "primary"
|
|
variant: string = "default"
|
|
borderBottom: boolean = true
|
|
class: string = ""
|
|
}
|
|
|
|
view {
|
|
<section
|
|
{...attrs}
|
|
data-ui-component="PageHeader"
|
|
data-size='{size}'
|
|
data-align='{centered ? "center" : align}'
|
|
data-color='{color}'
|
|
data-variant='{variant}'
|
|
data-compact='{compact ? "true" : "false"}'
|
|
data-max-width='{maxWidth}'
|
|
data-border-bottom='{borderBottom ? "true" : "false"}'
|
|
aria-labelledby='{id}'
|
|
class='wrn-page-header {class}'
|
|
>
|
|
<div
|
|
class="wrn-page-header__decoration"
|
|
aria-hidden="true"
|
|
>
|
|
<span
|
|
class="wrn-page-header__glow wrn-page-header__glow--one"
|
|
>
|
|
</span>
|
|
<span
|
|
class="wrn-page-header__glow wrn-page-header__glow--two"
|
|
>
|
|
</span>
|
|
<span
|
|
class="wrn-page-header__grid-pattern"
|
|
>
|
|
</span>
|
|
</div>
|
|
|
|
<div
|
|
class="wrn-page-header__inner"
|
|
>
|
|
{#if showBreadcrumbs && breadcrumbs.length > 0}
|
|
<div
|
|
class="wrn-page-header__breadcrumb"
|
|
>
|
|
<Breadcrumb
|
|
label="Breadcrumb"
|
|
items='{breadcrumbs}'
|
|
active='{breadcrumbs[breadcrumbs.length - 1]?.value || breadcrumbs[breadcrumbs.length - 1]?.label || breadcrumbs[breadcrumbs.length - 1]?.title || ""}'
|
|
color='{color}'
|
|
size='{compact ? "sm" : "default"}'
|
|
variant='{variant === "solid" ? "contrast" : "minimal"}'
|
|
/>
|
|
</div>
|
|
{:else if showBreadcrumbs && breadcrumbParent}
|
|
<div
|
|
class="wrn-page-header__breadcrumb"
|
|
>
|
|
<Breadcrumb
|
|
label="Breadcrumb"
|
|
items='{[
|
|
{
|
|
label: breadcrumbParent,
|
|
href: breadcrumbParentHref,
|
|
value: breadcrumbParent
|
|
},
|
|
{
|
|
label: breadcrumbCurrent || title,
|
|
value: breadcrumbCurrent || title,
|
|
current: true
|
|
}
|
|
]}'
|
|
active='{breadcrumbCurrent || title}'
|
|
color='{color}'
|
|
size='{compact ? "sm" : "default"}'
|
|
variant='{variant === "solid" ? "contrast" : "minimal"}'
|
|
/>
|
|
</div>
|
|
{:else if showBreadcrumbs && (breadcrumbCurrent || title)}
|
|
<div
|
|
class="wrn-page-header__breadcrumb"
|
|
>
|
|
<Breadcrumb
|
|
label="Breadcrumb"
|
|
items='{[
|
|
{
|
|
label: breadcrumbCurrent || title,
|
|
value: breadcrumbCurrent || title,
|
|
current: true
|
|
}
|
|
]}'
|
|
active='{breadcrumbCurrent || title}'
|
|
color='{color}'
|
|
size='{compact ? "sm" : "default"}'
|
|
variant='{variant === "solid" ? "contrast" : "minimal"}'
|
|
/>
|
|
</div>
|
|
{/if}
|
|
|
|
<div
|
|
class="wrn-page-header__layout"
|
|
>
|
|
<div
|
|
class="wrn-page-header__content"
|
|
>
|
|
<div
|
|
class="wrn-page-header__intro"
|
|
>
|
|
{#if icon}
|
|
<span
|
|
class="wrn-page-header__icon-wrap"
|
|
>
|
|
{#if icon === "sparkles"}
|
|
<span
|
|
class="icon-[lucide--sparkles] wrn-page-header__icon"
|
|
aria-hidden="true"
|
|
>
|
|
</span>
|
|
{:else if icon === "component"}
|
|
<span
|
|
class="icon-[lucide--component] wrn-page-header__icon"
|
|
aria-hidden="true"
|
|
>
|
|
</span>
|
|
{:else}
|
|
<span
|
|
class='{icon} wrn-page-header__icon'
|
|
aria-hidden="true"
|
|
>
|
|
</span>
|
|
{/if}
|
|
</span>
|
|
{/if}
|
|
|
|
<div
|
|
class="wrn-page-header__copy"
|
|
>
|
|
{#if eyebrow}
|
|
<div
|
|
class="wrn-page-header__eyebrow-row"
|
|
>
|
|
<span
|
|
class="wrn-page-header__eyebrow-mark"
|
|
aria-hidden="true"
|
|
>
|
|
</span>
|
|
<p
|
|
class="wrn-page-header__eyebrow"
|
|
>
|
|
{eyebrow}
|
|
</p>
|
|
</div>
|
|
{/if}
|
|
|
|
{#if title}
|
|
<h1
|
|
id='{id}'
|
|
class="wrn-page-header__title"
|
|
>
|
|
{title}
|
|
</h1>
|
|
{/if}
|
|
|
|
{#if description}
|
|
<p
|
|
class="wrn-page-header__description"
|
|
>
|
|
{description}
|
|
</p>
|
|
{/if}
|
|
|
|
<div
|
|
class="wrn-page-header__meta"
|
|
>
|
|
<slot
|
|
name="meta"
|
|
>
|
|
</slot>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{#if primaryLabel || secondaryLabel}
|
|
<div
|
|
class="wrn-page-header__actions"
|
|
>
|
|
{#if secondaryLabel}
|
|
<Button
|
|
label='{secondaryLabel}'
|
|
href='{secondaryHref || "#"}'
|
|
icon='{secondaryIcon}'
|
|
size='{compact ? "sm" : "default"}'
|
|
variant="outline"
|
|
color='{color}'
|
|
class="wrn-page-header__action wrn-page-header__action--secondary"
|
|
/>
|
|
{/if}
|
|
|
|
{#if primaryLabel}
|
|
<Button
|
|
label='{primaryLabel}'
|
|
href='{primaryHref || "#"}'
|
|
icon='{primaryIcon}'
|
|
size='{compact ? "sm" : "default"}'
|
|
variant="default"
|
|
color='{color}'
|
|
class="wrn-page-header__action wrn-page-header__action--primary"
|
|
/>
|
|
{/if}
|
|
|
|
<slot
|
|
name="actions"
|
|
>
|
|
</slot>
|
|
</div>
|
|
{:else}
|
|
<div
|
|
class="wrn-page-header__actions wrn-page-header__actions--slot-only"
|
|
>
|
|
<slot
|
|
name="actions"
|
|
>
|
|
</slot>
|
|
</div>
|
|
{/if}
|
|
</div>
|
|
|
|
<div
|
|
class="wrn-page-header__body"
|
|
>
|
|
<slot></slot>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
}
|
|
|
|
style {
|
|
.wrn-page-header {
|
|
--page-header-accent: var(--wrn-color-primary);
|
|
--page-header-soft: var(--wrn-color-primary-soft);
|
|
--page-header-muted: var(--wrn-color-primary-muted);
|
|
--page-header-accent-text: var(--wrn-color-primary-text);
|
|
|
|
position: relative;
|
|
isolation: isolate;
|
|
width: 100%;
|
|
overflow: hidden;
|
|
color: var(--wrn-color-text);
|
|
background: var(--wrn-color-background);
|
|
}
|
|
|
|
.wrn-page-header[data-color="secondary"] {
|
|
--page-header-accent: var(--wrn-color-secondary);
|
|
--page-header-soft: var(--wrn-color-secondary-soft);
|
|
--page-header-muted: var(--wrn-color-secondary-muted);
|
|
--page-header-accent-text: var(--wrn-color-secondary-text);
|
|
}
|
|
|
|
.wrn-page-header[data-color="info"] {
|
|
--page-header-accent: var(--wrn-color-info);
|
|
--page-header-soft: var(--wrn-color-info-soft);
|
|
--page-header-muted: var(--wrn-color-info-muted);
|
|
--page-header-accent-text: var(--wrn-color-info-text);
|
|
}
|
|
|
|
.wrn-page-header[data-color="success"] {
|
|
--page-header-accent: var(--wrn-color-success);
|
|
--page-header-soft: var(--wrn-color-success-soft);
|
|
--page-header-muted: var(--wrn-color-success-muted);
|
|
--page-header-accent-text: var(--wrn-color-success-text);
|
|
}
|
|
|
|
.wrn-page-header[data-color="warning"] {
|
|
--page-header-accent: var(--wrn-color-warning);
|
|
--page-header-soft: var(--wrn-color-warning-soft);
|
|
--page-header-muted: var(--wrn-color-warning-muted);
|
|
--page-header-accent-text: var(--wrn-color-warning-text);
|
|
}
|
|
|
|
.wrn-page-header[data-color="danger"] {
|
|
--page-header-accent: var(--wrn-color-danger);
|
|
--page-header-soft: var(--wrn-color-danger-soft);
|
|
--page-header-muted: var(--wrn-color-danger-muted);
|
|
--page-header-accent-text: var(--wrn-color-danger-text);
|
|
}
|
|
|
|
.wrn-page-header[data-variant="soft"] {
|
|
background: var(--wrn-color-surface);
|
|
}
|
|
|
|
.wrn-page-header[data-variant="raised"] {
|
|
background: var(--wrn-color-surface-raised);
|
|
box-shadow: var(--wrn-shadow-sm);
|
|
}
|
|
|
|
.wrn-page-header[data-variant="tinted"] {
|
|
background:
|
|
linear-gradient(135deg, var(--page-header-soft), transparent 72%),
|
|
var(--wrn-color-background);
|
|
}
|
|
|
|
.wrn-page-header[data-variant="solid"] {
|
|
color: #ffffff;
|
|
background: var(--page-header-accent);
|
|
}
|
|
|
|
.wrn-page-header[data-variant="minimal"] {
|
|
background: transparent;
|
|
}
|
|
|
|
.wrn-page-header[data-border-bottom="true"] {
|
|
border-bottom: 1px solid var(--wrn-color-border);
|
|
}
|
|
|
|
.wrn-page-header[data-variant="solid"][data-border-bottom="true"] {
|
|
border-bottom-color: rgba(255, 255, 255, 0.18);
|
|
}
|
|
|
|
.wrn-page-header__decoration {
|
|
position: absolute;
|
|
inset: 0;
|
|
z-index: -1;
|
|
overflow: hidden;
|
|
pointer-events: none;
|
|
}
|
|
|
|
.wrn-page-header__glow {
|
|
position: absolute;
|
|
display: block;
|
|
border-radius: 999px;
|
|
filter: blur(60px);
|
|
opacity: 0.17;
|
|
}
|
|
|
|
.wrn-page-header__glow--one {
|
|
top: -9rem;
|
|
right: -5rem;
|
|
width: 24rem;
|
|
height: 24rem;
|
|
background: var(--page-header-accent);
|
|
}
|
|
|
|
.wrn-page-header__glow--two {
|
|
bottom: -10rem;
|
|
left: 18%;
|
|
width: 18rem;
|
|
height: 18rem;
|
|
background: var(--page-header-muted);
|
|
opacity: 0.13;
|
|
}
|
|
|
|
.wrn-page-header__grid-pattern {
|
|
position: absolute;
|
|
inset: 0;
|
|
opacity: 0.2;
|
|
background-image:
|
|
linear-gradient(to right, var(--wrn-color-border) 1px, transparent 1px),
|
|
linear-gradient(to bottom, var(--wrn-color-border) 1px, transparent 1px);
|
|
background-size: 32px 32px;
|
|
mask-image: linear-gradient(to bottom, rgba(0, 0, 0, 0.35), transparent 78%);
|
|
}
|
|
|
|
.wrn-page-header[data-variant="minimal"] .wrn-page-header__decoration,
|
|
.wrn-page-header[data-compact="true"] .wrn-page-header__grid-pattern {
|
|
display: none;
|
|
}
|
|
|
|
.wrn-page-header[data-variant="solid"] .wrn-page-header__grid-pattern {
|
|
opacity: 0.1;
|
|
background-image:
|
|
linear-gradient(to right, rgba(255, 255, 255, 0.28) 1px, transparent 1px),
|
|
linear-gradient(to bottom, rgba(255, 255, 255, 0.28) 1px, transparent 1px);
|
|
}
|
|
|
|
.wrn-page-header__inner {
|
|
position: relative;
|
|
width: 100%;
|
|
max-width: 80rem;
|
|
margin-inline: auto;
|
|
padding: 1.25rem 1rem 2.75rem;
|
|
}
|
|
|
|
.wrn-page-header[data-max-width="compact"] .wrn-page-header__inner,
|
|
.wrn-page-header[data-max-width="lg"] .wrn-page-header__inner {
|
|
max-width: 64rem;
|
|
}
|
|
|
|
.wrn-page-header[data-max-width="wide"] .wrn-page-header__inner,
|
|
.wrn-page-header[data-max-width="2xl"] .wrn-page-header__inner {
|
|
max-width: 90rem;
|
|
}
|
|
|
|
.wrn-page-header[data-max-width="full"] .wrn-page-header__inner {
|
|
max-width: none;
|
|
}
|
|
|
|
.wrn-page-header[data-compact="true"] .wrn-page-header__inner {
|
|
padding-top: 1rem;
|
|
padding-bottom: 1.75rem;
|
|
}
|
|
|
|
.wrn-page-header[data-size="lg"] .wrn-page-header__inner {
|
|
padding-bottom: 3.5rem;
|
|
}
|
|
|
|
.wrn-page-header__breadcrumb {
|
|
display: flex;
|
|
align-items: center;
|
|
min-width: 0;
|
|
margin-bottom: 1.75rem;
|
|
padding-bottom: 0.9rem;
|
|
border-bottom: 1px solid var(--wrn-color-border);
|
|
}
|
|
|
|
.wrn-page-header[data-variant="solid"] .wrn-page-header__breadcrumb {
|
|
border-bottom-color: rgba(255, 255, 255, 0.18);
|
|
}
|
|
|
|
.wrn-page-header[data-compact="true"] .wrn-page-header__breadcrumb {
|
|
margin-bottom: 1.25rem;
|
|
padding-bottom: 0.7rem;
|
|
}
|
|
|
|
.wrn-page-header__layout {
|
|
display: grid;
|
|
grid-template-columns: minmax(0, 1fr);
|
|
gap: 1.75rem;
|
|
align-items: start;
|
|
}
|
|
|
|
.wrn-page-header__content,
|
|
.wrn-page-header__copy {
|
|
min-width: 0;
|
|
}
|
|
|
|
.wrn-page-header__intro {
|
|
display: flex;
|
|
align-items: flex-start;
|
|
gap: 1rem;
|
|
min-width: 0;
|
|
}
|
|
|
|
.wrn-page-header__icon-wrap {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
flex: 0 0 auto;
|
|
width: 3.25rem;
|
|
height: 3.25rem;
|
|
margin-top: 0.15rem;
|
|
color: var(--page-header-accent);
|
|
background: var(--page-header-soft);
|
|
border: 1px solid var(--page-header-muted);
|
|
border-radius: 1rem;
|
|
box-shadow: var(--wrn-shadow-sm);
|
|
}
|
|
|
|
.wrn-page-header[data-compact="true"] .wrn-page-header__icon-wrap {
|
|
width: 2.75rem;
|
|
height: 2.75rem;
|
|
border-radius: 0.8rem;
|
|
}
|
|
|
|
.wrn-page-header[data-variant="solid"] .wrn-page-header__icon-wrap {
|
|
color: #ffffff;
|
|
background: rgba(255, 255, 255, 0.12);
|
|
border-color: rgba(255, 255, 255, 0.22);
|
|
}
|
|
|
|
.wrn-page-header__icon {
|
|
width: 1.35rem;
|
|
height: 1.35rem;
|
|
}
|
|
|
|
.wrn-page-header__eyebrow-row {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 0.65rem;
|
|
margin-bottom: 0.65rem;
|
|
}
|
|
|
|
.wrn-page-header__eyebrow-mark {
|
|
width: 1.75rem;
|
|
height: 2px;
|
|
flex: 0 0 auto;
|
|
background: var(--page-header-accent);
|
|
border-radius: 999px;
|
|
}
|
|
|
|
.wrn-page-header__eyebrow {
|
|
margin: 0;
|
|
color: var(--page-header-accent-text);
|
|
font-size: 0.72rem;
|
|
font-weight: 800;
|
|
line-height: 1.3;
|
|
letter-spacing: 0.16em;
|
|
text-transform: uppercase;
|
|
}
|
|
|
|
.wrn-page-header[data-variant="solid"] .wrn-page-header__eyebrow,
|
|
.wrn-page-header[data-variant="solid"] .wrn-page-header__title,
|
|
.wrn-page-header[data-variant="solid"] .wrn-page-header__description {
|
|
color: #ffffff;
|
|
}
|
|
|
|
.wrn-page-header[data-variant="solid"] .wrn-page-header__eyebrow-mark {
|
|
background: rgba(255, 255, 255, 0.8);
|
|
}
|
|
|
|
.wrn-page-header__title {
|
|
max-width: 54rem;
|
|
margin: 0;
|
|
color: var(--wrn-color-text);
|
|
font-size: clamp(2rem, 4vw, 3.75rem);
|
|
font-weight: 800;
|
|
line-height: 1.08;
|
|
letter-spacing: -0.035em;
|
|
text-wrap: balance;
|
|
}
|
|
|
|
.wrn-page-header[data-compact="true"] .wrn-page-header__title {
|
|
font-size: clamp(1.75rem, 3vw, 2.65rem);
|
|
}
|
|
|
|
.wrn-page-header[data-size="lg"] .wrn-page-header__title {
|
|
font-size: clamp(2.35rem, 5vw, 4.5rem);
|
|
}
|
|
|
|
.wrn-page-header__description {
|
|
max-width: 48rem;
|
|
margin: 0.9rem 0 0;
|
|
color: var(--wrn-color-text-muted);
|
|
font-size: 1rem;
|
|
line-height: 1.75;
|
|
text-wrap: pretty;
|
|
}
|
|
|
|
.wrn-page-header[data-size="lg"] .wrn-page-header__description {
|
|
font-size: 1.075rem;
|
|
}
|
|
|
|
.wrn-page-header[data-variant="solid"] .wrn-page-header__description {
|
|
opacity: 0.82;
|
|
}
|
|
|
|
.wrn-page-header__meta:empty,
|
|
.wrn-page-header__body:empty,
|
|
.wrn-page-header__actions--slot-only:empty {
|
|
display: none;
|
|
}
|
|
|
|
/* Compiled empty slots retain inert template markers, so :empty alone
|
|
cannot collapse their spacing in the rendered document. */
|
|
.wrn-page-header__meta:not(:has(> :not(template))),
|
|
.wrn-page-header__body:not(:has(> :not(template))),
|
|
.wrn-page-header__actions--slot-only:not(:has(> :not(template))) {
|
|
display: none;
|
|
}
|
|
|
|
.wrn-page-header__meta {
|
|
margin-top: 1.1rem;
|
|
}
|
|
|
|
.wrn-page-header__actions {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
align-items: center;
|
|
gap: 0.75rem;
|
|
min-width: 0;
|
|
}
|
|
|
|
/*
|
|
* Slot content is app-authored, so a bare `p { color: ... }` in the app
|
|
* stylesheet beats anything this container merely passes down by
|
|
* inheritance. State it, at a specificity the app can still override.
|
|
*/
|
|
.wrn-page-header__body {
|
|
color: var(--wrn-color-text);
|
|
margin-top: 1.75rem;
|
|
}
|
|
|
|
.wrn-page-header[data-align="center"] .wrn-page-header__layout {
|
|
justify-items: center;
|
|
text-align: center;
|
|
}
|
|
|
|
.wrn-page-header[data-align="center"] .wrn-page-header__intro {
|
|
flex-direction: column;
|
|
align-items: center;
|
|
}
|
|
|
|
.wrn-page-header[data-align="center"] .wrn-page-header__eyebrow-row,
|
|
.wrn-page-header[data-align="center"] .wrn-page-header__actions {
|
|
justify-content: center;
|
|
}
|
|
|
|
.wrn-page-header[data-align="center"] .wrn-page-header__title,
|
|
.wrn-page-header[data-align="center"] .wrn-page-header__description {
|
|
margin-inline: auto;
|
|
}
|
|
|
|
.wrn-page-header[data-align="right"] .wrn-page-header__layout {
|
|
justify-items: end;
|
|
text-align: right;
|
|
}
|
|
|
|
.wrn-page-header[data-align="right"] .wrn-page-header__intro {
|
|
flex-direction: row-reverse;
|
|
}
|
|
|
|
.wrn-page-header[data-align="right"] .wrn-page-header__eyebrow-row,
|
|
.wrn-page-header[data-align="right"] .wrn-page-header__actions {
|
|
justify-content: flex-end;
|
|
}
|
|
|
|
.wrn-page-header[data-align="right"] .wrn-page-header__title,
|
|
.wrn-page-header[data-align="right"] .wrn-page-header__description {
|
|
margin-left: auto;
|
|
}
|
|
|
|
@media (min-width: 640px) {
|
|
.wrn-page-header__inner {
|
|
padding-inline: 1.5rem;
|
|
}
|
|
|
|
.wrn-page-header__intro {
|
|
gap: 1.25rem;
|
|
}
|
|
}
|
|
|
|
@media (min-width: 1024px) {
|
|
.wrn-page-header__inner {
|
|
padding-inline: 2rem;
|
|
}
|
|
|
|
.wrn-page-header__layout {
|
|
grid-template-columns: minmax(0, 1fr) auto;
|
|
align-items: start;
|
|
gap: 2.5rem;
|
|
}
|
|
|
|
.wrn-page-header[data-align="center"] .wrn-page-header__layout,
|
|
.wrn-page-header[data-align="right"] .wrn-page-header__layout {
|
|
grid-template-columns: minmax(0, 1fr);
|
|
}
|
|
|
|
.wrn-page-header__actions {
|
|
align-self: start;
|
|
justify-self: end;
|
|
justify-content: flex-end;
|
|
padding-top: 0;
|
|
padding-bottom: 0;
|
|
}
|
|
}
|
|
|
|
@media (max-width: 639px) {
|
|
.wrn-page-header__intro {
|
|
flex-direction: column;
|
|
}
|
|
|
|
.wrn-page-header__actions {
|
|
display: grid;
|
|
grid-template-columns: minmax(0, 1fr);
|
|
}
|
|
|
|
.wrn-page-header__action {
|
|
width: 100%;
|
|
}
|
|
}
|
|
|
|
@media (prefers-reduced-motion: reduce) {
|
|
.wrn-page-header__glow {
|
|
filter: blur(52px);
|
|
}
|
|
}
|
|
}
|
|
}
|