@hubpav/hwio-ui 0.1.5 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +4 -4
- package/src/components/HWioHeader.astro +15 -5
- package/src/components/HWioLogoStrip.astro +3 -2
- package/src/components/HWioPricingTiers.astro +2 -1
- package/src/styles/styles.css +0 -17
- package/src/styles/themes/hwio-dark.css +2 -2
- package/src/styles/themes/hwio-forestry-dark.css +2 -2
- package/src/types.ts +2 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hubpav/hwio-ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "HARDWARIO web design system for Astro: DaisyUI 5 themes generated from the brand tokens, the Tailwind entry stylesheet and the HWio* components.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -31,9 +31,9 @@
|
|
|
31
31
|
"build": "node scripts/build-themes.mjs"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@hubpav/hwio-brand": "0.
|
|
35
|
-
"@hubpav/hwio-web-runtime": "0.
|
|
36
|
-
"@hubpav/hwio-web-worker": "0.
|
|
34
|
+
"@hubpav/hwio-brand": "0.3.0",
|
|
35
|
+
"@hubpav/hwio-web-runtime": "0.3.0",
|
|
36
|
+
"@hubpav/hwio-web-worker": "0.3.0",
|
|
37
37
|
"daisyui": "5.7.28"
|
|
38
38
|
},
|
|
39
39
|
"peerDependencies": {
|
|
@@ -17,10 +17,17 @@ interface Props {
|
|
|
17
17
|
showThemeToggle?: boolean;
|
|
18
18
|
scrollspy?: boolean;
|
|
19
19
|
labels: { nav: string; menu: string; close: string; theme?: string; languages?: string };
|
|
20
|
+
/** Viewport from which the inline nav and CTAs replace the drawer (default lg; xl for long navs). */
|
|
21
|
+
desktopFrom?: 'lg' | 'xl';
|
|
20
22
|
id?: string;
|
|
21
23
|
class?: string;
|
|
22
24
|
}
|
|
23
|
-
const { nav, ctas = [], languages = [], showThemeToggle = true, scrollspy = false, labels, id = 'hwio-nav-drawer', class: className = '' } = Astro.props;
|
|
25
|
+
const { nav, ctas = [], languages = [], showThemeToggle = true, scrollspy = false, labels, desktopFrom = 'lg', id = 'hwio-nav-drawer', class: className = '' } = Astro.props;
|
|
26
|
+
const BREAK = {
|
|
27
|
+
lg: { nav: 'hidden flex-1 justify-center lg:flex', ctas: 'hidden items-center gap-2 lg:flex', drawer: 'drawer drawer-end w-auto lg:hidden' },
|
|
28
|
+
xl: { nav: 'hidden flex-1 justify-center xl:flex', ctas: 'hidden items-center gap-2 xl:flex', drawer: 'drawer drawer-end w-auto xl:hidden' },
|
|
29
|
+
} as const;
|
|
30
|
+
const bp = BREAK[desktopFrom];
|
|
24
31
|
const CTA_VARIANT = { primary: 'primary', secondary: 'secondary', ghost: 'ghost' } as const;
|
|
25
32
|
---
|
|
26
33
|
<header class:list={['sticky top-0 z-50 border-b border-base-300 bg-base-100/90 backdrop-blur supports-[backdrop-filter]:bg-base-100/80', className]} data-hwio-font-exempt>
|
|
@@ -29,7 +36,7 @@ const CTA_VARIANT = { primary: 'primary', secondary: 'secondary', ghost: 'ghost'
|
|
|
29
36
|
<slot name="logo" />
|
|
30
37
|
</div>
|
|
31
38
|
|
|
32
|
-
<nav class=
|
|
39
|
+
<nav class={bp.nav} aria-label={labels.nav} data-hwio-scrollspy={scrollspy ? 'true' : undefined}>
|
|
33
40
|
<ul class="menu menu-horizontal flex-nowrap gap-0 px-0 whitespace-nowrap">
|
|
34
41
|
{nav.map((item) => (
|
|
35
42
|
<li>
|
|
@@ -51,12 +58,15 @@ const CTA_VARIANT = { primary: 'primary', secondary: 'secondary', ghost: 'ghost'
|
|
|
51
58
|
<div class="ml-auto flex items-center gap-2">
|
|
52
59
|
{showThemeToggle && <HWioThemeToggle label={labels.theme ?? 'Theme'} />}
|
|
53
60
|
{languages.length > 1 && <HWioLanguageSwitcher items={languages} label={labels.languages ?? 'Language'} />}
|
|
54
|
-
<div class=
|
|
61
|
+
<div class={bp.ctas}>
|
|
55
62
|
{ctas.map((cta) => (
|
|
56
|
-
<HWioButton href={cta.href} external={cta.external} variant={CTA_VARIANT[cta.variant ?? 'primary']} size="sm" track={cta.track ?? { id: 'header-cta', location: 'header' }}
|
|
63
|
+
<HWioButton href={cta.href} external={cta.external} variant={CTA_VARIANT[cta.variant ?? 'primary']} size="sm" track={cta.track ?? { id: 'header-cta', location: 'header' }} class={cta.icon ? '2xl:px-4 px-2.5' : ''} aria-label={cta.icon ? cta.label : undefined} title={cta.icon ? cta.label : undefined}>
|
|
64
|
+
{cta.icon && <HWioIcon name={cta.icon as 'bag'} size="sm" />}
|
|
65
|
+
{cta.icon ? <span class="hidden 2xl:inline">{cta.label}</span> : cta.label}
|
|
66
|
+
</HWioButton>
|
|
57
67
|
))}
|
|
58
68
|
</div>
|
|
59
|
-
<div class=
|
|
69
|
+
<div class={bp.drawer}>
|
|
60
70
|
<input id={id} type="checkbox" class="drawer-toggle" />
|
|
61
71
|
<div class="drawer-content">
|
|
62
72
|
<label for={id} class="btn btn-ghost btn-square drawer-button" aria-label={labels.menu} aria-controls={`${id}-panel`} aria-expanded="false" tabindex="0" role="button">
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
---
|
|
2
2
|
/** Customer/partner logos as a static row or an infinite marquee (paused on hover, static under reduced motion). */
|
|
3
3
|
import type { HWioTone } from '../types';
|
|
4
|
-
interface Logo { src: string; alt: string; href?: string; width: number; height: number; class?: string }
|
|
4
|
+
interface Logo { src: string; alt: string; href?: string; width: number; height: number; class?: string; /** Rendered height step (default md = 28 px); logos with thin marks go up, dense ones down. */ size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl' }
|
|
5
5
|
interface Props { id?: string; logos: Logo[]; label?: string; marquee?: boolean; grey?: boolean; tone?: HWioTone; class?: string }
|
|
6
6
|
const { id, logos, label, marquee = true, grey = true, tone = 'base', class: className = '' } = Astro.props;
|
|
7
7
|
const TONE = { base: 'bg-base-100', alt: 'bg-base-200', neutral: 'bg-neutral text-neutral-content' } as const;
|
|
8
8
|
const FADE = { base: 'from-base-100', alt: 'from-base-200', neutral: 'from-neutral' } as const;
|
|
9
9
|
const groups = marquee ? [0, 1, 2, 3] : [0];
|
|
10
|
+
const SIZE = { xs: 'h-6', sm: 'h-7', md: 'h-7', lg: 'h-10', xl: 'h-12' } as const;
|
|
10
11
|
---
|
|
11
12
|
<section id={id} class:list={['overflow-hidden border-y border-base-300 py-10', TONE[tone], className]}>
|
|
12
13
|
{label && <div class="container"><p class="mb-8 text-center text-sm font-semibold opacity-70">{label}</p></div>}
|
|
@@ -17,7 +18,7 @@ const groups = marquee ? [0, 1, 2, 3] : [0];
|
|
|
17
18
|
{groups.map((g) => (
|
|
18
19
|
<div class="flex shrink-0 items-center" aria-hidden={g > 0 ? 'true' : undefined}>
|
|
19
20
|
{logos.map((logo) => {
|
|
20
|
-
const img = <img src={logo.src} alt={logo.alt} width={logo.width} height={logo.height} loading="lazy" decoding="async" class:list={['
|
|
21
|
+
const img = <img src={logo.src} alt={logo.alt} width={logo.width} height={logo.height} loading="lazy" decoding="async" class:list={[SIZE[logo.size ?? 'md'], 'w-auto transition-transform duration-300 hover:scale-105', grey ? 'hwio-logo-grey' : '', logo.class]} />;
|
|
21
22
|
return logo.href
|
|
22
23
|
? <a href={logo.href} target="_blank" rel="noopener noreferrer" class="mx-8" tabindex={g > 0 ? -1 : undefined}>{img}</a>
|
|
23
24
|
: <span class="mx-8">{img}</span>;
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import type { HWioCta } from '../types';
|
|
3
3
|
import HWioButton from './HWioButton.astro';
|
|
4
4
|
import HWioIcon from './HWioIcon.astro';
|
|
5
|
-
interface Tier { name: string; price?: string; description?: string; features: string[]; cta?: HWioCta; featured?: boolean; badge?: string }
|
|
5
|
+
interface Tier { eyebrow?: string; name: string; price?: string; description?: string; features: string[]; cta?: HWioCta; featured?: boolean; badge?: string }
|
|
6
6
|
interface Props { tiers: Tier[]; class?: string }
|
|
7
7
|
const { tiers, class: className = '' } = Astro.props;
|
|
8
8
|
const COLS = { 1: 'grid gap-6', 2: 'grid gap-6 md:grid-cols-2', 3: 'grid gap-6 md:grid-cols-3', 4: 'grid gap-6 md:grid-cols-2 lg:grid-cols-4' } as const;
|
|
@@ -12,6 +12,7 @@ const cols = (Math.min(Math.max(tiers.length, 1), 4) as 1 | 2 | 3 | 4);
|
|
|
12
12
|
{tiers.map((tier) => (
|
|
13
13
|
<article class:list={['card card-border bg-base-100 h-full', tier.featured ? 'border-primary shadow-lg' : '']}>
|
|
14
14
|
<div class="card-body">
|
|
15
|
+
{tier.eyebrow && <p class="hwio-kicker">{tier.eyebrow}</p>}
|
|
15
16
|
<div class="flex items-start justify-between gap-2">
|
|
16
17
|
<h3 class="card-title text-[1.375rem]">{tier.name}</h3>
|
|
17
18
|
{tier.badge && <span class="badge badge-primary">{tier.badge}</span>}
|
package/src/styles/styles.css
CHANGED
|
@@ -226,20 +226,3 @@
|
|
|
226
226
|
.btn-lg { height: var(--size); --fontsize: 0.9375rem; padding-inline: 1.75rem; }
|
|
227
227
|
.btn-square, .btn-circle { padding-inline: 0; }
|
|
228
228
|
.card .card-body { --card-p: 2rem; }
|
|
229
|
-
|
|
230
|
-
/* Dark themes keep the navy primary for filled buttons (white on navy: 11.6:1), but navy text is
|
|
231
|
-
1.3-1.7:1 on the night surfaces, so outline and ghost primary buttons take the light brand blue
|
|
232
|
-
there (5.3-6.5:1) and fill with it on hover, dark text on top. Both dark cases: an explicit
|
|
233
|
-
data-theme ending in -dark, and the system preference with no stored choice (DaisyUI's prefersdark). */
|
|
234
|
-
[data-theme$="-dark"] .btn-outline.btn-primary,
|
|
235
|
-
[data-theme$="-dark"] .btn-ghost.btn-primary {
|
|
236
|
-
--btn-color: var(--color-info);
|
|
237
|
-
--btn-fg: var(--color-base-100);
|
|
238
|
-
}
|
|
239
|
-
@media (prefers-color-scheme: dark) {
|
|
240
|
-
:root:not([data-theme]) .btn-outline.btn-primary,
|
|
241
|
-
:root:not([data-theme]) .btn-ghost.btn-primary {
|
|
242
|
-
--btn-color: var(--color-info);
|
|
243
|
-
--btn-fg: var(--color-base-100);
|
|
244
|
-
}
|
|
245
|
-
}
|
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
--color-base-200: #1a1a22;
|
|
9
9
|
--color-base-300: #23232f;
|
|
10
10
|
--color-base-content: #e7e7ee;
|
|
11
|
-
--color-primary: #
|
|
12
|
-
--color-primary-content: #
|
|
11
|
+
--color-primary: #009cfa;
|
|
12
|
+
--color-primary-content: #0f0f14;
|
|
13
13
|
--color-secondary: #016ad4;
|
|
14
14
|
--color-secondary-content: #ffffff;
|
|
15
15
|
--color-accent: #f43f5e;
|
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
--color-base-200: #1a1a22;
|
|
9
9
|
--color-base-300: #23232f;
|
|
10
10
|
--color-base-content: #e7e7ee;
|
|
11
|
-
--color-primary: #
|
|
12
|
-
--color-primary-content: #
|
|
11
|
+
--color-primary: #5aa864;
|
|
12
|
+
--color-primary-content: #0f0f14;
|
|
13
13
|
--color-secondary: #016ad4;
|
|
14
14
|
--color-secondary-content: #ffffff;
|
|
15
15
|
--color-accent: #5aa864;
|
package/src/types.ts
CHANGED
|
@@ -24,6 +24,8 @@ export interface HWioMedia {
|
|
|
24
24
|
export interface HWioCta extends HWioLinkItem {
|
|
25
25
|
/** Visual weight; primary is the DaisyUI btn-primary fill. */
|
|
26
26
|
variant?: 'primary' | 'secondary' | 'ghost';
|
|
27
|
+
/** HWioIcon name. In HWioHeader a CTA with an icon collapses to the icon alone below 2xl (label as aria-label). */
|
|
28
|
+
icon?: string;
|
|
27
29
|
}
|
|
28
30
|
|
|
29
31
|
export type HWioTone = 'base' | 'alt' | 'neutral';
|