@contentrain/astro-kit 0.18.0 → 0.19.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 +11 -2
- package/components/_shared/Section.astro +3 -1
- package/components/contact-form/ContactForm.astro +12 -4
- package/components/contact-form/fixtures.json +1 -0
- package/components/contact-form/meta.json +2 -1
- package/components/cta/Cta.astro +3 -2
- package/components/cta/fixtures.json +2 -1
- package/components/cta/meta.json +1 -1
- package/package.json +2 -2
package/catalog.json
CHANGED
|
@@ -520,7 +520,15 @@
|
|
|
520
520
|
"stacked"
|
|
521
521
|
],
|
|
522
522
|
"default": "split",
|
|
523
|
-
"description": "split: details beside the form on wide screens. stacked: one
|
|
523
|
+
"description": "split: details beside the form on wide screens. stacked: one column (see align)."
|
|
524
|
+
},
|
|
525
|
+
"align": {
|
|
526
|
+
"options": [
|
|
527
|
+
"center",
|
|
528
|
+
"start"
|
|
529
|
+
],
|
|
530
|
+
"default": "center",
|
|
531
|
+
"description": "Stacked only, and the details alone before a Studio form. center: one centred column at a reading width. start: the section's whole column from the start edge, as a page builder's container whose text sets no alignment."
|
|
524
532
|
},
|
|
525
533
|
"tone": {
|
|
526
534
|
"options": [
|
|
@@ -653,10 +661,11 @@
|
|
|
653
661
|
"muted",
|
|
654
662
|
"inverse",
|
|
655
663
|
"accent",
|
|
664
|
+
"brand",
|
|
656
665
|
"none"
|
|
657
666
|
],
|
|
658
667
|
"default": "accent",
|
|
659
|
-
"description": "Background. On accent, primary buttons are drawn in the secondary style so they stay visible. none: no fill of its own; the page background shows through (a source colour the palette does not have)."
|
|
668
|
+
"description": "Background. On accent, primary buttons are drawn in the secondary style so they stay visible. brand: the site's brand colour role (`--color-brand`, the builder's own colour on a band) with its ink; buttons keep their style. none: no fill of its own; the page background shows through (a source colour the palette does not have)."
|
|
660
669
|
},
|
|
661
670
|
"actionsAlign": {
|
|
662
671
|
"options": [
|
|
@@ -12,6 +12,8 @@ const section = tv({
|
|
|
12
12
|
muted: 'bg-surface-muted text-ink',
|
|
13
13
|
inverse: 'bg-ink text-surface',
|
|
14
14
|
accent: 'bg-accent text-accent-ink',
|
|
15
|
+
// The site's brand colour where it is not the accent (a band the source paints in the builder's own colour).
|
|
16
|
+
brand: 'bg-brand text-brand-ink',
|
|
15
17
|
// No fill of its own: the page's background and text colour show through.
|
|
16
18
|
none: '',
|
|
17
19
|
},
|
|
@@ -28,7 +30,7 @@ const section = tv({
|
|
|
28
30
|
export type Tone = 'default' | 'muted' | 'inverse' | 'accent'
|
|
29
31
|
|
|
30
32
|
interface Props {
|
|
31
|
-
tone?: Tone | 'none' | undefined
|
|
33
|
+
tone?: Tone | 'brand' | 'none' | undefined
|
|
32
34
|
spacing?: 'none' | 'sm' | 'md' | 'lg' | undefined
|
|
33
35
|
/** `page` is the full frame, `prose` the reading column, `none` for full-bleed content. */
|
|
34
36
|
width?: 'page' | 'prose' | 'none' | undefined
|
|
@@ -37,12 +37,18 @@ const contact = tv({
|
|
|
37
37
|
variants: {
|
|
38
38
|
layout: {
|
|
39
39
|
split: { grid: 'md:grid-cols-[2fr_3fr] md:items-start' },
|
|
40
|
-
stacked: {
|
|
40
|
+
stacked: {},
|
|
41
41
|
},
|
|
42
|
+
// The stacked column: centred in a reading width, or the section's whole column from its start edge (a page
|
|
43
|
+
// builder's container whose text has no alignment of its own sits left, full width).
|
|
44
|
+
align: { center: {}, start: {} },
|
|
42
45
|
// accent/accent-ink is only ~5:1 — dimming text on it drops body copy under 4.5:1 (WCAG 1.4.3), so accent keeps it at full strength.
|
|
43
46
|
tone: { default: { form: 'border border-line bg-surface p-6 md:p-8' }, muted: { form: 'bg-surface p-6 text-ink md:p-8' }, inverse: { form: 'bg-surface p-6 text-ink md:p-8' }, accent: { form: 'bg-surface p-6 text-ink md:p-8', intro: 'opacity-100', term: 'opacity-100' } },
|
|
44
47
|
},
|
|
45
|
-
|
|
48
|
+
compoundVariants: [
|
|
49
|
+
{ layout: 'stacked', align: 'center', class: { grid: 'mx-auto max-w-2xl' } },
|
|
50
|
+
],
|
|
51
|
+
defaultVariants: { layout: 'split', tone: 'default', align: 'center' },
|
|
46
52
|
})
|
|
47
53
|
|
|
48
54
|
interface Props {
|
|
@@ -54,14 +60,16 @@ interface Props {
|
|
|
54
60
|
formHeading?: string | undefined
|
|
55
61
|
details?: ContactDetail[] | undefined
|
|
56
62
|
layout?: 'split' | 'stacked' | undefined
|
|
63
|
+
/** Stacked only (and the details alone, before a Studio form): a centred column, or the whole column from the start edge. */
|
|
64
|
+
align?: 'center' | 'start' | undefined
|
|
57
65
|
tone?: 'default' | 'muted' | 'inverse' | 'accent' | undefined
|
|
58
66
|
id?: string | undefined
|
|
59
67
|
}
|
|
60
68
|
|
|
61
|
-
const { model, heading, intro, formHeading, details = [], layout, tone, id = 'contact' } = Astro.props
|
|
69
|
+
const { model, heading, intro, formHeading, details = [], layout, align, tone, id = 'contact' } = Astro.props
|
|
62
70
|
// Nothing to render (Studio not bound yet): a split would leave an empty column — the details stand alone.
|
|
63
71
|
const formShown = formHome(model) !== null
|
|
64
|
-
const s = contact({ layout: formShown ? layout : 'stacked', tone })
|
|
72
|
+
const s = contact({ layout: formShown ? layout : 'stacked', align, tone })
|
|
65
73
|
const headingId = heading ? `${id}-title` : undefined
|
|
66
74
|
// A description list needs a term for every detail; an icon list carried from the source has values only.
|
|
67
75
|
const labelled = details.every(detail => detail.label)
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
}
|
|
14
14
|
},
|
|
15
15
|
{ "name": "stacked-muted", "props": { "model": "contact-submissions", "heading": "Write to us", "layout": "stacked", "tone": "muted", "id": "write" } },
|
|
16
|
+
{ "name": "stacked-start", "props": { "model": "contact-submissions", "intro": "Tell us what you make and when you want to launch.", "details": [{ "value": "Studio 4, Harbour Lane" }], "layout": "stacked", "align": "start", "id": "start" } },
|
|
16
17
|
{ "name": "split-inverse", "props": { "model": "contact-submissions", "heading": "Press", "tone": "inverse", "id": "press", "details": [{ "label": "Press office", "value": "press@northwind.example", "href": "mailto:press@northwind.example" }] } },
|
|
17
18
|
{ "name": "stacked-accent", "props": { "model": "newsletter-requests", "heading": "Request a print copy", "layout": "stacked", "tone": "accent", "id": "print" } },
|
|
18
19
|
{ "name": "form-heading", "props": { "model": "contact-submissions", "heading": "Contact", "intro": "Tell us where you are and what you need.", "formHeading": "Tell us about your project", "details": [{ "label": "Address", "value": "12 Harbour Street, Leith" }] } }
|
|
@@ -6,7 +6,8 @@
|
|
|
6
6
|
"uses": [],
|
|
7
7
|
"shared": ["Section.astro"],
|
|
8
8
|
"variants": {
|
|
9
|
-
"layout": { "options": ["split", "stacked"], "default": "split", "description": "split: details beside the form on wide screens. stacked: one
|
|
9
|
+
"layout": { "options": ["split", "stacked"], "default": "split", "description": "split: details beside the form on wide screens. stacked: one column (see align)." },
|
|
10
|
+
"align": { "options": ["center", "start"], "default": "center", "description": "Stacked only, and the details alone before a Studio form. center: one centred column at a reading width. start: the section's whole column from the start edge, as a page builder's container whose text sets no alignment." },
|
|
10
11
|
"tone": { "options": ["default", "muted", "inverse", "accent"], "default": "default", "description": "Section background; the form always sits on a surface card." }
|
|
11
12
|
},
|
|
12
13
|
"props": {
|
package/components/cta/Cta.astro
CHANGED
|
@@ -27,7 +27,7 @@ const cta = tv({
|
|
|
27
27
|
},
|
|
28
28
|
// accent/accent-ink is only ~5:1 — dimming text on it drops body copy under 4.5:1 (WCAG 1.4.3), so accent keeps it at full strength.
|
|
29
29
|
// none: no fill of its own — the page background and text colour show through.
|
|
30
|
-
tone: { default: {}, muted: {}, inverse: {}, accent: { body: 'opacity-100' }, none: {} },
|
|
30
|
+
tone: { default: {}, muted: {}, inverse: {}, accent: { body: 'opacity-100' }, brand: { body: 'opacity-100' }, none: {} },
|
|
31
31
|
// The buttons' own alignment: `start` keeps them at the start edge under centred text (a WordPress buttons block
|
|
32
32
|
// with no justification sits left in a group whose heading and paragraph are centred). The row is the text's
|
|
33
33
|
// column, as WordPress's content width is, not the whole section. Only centred needs it: inline and stacked
|
|
@@ -40,6 +40,7 @@ const cta = tv({
|
|
|
40
40
|
{ frame: 'card', tone: 'muted', class: { box: 'border-transparent bg-surface-muted text-ink' } },
|
|
41
41
|
{ frame: 'card', tone: 'inverse', class: { box: 'border-transparent bg-ink text-surface' } },
|
|
42
42
|
{ frame: 'card', tone: 'accent', class: { box: 'border-transparent bg-accent text-accent-ink' } },
|
|
43
|
+
{ frame: 'card', tone: 'brand', class: { box: 'border-transparent bg-brand text-brand-ink' } },
|
|
43
44
|
{ layout: 'centered', actionsAlign: 'start', class: { actions: 'w-full max-w-2xl justify-start' } },
|
|
44
45
|
],
|
|
45
46
|
defaultVariants: { layout: 'inline', frame: 'full', tone: 'accent', actionsAlign: 'inherit' },
|
|
@@ -51,7 +52,7 @@ interface Props {
|
|
|
51
52
|
actions: ActionInput[]
|
|
52
53
|
layout?: 'inline' | 'centered' | 'stacked' | undefined
|
|
53
54
|
frame?: 'full' | 'card' | undefined
|
|
54
|
-
tone?: 'default' | 'muted' | 'inverse' | 'accent' | 'none' | undefined
|
|
55
|
+
tone?: 'default' | 'muted' | 'inverse' | 'accent' | 'brand' | 'none' | undefined
|
|
55
56
|
/** The buttons' alignment: as the layout sets it, or at the start edge under centred text (layout centered). */
|
|
56
57
|
actionsAlign?: 'inherit' | 'start' | undefined
|
|
57
58
|
id?: string | undefined
|
|
@@ -4,5 +4,6 @@
|
|
|
4
4
|
{ "name": "card-default", "props": { "heading": "Write for the journal", "body": "We publish reader essays every season.", "frame": "card", "tone": "default", "actions": [{ "label": "Pitch an essay", "href": "/pitch/" }] } },
|
|
5
5
|
{ "name": "card-muted", "props": { "heading": "Support independent travel writing", "frame": "card", "tone": "muted", "layout": "centered", "actions": [{ "label": "Become a member", "href": "/members/" }] } },
|
|
6
6
|
{ "name": "stacked-none", "props": { "heading": "Ready when you are", "body": "Tell us where you want to go and we will send a first plan within a week.", "layout": "stacked", "tone": "none", "actions": [{ "label": "Start planning", "href": "/contact/" }] } },
|
|
7
|
-
{ "name": "centered-actions-start", "props": { "heading": "See what is on this week", "body": "New films every Thursday, and a late show on Saturdays.", "layout": "centered", "tone": "inverse", "actionsAlign": "start", "actions": [{ "label": "Programme", "href": "/programme/" }] } }
|
|
7
|
+
{ "name": "centered-actions-start", "props": { "heading": "See what is on this week", "body": "New films every Thursday, and a late show on Saturdays.", "layout": "centered", "tone": "inverse", "actionsAlign": "start", "actions": [{ "label": "Programme", "href": "/programme/" }] } },
|
|
8
|
+
{ "name": "centered-brand", "props": { "heading": "Ready when you are", "body": "Two launch slots left this quarter.", "layout": "centered", "tone": "brand", "actions": [{ "label": "Book a launch call", "href": "/contact/" }] } }
|
|
8
9
|
]
|
package/components/cta/meta.json
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"variants": {
|
|
9
9
|
"layout": { "options": ["inline", "centered", "stacked"], "default": "inline", "description": "inline: text left, buttons right on wide screens. centered: everything centred. stacked: heading, text and buttons in one column at the start edge on every width." },
|
|
10
10
|
"frame": { "options": ["full", "card"], "default": "full", "description": "full: the tone fills the section. card: a rounded box in a plain section carries the tone." },
|
|
11
|
-
"tone": { "options": ["default", "muted", "inverse", "accent", "none"], "default": "accent", "description": "Background. On accent, primary buttons are drawn in the secondary style so they stay visible. none: no fill of its own; the page background shows through (a source colour the palette does not have)." },
|
|
11
|
+
"tone": { "options": ["default", "muted", "inverse", "accent", "brand", "none"], "default": "accent", "description": "Background. On accent, primary buttons are drawn in the secondary style so they stay visible. brand: the site's brand colour role (`--color-brand`, the builder's own colour on a band) with its ink; buttons keep their style. none: no fill of its own; the page background shows through (a source colour the palette does not have)." },
|
|
12
12
|
"actionsAlign": { "options": ["inherit", "start"], "default": "inherit", "description": "The buttons' alignment. inherit: as the layout sets it. start: at the start edge under centred heading and text (layout centered; a WordPress buttons block with no justification in a centred group). inline and stacked ignore it." }
|
|
13
13
|
},
|
|
14
14
|
"props": {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contentrain/astro-kit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.19.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.
|
|
45
|
+
"@contentrain/types": "1.37.0"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
48
|
"@types/node": "^22.10.0",
|