@contentrain/astro-kit 0.31.0 → 0.33.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 +4600 -1584
- package/components/_shared/Button.astro +2 -1
- package/components/_shared/KitImage.astro +9 -4
- package/components/_shared/Section.astro +3 -1
- package/components/_shared/SectionHeader.astro +27 -0
- package/components/_shared/measured.ts +23 -0
- package/components/_shared/safe-url.ts +67 -0
- package/components/_shared/social.ts +73 -0
- package/components/announcement/Announcement.astro +2 -1
- package/components/announcement/meta.json +1 -1
- package/components/band/Band.astro +3 -2
- package/components/band/meta.json +1 -0
- package/components/breadcrumb/Breadcrumb.astro +2 -1
- package/components/breadcrumb/meta.json +1 -1
- package/components/card-grid/CardGrid.astro +2 -1
- package/components/card-grid/meta.json +1 -0
- package/components/consent/Consent.astro +2 -1
- package/components/consent/meta.json +1 -1
- package/components/contact-details/ContactDetails.astro +3 -2
- package/components/contact-details/meta.json +1 -0
- package/components/contact-form/ContactForm.astro +51 -14
- package/components/contact-form/fixtures.json +169 -9
- package/components/contact-form/meta.json +284 -15
- package/components/cta/Cta.astro +52 -12
- package/components/cta/fixtures.json +5 -1
- package/components/cta/meta.json +11 -2
- package/components/dialog/Dialog.astro +113 -0
- package/components/dialog/fixtures.json +84 -0
- package/components/dialog/meta.json +252 -0
- package/components/embed/meta.json +1 -1
- package/components/faq/Faq.astro +60 -17
- package/components/faq/fixtures.json +79 -0
- package/components/faq/meta.json +9 -3
- package/components/feature-list/FeatureList.astro +28 -4
- package/components/feature-list/meta.json +16 -3
- package/components/footer/Footer.astro +5 -4
- package/components/footer/meta.json +1 -0
- package/components/gallery/Gallery.astro +49 -14
- package/components/gallery/fixtures.json +275 -0
- package/components/gallery/meta.json +267 -14
- package/components/header/Header.astro +17 -5
- package/components/header/fixtures.json +90 -1
- package/components/header/meta.json +5 -3
- package/components/hero/meta.json +1 -0
- package/components/language-switcher/LanguageSwitcher.astro +68 -0
- package/components/language-switcher/fixtures.json +51 -0
- package/components/language-switcher/meta.json +73 -0
- package/components/logo-cloud/LogoCloud.astro +86 -21
- package/components/logo-cloud/fixtures.json +239 -0
- package/components/logo-cloud/meta.json +145 -5
- package/components/nav/Nav.astro +77 -24
- package/components/nav/NavTree.astro +40 -0
- package/components/nav/fixtures.json +165 -0
- package/components/nav/meta.json +11 -2
- package/components/newsletter/Newsletter.astro +2 -1
- package/components/newsletter/meta.json +1 -0
- package/components/pagination/Pagination.astro +4 -3
- package/components/pagination/meta.json +1 -1
- package/components/post-card/PostCard.astro +8 -5
- package/components/post-card/meta.json +3 -2
- package/components/post-list/PostList.astro +115 -0
- package/components/post-list/fixtures.json +387 -0
- package/components/post-list/meta.json +309 -0
- package/components/pricing/Pricing.astro +128 -24
- package/components/pricing/fixtures.json +288 -4
- package/components/pricing/meta.json +188 -1
- package/components/search-box/SearchBox.astro +51 -0
- package/components/search-box/fixtures.json +31 -0
- package/components/search-box/meta.json +75 -0
- package/components/slider/Slider.astro +19 -115
- package/components/slider/SliderTrack.astro +178 -0
- package/components/slider/fixtures.json +2 -1
- package/components/slider/meta.json +11 -5
- package/components/social-links/SocialLinks.astro +74 -0
- package/components/social-links/fixtures.json +67 -0
- package/components/social-links/meta.json +94 -0
- package/components/split/Split.astro +76 -14
- package/components/split/fixtures.json +8 -1
- package/components/split/meta.json +226 -4
- package/components/stats/Stats.astro +54 -11
- package/components/stats/fixtures.json +260 -0
- package/components/stats/meta.json +151 -4
- package/components/steps/Steps.astro +36 -8
- package/components/steps/fixtures.json +217 -5
- package/components/steps/meta.json +157 -3
- package/components/tabs/Tabs.astro +10 -3
- package/components/tabs/fixtures.json +4 -0
- package/components/tabs/meta.json +5 -2
- package/components/team/Team.astro +54 -9
- package/components/team/fixtures.json +217 -4
- package/components/team/meta.json +169 -3
- package/components/team/team.ts +4 -0
- package/components/testimonial/Testimonial.astro +71 -21
- package/components/testimonial/fixtures.json +73 -0
- package/components/testimonial/meta.json +168 -6
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/mapping/classic.json +124 -3
- package/mapping/divi.json +26 -8
- package/mapping/elementor.json +133 -14
- package/mapping/gutenberg.json +38 -10
- package/package.json +2 -2
|
@@ -2,10 +2,14 @@
|
|
|
2
2
|
// Price plans side by side: a name, a price and what it includes, with a
|
|
3
3
|
// button each. The featured plan is raised and carries a badge, so it stands
|
|
4
4
|
// out by more than its colour. Each plan's features are a markdown list,
|
|
5
|
-
// rendered at build time.
|
|
5
|
+
// rendered at build time. Variants: `layout="table"` is a comparison table
|
|
6
|
+
// (plan columns, feature rows); `billingToggle="radio"` swaps monthly and yearly
|
|
7
|
+
// prices with two radio inputs and CSS `:has()` — no script.
|
|
6
8
|
import { tv } from 'tailwind-variants'
|
|
7
9
|
import Button from '../_shared/Button.astro'
|
|
8
10
|
import Section, { type Tone } from '../_shared/Section.astro'
|
|
11
|
+
import { measuredGrid } from '../_shared/measured'
|
|
12
|
+
import type { MeasuredStyle } from '../_shared/types'
|
|
9
13
|
import { renderMarkdown } from '../../../lib/markdown'
|
|
10
14
|
|
|
11
15
|
const pricing = tv({
|
|
@@ -14,6 +18,12 @@ const pricing = tv({
|
|
|
14
18
|
heading: 'text-3xl [font-weight:var(--font-weight-heading,700)] tracking-tight text-balance md:text-4xl',
|
|
15
19
|
intro: 'text-lg opacity-80',
|
|
16
20
|
list: 'grid items-stretch gap-6 sm:grid-cols-2',
|
|
21
|
+
toggle: 'mx-auto mb-8 flex w-fit rounded-full border border-line p-1',
|
|
22
|
+
toggleOption: 'rounded-full px-4 py-1.5 text-sm font-medium has-[:checked]:bg-accent has-[:checked]:text-accent-ink has-[:focus-visible]:outline-2 has-[:focus-visible]:outline-offset-2 has-[:focus-visible]:outline-accent',
|
|
23
|
+
tableWrap: 'overflow-x-auto',
|
|
24
|
+
table: 'w-full min-w-[32rem] border-collapse text-start',
|
|
25
|
+
cell: 'border-b border-line px-4 py-3 text-center align-top',
|
|
26
|
+
rowHead: 'border-b border-line px-4 py-3 text-start font-normal',
|
|
17
27
|
plan: 'relative flex flex-col gap-5 rounded-card border border-line bg-surface p-6 text-ink md:p-8',
|
|
18
28
|
badge: 'absolute -top-3 start-6 rounded-full bg-accent px-3 py-1 text-xs font-semibold text-accent-ink',
|
|
19
29
|
name: 'text-lg [font-weight:var(--font-weight-heading,600)]',
|
|
@@ -30,9 +40,16 @@ const pricing = tv({
|
|
|
30
40
|
'3': { list: 'lg:grid-cols-3' },
|
|
31
41
|
'4': { list: 'lg:grid-cols-4' },
|
|
32
42
|
},
|
|
43
|
+
// Which mark leads each feature in the cards: a check, a dot or none (the markdown list's own bullets).
|
|
44
|
+
featureStyle: {
|
|
45
|
+
check: { features: '[&_ul]:list-none [&_ul]:ps-0 [&_li]:flex [&_li]:gap-2 [&_li]:before:shrink-0 [&_li]:before:font-semibold [&_li]:before:text-accent-text [&_li]:before:content-["✓"]' },
|
|
46
|
+
dot: { features: '[&_ul]:list-none [&_ul]:ps-0 [&_li]:flex [&_li]:gap-2 [&_li]:before:mt-2 [&_li]:before:size-1.5 [&_li]:before:shrink-0 [&_li]:before:rounded-full [&_li]:before:bg-accent [&_li]:before:content-[""]' },
|
|
47
|
+
plain: {},
|
|
48
|
+
},
|
|
49
|
+
compact: { true: { list: 'gap-4', plan: 'gap-3 p-4 md:p-5', amount: 'text-3xl' }, false: {} },
|
|
33
50
|
tone: { default: {}, muted: { plan: 'border-transparent' }, inverse: { plan: 'border-transparent' }, accent: { intro: 'opacity-100', plan: 'border-transparent', badge: 'bg-ink text-surface' } },
|
|
34
51
|
},
|
|
35
|
-
defaultVariants: { columns: '3', tone: 'default' },
|
|
52
|
+
defaultVariants: { columns: '3', featureStyle: 'plain', compact: false, tone: 'default' },
|
|
36
53
|
})
|
|
37
54
|
|
|
38
55
|
interface Plan {
|
|
@@ -45,6 +62,11 @@ interface Plan {
|
|
|
45
62
|
ctaLabel?: string | undefined
|
|
46
63
|
ctaHref?: string | undefined
|
|
47
64
|
featured?: boolean | undefined
|
|
65
|
+
/** A free-text badge ("Best value"); a featured plan without one reads `featuredLabel`. */
|
|
66
|
+
badge?: string | undefined
|
|
67
|
+
/** The other billing period's price and period (`billingToggle="radio"`). */
|
|
68
|
+
priceAlt?: string | undefined
|
|
69
|
+
periodAlt?: string | undefined
|
|
48
70
|
}
|
|
49
71
|
|
|
50
72
|
interface Props {
|
|
@@ -54,43 +76,125 @@ interface Props {
|
|
|
54
76
|
/** Badge on the featured plan. */
|
|
55
77
|
featuredLabel?: string | undefined
|
|
56
78
|
columns?: '2' | '3' | '4' | undefined
|
|
79
|
+
/** `cards` side by side, or one comparison `table` (plans as columns, features as rows). */
|
|
80
|
+
layout?: 'cards' | 'table' | undefined
|
|
81
|
+
featureStyle?: 'check' | 'dot' | 'plain' | undefined
|
|
82
|
+
compact?: boolean | undefined
|
|
83
|
+
/** `radio`: two labelled radios swap each plan's price for its `priceAlt` — no script. */
|
|
84
|
+
billingToggle?: 'none' | 'radio' | undefined
|
|
85
|
+
/** Texts of the toggle: its two options and the legend read to screen readers. */
|
|
86
|
+
billingMainLabel?: string | undefined
|
|
87
|
+
billingAltLabel?: string | undefined
|
|
88
|
+
billingLegend?: string | undefined
|
|
89
|
+
/** Table cell texts for screen readers. */
|
|
90
|
+
includedLabel?: string | undefined
|
|
91
|
+
notIncludedLabel?: string | undefined
|
|
57
92
|
tone?: Tone | undefined
|
|
93
|
+
/** The source section's measured style (`MeasuredStyle`): frame, padding, fill, background image, columns per width, gap. Absent, the site's tokens; present, it wins over tone and columns. */
|
|
94
|
+
measured?: MeasuredStyle | undefined
|
|
58
95
|
id?: string | undefined
|
|
59
96
|
}
|
|
60
97
|
|
|
61
|
-
const { heading, intro, plans, featuredLabel = 'Most popular', columns, tone, id } = Astro.props
|
|
62
|
-
const s = pricing({ columns, tone })
|
|
98
|
+
const { heading, intro, plans, featuredLabel = 'Most popular', columns, layout = 'cards', featureStyle, compact, billingToggle = 'none', billingMainLabel = 'Monthly', billingAltLabel = 'Yearly', billingLegend = 'Billing period', includedLabel = 'Included', notIncludedLabel = 'Not included', tone, measured, id } = Astro.props
|
|
99
|
+
const s = pricing({ columns, featureStyle, compact: compact ?? false, tone })
|
|
100
|
+
// The radio group's name must be unique on the page: the section's id, or a hash of its plans when it has none.
|
|
101
|
+
const group = id ?? `pricing-${[...JSON.stringify(plans)].reduce((h, c) => (h * 31 + c.charCodeAt(0)) >>> 0, 7).toString(36)}`
|
|
102
|
+
const toggled = billingToggle === 'radio' && plans.some(plan => plan.priceAlt)
|
|
103
|
+
// The cards' list items, as plain strings, for the table's feature rows (the markdown list's `- ` / `* ` lines).
|
|
104
|
+
const itemsOf = (md?: string) => (md ?? '').split('\n').flatMap((line) => { const m = /^\s*[-*]\s+(.*\S)/.exec(line); return m ? [m[1]!.replace(/[*_`]/g, '')] : [] })
|
|
105
|
+
const rows = layout === 'table' ? [...new Set(plans.flatMap(plan => itemsOf(plan.features)))] : []
|
|
106
|
+
const included = plans.map(plan => new Set(itemsOf(plan.features)))
|
|
63
107
|
const headingId = heading && id ? `${id}-title` : undefined
|
|
64
108
|
// One level under the section heading, or the section's heading when there is none.
|
|
65
109
|
const PlanHeading = heading ? 'h3' : 'h2'
|
|
66
110
|
const features = await Promise.all(plans.map(plan => renderMarkdown(plan.features)))
|
|
67
111
|
---
|
|
68
112
|
{plans.length > 0 && (
|
|
69
|
-
<Section tone={tone} id={id} aria-labelledby={headingId}>
|
|
113
|
+
<Section measured={measured} tone={tone} id={id} aria-labelledby={headingId}>
|
|
70
114
|
{(heading || intro) && (
|
|
71
115
|
<header class={s.header()}>
|
|
72
116
|
{heading && <h2 id={headingId} class={s.heading()}>{heading}</h2>}
|
|
73
117
|
{intro && <p class={s.intro()} data-kit-text>{intro}</p>}
|
|
74
118
|
</header>
|
|
75
119
|
)}
|
|
76
|
-
|
|
77
|
-
{plans.map(
|
|
78
|
-
<
|
|
79
|
-
|
|
80
|
-
<
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
120
|
+
{layout === 'table' ? (
|
|
121
|
+
<div class={s.tableWrap()} tabindex="0" role="region" aria-labelledby={headingId} aria-label={headingId ? undefined : plans.map(plan => plan.name).join(', ')}>
|
|
122
|
+
<table class={s.table()}>
|
|
123
|
+
<caption class="sr-only">{heading ?? plans.map(plan => plan.name).join(', ')}</caption>
|
|
124
|
+
<thead>
|
|
125
|
+
<tr>
|
|
126
|
+
<td class={s.cell()} />
|
|
127
|
+
{plans.map(plan => (
|
|
128
|
+
<th scope="col" class={s.cell({ class: plan.featured ? 'bg-surface-muted' : undefined })}>
|
|
129
|
+
<span class="block text-lg [font-weight:var(--font-weight-heading,600)]">{plan.name}</span>
|
|
130
|
+
<span class="block text-2xl [font-weight:var(--font-weight-heading,700)]">{plan.price}</span>
|
|
131
|
+
{plan.period && <span class="block text-sm opacity-75">{plan.period}</span>}
|
|
132
|
+
{(plan.badge ?? (plan.featured ? featuredLabel : undefined)) && <span class="mt-1 inline-block rounded-full bg-accent px-3 py-0.5 text-xs font-semibold text-accent-ink">{plan.badge ?? featuredLabel}</span>}
|
|
133
|
+
</th>
|
|
134
|
+
))}
|
|
135
|
+
</tr>
|
|
136
|
+
</thead>
|
|
137
|
+
<tbody>
|
|
138
|
+
{rows.map(row => (
|
|
139
|
+
<tr>
|
|
140
|
+
<th scope="row" class={s.rowHead()}>{row}</th>
|
|
141
|
+
{plans.map((plan, i) => (
|
|
142
|
+
<td class={s.cell({ class: plan.featured ? 'bg-surface-muted' : undefined })}>
|
|
143
|
+
{included[i]!.has(row)
|
|
144
|
+
? <><span aria-hidden="true">✓</span><span class="sr-only">{includedLabel}</span></>
|
|
145
|
+
: <><span aria-hidden="true" class="opacity-50">–</span><span class="sr-only">{notIncludedLabel}</span></>}
|
|
146
|
+
</td>
|
|
147
|
+
))}
|
|
148
|
+
</tr>
|
|
149
|
+
))}
|
|
150
|
+
{plans.some(plan => plan.ctaLabel && plan.ctaHref) && (
|
|
151
|
+
<tr>
|
|
152
|
+
<td class={s.cell()} />
|
|
153
|
+
{plans.map(plan => (
|
|
154
|
+
<td class={s.cell({ class: plan.featured ? 'bg-surface-muted' : undefined })}>
|
|
155
|
+
{plan.ctaLabel && plan.ctaHref && <Button action={{ label: plan.ctaLabel, href: plan.ctaHref, style: plan.featured ? 'primary' : 'ghost' }} />}
|
|
156
|
+
</td>
|
|
157
|
+
))}
|
|
158
|
+
</tr>
|
|
159
|
+
)}
|
|
160
|
+
</tbody>
|
|
161
|
+
</table>
|
|
162
|
+
</div>
|
|
163
|
+
) : (
|
|
164
|
+
<div class={toggled ? '[&:has(input[value=alt]:checked)_[data-price=main]]:hidden [&:not(:has(input[value=alt]:checked))_[data-price=alt]]:hidden' : undefined}>
|
|
165
|
+
{toggled && (
|
|
166
|
+
<fieldset class={s.toggle()}>
|
|
167
|
+
<legend class="sr-only">{billingLegend}</legend>
|
|
168
|
+
<label class={s.toggleOption()}><input type="radio" name={`${group}-billing`} value="main" checked class="sr-only" />{billingMainLabel}</label>
|
|
169
|
+
<label class={s.toggleOption()}><input type="radio" name={`${group}-billing`} value="alt" class="sr-only" />{billingAltLabel}</label>
|
|
170
|
+
</fieldset>
|
|
171
|
+
)}
|
|
172
|
+
<ul class={s.list({ class: measuredGrid(measured) })}>
|
|
173
|
+
{plans.map((plan, i) => (
|
|
174
|
+
<li class={s.plan({ class: plan.featured ? 'ring-2 ring-accent shadow-lg md:-my-2 md:py-10' : undefined })}>
|
|
175
|
+
{(plan.badge ?? (plan.featured ? featuredLabel : undefined)) && <p class={s.badge()}>{plan.badge ?? featuredLabel}</p>}
|
|
176
|
+
<PlanHeading class={s.name()}>{plan.name}</PlanHeading>
|
|
177
|
+
<p class={s.price()} data-price="main">
|
|
178
|
+
<span class={s.amount()}>{plan.price}</span>
|
|
179
|
+
{plan.period && <span class={s.period()}>{plan.period}</span>}
|
|
180
|
+
</p>
|
|
181
|
+
{toggled && plan.priceAlt && (
|
|
182
|
+
<p class={s.price()} data-price="alt">
|
|
183
|
+
<span class={s.amount()}>{plan.priceAlt}</span>
|
|
184
|
+
{plan.periodAlt && <span class={s.period()}>{plan.periodAlt}</span>}
|
|
185
|
+
</p>
|
|
186
|
+
)}
|
|
187
|
+
{plan.description && <p class={s.description()} data-kit-text>{plan.description}</p>}
|
|
188
|
+
{features[i] && <div class={s.features()} set:html={features[i]} />}
|
|
189
|
+
{plan.ctaLabel && plan.ctaHref && (
|
|
190
|
+
<div class={s.action()}>
|
|
191
|
+
<Button action={{ label: plan.ctaLabel, href: plan.ctaHref, style: plan.featured ? 'primary' : 'ghost' }} class="w-full" />
|
|
192
|
+
</div>
|
|
193
|
+
)}
|
|
194
|
+
</li>
|
|
195
|
+
))}
|
|
196
|
+
</ul>
|
|
197
|
+
</div>
|
|
198
|
+
)}
|
|
95
199
|
</Section>
|
|
96
200
|
)}
|
|
@@ -1,6 +1,290 @@
|
|
|
1
1
|
[
|
|
2
|
-
{
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
{
|
|
3
|
+
"name": "three-featured",
|
|
4
|
+
"props": {
|
|
5
|
+
"id": "pricing",
|
|
6
|
+
"heading": "Pricing",
|
|
7
|
+
"intro": "Start free, upgrade when the team grows.",
|
|
8
|
+
"plans": [
|
|
9
|
+
{
|
|
10
|
+
"name": "Free",
|
|
11
|
+
"price": "$0",
|
|
12
|
+
"period": "/month",
|
|
13
|
+
"description": "For one person and one site.",
|
|
14
|
+
"features": "- 1 project\n- Git-backed content\n- Community support",
|
|
15
|
+
"ctaLabel": "Start free",
|
|
16
|
+
"ctaHref": "/signup/"
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"name": "Pro",
|
|
20
|
+
"price": "$12",
|
|
21
|
+
"period": "/month",
|
|
22
|
+
"description": "For freelancers.",
|
|
23
|
+
"features": "- 5 projects\n- Media library\n- Email support",
|
|
24
|
+
"ctaLabel": "Choose Pro",
|
|
25
|
+
"ctaHref": "/signup/?plan=pro",
|
|
26
|
+
"featured": true
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"name": "Team",
|
|
30
|
+
"price": "$29",
|
|
31
|
+
"period": "/month",
|
|
32
|
+
"description": "For studios and teams.",
|
|
33
|
+
"features": "- Unlimited projects\n- Reviews and roles\n- Priority support",
|
|
34
|
+
"ctaLabel": "Choose Team",
|
|
35
|
+
"ctaHref": "/signup/?plan=team"
|
|
36
|
+
}
|
|
37
|
+
]
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"name": "two-muted",
|
|
42
|
+
"props": {
|
|
43
|
+
"columns": "2",
|
|
44
|
+
"tone": "muted",
|
|
45
|
+
"featuredLabel": "Best value",
|
|
46
|
+
"plans": [
|
|
47
|
+
{
|
|
48
|
+
"name": "Monthly",
|
|
49
|
+
"price": "€15",
|
|
50
|
+
"period": "per month",
|
|
51
|
+
"features": "- Cancel anytime",
|
|
52
|
+
"ctaLabel": "Subscribe",
|
|
53
|
+
"ctaHref": "/buy/monthly/"
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
"name": "Yearly",
|
|
57
|
+
"price": "€150",
|
|
58
|
+
"period": "per year",
|
|
59
|
+
"features": "- Two months free\n- **Priority** support",
|
|
60
|
+
"ctaLabel": "Subscribe",
|
|
61
|
+
"ctaHref": "/buy/yearly/",
|
|
62
|
+
"featured": true
|
|
63
|
+
}
|
|
64
|
+
]
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
"name": "four-inverse",
|
|
69
|
+
"props": {
|
|
70
|
+
"columns": "4",
|
|
71
|
+
"tone": "inverse",
|
|
72
|
+
"heading": "Plans",
|
|
73
|
+
"plans": [
|
|
74
|
+
{
|
|
75
|
+
"name": "Solo",
|
|
76
|
+
"price": "$0",
|
|
77
|
+
"features": "- 1 site"
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
"name": "Pro",
|
|
81
|
+
"price": "$12",
|
|
82
|
+
"period": "/mo",
|
|
83
|
+
"features": "- 5 sites",
|
|
84
|
+
"featured": true,
|
|
85
|
+
"ctaLabel": "Buy",
|
|
86
|
+
"ctaHref": "/buy/"
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
"name": "Team",
|
|
90
|
+
"price": "$29",
|
|
91
|
+
"period": "/mo",
|
|
92
|
+
"features": "- 20 sites"
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
"name": "Enterprise",
|
|
96
|
+
"price": "On request",
|
|
97
|
+
"description": "Custom terms.",
|
|
98
|
+
"ctaLabel": "Contact us",
|
|
99
|
+
"ctaHref": "/contact/"
|
|
100
|
+
}
|
|
101
|
+
]
|
|
102
|
+
}
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
"name": "accent",
|
|
106
|
+
"props": {
|
|
107
|
+
"tone": "accent",
|
|
108
|
+
"heading": "One price",
|
|
109
|
+
"plans": [
|
|
110
|
+
{
|
|
111
|
+
"name": "Studio",
|
|
112
|
+
"price": "$49",
|
|
113
|
+
"period": "once",
|
|
114
|
+
"features": "- Everything",
|
|
115
|
+
"ctaLabel": "Buy now",
|
|
116
|
+
"ctaHref": "/buy/",
|
|
117
|
+
"featured": true
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
"name": "Support",
|
|
121
|
+
"price": "$9",
|
|
122
|
+
"period": "/month",
|
|
123
|
+
"features": "- Updates and help",
|
|
124
|
+
"ctaLabel": "Add support",
|
|
125
|
+
"ctaHref": "/buy/support/"
|
|
126
|
+
}
|
|
127
|
+
]
|
|
128
|
+
}
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
"name": "table",
|
|
132
|
+
"props": {
|
|
133
|
+
"id": "compare",
|
|
134
|
+
"heading": "Compare plans",
|
|
135
|
+
"layout": "table",
|
|
136
|
+
"plans": [
|
|
137
|
+
{
|
|
138
|
+
"name": "Free",
|
|
139
|
+
"price": "$0",
|
|
140
|
+
"features": "- 1 project\n- Community support",
|
|
141
|
+
"ctaLabel": "Start",
|
|
142
|
+
"ctaHref": "/signup/"
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
"name": "Pro",
|
|
146
|
+
"price": "$12",
|
|
147
|
+
"period": "/month",
|
|
148
|
+
"features": "- 1 project\n- 5 projects\n- Media library\n- Email support",
|
|
149
|
+
"ctaLabel": "Choose",
|
|
150
|
+
"ctaHref": "/signup/?plan=pro",
|
|
151
|
+
"featured": true
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
"name": "Team",
|
|
155
|
+
"price": "$29",
|
|
156
|
+
"period": "/month",
|
|
157
|
+
"features": "- 1 project\n- 5 projects\n- Media library\n- Email support\n- Roles and reviews\n- Priority support\n- Audit log\n- SSO",
|
|
158
|
+
"ctaLabel": "Choose",
|
|
159
|
+
"ctaHref": "/signup/?plan=team"
|
|
160
|
+
}
|
|
161
|
+
]
|
|
162
|
+
}
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
"name": "check-compact",
|
|
166
|
+
"props": {
|
|
167
|
+
"featureStyle": "check",
|
|
168
|
+
"compact": true,
|
|
169
|
+
"plans": [
|
|
170
|
+
{
|
|
171
|
+
"name": "Free",
|
|
172
|
+
"price": "$0",
|
|
173
|
+
"period": "/month",
|
|
174
|
+
"description": "For one person and one site.",
|
|
175
|
+
"features": "- 1 project\n- Git-backed content\n- Community support",
|
|
176
|
+
"ctaLabel": "Start free",
|
|
177
|
+
"ctaHref": "/signup/"
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
"name": "Pro",
|
|
181
|
+
"price": "$12",
|
|
182
|
+
"period": "/month",
|
|
183
|
+
"description": "For freelancers.",
|
|
184
|
+
"features": "- 5 projects\n- Media library\n- Email support",
|
|
185
|
+
"ctaLabel": "Choose Pro",
|
|
186
|
+
"ctaHref": "/signup/?plan=pro",
|
|
187
|
+
"featured": true
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
"name": "Team",
|
|
191
|
+
"price": "$29",
|
|
192
|
+
"period": "/month",
|
|
193
|
+
"description": "For studios and teams.",
|
|
194
|
+
"features": "- Unlimited projects\n- Reviews and roles\n- Priority support",
|
|
195
|
+
"ctaLabel": "Choose Team",
|
|
196
|
+
"ctaHref": "/signup/?plan=team"
|
|
197
|
+
}
|
|
198
|
+
]
|
|
199
|
+
}
|
|
200
|
+
},
|
|
201
|
+
{
|
|
202
|
+
"name": "dot-features",
|
|
203
|
+
"props": {
|
|
204
|
+
"featureStyle": "dot",
|
|
205
|
+
"plans": [
|
|
206
|
+
{
|
|
207
|
+
"name": "Free",
|
|
208
|
+
"price": "$0",
|
|
209
|
+
"period": "/month",
|
|
210
|
+
"description": "For one person and one site.",
|
|
211
|
+
"features": "- 1 project\n- Git-backed content\n- Community support",
|
|
212
|
+
"ctaLabel": "Start free",
|
|
213
|
+
"ctaHref": "/signup/"
|
|
214
|
+
},
|
|
215
|
+
{
|
|
216
|
+
"name": "Pro",
|
|
217
|
+
"price": "$12",
|
|
218
|
+
"period": "/month",
|
|
219
|
+
"description": "For freelancers.",
|
|
220
|
+
"features": "- 5 projects\n- Media library\n- Email support",
|
|
221
|
+
"ctaLabel": "Choose Pro",
|
|
222
|
+
"ctaHref": "/signup/?plan=pro",
|
|
223
|
+
"featured": true
|
|
224
|
+
},
|
|
225
|
+
{
|
|
226
|
+
"name": "Team",
|
|
227
|
+
"price": "$29",
|
|
228
|
+
"period": "/month",
|
|
229
|
+
"description": "For studios and teams.",
|
|
230
|
+
"features": "- Unlimited projects\n- Reviews and roles\n- Priority support",
|
|
231
|
+
"ctaLabel": "Choose Team",
|
|
232
|
+
"ctaHref": "/signup/?plan=team"
|
|
233
|
+
}
|
|
234
|
+
]
|
|
235
|
+
}
|
|
236
|
+
},
|
|
237
|
+
{
|
|
238
|
+
"name": "billing-toggle",
|
|
239
|
+
"props": {
|
|
240
|
+
"id": "billing",
|
|
241
|
+
"heading": "Billing",
|
|
242
|
+
"billingToggle": "radio",
|
|
243
|
+
"columns": "2",
|
|
244
|
+
"plans": [
|
|
245
|
+
{
|
|
246
|
+
"name": "Basic",
|
|
247
|
+
"price": "€15",
|
|
248
|
+
"period": "/month",
|
|
249
|
+
"priceAlt": "€150",
|
|
250
|
+
"periodAlt": "/year",
|
|
251
|
+
"features": "- 1 site",
|
|
252
|
+
"ctaLabel": "Subscribe",
|
|
253
|
+
"ctaHref": "/buy/basic/"
|
|
254
|
+
},
|
|
255
|
+
{
|
|
256
|
+
"name": "Plus",
|
|
257
|
+
"price": "€29",
|
|
258
|
+
"period": "/month",
|
|
259
|
+
"priceAlt": "€290",
|
|
260
|
+
"periodAlt": "/year",
|
|
261
|
+
"features": "- 5 sites\n- Priority support",
|
|
262
|
+
"ctaLabel": "Subscribe",
|
|
263
|
+
"ctaHref": "/buy/plus/",
|
|
264
|
+
"badge": "Best value"
|
|
265
|
+
}
|
|
266
|
+
],
|
|
267
|
+
"billingMainLabel": "Monthly",
|
|
268
|
+
"billingAltLabel": "Yearly",
|
|
269
|
+
"billingLegend": "Billing period"
|
|
270
|
+
}
|
|
271
|
+
},
|
|
272
|
+
{
|
|
273
|
+
"name": "missing-period-description",
|
|
274
|
+
"props": {
|
|
275
|
+
"plans": [
|
|
276
|
+
{
|
|
277
|
+
"name": "Custom",
|
|
278
|
+
"price": "On request",
|
|
279
|
+
"ctaLabel": "Talk to us",
|
|
280
|
+
"ctaHref": "/contact/"
|
|
281
|
+
},
|
|
282
|
+
{
|
|
283
|
+
"name": "Open",
|
|
284
|
+
"price": "Free",
|
|
285
|
+
"features": "- Everything"
|
|
286
|
+
}
|
|
287
|
+
]
|
|
288
|
+
}
|
|
289
|
+
}
|
|
6
290
|
]
|