feat: support WRN imports and dynamic public shell
This commit is contained in:
@@ -3253,7 +3253,7 @@ Reusable progress bar component.
|
||||
Reusable public footer component.
|
||||
|
||||
- Mount: `data-component="PublicFooter"`
|
||||
- Props: `class: string = ""`, `homeHref: string = "/"`, `brandName: string = "WrNexus"`, `brandTagline: string = "Identity Cloud"`, `brandAriaLabel: string = "WrNexus home"`, `newsletterEyebrow: string = "WrNexus updates"`, `newsletterTitle: string = "Identity insights delivered to your inbox"`, `newsletterDescription: string = "Get product updates, security guidance, implementation strategies, and practical identity architecture resources."`, `newsletterAction: string = "/api/newsletter/subscribe"`, `newsletterButtonLabel: string = "Subscribe"`, `newsletterPlaceholder: string = "Enter your work email"`, `newsletterSuccessMessage: string = "Thanks. Please check your inbox to confirm your subscription."`, `copyrightText: string = "© 2026 WrNexus. All rights reserved."`, `attributionText: string = "Built by WorkRoot Workspace."`, `showNewsletter: boolean = true`, `showSocialLinks: boolean = true`, `showThemeToggle: boolean = true`
|
||||
- Props: `class: string = ""`, `homeHref: string = "/"`, `brandName: string = "WrNexus"`, `brandTagline: string = "Identity Cloud"`, `brandAriaLabel: string = "WrNexus home"`, `brandIcon: string = "icon-[lucide--blocks]"`, `brandDescription: string = "Secure authentication, user management, organizations, authorization, and enterprise identity for modern applications."`, `statusLabel: string = "All systems operational"`, `statusHref: string = "/status"`, `newsletterEyebrow: string = "WrNexus updates"`, `newsletterTitle: string = "Identity insights delivered to your inbox"`, `newsletterDescription: string = "Get product updates, security guidance, implementation strategies, and practical identity architecture resources."`, `newsletterAction: string = "/api/newsletter/subscribe"`, `newsletterButtonLabel: string = "Subscribe"`, `newsletterPlaceholder: string = "Enter your work email"`, `newsletterSuccessMessage: string = "Thanks. Please check your inbox to confirm your subscription."`, `newsletterPrivacyLabel: string = "privacy policy"`, `newsletterPrivacyHref: string = "/privacy"`, `newsletterFinePrintPrefix: string = "No spam. Unsubscribe at any time. Read our"`, `newsletterFinePrintSuffix: string = "."`, `newsletterEmailLabel: string = "Work email address"`, `newsletterEmailName: string = "email"`, `copyrightText: string = "© 2026 WrNexus. All rights reserved."`, `attributionText: string = "Built by WorkRoot Workspace."`, `showNewsletter: boolean = true`, `showSocialLinks: boolean = true`, `showThemeToggle: boolean = true`, `showStatus: boolean = true`, `showCookiePreferences: boolean = true`, `cookiePreferencesLabel: string = "Cookie preferences"`, `themeLabel: string = "Theme"`, `themeToggleLabel: string = "Toggle color theme"`, `legalTitle: string = "Legal"`, `socialLinks: PublicFooterLink[] = []`, `navigationColumns: PublicFooterColumn[] = []`, `legalLinks: PublicFooterLink[] = []`, `navigationAriaLabel: string = "Footer navigation"`
|
||||
- Slots: `navigation`
|
||||
- Events: `submit`
|
||||
|
||||
@@ -7203,7 +7203,7 @@ Reusable product page shell component.
|
||||
Reusable public header component.
|
||||
|
||||
- Mount: `data-component="PublicHeader"`
|
||||
- Props: `class: string = ""`, `homeHref: string = "/"`, `brandName: string = "WrNexus"`, `brandTagline: string = "Identity Cloud"`, `brandAriaLabel: string = "WrNexus home"`, `brandIcon: string = "icon-[lucide--blocks]"`, `pricingLabel: string = "Pricing"`, `pricingHref: string = "/pricing"`, `statusLabel: string = "All systems operational"`, `statusHref: string = "/status"`, `signInLabel: string = "Sign in"`, `signInHref: string = "/sign-in"`, `primaryLabel: string = "Start free"`, `primaryHref: string = "/sign-up"`, `showStatus: boolean = true`, `showThemeToggle: boolean = true`, `showSignIn: boolean = true`, `showPrimaryAction: boolean = true`, `productLabel: string = "Product"`, `solutionsLabel: string = "Solutions"`, `developersLabel: string = "Developers"`, `resourcesLabel: string = "Resources"`
|
||||
- Props: `class: string = ""`, `homeHref: string = "/"`, `brandName: string = "WrNexus"`, `brandTagline: string = "Identity Cloud"`, `brandAriaLabel: string = "WrNexus home"`, `brandIcon: string = "icon-[lucide--blocks]"`, `pricingLabel: string = "Pricing"`, `pricingHref: string = "/pricing"`, `statusLabel: string = "All systems operational"`, `statusHref: string = "/status"`, `signInLabel: string = "Sign in"`, `signInHref: string = "/sign-in"`, `primaryLabel: string = "Start free"`, `primaryHref: string = "/sign-up"`, `showStatus: boolean = true`, `showThemeToggle: boolean = true`, `showSignIn: boolean = true`, `showPrimaryAction: boolean = true`, `productLabel: string = "Product"`, `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`
|
||||
- Slots: `navigation`, `actions`
|
||||
- Events: `click`
|
||||
|
||||
|
||||
@@ -33954,6 +33954,30 @@
|
||||
"required": false,
|
||||
"default": "\"WrNexus home\""
|
||||
},
|
||||
{
|
||||
"name": "brandIcon",
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"default": "\"icon-[lucide--blocks]\""
|
||||
},
|
||||
{
|
||||
"name": "brandDescription",
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"default": "\"Secure authentication, user management, organizations, authorization, and enterprise identity for modern applications.\""
|
||||
},
|
||||
{
|
||||
"name": "statusLabel",
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"default": "\"All systems operational\""
|
||||
},
|
||||
{
|
||||
"name": "statusHref",
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"default": "\"/status\""
|
||||
},
|
||||
{
|
||||
"name": "newsletterEyebrow",
|
||||
"type": "string",
|
||||
@@ -33996,6 +34020,42 @@
|
||||
"required": false,
|
||||
"default": "\"Thanks. Please check your inbox to confirm your subscription.\""
|
||||
},
|
||||
{
|
||||
"name": "newsletterPrivacyLabel",
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"default": "\"privacy policy\""
|
||||
},
|
||||
{
|
||||
"name": "newsletterPrivacyHref",
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"default": "\"/privacy\""
|
||||
},
|
||||
{
|
||||
"name": "newsletterFinePrintPrefix",
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"default": "\"No spam. Unsubscribe at any time. Read our\""
|
||||
},
|
||||
{
|
||||
"name": "newsletterFinePrintSuffix",
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"default": "\".\""
|
||||
},
|
||||
{
|
||||
"name": "newsletterEmailLabel",
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"default": "\"Work email address\""
|
||||
},
|
||||
{
|
||||
"name": "newsletterEmailName",
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"default": "\"email\""
|
||||
},
|
||||
{
|
||||
"name": "copyrightText",
|
||||
"type": "string",
|
||||
@@ -34025,6 +34085,66 @@
|
||||
"type": "boolean",
|
||||
"required": false,
|
||||
"default": "true"
|
||||
},
|
||||
{
|
||||
"name": "showStatus",
|
||||
"type": "boolean",
|
||||
"required": false,
|
||||
"default": "true"
|
||||
},
|
||||
{
|
||||
"name": "showCookiePreferences",
|
||||
"type": "boolean",
|
||||
"required": false,
|
||||
"default": "true"
|
||||
},
|
||||
{
|
||||
"name": "cookiePreferencesLabel",
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"default": "\"Cookie preferences\""
|
||||
},
|
||||
{
|
||||
"name": "themeLabel",
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"default": "\"Theme\""
|
||||
},
|
||||
{
|
||||
"name": "themeToggleLabel",
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"default": "\"Toggle color theme\""
|
||||
},
|
||||
{
|
||||
"name": "legalTitle",
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"default": "\"Legal\""
|
||||
},
|
||||
{
|
||||
"name": "socialLinks",
|
||||
"type": "PublicFooterLink[]",
|
||||
"required": false,
|
||||
"default": "[]"
|
||||
},
|
||||
{
|
||||
"name": "navigationColumns",
|
||||
"type": "PublicFooterColumn[]",
|
||||
"required": false,
|
||||
"default": "[]"
|
||||
},
|
||||
{
|
||||
"name": "legalLinks",
|
||||
"type": "PublicFooterLink[]",
|
||||
"required": false,
|
||||
"default": "[]"
|
||||
},
|
||||
{
|
||||
"name": "navigationAriaLabel",
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"default": "\"Footer navigation\""
|
||||
}
|
||||
],
|
||||
"slots": ["navigation"],
|
||||
@@ -34168,6 +34288,54 @@
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"default": "\"Resources\""
|
||||
},
|
||||
{
|
||||
"name": "navigationAriaLabel",
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"default": "\"Main navigation\""
|
||||
},
|
||||
{
|
||||
"name": "themeToggleLabel",
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"default": "\"Toggle color theme\""
|
||||
},
|
||||
{
|
||||
"name": "mobileMenuOpenLabel",
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"default": "\"Open navigation menu\""
|
||||
},
|
||||
{
|
||||
"name": "mobileMenuCloseLabel",
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"default": "\"Close navigation menu\""
|
||||
},
|
||||
{
|
||||
"name": "navigationItems",
|
||||
"type": "PublicHeaderNavigationItem[]",
|
||||
"required": false,
|
||||
"default": "[]"
|
||||
},
|
||||
{
|
||||
"name": "actionItems",
|
||||
"type": "PublicHeaderActionItem[]",
|
||||
"required": false,
|
||||
"default": "[]"
|
||||
},
|
||||
{
|
||||
"name": "showNavigation",
|
||||
"type": "boolean",
|
||||
"required": false,
|
||||
"default": "true"
|
||||
},
|
||||
{
|
||||
"name": "showMobileThemeToggle",
|
||||
"type": "boolean",
|
||||
"required": false,
|
||||
"default": "true"
|
||||
}
|
||||
],
|
||||
"slots": ["navigation", "actions"],
|
||||
|
||||
@@ -1,10 +1,27 @@
|
||||
component PublicFooter {
|
||||
types {
|
||||
interface PublicFooterLink {
|
||||
label: string
|
||||
href: string
|
||||
ariaLabel?: string
|
||||
target?: string
|
||||
icon?: string
|
||||
}
|
||||
interface PublicFooterColumn {
|
||||
title: string
|
||||
links: PublicFooterLink[]
|
||||
}
|
||||
}
|
||||
props {
|
||||
class: string = ""
|
||||
homeHref: string = "/"
|
||||
brandName: string = "WrNexus"
|
||||
brandTagline: string = "Identity Cloud"
|
||||
brandAriaLabel: string = "WrNexus home"
|
||||
brandIcon: string = "icon-[lucide--blocks]"
|
||||
brandDescription: string = "Secure authentication, user management, organizations, authorization, and enterprise identity for modern applications."
|
||||
statusLabel: string = "All systems operational"
|
||||
statusHref: string = "/status"
|
||||
newsletterEyebrow: string = "WrNexus updates"
|
||||
newsletterTitle: string = "Identity insights delivered to your inbox"
|
||||
newsletterDescription: string = "Get product updates, security guidance, implementation strategies, and practical identity architecture resources."
|
||||
@@ -12,11 +29,27 @@ component PublicFooter {
|
||||
newsletterButtonLabel: string = "Subscribe"
|
||||
newsletterPlaceholder: string = "Enter your work email"
|
||||
newsletterSuccessMessage: string = "Thanks. Please check your inbox to confirm your subscription."
|
||||
newsletterPrivacyLabel: string = "privacy policy"
|
||||
newsletterPrivacyHref: string = "/privacy"
|
||||
newsletterFinePrintPrefix: string = "No spam. Unsubscribe at any time. Read our"
|
||||
newsletterFinePrintSuffix: string = "."
|
||||
newsletterEmailLabel: string = "Work email address"
|
||||
newsletterEmailName: string = "email"
|
||||
copyrightText: string = "© 2026 WrNexus. All rights reserved."
|
||||
attributionText: string = "Built by WorkRoot Workspace."
|
||||
showNewsletter: boolean = true
|
||||
showSocialLinks: boolean = true
|
||||
showThemeToggle: boolean = true
|
||||
showStatus: boolean = true
|
||||
showCookiePreferences: boolean = true
|
||||
cookiePreferencesLabel: string = "Cookie preferences"
|
||||
themeLabel: string = "Theme"
|
||||
themeToggleLabel: string = "Toggle color theme"
|
||||
legalTitle: string = "Legal"
|
||||
socialLinks: PublicFooterLink[] = []
|
||||
navigationColumns: PublicFooterColumn[] = []
|
||||
legalLinks: PublicFooterLink[] = []
|
||||
navigationAriaLabel: string = "Footer navigation"
|
||||
}
|
||||
state email = ""
|
||||
state newsletterSubmitted = false
|
||||
@@ -81,7 +114,7 @@ component PublicFooter {
|
||||
class="sr-only"
|
||||
for="footer-newsletter-email"
|
||||
>
|
||||
Work email address
|
||||
{newsletterEmailLabel}
|
||||
</label>
|
||||
|
||||
<div class="relative min-w-0 flex-1">
|
||||
@@ -89,7 +122,7 @@ component PublicFooter {
|
||||
|
||||
<input
|
||||
id="footer-newsletter-email"
|
||||
name="email"
|
||||
name="{newsletterEmailName}"
|
||||
type="email"
|
||||
autocomplete="email"
|
||||
required
|
||||
@@ -113,13 +146,13 @@ component PublicFooter {
|
||||
<p class="mt-3 flex items-start gap-2 text-xs leading-5 text-slate-500 dark:text-slate-400">
|
||||
<span class="icon-[lucide--shield-check] mt-0.5 h-3.5 w-3.5 shrink-0" aria-hidden="true" ></span>
|
||||
|
||||
No spam. Unsubscribe at any time. Read our
|
||||
{newsletterFinePrintPrefix}
|
||||
<a
|
||||
href="/privacy"
|
||||
href="{newsletterPrivacyHref}"
|
||||
class="font-semibold text-indigo-600 hover:text-indigo-800 dark:text-indigo-400 dark:hover:text-indigo-300"
|
||||
>
|
||||
privacy policy
|
||||
</a>.
|
||||
{newsletterPrivacyLabel}
|
||||
</a>{newsletterFinePrintSuffix}
|
||||
</p>
|
||||
|
||||
<div
|
||||
@@ -148,7 +181,7 @@ component PublicFooter {
|
||||
<span
|
||||
class="grid h-11 w-11 place-items-center rounded-2xl bg-indigo-600 text-white shadow-lg shadow-indigo-600/20 transition group-hover:-translate-y-0.5 group-hover:bg-indigo-500"
|
||||
>
|
||||
<span class="icon-[lucide--blocks] h-5 w-5" aria-hidden="true" ></span>
|
||||
<span class="{brandIcon} h-5 w-5" aria-hidden="true" ></span>
|
||||
</span>
|
||||
|
||||
<span>
|
||||
@@ -165,13 +198,12 @@ component PublicFooter {
|
||||
</a>
|
||||
|
||||
<p class="mt-5 max-w-sm text-sm leading-6 text-slate-600 dark:text-slate-400">
|
||||
Secure authentication, user management, organizations,
|
||||
authorization, and enterprise identity for modern applications.
|
||||
{brandDescription}
|
||||
</p>
|
||||
|
||||
<div class="mt-6 flex flex-wrap items-center gap-2">
|
||||
<div data-show="showStatus" class="mt-6 flex flex-wrap items-center gap-2">
|
||||
<a
|
||||
href="/status"
|
||||
href="{statusHref}"
|
||||
class="inline-flex items-center gap-2 rounded-xl border border-emerald-200 bg-emerald-50 px-3 py-2 text-xs font-semibold text-emerald-800 transition hover:border-emerald-300 hover:bg-emerald-100 dark:border-emerald-500/20 dark:bg-emerald-500/10 dark:text-emerald-300 dark:hover:border-emerald-500/30"
|
||||
>
|
||||
<span class="relative flex h-2 w-2">
|
||||
@@ -179,12 +211,17 @@ component PublicFooter {
|
||||
<span class="relative inline-flex h-2 w-2 rounded-full bg-emerald-500"></span>
|
||||
</span>
|
||||
|
||||
All systems operational
|
||||
{statusLabel}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<!-- Social links -->
|
||||
<div data-show="showSocialLinks" class="mt-6 flex items-center gap-2">
|
||||
{#if socialLinks.length > 0}
|
||||
{#each socialLinks as item}
|
||||
<a href="{item.href}" target="{item.target || '_blank'}" rel="noopener noreferrer" aria-label="{item.ariaLabel || item.label}" class="grid h-10 w-10 place-items-center rounded-xl border border-slate-200 bg-white text-slate-500 transition hover:border-indigo-300 hover:text-indigo-700 dark:border-white/10 dark:bg-white/5 dark:text-slate-400 dark:hover:border-indigo-500/30 dark:hover:text-indigo-300"><span class="{item.icon || 'icon-[lucide--external-link]'} h-4.5 w-4.5" aria-hidden="true"></span><span class="sr-only">{item.label}</span></a>
|
||||
{/each}
|
||||
{:else}
|
||||
<a
|
||||
href="https://github.com/wrnexus"
|
||||
target="_blank"
|
||||
@@ -224,15 +261,21 @@ component PublicFooter {
|
||||
>
|
||||
<span class="icon-[lucide--youtube] h-4.5 w-4.5" aria-hidden="true" ></span>
|
||||
</a>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Navigation columns -->
|
||||
<nav
|
||||
aria-label="Footer navigation"
|
||||
aria-label="{navigationAriaLabel}"
|
||||
class="grid grid-cols-2 gap-x-6 gap-y-10 sm:grid-cols-3 xl:grid-cols-5"
|
||||
>
|
||||
<slot name="navigation">
|
||||
{#if navigationColumns.length > 0}
|
||||
{#each navigationColumns as column}
|
||||
<div><h3 class="text-sm font-bold text-slate-950 dark:text-white">{column.title}</h3><ul class="mt-4 space-y-3">{#each column.links as item}<li><a href="{item.href}" target="{item.target || '_self'}" aria-label="{item.ariaLabel || item.label}" class="footer-link">{item.label}</a></li>{/each}</ul></div>
|
||||
{/each}
|
||||
{:else}
|
||||
<!-- Product -->
|
||||
<div>
|
||||
<h3 class="text-sm font-bold text-slate-950 dark:text-white">
|
||||
@@ -547,6 +590,7 @@ component PublicFooter {
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
{/if}
|
||||
</slot>
|
||||
</nav>
|
||||
</div>
|
||||
@@ -570,6 +614,9 @@ component PublicFooter {
|
||||
</div>
|
||||
|
||||
<div class="flex flex-wrap items-center gap-x-5 gap-y-3">
|
||||
{#if legalLinks.length > 0}
|
||||
{#each legalLinks as item}<a href="{item.href}" target="{item.target || '_self'}" class="footer-bottom-link">{item.label}</a>{/each}
|
||||
{:else}
|
||||
<a
|
||||
href="/privacy"
|
||||
class="footer-bottom-link"
|
||||
@@ -595,27 +642,30 @@ component PublicFooter {
|
||||
href="/legal"
|
||||
class="footer-bottom-link"
|
||||
>
|
||||
Legal
|
||||
{legalTitle}
|
||||
</a>
|
||||
{/if}
|
||||
|
||||
<button data-show="showThemeToggle"
|
||||
<button data-show="showCookiePreferences"
|
||||
type="button"
|
||||
data-open-cookie-preferences
|
||||
class="footer-bottom-link"
|
||||
>
|
||||
Cookie preferences
|
||||
{cookiePreferencesLabel}
|
||||
</button>
|
||||
|
||||
<button
|
||||
<button data-show="showThemeToggle"
|
||||
type="button"
|
||||
data-wire-theme-toggle
|
||||
aria-label="{themeToggleLabel}"
|
||||
title="{themeToggleLabel}"
|
||||
class="inline-flex items-center gap-2 rounded-lg text-xs font-semibold text-slate-500 transition hover:text-indigo-700 dark:text-slate-400 dark:hover:text-indigo-300"
|
||||
>
|
||||
<span class="icon-[lucide--moon] h-3.5 w-3.5 dark:hidden" aria-hidden="true" ></span>
|
||||
|
||||
<span class="icon-[lucide--sun] hidden h-3.5 w-3.5 dark:block" aria-hidden="true" ></span>
|
||||
|
||||
Theme
|
||||
{themeLabel}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -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>
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@wrnexus/ui",
|
||||
"version": "0.2.73",
|
||||
"version": "0.2.74",
|
||||
"type": "module",
|
||||
"description": "@wrnexus/ui — part of the WrNexus framework.",
|
||||
"license": "MIT",
|
||||
@@ -25,7 +25,7 @@
|
||||
"./ui.css": "./ui.css"
|
||||
},
|
||||
"dependencies": {
|
||||
"@wrnexus/core": "^0.2.73"
|
||||
"@wrnexus/core": "^0.2.74"
|
||||
},
|
||||
"files": [
|
||||
"dist",
|
||||
|
||||
@@ -1186,6 +1186,44 @@
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.wire-public-header-action {
|
||||
display: inline-flex;
|
||||
min-height: 2.5rem;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 0.5rem;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 0.75rem;
|
||||
padding: 0.625rem 1rem;
|
||||
color: var(--wire-color-text);
|
||||
font-size: 0.875rem;
|
||||
font-weight: 700;
|
||||
text-decoration: none;
|
||||
transition:
|
||||
background var(--wire-motion-base),
|
||||
border-color var(--wire-motion-base),
|
||||
color var(--wire-motion-base),
|
||||
transform var(--wire-motion-base) var(--wire-ease-emphasized);
|
||||
}
|
||||
.wire-public-header-action--primary {
|
||||
color: var(--wire-color-primary-contrast);
|
||||
background: var(--wire-color-primary);
|
||||
box-shadow: 0 0.75rem 1.5rem color-mix(in srgb, var(--wire-color-primary) 20%, transparent);
|
||||
}
|
||||
.wire-public-header-action--primary:hover {
|
||||
background: var(--wire-color-primary-hover);
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
.wire-public-header-action--secondary {
|
||||
border-color: var(--wire-color-border);
|
||||
background: var(--wire-color-surface);
|
||||
}
|
||||
.wire-public-header-action--secondary:hover,
|
||||
.wire-public-header-action--ghost:hover {
|
||||
color: var(--wire-color-primary);
|
||||
background: var(--wire-color-surface-2);
|
||||
}
|
||||
.wire-auth-field__input {
|
||||
width: 100%;
|
||||
min-height: 3.5rem;
|
||||
|
||||
Reference in New Issue
Block a user