feat: support WRN imports and dynamic public shell
This commit is contained in:
@@ -1,4 +1,15 @@
|
||||
component PublicHeader {
|
||||
types {
|
||||
interface PublicHeaderNavigationItem {
|
||||
label: string
|
||||
href: string
|
||||
ariaLabel?: string
|
||||
target?: string
|
||||
}
|
||||
interface PublicHeaderActionItem extends PublicHeaderNavigationItem {
|
||||
variant?: "primary" | "secondary" | "ghost"
|
||||
}
|
||||
}
|
||||
props {
|
||||
class: string = ""
|
||||
homeHref: string = "/"
|
||||
@@ -22,6 +33,14 @@ component PublicHeader {
|
||||
solutionsLabel: string = "Solutions"
|
||||
developersLabel: string = "Developers"
|
||||
resourcesLabel: string = "Resources"
|
||||
navigationAriaLabel: string = "Main navigation"
|
||||
themeToggleLabel: string = "Toggle color theme"
|
||||
mobileMenuOpenLabel: string = "Open navigation menu"
|
||||
mobileMenuCloseLabel: string = "Close navigation menu"
|
||||
navigationItems: PublicHeaderNavigationItem[] = []
|
||||
actionItems: PublicHeaderActionItem[] = []
|
||||
showNavigation: boolean = true
|
||||
showMobileThemeToggle: boolean = true
|
||||
}
|
||||
state activeMenu = ""
|
||||
state mobileMenuOpen = false
|
||||
@@ -71,10 +90,16 @@ component PublicHeader {
|
||||
|
||||
<!-- Desktop navigation -->
|
||||
<nav
|
||||
aria-label="Main navigation"
|
||||
aria-label="{navigationAriaLabel}"
|
||||
data-show="showNavigation"
|
||||
class="hidden items-center gap-1 lg:flex"
|
||||
>
|
||||
<slot name="navigation">
|
||||
{#if navigationItems.length > 0}
|
||||
{#each navigationItems as item}
|
||||
<a href="{item.href}" aria-label="{item.ariaLabel || item.label}" target="{item.target || '_self'}" class="inline-flex h-10 items-center rounded-xl px-3.5 text-sm font-semibold text-slate-700 transition hover:bg-slate-100 hover:text-slate-950 focus:outline-none focus-visible:ring-2 focus-visible:ring-indigo-500 dark:text-slate-300 dark:hover:bg-white/5 dark:hover:text-white">{item.label}</a>
|
||||
{/each}
|
||||
{:else}
|
||||
<!-- Product -->
|
||||
<button
|
||||
type="button"
|
||||
@@ -171,12 +196,18 @@ component PublicHeader {
|
||||
>
|
||||
{pricingLabel}
|
||||
</a>
|
||||
{/if}
|
||||
</slot>
|
||||
</nav>
|
||||
|
||||
<!-- Desktop actions -->
|
||||
<div class="hidden items-center gap-2 lg:flex">
|
||||
<slot name="actions">
|
||||
{#if actionItems.length > 0}
|
||||
{#each actionItems as item}
|
||||
<a href="{item.href}" aria-label="{item.ariaLabel || item.label}" target="{item.target || '_self'}" class="wire-public-header-action wire-public-header-action--{item.variant || 'secondary'}">{item.label}{#if item.variant === 'primary'}<span aria-hidden="true">→</span>{/if}</a>
|
||||
{/each}
|
||||
{:else}
|
||||
<a data-show="showStatus"
|
||||
href="{statusHref}"
|
||||
class="mr-1 inline-flex items-center gap-2 rounded-xl px-3 py-2 text-xs font-semibold text-slate-500 transition hover:bg-slate-100 hover:text-slate-950 dark:text-slate-400 dark:hover:bg-white/5 dark:hover:text-white"
|
||||
@@ -192,8 +223,8 @@ component PublicHeader {
|
||||
<button data-show="showThemeToggle"
|
||||
type="button"
|
||||
data-wire-theme-toggle
|
||||
aria-label="Toggle color theme"
|
||||
title="Toggle color theme"
|
||||
aria-label="{themeToggleLabel}"
|
||||
title="{themeToggleLabel}"
|
||||
class="grid h-10 w-10 place-items-center rounded-xl border border-slate-200 bg-white text-slate-600 shadow-sm transition hover:border-slate-300 hover:bg-slate-100 hover:text-slate-950 focus:outline-none focus-visible:ring-2 focus-visible:ring-indigo-500 dark:border-white/10 dark:bg-white/5 dark:text-slate-300 dark:hover:border-white/20 dark:hover:bg-white/10 dark:hover:text-white"
|
||||
>
|
||||
<span class="icon-[lucide--moon] h-4 w-4 dark:hidden" aria-hidden="true" ></span>
|
||||
@@ -201,7 +232,7 @@ component PublicHeader {
|
||||
<span class="icon-[lucide--sun] hidden h-4 w-4 dark:block" aria-hidden="true" ></span>
|
||||
|
||||
<span class="sr-only">
|
||||
Toggle color theme
|
||||
{themeToggleLabel}
|
||||
</span>
|
||||
</button>
|
||||
|
||||
@@ -220,16 +251,17 @@ component PublicHeader {
|
||||
|
||||
<span class="icon-[lucide--arrow-right] h-4 w-4 transition-transform group-hover:translate-x-0.5" aria-hidden="true" ></span>
|
||||
</a>
|
||||
{/if}
|
||||
</slot>
|
||||
</div>
|
||||
|
||||
<!-- Mobile actions -->
|
||||
<div class="flex items-center gap-2 lg:hidden">
|
||||
<button
|
||||
<button data-show="showThemeToggle && showMobileThemeToggle"
|
||||
type="button"
|
||||
data-wire-theme-toggle
|
||||
aria-label="Toggle color theme"
|
||||
title="Toggle color theme"
|
||||
aria-label="{themeToggleLabel}"
|
||||
title="{themeToggleLabel}"
|
||||
class="grid h-10 w-10 place-items-center rounded-xl border border-slate-200 bg-white text-slate-600 shadow-sm transition hover:bg-slate-100 hover:text-slate-950 focus:outline-none focus-visible:ring-2 focus-visible:ring-indigo-500 dark:border-white/10 dark:bg-white/5 dark:text-slate-300 dark:hover:bg-white/10 dark:hover:text-white"
|
||||
>
|
||||
<span class="icon-[lucide--moon] h-4 w-4 dark:hidden" aria-hidden="true" ></span>
|
||||
@@ -240,7 +272,7 @@ component PublicHeader {
|
||||
<button
|
||||
type="button"
|
||||
@click="mobileMenuOpen = !mobileMenuOpen"
|
||||
aria-label="{mobileMenuOpen ? 'Close navigation menu' : 'Open navigation menu'}"
|
||||
aria-label="{mobileMenuOpen ? mobileMenuCloseLabel : mobileMenuOpenLabel}"
|
||||
aria-expanded="{mobileMenuOpen}"
|
||||
aria-controls="public-mobile-navigation"
|
||||
class="grid h-10 w-10 place-items-center rounded-xl border border-slate-200 bg-white text-slate-700 shadow-sm transition hover:bg-slate-100 hover:text-slate-950 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:bg-white/10 dark:hover:text-white"
|
||||
@@ -258,7 +290,7 @@ component PublicHeader {
|
||||
</div>
|
||||
|
||||
<!-- Outside-click backdrop -->
|
||||
<button type="button" data-show="activeMenu !== ''" @click="activeMenu = ''" aria-label="Close navigation menu" class="fixed inset-0 z-40 hidden cursor-default bg-transparent lg:block" class:hidden="activeMenu === ''" class:block="activeMenu !== ''" ></button>
|
||||
<button type="button" data-show="activeMenu !== ''" @click="activeMenu = ''" aria-label="{mobileMenuCloseLabel}" class="fixed inset-0 z-40 hidden cursor-default bg-transparent lg:block" class:hidden="activeMenu === ''" class:block="activeMenu !== ''" ></button>
|
||||
|
||||
<!-- Desktop mega menus -->
|
||||
<div
|
||||
@@ -302,7 +334,16 @@ component PublicHeader {
|
||||
class:hidden="!mobileMenuOpen"
|
||||
class:block="mobileMenuOpen"
|
||||
>
|
||||
{#if navigationItems.length > 0 || actionItems.length > 0}
|
||||
<nav aria-label="{navigationAriaLabel}" class="border-t border-slate-200 bg-white px-5 py-5 shadow-xl dark:border-white/10 dark:bg-slate-950">
|
||||
<div class="grid gap-2">
|
||||
{#each navigationItems as item}<a href="{item.href}" target="{item.target || '_self'}" class="rounded-xl px-4 py-3 text-sm font-semibold text-slate-700 hover:bg-slate-100 dark:text-slate-200 dark:hover:bg-white/5">{item.label}</a>{/each}
|
||||
{#each actionItems as item}<a href="{item.href}" target="{item.target || '_self'}" class="wire-public-header-action wire-public-header-action--{item.variant || 'secondary'}">{item.label}</a>{/each}
|
||||
</div>
|
||||
</nav>
|
||||
{:else}
|
||||
<PublicMobileNavigation />
|
||||
{/if}
|
||||
</div>
|
||||
</header>
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user