@cogenta/theme-restaurant 0.3.2 → 0.5.3
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/dist/src/index.d.ts +3 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +3 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/render/blocks/accordion.d.ts +7 -0
- package/dist/src/render/blocks/accordion.d.ts.map +1 -1
- package/dist/src/render/blocks/accordion.js +10 -16
- package/dist/src/render/blocks/accordion.js.map +1 -1
- package/dist/src/render/blocks/collection-list.d.ts +4 -11
- package/dist/src/render/blocks/collection-list.d.ts.map +1 -1
- package/dist/src/render/blocks/collection-list.js +96 -96
- package/dist/src/render/blocks/collection-list.js.map +1 -1
- package/dist/src/render/blocks/cta.d.ts +7 -4
- package/dist/src/render/blocks/cta.d.ts.map +1 -1
- package/dist/src/render/blocks/cta.js +9 -7
- package/dist/src/render/blocks/cta.js.map +1 -1
- package/dist/src/render/blocks/embed.d.ts.map +1 -1
- package/dist/src/render/blocks/embed.js +30 -28
- package/dist/src/render/blocks/embed.js.map +1 -1
- package/dist/src/render/blocks/faq.d.ts +13 -1
- package/dist/src/render/blocks/faq.d.ts.map +1 -1
- package/dist/src/render/blocks/faq.js +15 -11
- package/dist/src/render/blocks/faq.js.map +1 -1
- package/dist/src/render/blocks/feature-grid.d.ts.map +1 -1
- package/dist/src/render/blocks/feature-grid.js +43 -16
- package/dist/src/render/blocks/feature-grid.js.map +1 -1
- package/dist/src/render/blocks/gallery.d.ts +0 -7
- package/dist/src/render/blocks/gallery.d.ts.map +1 -1
- package/dist/src/render/blocks/gallery.js +28 -10
- package/dist/src/render/blocks/gallery.js.map +1 -1
- package/dist/src/render/blocks/hero.d.ts +16 -9
- package/dist/src/render/blocks/hero.d.ts.map +1 -1
- package/dist/src/render/blocks/hero.js +27 -20
- package/dist/src/render/blocks/hero.js.map +1 -1
- package/dist/src/render/blocks/logo-strip.d.ts +6 -0
- package/dist/src/render/blocks/logo-strip.d.ts.map +1 -1
- package/dist/src/render/blocks/logo-strip.js +7 -9
- package/dist/src/render/blocks/logo-strip.js.map +1 -1
- package/dist/src/render/blocks/logos.d.ts +8 -0
- package/dist/src/render/blocks/logos.d.ts.map +1 -1
- package/dist/src/render/blocks/logos.js +18 -18
- package/dist/src/render/blocks/logos.js.map +1 -1
- package/dist/src/render/blocks/media-figure.d.ts +14 -3
- package/dist/src/render/blocks/media-figure.d.ts.map +1 -1
- package/dist/src/render/blocks/media-figure.js +34 -16
- package/dist/src/render/blocks/media-figure.js.map +1 -1
- package/dist/src/render/blocks/pricing-table.d.ts.map +1 -1
- package/dist/src/render/blocks/pricing-table.js +17 -22
- package/dist/src/render/blocks/pricing-table.js.map +1 -1
- package/dist/src/render/blocks/prose.d.ts +11 -6
- package/dist/src/render/blocks/prose.d.ts.map +1 -1
- package/dist/src/render/blocks/prose.js +13 -7
- package/dist/src/render/blocks/prose.js.map +1 -1
- package/dist/src/render/blocks/quote.d.ts +6 -2
- package/dist/src/render/blocks/quote.d.ts.map +1 -1
- package/dist/src/render/blocks/quote.js +14 -12
- package/dist/src/render/blocks/quote.js.map +1 -1
- package/dist/src/render/blocks/stat-counter.d.ts +6 -0
- package/dist/src/render/blocks/stat-counter.d.ts.map +1 -1
- package/dist/src/render/blocks/stat-counter.js +7 -10
- package/dist/src/render/blocks/stat-counter.js.map +1 -1
- package/dist/src/render/blocks/stats.d.ts +7 -0
- package/dist/src/render/blocks/stats.d.ts.map +1 -1
- package/dist/src/render/blocks/stats.js +8 -16
- package/dist/src/render/blocks/stats.js.map +1 -1
- package/dist/src/render/blocks/testimonial.d.ts +5 -11
- package/dist/src/render/blocks/testimonial.d.ts.map +1 -1
- package/dist/src/render/blocks/testimonial.js +9 -17
- package/dist/src/render/blocks/testimonial.js.map +1 -1
- package/dist/src/render/chrome.d.ts.map +1 -1
- package/dist/src/render/chrome.js +101 -84
- package/dist/src/render/chrome.js.map +1 -1
- package/dist/src/render/dish.d.ts +13 -0
- package/dist/src/render/dish.d.ts.map +1 -0
- package/dist/src/render/dish.js +84 -0
- package/dist/src/render/dish.js.map +1 -0
- package/dist/src/render/layout.d.ts +23 -0
- package/dist/src/render/layout.d.ts.map +1 -0
- package/dist/src/render/layout.js +33 -0
- package/dist/src/render/layout.js.map +1 -0
- package/dist/src/render/menu.d.ts +53 -0
- package/dist/src/render/menu.d.ts.map +1 -0
- package/dist/src/render/menu.js +99 -0
- package/dist/src/render/menu.js.map +1 -0
- package/dist/src/render/render-block.d.ts +19 -0
- package/dist/src/render/render-block.d.ts.map +1 -1
- package/dist/src/render/render-block.js +50 -39
- package/dist/src/render/render-block.js.map +1 -1
- package/dist/src/render/strings.d.ts +15 -0
- package/dist/src/render/strings.d.ts.map +1 -0
- package/dist/src/render/strings.js +23 -0
- package/dist/src/render/strings.js.map +1 -0
- package/dist/src/render/term-archive.d.ts +10 -4
- package/dist/src/render/term-archive.d.ts.map +1 -1
- package/dist/src/render/term-archive.js +25 -16
- package/dist/src/render/term-archive.js.map +1 -1
- package/dist/src/render/widget-areas.d.ts +13 -0
- package/dist/src/render/widget-areas.d.ts.map +1 -0
- package/dist/src/render/widget-areas.js +20 -0
- package/dist/src/render/widget-areas.js.map +1 -0
- package/dist/theme.config.d.ts +1 -1
- package/dist/theme.config.js +2 -2
- package/dist/theme.config.js.map +1 -1
- package/package.json +5 -5
- package/src/index.ts +3 -0
- package/src/render/blocks/accordion.ts +18 -47
- package/src/render/blocks/collection-list.ts +245 -133
- package/src/render/blocks/cta.ts +20 -11
- package/src/render/blocks/embed.ts +45 -36
- package/src/render/blocks/faq.ts +32 -25
- package/src/render/blocks/feature-grid.ts +83 -33
- package/src/render/blocks/gallery.ts +39 -21
- package/src/render/blocks/hero.ts +41 -34
- package/src/render/blocks/logo-strip.ts +27 -25
- package/src/render/blocks/logos.ts +34 -43
- package/src/render/blocks/media-figure.ts +49 -24
- package/src/render/blocks/pricing-table.ts +30 -42
- package/src/render/blocks/prose.ts +18 -9
- package/src/render/blocks/quote.ts +29 -19
- package/src/render/blocks/stat-counter.ts +24 -29
- package/src/render/blocks/stats.ts +30 -40
- package/src/render/blocks/testimonial.ts +17 -22
- package/src/render/chrome.ts +113 -95
- package/src/render/dish.ts +195 -0
- package/src/render/layout.ts +64 -0
- package/src/render/menu.ts +117 -0
- package/src/render/render-block.ts +51 -40
- package/src/render/strings.ts +44 -0
- package/src/render/term-archive.ts +78 -44
- package/src/render/widget-areas.ts +23 -0
- package/src/styles/archive.css +46 -56
- package/src/styles/base.css +807 -554
- package/src/styles/blocks.css +723 -641
- package/src/styles/menu.css +482 -0
- package/src/styles/theme.css +24 -25
- package/src/styles/tokens.css +239 -225
- package/src/styles/widgets.css +853 -0
- package/tokens.json +16 -16
|
@@ -1,74 +1,62 @@
|
|
|
1
1
|
import type { PricingTableBlock, PricingTier } from '@cogenta/blocks'
|
|
2
2
|
import {
|
|
3
3
|
actionLink,
|
|
4
|
-
blockHeadingTag,
|
|
5
|
-
type HeadingTag,
|
|
6
4
|
type HtmlElement,
|
|
7
5
|
h,
|
|
8
6
|
heading,
|
|
9
7
|
nestedHeadingTag,
|
|
10
8
|
type RenderContext,
|
|
11
9
|
} from '@cogenta/theme-kit'
|
|
10
|
+
import { section, sectionHead } from '../layout.js'
|
|
12
11
|
|
|
13
12
|
/**
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
13
|
+
* Set menus side by side (lunch, the evening menu, a menu for a private
|
|
14
|
+
* party), set the way a menu card prints them: ruled columns rather than
|
|
15
|
+
* cards, the name of the menu in small capitals, the price light and large in
|
|
16
|
+
* the display serif with tabular figures and what it covers ("per guest")
|
|
17
|
+
* under it, then the courses one per line between hairlines, and the action
|
|
18
|
+
* at the foot.
|
|
19
|
+
*
|
|
20
|
+
* `highlighted` is an editorial emphasis, drawn as the column's top rule in
|
|
21
|
+
* ink instead of a hairline. No ribbon, no raised card, no accent fill.
|
|
20
22
|
*/
|
|
21
|
-
function
|
|
23
|
+
function tier(item: PricingTier, ctx: RenderContext, titled: boolean): HtmlElement {
|
|
22
24
|
return h(
|
|
23
25
|
'li',
|
|
24
|
-
{
|
|
25
|
-
|
|
26
|
-
'data-highlighted': tier.highlighted === true ? 'true' : undefined,
|
|
27
|
-
'aria-current': tier.highlighted === true ? 'true' : undefined,
|
|
28
|
-
},
|
|
29
|
-
heading(tag, { class: 'cg-set-menu__name' }, tier.name),
|
|
26
|
+
{ class: 'cr-set__tier', 'data-highlighted': item.highlighted === true ? 'true' : 'false' },
|
|
27
|
+
heading(nestedHeadingTag('pricingTable', titled), { class: 'cr-set__name' }, item.name),
|
|
30
28
|
h(
|
|
31
29
|
'p',
|
|
32
|
-
{ class: '
|
|
33
|
-
h('span', { class: '
|
|
34
|
-
|
|
35
|
-
? null
|
|
36
|
-
: h('span', { class: 'cg-set-menu__interval' }, tier.interval),
|
|
30
|
+
{ class: 'cr-set__price' },
|
|
31
|
+
h('span', { class: 'cr-set__amount' }, item.price),
|
|
32
|
+
item.interval === undefined ? null : h('span', { class: 'cr-set__interval' }, item.interval),
|
|
37
33
|
),
|
|
38
|
-
|
|
34
|
+
item.features.length === 0
|
|
39
35
|
? null
|
|
40
36
|
: h(
|
|
41
37
|
'ul',
|
|
42
|
-
{ class: '
|
|
43
|
-
|
|
38
|
+
{ class: 'cr-set__courses' },
|
|
39
|
+
item.features.map((feature) => h('li', { class: 'cr-set__course' }, feature)),
|
|
44
40
|
),
|
|
45
|
-
|
|
41
|
+
item.action === undefined
|
|
46
42
|
? null
|
|
47
|
-
: h(
|
|
48
|
-
'div',
|
|
49
|
-
{ class: 'cg-set-menu__action' },
|
|
50
|
-
actionLink(ctx, { ...tier.action, emphasis: tier.action.emphasis ?? 'primary' }),
|
|
51
|
-
),
|
|
43
|
+
: h('div', { class: 'cr-set__action' }, actionLink(ctx, item.action)),
|
|
52
44
|
)
|
|
53
45
|
}
|
|
54
46
|
|
|
55
47
|
export function renderPricingTable(block: PricingTableBlock, ctx: RenderContext): HtmlElement {
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
return h(
|
|
48
|
+
const titled = block.title !== undefined
|
|
49
|
+
return section(
|
|
59
50
|
'section',
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
block.title ?? '',
|
|
66
|
-
)
|
|
67
|
-
: null,
|
|
51
|
+
'pricingTable',
|
|
52
|
+
'cr-set',
|
|
53
|
+
{ 'data-count': String(Math.min(block.tiers.length, 4)) },
|
|
54
|
+
'div',
|
|
55
|
+
sectionHead('pricingTable', block.title),
|
|
68
56
|
h(
|
|
69
57
|
'ul',
|
|
70
|
-
{ class: '
|
|
71
|
-
block.tiers.map((
|
|
58
|
+
{ class: 'cr-set__tiers' },
|
|
59
|
+
block.tiers.map((item) => tier(item, ctx, titled)),
|
|
72
60
|
),
|
|
73
61
|
)
|
|
74
62
|
}
|
|
@@ -1,19 +1,28 @@
|
|
|
1
1
|
import type { ProseBlock } from '@cogenta/blocks'
|
|
2
2
|
import { type HtmlElement, h, type RenderContext, renderRichText } from '@cogenta/theme-kit'
|
|
3
|
+
import { section } from '../layout.js'
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
|
-
*
|
|
6
|
-
* `tokens.css`), the quiet editorial interlude every one of the reference
|
|
7
|
-
* templates (Divi/Astra "Restaurant") places between the hero and the menu.
|
|
6
|
+
* Running text: the kitchen's story, how to book, a legal notice.
|
|
8
7
|
*
|
|
9
|
-
* `prose` declares `headingLevel: 'none'
|
|
10
|
-
* own
|
|
11
|
-
*
|
|
8
|
+
* `prose` declares `headingLevel: 'none'`, so it adds no heading of its own;
|
|
9
|
+
* the rich text's own headings start at `h2`. The column starts at the third
|
|
10
|
+
* of twelve and holds a reading measure of about sixty-four characters, so a
|
|
11
|
+
* page title set at the first column and the text under it make one
|
|
12
|
+
* asymmetric line rather than a centred column.
|
|
13
|
+
*
|
|
14
|
+
* One exception, asked for by the editor rather than guessed: a prose block
|
|
15
|
+
* whose `align` variant is `center` is a welcome, a few sentences set large
|
|
16
|
+
* in the display serif and centred under the opening photograph, the way a
|
|
17
|
+
* menu card opens with a line from the house.
|
|
12
18
|
*/
|
|
13
19
|
export function renderProse(block: ProseBlock, ctx: RenderContext): HtmlElement {
|
|
14
|
-
return
|
|
20
|
+
return section(
|
|
21
|
+
'div',
|
|
22
|
+
'prose',
|
|
23
|
+
'cr-prose',
|
|
24
|
+
{},
|
|
15
25
|
'div',
|
|
16
|
-
{ class: '
|
|
17
|
-
h('div', { class: 'cg-story__body' }, renderRichText(ctx, block.body)),
|
|
26
|
+
h('div', { class: 'cr-prose__body' }, renderRichText(ctx, block.body)),
|
|
18
27
|
)
|
|
19
28
|
}
|
|
@@ -1,38 +1,48 @@
|
|
|
1
1
|
import type { QuoteBlock } from '@cogenta/blocks'
|
|
2
2
|
import { type HtmlElement, h, image, type RenderContext } from '@cogenta/theme-kit'
|
|
3
|
+
import { section } from '../layout.js'
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
|
-
* A
|
|
6
|
-
*
|
|
6
|
+
* A line from the press, set the way a newspaper sets a pull quote rather
|
|
7
|
+
* than the way a template sets a review card: the words large and light in
|
|
8
|
+
* the display serif across nine columns from the second, with real quotation
|
|
9
|
+
* marks hung in the margin by the stylesheet; the writer's name and the
|
|
10
|
+
* publication small beneath, after a short hairline. A portrait, when there
|
|
11
|
+
* is one, is a small square beside the name, never a circle above the words.
|
|
7
12
|
*/
|
|
8
13
|
export function renderQuote(block: QuoteBlock, ctx: RenderContext): HtmlElement {
|
|
9
|
-
const
|
|
10
|
-
block.author
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
{ class: 'cg-line', 'data-block': 'quote' },
|
|
14
|
-
h('blockquote', { class: 'cg-line__text' }, h('p', { 'data-field': 'text' }, block.text)),
|
|
15
|
-
hasAttribution
|
|
16
|
-
? h(
|
|
14
|
+
const who =
|
|
15
|
+
block.author === undefined && block.role === undefined
|
|
16
|
+
? null
|
|
17
|
+
: h(
|
|
17
18
|
'figcaption',
|
|
18
|
-
{ class: '
|
|
19
|
+
{ class: 'cr-quote__attribution' },
|
|
19
20
|
block.avatar === undefined
|
|
20
21
|
? null
|
|
21
|
-
: image(ctx, block.avatar, {
|
|
22
|
-
className: 'cg-line__avatar',
|
|
23
|
-
variant: { width: 72, height: 72, fit: 'cover' },
|
|
24
|
-
}),
|
|
22
|
+
: image(ctx, block.avatar, { className: 'cr-quote__avatar', sizes: '3rem' }),
|
|
25
23
|
h(
|
|
26
24
|
'span',
|
|
27
|
-
{ class: '
|
|
25
|
+
{ class: 'cr-quote__who' },
|
|
28
26
|
block.author === undefined
|
|
29
27
|
? null
|
|
30
|
-
: h('span', { class: '
|
|
28
|
+
: h('span', { class: 'cr-quote__author', 'data-field': 'author' }, block.author),
|
|
31
29
|
block.role === undefined
|
|
32
30
|
? null
|
|
33
|
-
: h('span', { class: '
|
|
31
|
+
: h('span', { class: 'cr-quote__role', 'data-field': 'role' }, block.role),
|
|
34
32
|
),
|
|
35
33
|
)
|
|
36
|
-
|
|
34
|
+
|
|
35
|
+
return section(
|
|
36
|
+
'div',
|
|
37
|
+
'quote',
|
|
38
|
+
'cr-quote',
|
|
39
|
+
{},
|
|
40
|
+
'figure',
|
|
41
|
+
h(
|
|
42
|
+
'blockquote',
|
|
43
|
+
{ class: 'cr-quote__quote' },
|
|
44
|
+
h('p', { class: 'cr-quote__text', 'data-field': 'text' }, block.text),
|
|
45
|
+
),
|
|
46
|
+
who,
|
|
37
47
|
)
|
|
38
48
|
}
|
|
@@ -1,37 +1,32 @@
|
|
|
1
|
-
import type { StatCounterBlock
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
type HtmlElement,
|
|
5
|
-
h,
|
|
6
|
-
heading,
|
|
7
|
-
type RenderContext,
|
|
8
|
-
} from '@cogenta/theme-kit'
|
|
1
|
+
import type { StatCounterBlock } from '@cogenta/blocks'
|
|
2
|
+
import { type HtmlElement, h, type RenderContext } from '@cogenta/theme-kit'
|
|
3
|
+
import { section, sectionHead } from '../layout.js'
|
|
9
4
|
|
|
10
5
|
/**
|
|
11
|
-
* `
|
|
12
|
-
* same
|
|
13
|
-
*
|
|
6
|
+
* The narrower sibling of `stats` (a value and a label, no unit), drawn in
|
|
7
|
+
* the same register: figures in the display serif under one hairline.
|
|
8
|
+
* Nothing counts up; a number that animates into place is a number a guest
|
|
9
|
+
* has to wait for.
|
|
14
10
|
*/
|
|
15
|
-
function renderItem(item: StatCounterItem): HtmlElement {
|
|
16
|
-
return h(
|
|
17
|
-
'div',
|
|
18
|
-
{ class: 'cg-tally' },
|
|
19
|
-
h('dd', { class: 'cg-tally__value' }, item.value),
|
|
20
|
-
h('dt', { class: 'cg-tally__label' }, item.label),
|
|
21
|
-
)
|
|
22
|
-
}
|
|
23
|
-
|
|
24
11
|
export function renderStatCounter(block: StatCounterBlock, _ctx: RenderContext): HtmlElement {
|
|
25
|
-
return
|
|
12
|
+
return section(
|
|
26
13
|
'section',
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
14
|
+
'statCounter',
|
|
15
|
+
'cr-figures',
|
|
16
|
+
{ 'data-count': String(Math.min(block.stats.length, 4)) },
|
|
17
|
+
'div',
|
|
18
|
+
sectionHead('statCounter', block.title),
|
|
19
|
+
h(
|
|
20
|
+
'dl',
|
|
21
|
+
{ class: 'cr-figures__items' },
|
|
22
|
+
block.stats.map((stat) =>
|
|
23
|
+
h(
|
|
24
|
+
'div',
|
|
25
|
+
{ class: 'cr-figures__item' },
|
|
26
|
+
h('dt', { class: 'cr-figures__label' }, stat.label),
|
|
27
|
+
h('dd', { class: 'cr-figures__value' }, stat.value),
|
|
34
28
|
),
|
|
35
|
-
|
|
29
|
+
),
|
|
30
|
+
),
|
|
36
31
|
)
|
|
37
32
|
}
|
|
@@ -1,48 +1,38 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
type HtmlElement,
|
|
5
|
-
h,
|
|
6
|
-
heading,
|
|
7
|
-
type RenderContext,
|
|
8
|
-
} from '@cogenta/theme-kit'
|
|
1
|
+
import type { StatsBlock } from '@cogenta/blocks'
|
|
2
|
+
import { type HtmlElement, h, type RenderContext } from '@cogenta/theme-kit'
|
|
3
|
+
import { section, sectionHead } from '../layout.js'
|
|
9
4
|
|
|
10
5
|
/**
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* the
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
* A description list, as every built-in theme uses for `stats`: each figure
|
|
17
|
-
* is the description of its label, which is what `<dt>`/`<dd>` mean, and it
|
|
18
|
-
* survives being read linearly (WCAG 1.3.2 — reading order and visual order
|
|
19
|
-
* stay independent regardless of how the skin repaints them).
|
|
6
|
+
* Figures a kitchen can stand behind (covers a night, farms it buys from, the
|
|
7
|
+
* year it opened), set as a row of columns under one hairline: the number
|
|
8
|
+
* (the `dd`, drawn above its label) light and large in the display serif with
|
|
9
|
+
* lining tabular figures, its unit a step smaller, and a sentence of context
|
|
10
|
+
* under it. No box, no tint, no counter animation.
|
|
20
11
|
*/
|
|
21
|
-
function renderItem(item: StatItem): HtmlElement {
|
|
22
|
-
return h(
|
|
23
|
-
'div',
|
|
24
|
-
{ class: 'cg-figures__item' },
|
|
25
|
-
h(
|
|
26
|
-
'dd',
|
|
27
|
-
{ class: 'cg-figures__value' },
|
|
28
|
-
item.value,
|
|
29
|
-
item.unit === undefined ? null : h('span', { class: 'cg-figures__unit' }, item.unit),
|
|
30
|
-
),
|
|
31
|
-
h('dt', { class: 'cg-figures__label' }, item.label),
|
|
32
|
-
)
|
|
33
|
-
}
|
|
34
|
-
|
|
35
12
|
export function renderStats(block: StatsBlock, _ctx: RenderContext): HtmlElement {
|
|
36
|
-
return
|
|
13
|
+
return section(
|
|
37
14
|
'section',
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
15
|
+
'stats',
|
|
16
|
+
'cr-figures',
|
|
17
|
+
{ 'data-count': String(Math.min(block.items.length, 4)) },
|
|
18
|
+
'div',
|
|
19
|
+
sectionHead('stats', block.title),
|
|
20
|
+
h(
|
|
21
|
+
'dl',
|
|
22
|
+
{ class: 'cr-figures__items' },
|
|
23
|
+
block.items.map((item) =>
|
|
24
|
+
h(
|
|
25
|
+
'div',
|
|
26
|
+
{ class: 'cr-figures__item' },
|
|
27
|
+
h('dt', { class: 'cr-figures__label' }, item.label),
|
|
28
|
+
h(
|
|
29
|
+
'dd',
|
|
30
|
+
{ class: 'cr-figures__value' },
|
|
31
|
+
item.value,
|
|
32
|
+
item.unit === undefined ? null : h('span', { class: 'cr-figures__unit' }, item.unit),
|
|
33
|
+
),
|
|
45
34
|
),
|
|
46
|
-
|
|
35
|
+
),
|
|
36
|
+
),
|
|
47
37
|
)
|
|
48
38
|
}
|
|
@@ -1,41 +1,36 @@
|
|
|
1
1
|
import type { TestimonialBlock } from '@cogenta/blocks'
|
|
2
2
|
import { type HtmlElement, h, image, type RenderContext, renderRichText } from '@cogenta/theme-kit'
|
|
3
|
+
import { section } from '../layout.js'
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
|
-
* A
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* pattern the HTML spec prescribes: putting the author inside the
|
|
11
|
-
* `<blockquote>` would claim the author's name was part of what was said.
|
|
12
|
-
*
|
|
13
|
-
* The avatar is decorative — the name sits right beside it in text — so its
|
|
14
|
-
* media entity's alt text is expected to be empty; `image` still writes the
|
|
15
|
-
* attribute either way (WCAG 1.1.1).
|
|
6
|
+
* A guest's own words, set like a note left in the book by the door: the text
|
|
7
|
+
* in the serif italic at the lead size on seven columns from the fourth, the
|
|
8
|
+
* name and the occasion beneath it at the caption size. Smaller and quieter
|
|
9
|
+
* than a press quote, on purpose. The layout does not depend on a portrait;
|
|
10
|
+
* when one is there it is a small square beside the name.
|
|
16
11
|
*/
|
|
17
12
|
export function renderTestimonial(block: TestimonialBlock, ctx: RenderContext): HtmlElement {
|
|
18
13
|
const { attribution } = block
|
|
19
|
-
return
|
|
14
|
+
return section(
|
|
15
|
+
'div',
|
|
16
|
+
'testimonial',
|
|
17
|
+
'cr-note',
|
|
18
|
+
{},
|
|
20
19
|
'figure',
|
|
21
|
-
{ class: '
|
|
22
|
-
h('blockquote', { class: 'cg-testimonial__quote' }, renderRichText(ctx, block.quote)),
|
|
20
|
+
h('blockquote', { class: 'cr-note__quote' }, renderRichText(ctx, block.quote)),
|
|
23
21
|
h(
|
|
24
22
|
'figcaption',
|
|
25
|
-
{ class: '
|
|
23
|
+
{ class: 'cr-note__attribution' },
|
|
26
24
|
attribution.avatar === undefined
|
|
27
25
|
? null
|
|
28
|
-
: image(ctx, attribution.avatar, {
|
|
29
|
-
className: 'cg-testimonial__avatar',
|
|
30
|
-
variant: { width: 88, height: 88, fit: 'cover' },
|
|
31
|
-
}),
|
|
26
|
+
: image(ctx, attribution.avatar, { className: 'cr-note__avatar', sizes: '3.5rem' }),
|
|
32
27
|
h(
|
|
33
28
|
'span',
|
|
34
|
-
{ class: '
|
|
35
|
-
h('span', { class: '
|
|
29
|
+
{ class: 'cr-note__who' },
|
|
30
|
+
h('span', { class: 'cr-note__name' }, attribution.name),
|
|
36
31
|
attribution.role === undefined
|
|
37
32
|
? null
|
|
38
|
-
: h('span', { class: '
|
|
33
|
+
: h('span', { class: 'cr-note__role' }, attribution.role),
|
|
39
34
|
),
|
|
40
35
|
),
|
|
41
36
|
)
|