@contentrain/astro-kit 0.3.1 → 0.4.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/catalog.json CHANGED
@@ -739,7 +739,7 @@
739
739
  },
740
740
  "copyright": {
741
741
  "type": "string",
742
- "description": "Copyright line; defaults to © <year> <siteName>."
742
+ "description": "Copyright line; {year} is the current year. Defaults to © <year> <siteName>."
743
743
  },
744
744
  "navLabel": {
745
745
  "type": "string",
@@ -937,6 +937,19 @@
937
937
  "required": true,
938
938
  "description": "Site title (site.title)."
939
939
  },
940
+ "tagline": {
941
+ "type": "string",
942
+ "description": "A line under the site name, as themes that print the tagline in the header do (site.tagline)."
943
+ },
944
+ "brandSize": {
945
+ "type": "string",
946
+ "description": "The site name's size where the source theme sets its own (a CSS length)."
947
+ },
948
+ "linkNav": {
949
+ "type": "boolean",
950
+ "default": false,
951
+ "description": "The navigation in the site's link colour, as themes that colour every link do."
952
+ },
940
953
  "logo": {
941
954
  "type": "object",
942
955
  "fields": {
@@ -1575,6 +1588,11 @@
1575
1588
  "max": 3,
1576
1589
  "default": 2,
1577
1590
  "description": "Title heading level in the page outline."
1591
+ },
1592
+ "linkTitle": {
1593
+ "type": "boolean",
1594
+ "default": false,
1595
+ "description": "The title in the site's link colour (--color-link), as themes that colour every link do."
1578
1596
  }
1579
1597
  },
1580
1598
  "slots": {},
@@ -33,7 +33,7 @@ interface Props {
33
33
  /** A single row of links (the footer menu). */
34
34
  links?: LinkInput[] | undefined
35
35
  social?: LinkInput[] | undefined
36
- /** The copyright line, e.g. "© 2026 Northwind Studio". */
36
+ /** The copyright line, e.g. "© 2026 Northwind Studio"; `{year}` is the current year. */
37
37
  copyright?: string | undefined
38
38
  /** Accessible name of the footer navigation ("Footer"). */
39
39
  navLabel?: string | undefined
@@ -43,7 +43,8 @@ interface Props {
43
43
 
44
44
  const { siteName, tagline, columns = [], links = [], social = [], copyright, navLabel = 'Footer', layout = 'simple', tone } = Astro.props
45
45
  const { root, inner, muted, link } = footer({ layout, tone })
46
- const line = copyright ?? `© ${new Date().getFullYear()} ${siteName}`
46
+ const year = String(new Date().getFullYear())
47
+ const line = copyright?.replaceAll('{year}', year) ?? `© ${year} ${siteName}`
47
48
  ---
48
49
  <footer class={root()}>
49
50
  <div class={inner()} style={layout === 'columns' ? `--footer-columns: ${Math.max(columns.length, 1)}` : undefined}>
@@ -93,7 +93,7 @@
93
93
  },
94
94
  "copyright": {
95
95
  "type": "string",
96
- "description": "Copyright line; defaults to © <year> <siteName>."
96
+ "description": "Copyright line; {year} is the current year. Defaults to © <year> <siteName>."
97
97
  },
98
98
  "navLabel": {
99
99
  "type": "string",
@@ -31,6 +31,12 @@ const header = tv({
31
31
 
32
32
  interface Props {
33
33
  siteName: string
34
+ /** A line under the site name, as themes that print the site's tagline in the header do. */
35
+ tagline?: string | undefined
36
+ /** The site name's size, where the source theme sets its own (a CSS length). */
37
+ brandSize?: string | undefined
38
+ /** The navigation in the site's link colour, as themes that colour every link do (Hello Elementor). */
39
+ linkNav?: boolean | undefined
34
40
  logo?: ImageInput | undefined
35
41
  /** Show the site name next to the logo. */
36
42
  showName?: boolean | undefined
@@ -45,16 +51,28 @@ interface Props {
45
51
  position?: 'static' | 'sticky' | undefined
46
52
  }
47
53
 
48
- const { siteName, logo, showName = true, homeHref = '/', items, action, navLabel, menuLabel, closeLabel, layout, tone, position } = Astro.props
54
+ const { siteName, tagline, brandSize, linkNav, logo, showName = true, homeHref = '/', items, action, navLabel, menuLabel, closeLabel, layout, tone, position } = Astro.props
49
55
  const { root, inner, brand } = header({ layout, tone, position })
50
56
  ---
51
57
  <header class={root()}>
52
58
  <div class={inner()}>
53
- <a href={homeHref} class={brand()} aria-label={showName ? undefined : siteName} data-kit-brand>
54
- {logo && <KitImage image={logo} priority class="h-8 w-auto" sizes="160px" />}
55
- {showName && <span>{siteName}</span>}
56
- </a>
57
- <div class:list={['flex items-center gap-4', layout === 'centered' ? 'justify-center' : 'ml-auto']}>
59
+ {tagline
60
+ ? (
61
+ <div class="flex flex-col gap-1">
62
+ <a href={homeHref} class={brand()} aria-label={showName ? undefined : siteName} style={brandSize ? `font-size: ${brandSize}` : undefined} data-kit-brand>
63
+ {logo && <KitImage image={logo} priority class="h-8 w-auto" sizes="160px" />}
64
+ {showName && <span>{siteName}</span>}
65
+ </a>
66
+ <p class="opacity-75" data-kit-tagline>{tagline}</p>
67
+ </div>
68
+ )
69
+ : (
70
+ <a href={homeHref} class={brand()} aria-label={showName ? undefined : siteName} style={brandSize ? `font-size: ${brandSize}` : undefined} data-kit-brand>
71
+ {logo && <KitImage image={logo} priority class="h-8 w-auto" sizes="160px" />}
72
+ {showName && <span>{siteName}</span>}
73
+ </a>
74
+ )}
75
+ <div class:list={['flex items-center gap-4', layout === 'centered' ? 'justify-center' : 'ml-auto', linkNav && 'text-[color:var(--color-link,var(--color-accent))]']}>
58
76
  <Nav items={items} label={navLabel} menuLabel={menuLabel} closeLabel={closeLabel} part="nav-header" align={layout === 'centered' ? 'center' : 'end'} />
59
77
  {action && <Button action={action} size="sm" class="hidden md:inline-flex" />}
60
78
  </div>
@@ -12,6 +12,9 @@
12
12
  },
13
13
  "props": {
14
14
  "siteName": { "type": "string", "required": true, "description": "Site title (site.title)." },
15
+ "tagline": { "type": "string", "description": "A line under the site name, as themes that print the tagline in the header do (site.tagline)." },
16
+ "brandSize": { "type": "string", "description": "The site name's size where the source theme sets its own (a CSS length)." },
17
+ "linkNav": { "type": "boolean", "default": false, "description": "The navigation in the site's link colour, as themes that colour every link do." },
15
18
  "logo": { "type": "object", "fields": { "src": { "type": "image", "required": true }, "alt": { "type": "string", "required": true }, "width": { "type": "integer" }, "height": { "type": "integer" } }, "description": "Logo image (site.logo)." },
16
19
  "showName": { "type": "boolean", "default": true, "description": "Show the site name next to the logo." },
17
20
  "homeHref": { "type": "url", "default": "/", "description": "Where the brand links." },
@@ -37,9 +37,11 @@ interface Props {
37
37
  author?: string | undefined
38
38
  headingLevel?: 2 | 3 | undefined
39
39
  layout?: 'vertical' | 'horizontal' | 'minimal' | undefined
40
+ /** The title in the site's link colour, as themes that colour every link do (Hello Elementor). */
41
+ linkTitle?: boolean | undefined
40
42
  }
41
43
 
42
- const { title, href, excerpt, date: rawDate, locale = 'en', image, category, author, headingLevel = 2, layout } = Astro.props
44
+ const { title, href, excerpt, date: rawDate, locale = 'en', image, category, author, headingLevel = 2, layout, linkTitle } = Astro.props
43
45
  const date = rawDate === undefined ? undefined : new Date(rawDate)
44
46
  const slots = card({ layout })
45
47
  const Heading = `h${headingLevel}` as 'h2' | 'h3'
@@ -58,7 +60,7 @@ const Heading = `h${headingLevel}` as 'h2' | 'h3'
58
60
  {date && <time datetime={date.toISOString()}>{date.toLocaleDateString(locale, { dateStyle: 'long', timeZone: 'UTC' })}</time>}
59
61
  </p>
60
62
  )}
61
- <Heading class={slots.title()}>
63
+ <Heading class={slots.title({ class: linkTitle ? 'text-[color:var(--color-link,var(--color-accent))]' : undefined })}>
62
64
  <a href={href} class="text-current no-underline after:absolute after:inset-0 after:content-[''] hover:text-accent">{title}</a>
63
65
  </Heading>
64
66
  {excerpt && <p class={slots.excerpt()}>{excerpt}</p>}
@@ -17,7 +17,8 @@
17
17
  "image": { "type": "object", "fields": { "src": { "type": "image", "required": true }, "alt": { "type": "string", "required": true }, "width": { "type": "integer" }, "height": { "type": "integer" } }, "description": "Cover (posts.cover → media)." },
18
18
  "category": { "type": "object", "fields": { "label": { "type": "string", "required": true }, "href": { "type": "url", "required": true } }, "description": "Primary category and its archive." },
19
19
  "author": { "type": "string", "description": "Author name (posts.author → authors.name)." },
20
- "headingLevel": { "type": "integer", "min": 2, "max": 3, "default": 2, "description": "Title heading level in the page outline." }
20
+ "headingLevel": { "type": "integer", "min": 2, "max": 3, "default": 2, "description": "Title heading level in the page outline." },
21
+ "linkTitle": { "type": "boolean", "default": false, "description": "The title in the site's link colour (--color-link), as themes that colour every link do." }
21
22
  },
22
23
  "slots": {},
23
24
  "js": "none",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contentrain/astro-kit",
3
- "version": "0.3.1",
3
+ "version": "0.4.0",
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.27.0"
45
+ "@contentrain/types": "1.28.0"
46
46
  },
47
47
  "devDependencies": {
48
48
  "@types/node": "^22.10.0",