@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.
Files changed (138) hide show
  1. package/dist/src/index.d.ts +3 -0
  2. package/dist/src/index.d.ts.map +1 -1
  3. package/dist/src/index.js +3 -0
  4. package/dist/src/index.js.map +1 -1
  5. package/dist/src/render/blocks/accordion.d.ts +7 -0
  6. package/dist/src/render/blocks/accordion.d.ts.map +1 -1
  7. package/dist/src/render/blocks/accordion.js +10 -16
  8. package/dist/src/render/blocks/accordion.js.map +1 -1
  9. package/dist/src/render/blocks/collection-list.d.ts +4 -11
  10. package/dist/src/render/blocks/collection-list.d.ts.map +1 -1
  11. package/dist/src/render/blocks/collection-list.js +96 -96
  12. package/dist/src/render/blocks/collection-list.js.map +1 -1
  13. package/dist/src/render/blocks/cta.d.ts +7 -4
  14. package/dist/src/render/blocks/cta.d.ts.map +1 -1
  15. package/dist/src/render/blocks/cta.js +9 -7
  16. package/dist/src/render/blocks/cta.js.map +1 -1
  17. package/dist/src/render/blocks/embed.d.ts.map +1 -1
  18. package/dist/src/render/blocks/embed.js +30 -28
  19. package/dist/src/render/blocks/embed.js.map +1 -1
  20. package/dist/src/render/blocks/faq.d.ts +13 -1
  21. package/dist/src/render/blocks/faq.d.ts.map +1 -1
  22. package/dist/src/render/blocks/faq.js +15 -11
  23. package/dist/src/render/blocks/faq.js.map +1 -1
  24. package/dist/src/render/blocks/feature-grid.d.ts.map +1 -1
  25. package/dist/src/render/blocks/feature-grid.js +43 -16
  26. package/dist/src/render/blocks/feature-grid.js.map +1 -1
  27. package/dist/src/render/blocks/gallery.d.ts +0 -7
  28. package/dist/src/render/blocks/gallery.d.ts.map +1 -1
  29. package/dist/src/render/blocks/gallery.js +28 -10
  30. package/dist/src/render/blocks/gallery.js.map +1 -1
  31. package/dist/src/render/blocks/hero.d.ts +16 -9
  32. package/dist/src/render/blocks/hero.d.ts.map +1 -1
  33. package/dist/src/render/blocks/hero.js +27 -20
  34. package/dist/src/render/blocks/hero.js.map +1 -1
  35. package/dist/src/render/blocks/logo-strip.d.ts +6 -0
  36. package/dist/src/render/blocks/logo-strip.d.ts.map +1 -1
  37. package/dist/src/render/blocks/logo-strip.js +7 -9
  38. package/dist/src/render/blocks/logo-strip.js.map +1 -1
  39. package/dist/src/render/blocks/logos.d.ts +8 -0
  40. package/dist/src/render/blocks/logos.d.ts.map +1 -1
  41. package/dist/src/render/blocks/logos.js +18 -18
  42. package/dist/src/render/blocks/logos.js.map +1 -1
  43. package/dist/src/render/blocks/media-figure.d.ts +14 -3
  44. package/dist/src/render/blocks/media-figure.d.ts.map +1 -1
  45. package/dist/src/render/blocks/media-figure.js +34 -16
  46. package/dist/src/render/blocks/media-figure.js.map +1 -1
  47. package/dist/src/render/blocks/pricing-table.d.ts.map +1 -1
  48. package/dist/src/render/blocks/pricing-table.js +17 -22
  49. package/dist/src/render/blocks/pricing-table.js.map +1 -1
  50. package/dist/src/render/blocks/prose.d.ts +11 -6
  51. package/dist/src/render/blocks/prose.d.ts.map +1 -1
  52. package/dist/src/render/blocks/prose.js +13 -7
  53. package/dist/src/render/blocks/prose.js.map +1 -1
  54. package/dist/src/render/blocks/quote.d.ts +6 -2
  55. package/dist/src/render/blocks/quote.d.ts.map +1 -1
  56. package/dist/src/render/blocks/quote.js +14 -12
  57. package/dist/src/render/blocks/quote.js.map +1 -1
  58. package/dist/src/render/blocks/stat-counter.d.ts +6 -0
  59. package/dist/src/render/blocks/stat-counter.d.ts.map +1 -1
  60. package/dist/src/render/blocks/stat-counter.js +7 -10
  61. package/dist/src/render/blocks/stat-counter.js.map +1 -1
  62. package/dist/src/render/blocks/stats.d.ts +7 -0
  63. package/dist/src/render/blocks/stats.d.ts.map +1 -1
  64. package/dist/src/render/blocks/stats.js +8 -16
  65. package/dist/src/render/blocks/stats.js.map +1 -1
  66. package/dist/src/render/blocks/testimonial.d.ts +5 -11
  67. package/dist/src/render/blocks/testimonial.d.ts.map +1 -1
  68. package/dist/src/render/blocks/testimonial.js +9 -17
  69. package/dist/src/render/blocks/testimonial.js.map +1 -1
  70. package/dist/src/render/chrome.d.ts.map +1 -1
  71. package/dist/src/render/chrome.js +101 -84
  72. package/dist/src/render/chrome.js.map +1 -1
  73. package/dist/src/render/dish.d.ts +13 -0
  74. package/dist/src/render/dish.d.ts.map +1 -0
  75. package/dist/src/render/dish.js +84 -0
  76. package/dist/src/render/dish.js.map +1 -0
  77. package/dist/src/render/layout.d.ts +23 -0
  78. package/dist/src/render/layout.d.ts.map +1 -0
  79. package/dist/src/render/layout.js +33 -0
  80. package/dist/src/render/layout.js.map +1 -0
  81. package/dist/src/render/menu.d.ts +53 -0
  82. package/dist/src/render/menu.d.ts.map +1 -0
  83. package/dist/src/render/menu.js +99 -0
  84. package/dist/src/render/menu.js.map +1 -0
  85. package/dist/src/render/render-block.d.ts +19 -0
  86. package/dist/src/render/render-block.d.ts.map +1 -1
  87. package/dist/src/render/render-block.js +50 -39
  88. package/dist/src/render/render-block.js.map +1 -1
  89. package/dist/src/render/strings.d.ts +15 -0
  90. package/dist/src/render/strings.d.ts.map +1 -0
  91. package/dist/src/render/strings.js +23 -0
  92. package/dist/src/render/strings.js.map +1 -0
  93. package/dist/src/render/term-archive.d.ts +10 -4
  94. package/dist/src/render/term-archive.d.ts.map +1 -1
  95. package/dist/src/render/term-archive.js +25 -16
  96. package/dist/src/render/term-archive.js.map +1 -1
  97. package/dist/src/render/widget-areas.d.ts +13 -0
  98. package/dist/src/render/widget-areas.d.ts.map +1 -0
  99. package/dist/src/render/widget-areas.js +20 -0
  100. package/dist/src/render/widget-areas.js.map +1 -0
  101. package/dist/theme.config.d.ts +1 -1
  102. package/dist/theme.config.js +2 -2
  103. package/dist/theme.config.js.map +1 -1
  104. package/package.json +5 -5
  105. package/src/index.ts +3 -0
  106. package/src/render/blocks/accordion.ts +18 -47
  107. package/src/render/blocks/collection-list.ts +245 -133
  108. package/src/render/blocks/cta.ts +20 -11
  109. package/src/render/blocks/embed.ts +45 -36
  110. package/src/render/blocks/faq.ts +32 -25
  111. package/src/render/blocks/feature-grid.ts +83 -33
  112. package/src/render/blocks/gallery.ts +39 -21
  113. package/src/render/blocks/hero.ts +41 -34
  114. package/src/render/blocks/logo-strip.ts +27 -25
  115. package/src/render/blocks/logos.ts +34 -43
  116. package/src/render/blocks/media-figure.ts +49 -24
  117. package/src/render/blocks/pricing-table.ts +30 -42
  118. package/src/render/blocks/prose.ts +18 -9
  119. package/src/render/blocks/quote.ts +29 -19
  120. package/src/render/blocks/stat-counter.ts +24 -29
  121. package/src/render/blocks/stats.ts +30 -40
  122. package/src/render/blocks/testimonial.ts +17 -22
  123. package/src/render/chrome.ts +113 -95
  124. package/src/render/dish.ts +195 -0
  125. package/src/render/layout.ts +64 -0
  126. package/src/render/menu.ts +117 -0
  127. package/src/render/render-block.ts +51 -40
  128. package/src/render/strings.ts +44 -0
  129. package/src/render/term-archive.ts +78 -44
  130. package/src/render/widget-areas.ts +23 -0
  131. package/src/styles/archive.css +46 -56
  132. package/src/styles/base.css +807 -554
  133. package/src/styles/blocks.css +723 -641
  134. package/src/styles/menu.css +482 -0
  135. package/src/styles/theme.css +24 -25
  136. package/src/styles/tokens.css +239 -225
  137. package/src/styles/widgets.css +853 -0
  138. 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
- * `blocks@2.0` (RFC 0001). Rendered as a set-menu comparison — a "tasting
15
- * menu" / "prix fixe" tier is the shape this block already has (a name, a
16
- * price, a feature list), so this theme reuses the same restrained bordered
17
- * plates the rest of the vocabulary uses rather than a distinct pricing
18
- * skin. `highlighted` becomes a small "chef's pick" rule rather than a
19
- * colour.
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 renderTier(tier: PricingTier, ctx: RenderContext, tag: HeadingTag): HtmlElement {
23
+ function tier(item: PricingTier, ctx: RenderContext, titled: boolean): HtmlElement {
22
24
  return h(
23
25
  'li',
24
- {
25
- class: 'cg-set-menu__tier',
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: 'cg-set-menu__price' },
33
- h('span', { class: 'cg-set-menu__amount' }, tier.price),
34
- tier.interval === undefined
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
- tier.features.length === 0
34
+ item.features.length === 0
39
35
  ? null
40
36
  : h(
41
37
  'ul',
42
- { class: 'cg-set-menu__features' },
43
- tier.features.map((feature) => h('li', { class: 'cg-set-menu__feature' }, feature)),
38
+ { class: 'cr-set__courses' },
39
+ item.features.map((feature) => h('li', { class: 'cr-set__course' }, feature)),
44
40
  ),
45
- tier.action === undefined
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 hasTitle = block.title !== undefined
57
- const tierTag = nestedHeadingTag('pricingTable', hasTitle)
58
- return h(
48
+ const titled = block.title !== undefined
49
+ return section(
59
50
  'section',
60
- { class: 'cg-set-menu', 'data-block': 'pricingTable' },
61
- hasTitle
62
- ? heading(
63
- blockHeadingTag('pricingTable') ?? 'h2',
64
- { class: 'cg-set-menu__title', 'data-field': 'title' },
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: 'cg-set-menu__tiers' },
71
- block.tiers.map((tier) => renderTier(tier, ctx, tierTag)),
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
- * "Our story" — a short, centred, narrow column (`--cg-measure-narrow` in
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'`: it contributes no heading of its
10
- * own. Whatever headings appear come from the rich text document, whose
11
- * vocabulary starts at `h2`.
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 h(
20
+ return section(
21
+ 'div',
22
+ 'prose',
23
+ 'cr-prose',
24
+ {},
15
25
  'div',
16
- { class: 'cg-story', 'data-block': 'prose' },
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 single centred line, set in the display serif — the "menu insert"
6
- * pull-quote, distinct from `testimonial`'s guestbook card.
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 hasAttribution =
10
- block.author !== undefined || block.role !== undefined || block.avatar !== undefined
11
- return h(
12
- 'figure',
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: 'cg-line__attribution' },
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: 'cg-line__who' },
25
+ { class: 'cr-quote__who' },
28
26
  block.author === undefined
29
27
  ? null
30
- : h('span', { class: 'cg-line__author', 'data-field': 'author' }, block.author),
28
+ : h('span', { class: 'cr-quote__author', 'data-field': 'author' }, block.author),
31
29
  block.role === undefined
32
30
  ? null
33
- : h('span', { class: 'cg-line__role', 'data-field': 'role' }, block.role),
31
+ : h('span', { class: 'cr-quote__role', 'data-field': 'role' }, block.role),
34
32
  ),
35
33
  )
36
- : null,
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, StatCounterItem } from '@cogenta/blocks'
2
- import {
3
- blockHeadingTag,
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
- * `blocks@2.0` (RFC 0001). Narrower than `stats` (no `unit`) — rendered the
12
- * same restrained "figures row" way as `stats`, one accent hairline apart:
13
- * this theme has no boastful, boxed "impact numbers" register to reach for.
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 h(
12
+ return section(
26
13
  'section',
27
- { class: 'cg-tallies', 'data-block': 'statCounter' },
28
- block.title === undefined
29
- ? null
30
- : heading(
31
- blockHeadingTag('statCounter') ?? 'h2',
32
- { class: 'cg-tallies__title', 'data-field': 'title' },
33
- block.title,
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
- h('dl', { class: 'cg-tallies__items' }, block.stats.map(renderItem)),
29
+ ),
30
+ ),
36
31
  )
37
32
  }
@@ -1,48 +1,38 @@
1
- import type { StatItem, StatsBlock } from '@cogenta/blocks'
2
- import {
3
- blockHeadingTag,
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
- * "Since 1994 · 3 chefs · 120 seats" — a quiet row of figures set in the
12
- * display serif, separated by hairline rules rather than boxed into cards:
13
- * the restrained, editorial register this theme uses everywhere a fact is
14
- * stated rather than sold.
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 h(
13
+ return section(
37
14
  'section',
38
- { class: 'cg-figures', 'data-block': 'stats' },
39
- block.title === undefined
40
- ? null
41
- : heading(
42
- blockHeadingTag('stats') ?? 'h2',
43
- { class: 'cg-figures__title', 'data-field': 'title' },
44
- block.title,
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
- h('dl', { class: 'cg-figures__items' }, block.items.map(renderItem)),
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 centred, oversized quotation mark stands above the quote (a CSS
6
- * pseudo-glyph, not markup) — the guestbook-page treatment this theme's
7
- * elegance calls for, rather than a bordered "client success" card.
8
- *
9
- * `<figure><blockquote>…</blockquote><figcaption>` is the attribution
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 h(
14
+ return section(
15
+ 'div',
16
+ 'testimonial',
17
+ 'cr-note',
18
+ {},
20
19
  'figure',
21
- { class: 'cg-testimonial', 'data-block': 'testimonial' },
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: 'cg-testimonial__attribution' },
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: 'cg-testimonial__who' },
35
- h('span', { class: 'cg-testimonial__name' }, attribution.name),
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: 'cg-testimonial__role' }, attribution.role),
33
+ : h('span', { class: 'cr-note__role' }, attribution.role),
39
34
  ),
40
35
  ),
41
36
  )