@contentrain/astro-kit 0.49.3 → 0.50.1
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/catalog.json
CHANGED
|
@@ -3566,7 +3566,7 @@
|
|
|
3566
3566
|
{
|
|
3567
3567
|
"id": "header",
|
|
3568
3568
|
"name": "Header",
|
|
3569
|
-
"description": "Site header: brand (logo and/or name), navigation
|
|
3569
|
+
"description": "Site header: brand (logo and/or name), navigation, an optional call-to-action button and an optional utility row above the bar (phone, mail, address, hours).",
|
|
3570
3570
|
"category": "chrome",
|
|
3571
3571
|
"uses": [
|
|
3572
3572
|
"nav",
|
|
@@ -3739,7 +3739,23 @@
|
|
|
3739
3739
|
]
|
|
3740
3740
|
}
|
|
3741
3741
|
},
|
|
3742
|
-
"description": "Header button,
|
|
3742
|
+
"description": "Header button, on every screen width."
|
|
3743
|
+
},
|
|
3744
|
+
"strip": {
|
|
3745
|
+
"type": "array",
|
|
3746
|
+
"items": {
|
|
3747
|
+
"type": "object",
|
|
3748
|
+
"fields": {
|
|
3749
|
+
"label": {
|
|
3750
|
+
"type": "string",
|
|
3751
|
+
"required": true
|
|
3752
|
+
},
|
|
3753
|
+
"href": {
|
|
3754
|
+
"type": "url"
|
|
3755
|
+
}
|
|
3756
|
+
}
|
|
3757
|
+
},
|
|
3758
|
+
"description": "A row above the bar for what the source's header prints next to its menu: a phone number, a mail address, the address, the opening hours. A line with an href is a link (tel:, mailto:, a page). On a phone it folds into the menu drawer after the menu; with no menu it stays above the bar."
|
|
3743
3759
|
},
|
|
3744
3760
|
"search": {
|
|
3745
3761
|
"type": "object",
|
|
@@ -4664,6 +4680,22 @@
|
|
|
4664
4680
|
"part": {
|
|
4665
4681
|
"type": "string",
|
|
4666
4682
|
"description": "What the navigation is, for checks that find a page's parts (data-cr-part), e.g. \"nav-header\"."
|
|
4683
|
+
},
|
|
4684
|
+
"extra": {
|
|
4685
|
+
"type": "array",
|
|
4686
|
+
"items": {
|
|
4687
|
+
"type": "object",
|
|
4688
|
+
"fields": {
|
|
4689
|
+
"label": {
|
|
4690
|
+
"type": "string",
|
|
4691
|
+
"required": true
|
|
4692
|
+
},
|
|
4693
|
+
"href": {
|
|
4694
|
+
"type": "url"
|
|
4695
|
+
}
|
|
4696
|
+
}
|
|
4697
|
+
},
|
|
4698
|
+
"description": "Lines after the menu in the narrow-screen menu (a header's phone, address, hours); a line with an href is a link."
|
|
4667
4699
|
}
|
|
4668
4700
|
},
|
|
4669
4701
|
"slots": {},
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
|
-
// Site header: brand (logo and/or name), navigation
|
|
3
|
-
// action.
|
|
2
|
+
// Site header: brand (logo and/or name), navigation, an optional call to
|
|
3
|
+
// action and an optional utility row above the bar (phone, mail, address, hours).
|
|
4
4
|
import { tv } from 'tailwind-variants'
|
|
5
5
|
import Button from '../_shared/Button.astro'
|
|
6
6
|
import KitImage from '../_shared/KitImage.astro'
|
|
@@ -63,7 +63,14 @@ interface Props {
|
|
|
63
63
|
showName?: boolean | undefined
|
|
64
64
|
homeHref?: string | undefined
|
|
65
65
|
items: NavItem[]
|
|
66
|
+
/** The header's button, on every screen width. */
|
|
66
67
|
action?: ActionInput | undefined
|
|
68
|
+
/**
|
|
69
|
+
* A row above the bar for what the source's header prints next to its menu: a phone number, a mail address, the
|
|
70
|
+
* address, the opening hours. A line with an `href` is a link (`tel:`, `mailto:`, a page). On a phone the row folds
|
|
71
|
+
* into the menu drawer, after the menu; with no menu it stays above the bar.
|
|
72
|
+
*/
|
|
73
|
+
strip?: Array<{ label: string, href?: string | undefined }> | undefined
|
|
67
74
|
/** A search field in the bar (a GET form to the site's search page); below the bar until lg. */
|
|
68
75
|
search?: { label?: string | undefined, placeholder?: string | undefined, submitLabel?: string | undefined, action?: string | undefined } | undefined
|
|
69
76
|
navLabel?: string | undefined
|
|
@@ -76,7 +83,7 @@ interface Props {
|
|
|
76
83
|
menu?: 'flyout' | 'mega' | undefined
|
|
77
84
|
}
|
|
78
85
|
|
|
79
|
-
const { siteName, tagline, brandSize, brandWeight, brandTracking, bordered, offsetTop, padTop, padBottom, linkNav, brandColor, logo, showName = true, homeHref = '/', items, action, search, navLabel, menuLabel, closeLabel, layout, tone, position, menu } = Astro.props
|
|
86
|
+
const { siteName, tagline, brandSize, brandWeight, brandTracking, bordered, offsetTop, padTop, padBottom, linkNav, brandColor, logo, showName = true, homeHref = '/', items, action, strip = [], search, navLabel, menuLabel, closeLabel, layout, tone, position, menu } = Astro.props
|
|
80
87
|
const { root, inner, brand } = header({ layout, tone, position, bordered })
|
|
81
88
|
// The header's search field: `header-search` on a page, a second header's its own (its label points at its own input).
|
|
82
89
|
const searchId = search ? instanceId(Astro.locals, undefined, 'header-search') : undefined
|
|
@@ -84,11 +91,22 @@ const rootStyle = offsetTop ? `margin-top: ${offsetTop}` : undefined
|
|
|
84
91
|
const innerStyle = [padTop && `padding-top: ${padTop}`, padBottom && `padding-bottom: ${padBottom}`].filter(Boolean).join('; ') || undefined
|
|
85
92
|
const brandColour = brandColorValue(brandColor)
|
|
86
93
|
const brandStyle = [brandSize && `font-size: ${brandSize}`, brandWeight && `font-weight: ${brandWeight}`, brandTracking && `letter-spacing: ${brandTracking}`, brandColour && `color: ${brandColour}`].filter(Boolean).join('; ') || undefined
|
|
94
|
+
// The row above the bar folds into the drawer only where there is one: Nav prints nothing without items.
|
|
95
|
+
const stripFolds = items.length > 0
|
|
87
96
|
// A tagline under the name keeps its line on a phone, as themes print it: the navigation wraps below.
|
|
88
97
|
// The search field sits in the bar from lg; at md the bar already holds the navigation, so the field keeps its own row.
|
|
89
98
|
const wrap = search ? 'flex-wrap lg:flex-nowrap' : tagline ? 'flex-wrap md:flex-nowrap' : undefined
|
|
90
99
|
---
|
|
91
100
|
<header class={root()} style={rootStyle}>
|
|
101
|
+
{strip.length > 0 && (
|
|
102
|
+
<div class:list={['border-b border-current/10 text-sm', stripFolds && 'hidden md:block']} data-kit-strip>
|
|
103
|
+
<ul class={`container-page flex flex-wrap items-center justify-end gap-x-6 gap-y-1 py-2 ${muted}`}>
|
|
104
|
+
{strip.map(line => (
|
|
105
|
+
<li>{line.href ? <a href={safeHref(line.href)} class="text-current no-underline hover:underline">{line.label}</a> : line.label}</li>
|
|
106
|
+
))}
|
|
107
|
+
</ul>
|
|
108
|
+
</div>
|
|
109
|
+
)}
|
|
92
110
|
<div class={inner({ class: wrap })} style={innerStyle}>
|
|
93
111
|
{tagline
|
|
94
112
|
? (
|
|
@@ -112,8 +130,8 @@ const wrap = search ? 'flex-wrap lg:flex-nowrap' : tagline ? 'flex-wrap md:flex-
|
|
|
112
130
|
</div>
|
|
113
131
|
)}
|
|
114
132
|
<div class:list={['flex items-center gap-4', layout === 'centered' ? 'justify-center' : 'ms-auto']}>
|
|
115
|
-
<Nav items={items} menu={menu} label={navLabel} menuLabel={menuLabel} closeLabel={closeLabel} part="nav-header" color={linkNav ? 'link' : 'current'} align={layout === 'centered' ? 'center' : 'end'} />
|
|
116
|
-
{action && <Button action={action} size="sm"
|
|
133
|
+
<Nav items={items} menu={menu} label={navLabel} menuLabel={menuLabel} closeLabel={closeLabel} part="nav-header" extra={stripFolds ? strip : undefined} color={linkNav ? 'link' : 'current'} align={layout === 'centered' ? 'center' : 'end'} />
|
|
134
|
+
{action && <Button action={action} size="sm" />}
|
|
117
135
|
</div>
|
|
118
136
|
</div>
|
|
119
137
|
</header>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "header",
|
|
3
3
|
"name": "Header",
|
|
4
|
-
"description": "Site header: brand (logo and/or name), navigation
|
|
4
|
+
"description": "Site header: brand (logo and/or name), navigation, an optional call-to-action button and an optional utility row above the bar (phone, mail, address, hours).",
|
|
5
5
|
"category": "chrome",
|
|
6
6
|
"uses": ["nav", "search-box"],
|
|
7
7
|
"shared": ["Button.astro", "KitImage.astro", "image-widths.ts", "instance-id.ts", "muted.ts", "safe-url.ts", "types.ts"],
|
|
@@ -27,7 +27,8 @@
|
|
|
27
27
|
"showName": { "type": "boolean", "default": true, "description": "Show the site name next to the logo." },
|
|
28
28
|
"homeHref": { "type": "url", "default": "/", "description": "Where the brand links." },
|
|
29
29
|
"items": { "type": "array", "required": true, "items": { "type": "object", "fields": { "label": { "type": "string", "required": true }, "href": { "type": "url", "required": true }, "newTab": { "type": "boolean" }, "children": { "type": "array" } } }, "description": "Primary menu (menus → menu-items)." },
|
|
30
|
-
"action": { "type": "object", "fields": { "label": { "type": "string", "required": true }, "href": { "type": "url", "required": true }, "style": { "type": "select", "options": ["primary", "secondary", "ghost"] } }, "description": "Header button,
|
|
30
|
+
"action": { "type": "object", "fields": { "label": { "type": "string", "required": true }, "href": { "type": "url", "required": true }, "style": { "type": "select", "options": ["primary", "secondary", "ghost"] } }, "description": "Header button, on every screen width." },
|
|
31
|
+
"strip": { "type": "array", "items": { "type": "object", "fields": { "label": { "type": "string", "required": true }, "href": { "type": "url" } } }, "description": "A row above the bar for what the source's header prints next to its menu: a phone number, a mail address, the address, the opening hours. A line with an href is a link (tel:, mailto:, a page). On a phone it folds into the menu drawer after the menu; with no menu it stays above the bar." },
|
|
31
32
|
"search": { "type": "object", "fields": { "label": { "type": "string" }, "placeholder": { "type": "string" }, "submitLabel": { "type": "string" }, "action": { "type": "url" } }, "description": "A search field in the bar: a GET form to the site's search page (default /search); below the bar on a phone." },
|
|
32
33
|
"navLabel": { "type": "string", "description": "Accessible name of the navigation (ui-strings nav.label)." },
|
|
33
34
|
"menuLabel": { "type": "string", "description": "Narrow-screen toggle text (ui-strings nav.menu)." },
|
package/components/nav/Nav.astro
CHANGED
|
@@ -50,11 +50,13 @@ interface Props {
|
|
|
50
50
|
color?: 'current' | 'link' | undefined
|
|
51
51
|
/** Unique per page when a page has two navigations. */
|
|
52
52
|
id?: string | undefined
|
|
53
|
+
/** Lines after the menu in the narrow-screen menu (a header's phone, address, hours); a line with an `href` is a link. */
|
|
54
|
+
extra?: Array<{ label: string, href?: string | undefined }> | undefined
|
|
53
55
|
/** What the navigation is, for checks that find a page's parts (`data-cr-part`, e.g. "nav-header"). */
|
|
54
56
|
part?: string | undefined
|
|
55
57
|
}
|
|
56
58
|
|
|
57
|
-
const { items, label = 'Main', menuLabel = 'Menu', closeLabel = 'Close', mobile = 'popover', menu, align, density, color, id: givenId, part } = Astro.props
|
|
59
|
+
const { items, label = 'Main', menuLabel = 'Menu', closeLabel = 'Close', mobile = 'popover', menu, align, density, color, extra = [], id: givenId, part } = Astro.props
|
|
58
60
|
// Two on one page never share an id: their labels and controls would point into each other.
|
|
59
61
|
const id = instanceId(Astro.locals, givenId, 'site-nav')
|
|
60
62
|
const { list, link, sub, toggle } = nav({ menu, align, density, color })
|
|
@@ -117,6 +119,13 @@ const real = (href: string | undefined) => !!href && href !== '#'
|
|
|
117
119
|
{item.children && item.children.length > 0 && <NavTree items={item.children} current={current} kind="drawer" />}
|
|
118
120
|
</li>
|
|
119
121
|
))}
|
|
122
|
+
{extra.map((line, index) => (
|
|
123
|
+
<li class={index === 0 ? 'mt-4 border-t border-line pt-4' : undefined}>
|
|
124
|
+
{line.href
|
|
125
|
+
? <a href={safeHref(line.href)} class="block rounded-md px-3 py-2 text-sm text-ink no-underline hover:bg-surface-muted">{line.label}</a>
|
|
126
|
+
: <span class="block px-3 py-2 text-sm text-ink">{line.label}</span>}
|
|
127
|
+
</li>
|
|
128
|
+
))}
|
|
120
129
|
</ul>
|
|
121
130
|
</div>
|
|
122
131
|
</>
|
|
@@ -136,6 +145,13 @@ const real = (href: string | undefined) => !!href && href !== '#'
|
|
|
136
145
|
{item.children && item.children.length > 0 && <NavTree items={item.children} current={current} kind="drawer" />}
|
|
137
146
|
</li>
|
|
138
147
|
))}
|
|
148
|
+
{extra.map((line, index) => (
|
|
149
|
+
<li class={index === 0 ? 'mt-2 border-t border-line pt-2' : undefined}>
|
|
150
|
+
{line.href
|
|
151
|
+
? <a href={safeHref(line.href)} class="block rounded-md px-3 py-2 text-sm text-ink no-underline hover:bg-surface-muted">{line.label}</a>
|
|
152
|
+
: <span class="block px-3 py-2 text-sm text-ink">{line.label}</span>}
|
|
153
|
+
</li>
|
|
154
|
+
))}
|
|
139
155
|
</ul>
|
|
140
156
|
</details>
|
|
141
157
|
)}
|
package/components/nav/meta.json
CHANGED
|
@@ -97,6 +97,22 @@
|
|
|
97
97
|
"part": {
|
|
98
98
|
"type": "string",
|
|
99
99
|
"description": "What the navigation is, for checks that find a page's parts (data-cr-part), e.g. \"nav-header\"."
|
|
100
|
+
},
|
|
101
|
+
"extra": {
|
|
102
|
+
"type": "array",
|
|
103
|
+
"items": {
|
|
104
|
+
"type": "object",
|
|
105
|
+
"fields": {
|
|
106
|
+
"label": {
|
|
107
|
+
"type": "string",
|
|
108
|
+
"required": true
|
|
109
|
+
},
|
|
110
|
+
"href": {
|
|
111
|
+
"type": "url"
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
"description": "Lines after the menu in the narrow-screen menu (a header's phone, address, hours); a line with an href is a link."
|
|
100
116
|
}
|
|
101
117
|
},
|
|
102
118
|
"slots": {},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contentrain/astro-kit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.50.1",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "Copy-in Astro components for Contentrain sites (shadcn model): typed props, tailwind-variants, zero JavaScript by default — with a machine-readable catalog",
|
|
6
6
|
"type": "module",
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"mapping"
|
|
43
43
|
],
|
|
44
44
|
"dependencies": {
|
|
45
|
-
"@contentrain/types": "1.
|
|
45
|
+
"@contentrain/types": "1.77.0"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
48
|
"@types/node": "^22.10.0",
|