@cogenta/theme-docs 0.3.3 → 0.5.4
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 +2 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +2 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/render/blocks/accordion.d.ts +8 -0
- package/dist/src/render/blocks/accordion.d.ts.map +1 -1
- package/dist/src/render/blocks/accordion.js +10 -10
- package/dist/src/render/blocks/accordion.js.map +1 -1
- package/dist/src/render/blocks/collection-list.d.ts +3 -11
- package/dist/src/render/blocks/collection-list.d.ts.map +1 -1
- package/dist/src/render/blocks/collection-list.js +69 -68
- package/dist/src/render/blocks/collection-list.js.map +1 -1
- package/dist/src/render/blocks/cta.d.ts +6 -0
- package/dist/src/render/blocks/cta.d.ts.map +1 -1
- package/dist/src/render/blocks/cta.js +9 -4
- 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 +14 -13
- package/dist/src/render/blocks/embed.js.map +1 -1
- package/dist/src/render/blocks/faq.d.ts +7 -0
- package/dist/src/render/blocks/faq.d.ts.map +1 -1
- package/dist/src/render/blocks/faq.js +10 -10
- 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 +19 -19
- package/dist/src/render/blocks/feature-grid.js.map +1 -1
- package/dist/src/render/blocks/gallery.d.ts +8 -4
- package/dist/src/render/blocks/gallery.d.ts.map +1 -1
- package/dist/src/render/blocks/gallery.js +19 -13
- package/dist/src/render/blocks/gallery.js.map +1 -1
- package/dist/src/render/blocks/hero.d.ts +12 -9
- package/dist/src/render/blocks/hero.d.ts.map +1 -1
- package/dist/src/render/blocks/hero.js +22 -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 +6 -10
- package/dist/src/render/blocks/logo-strip.js.map +1 -1
- package/dist/src/render/blocks/logos.d.ts +10 -0
- package/dist/src/render/blocks/logos.d.ts.map +1 -1
- package/dist/src/render/blocks/logos.js +20 -17
- package/dist/src/render/blocks/logos.js.map +1 -1
- package/dist/src/render/blocks/media-figure.d.ts +0 -6
- package/dist/src/render/blocks/media-figure.d.ts.map +1 -1
- package/dist/src/render/blocks/media-figure.js +28 -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 +16 -20
- package/dist/src/render/blocks/pricing-table.js.map +1 -1
- package/dist/src/render/blocks/prose.d.ts +13 -1
- package/dist/src/render/blocks/prose.d.ts.map +1 -1
- package/dist/src/render/blocks/prose.js +12 -31
- package/dist/src/render/blocks/prose.js.map +1 -1
- package/dist/src/render/blocks/quote.d.ts +5 -3
- package/dist/src/render/blocks/quote.d.ts.map +1 -1
- package/dist/src/render/blocks/quote.js +10 -14
- package/dist/src/render/blocks/quote.js.map +1 -1
- package/dist/src/render/blocks/stat-counter.d.ts +5 -0
- package/dist/src/render/blocks/stat-counter.d.ts.map +1 -1
- package/dist/src/render/blocks/stat-counter.js +6 -10
- package/dist/src/render/blocks/stat-counter.js.map +1 -1
- package/dist/src/render/blocks/stats.d.ts +10 -0
- package/dist/src/render/blocks/stats.d.ts.map +1 -1
- package/dist/src/render/blocks/stats.js +13 -8
- package/dist/src/render/blocks/stats.js.map +1 -1
- package/dist/src/render/blocks/testimonial.d.ts +4 -5
- package/dist/src/render/blocks/testimonial.d.ts.map +1 -1
- package/dist/src/render/blocks/testimonial.js +9 -13
- package/dist/src/render/blocks/testimonial.js.map +1 -1
- package/dist/src/render/chrome.d.ts +36 -1
- package/dist/src/render/chrome.d.ts.map +1 -1
- package/dist/src/render/chrome.js +122 -80
- package/dist/src/render/chrome.js.map +1 -1
- package/dist/src/render/doc-index.d.ts +25 -0
- package/dist/src/render/doc-index.d.ts.map +1 -0
- package/dist/src/render/doc-index.js +49 -0
- package/dist/src/render/doc-index.js.map +1 -0
- package/dist/src/render/doc-page.d.ts +6 -0
- package/dist/src/render/doc-page.d.ts.map +1 -0
- package/dist/src/render/doc-page.js +127 -0
- package/dist/src/render/doc-page.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 +40 -0
- package/dist/src/render/layout.js.map +1 -0
- package/dist/src/render/render-block.d.ts +9 -6
- package/dist/src/render/render-block.d.ts.map +1 -1
- package/dist/src/render/render-block.js +47 -100
- package/dist/src/render/render-block.js.map +1 -1
- package/dist/src/render/rich-text.d.ts +26 -0
- package/dist/src/render/rich-text.d.ts.map +1 -0
- package/dist/src/render/rich-text.js +325 -0
- package/dist/src/render/rich-text.js.map +1 -0
- package/dist/src/render/search.d.ts +15 -0
- package/dist/src/render/search.d.ts.map +1 -0
- package/dist/src/render/search.js +31 -0
- package/dist/src/render/search.js.map +1 -0
- package/dist/src/render/strings.d.ts +51 -0
- package/dist/src/render/strings.d.ts.map +1 -0
- package/dist/src/render/strings.js +60 -0
- package/dist/src/render/strings.js.map +1 -0
- package/dist/src/render/term-archive.d.ts +5 -5
- package/dist/src/render/term-archive.d.ts.map +1 -1
- package/dist/src/render/term-archive.js +27 -16
- package/dist/src/render/term-archive.js.map +1 -1
- package/dist/src/render/widget-areas.d.ts +22 -0
- package/dist/src/render/widget-areas.d.ts.map +1 -0
- package/dist/src/render/widget-areas.js +29 -0
- package/dist/src/render/widget-areas.js.map +1 -0
- package/package.json +4 -4
- package/src/index.ts +2 -0
- package/src/render/blocks/accordion.ts +31 -42
- package/src/render/blocks/collection-list.ts +132 -123
- package/src/render/blocks/cta.ts +23 -18
- package/src/render/blocks/embed.ts +37 -28
- package/src/render/blocks/faq.ts +26 -37
- package/src/render/blocks/feature-grid.ts +34 -42
- package/src/render/blocks/gallery.ts +33 -29
- package/src/render/blocks/hero.ts +41 -45
- package/src/render/blocks/logo-strip.ts +21 -21
- package/src/render/blocks/logos.ts +32 -42
- package/src/render/blocks/media-figure.ts +47 -25
- package/src/render/blocks/pricing-table.ts +34 -41
- package/src/render/blocks/prose.ts +25 -40
- package/src/render/blocks/quote.ts +25 -19
- package/src/render/blocks/stat-counter.ts +27 -29
- package/src/render/blocks/stats.ts +35 -32
- package/src/render/blocks/testimonial.ts +18 -19
- package/src/render/chrome.ts +170 -83
- package/src/render/doc-index.ts +65 -0
- package/src/render/doc-page.ts +303 -0
- package/src/render/layout.ts +73 -0
- package/src/render/render-block.ts +67 -191
- package/src/render/rich-text.ts +446 -0
- package/src/render/search.ts +41 -0
- package/src/render/strings.ts +67 -0
- package/src/render/term-archive.ts +62 -38
- package/src/render/widget-areas.ts +33 -0
- package/src/styles/archive.css +21 -27
- package/src/styles/base.css +438 -838
- package/src/styles/blocks.css +658 -916
- package/src/styles/chrome.css +439 -0
- package/src/styles/docs.css +404 -0
- package/src/styles/rich.css +337 -0
- package/src/styles/theme.css +28 -23
- package/src/styles/tokens.css +209 -215
- package/src/styles/widgets.css +890 -0
- package/tokens.json +15 -15
package/src/render/blocks/faq.ts
CHANGED
|
@@ -1,46 +1,35 @@
|
|
|
1
|
-
import type { FaqBlock
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
h,
|
|
6
|
-
heading,
|
|
7
|
-
type RenderContext,
|
|
8
|
-
renderRichText,
|
|
9
|
-
} from '@cogenta/theme-kit'
|
|
1
|
+
import type { FaqBlock } from '@cogenta/blocks'
|
|
2
|
+
import { type HtmlElement, h, nestedHeadingTag, type RenderContext } from '@cogenta/theme-kit'
|
|
3
|
+
import { section, sectionHead } from '../layout.js'
|
|
4
|
+
import { renderDocsRichText } from '../rich-text.js'
|
|
10
5
|
|
|
11
6
|
/**
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
7
|
+
* Questions a reader asks before reading further ("Which databases are
|
|
8
|
+
* supported"), answered in the open: no disclosure to click. The title on
|
|
9
|
+
* the first four columns, the questions and answers on the last eight in two
|
|
10
|
+
* columns of ruled items on a wide screen, each question a real heading so a
|
|
11
|
+
* screen reader's heading list reaches it.
|
|
15
12
|
*/
|
|
16
|
-
function renderItem(item: FaqItem, ctx: RenderContext): HtmlElement {
|
|
17
|
-
return h(
|
|
18
|
-
'li',
|
|
19
|
-
{ class: 'cg-faq__item' },
|
|
20
|
-
h(
|
|
21
|
-
'details',
|
|
22
|
-
{ class: 'cg-faq__details' },
|
|
23
|
-
h('summary', { class: 'cg-faq__question' }, item.question),
|
|
24
|
-
h('div', { class: 'cg-faq__answer' }, renderRichText(ctx, item.answer)),
|
|
25
|
-
),
|
|
26
|
-
)
|
|
27
|
-
}
|
|
28
|
-
|
|
29
13
|
export function renderFaq(block: FaqBlock, ctx: RenderContext): HtmlElement {
|
|
30
|
-
|
|
14
|
+
const tag = nestedHeadingTag('faq', block.title !== undefined)
|
|
15
|
+
return section(
|
|
31
16
|
'section',
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
{ class: 'cg-faq__title', 'data-field': 'title' },
|
|
38
|
-
block.title,
|
|
39
|
-
),
|
|
17
|
+
'faq',
|
|
18
|
+
'cd-faq',
|
|
19
|
+
{ 'data-titled': block.title === undefined ? 'false' : 'true' },
|
|
20
|
+
'div',
|
|
21
|
+
sectionHead('faq', block.title),
|
|
40
22
|
h(
|
|
41
|
-
'
|
|
42
|
-
{ class: '
|
|
43
|
-
block.items.map((item) =>
|
|
23
|
+
'div',
|
|
24
|
+
{ class: 'cd-faq__items' },
|
|
25
|
+
block.items.map((item) =>
|
|
26
|
+
h(
|
|
27
|
+
'div',
|
|
28
|
+
{ class: 'cd-faq__item' },
|
|
29
|
+
h(tag, { class: 'cd-faq__question' }, item.question),
|
|
30
|
+
h('div', { class: 'cd-faq__answer cd-rich' }, renderDocsRichText(ctx, item.answer)),
|
|
31
|
+
),
|
|
32
|
+
),
|
|
44
33
|
),
|
|
45
34
|
)
|
|
46
35
|
}
|
|
@@ -1,67 +1,59 @@
|
|
|
1
1
|
import type { FeatureGridBlock, FeatureItem } from '@cogenta/blocks'
|
|
2
2
|
import {
|
|
3
|
-
blockHeadingTag,
|
|
4
|
-
type HeadingTag,
|
|
5
3
|
type HtmlElement,
|
|
6
4
|
h,
|
|
7
|
-
heading,
|
|
8
5
|
href,
|
|
9
6
|
nestedHeadingTag,
|
|
10
7
|
type RenderContext,
|
|
11
8
|
renderIcon,
|
|
12
9
|
} from '@cogenta/theme-kit'
|
|
10
|
+
import { optionalText, section, sectionHead } from '../layout.js'
|
|
13
11
|
|
|
14
12
|
/**
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
13
|
+
* Short entries in three columns: "Start here", "Get help". No card, no tile,
|
|
14
|
+
* no background: each entry hangs from a hairline, its title is the link (an
|
|
15
|
+
* underlined arrow link when there is one), and one or two lines under it say
|
|
16
|
+
* what the reader will find. An icon, when the item names one this theme
|
|
17
|
+
* knows, is a small stroke drawing inline before the title in the secondary
|
|
18
|
+
* ink, the size of the text it sits beside.
|
|
18
19
|
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* already names the card. An unrecognised name keeps the bare, empty
|
|
22
|
-
* `data-icon` span for a skin/plugin to key off.
|
|
20
|
+
* Three columns on a desk, two on a tablet, one on a phone; four items make
|
|
21
|
+
* a row of four on a wide screen, so no row is left with an empty cell.
|
|
23
22
|
*/
|
|
24
|
-
function
|
|
25
|
-
const
|
|
26
|
-
item.link === undefined
|
|
27
|
-
? heading(tag, { class: 'cg-feature__title' }, item.title)
|
|
28
|
-
: heading(
|
|
29
|
-
tag,
|
|
30
|
-
{ class: 'cg-feature__title' },
|
|
31
|
-
h('a', { class: 'cg-feature__link', href: href(ctx, item.link) }, item.title),
|
|
32
|
-
)
|
|
33
|
-
return h(
|
|
34
|
-
'li',
|
|
35
|
-
{ class: 'cg-feature' },
|
|
23
|
+
function entry(item: FeatureItem, ctx: RenderContext, tag: string): HtmlElement {
|
|
24
|
+
const icon =
|
|
36
25
|
item.icon === undefined
|
|
37
26
|
? null
|
|
38
|
-
:
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
27
|
+
: renderIcon(item.icon, { className: 'cd-features__icon', size: 18 })
|
|
28
|
+
return h(
|
|
29
|
+
'li',
|
|
30
|
+
{ class: 'cd-features__item' },
|
|
31
|
+
h(
|
|
32
|
+
tag,
|
|
33
|
+
{ class: 'cd-features__title' },
|
|
34
|
+
icon,
|
|
35
|
+
item.link === undefined
|
|
36
|
+
? h('span', {}, item.title)
|
|
37
|
+
: h('a', { class: 'cd-arrow-link', href: href(ctx, item.link) }, item.title),
|
|
38
|
+
),
|
|
39
|
+
optionalText('p', 'cd-features__text', item.text),
|
|
45
40
|
)
|
|
46
41
|
}
|
|
47
42
|
|
|
48
43
|
export function renderFeatureGrid(block: FeatureGridBlock, ctx: RenderContext): HtmlElement {
|
|
49
|
-
const
|
|
50
|
-
const
|
|
51
|
-
return
|
|
44
|
+
const tag = nestedHeadingTag('featureGrid', block.title !== undefined)
|
|
45
|
+
const count = block.items.length
|
|
46
|
+
return section(
|
|
52
47
|
'section',
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
block.title ?? '',
|
|
59
|
-
)
|
|
60
|
-
: null,
|
|
48
|
+
'featureGrid',
|
|
49
|
+
'cd-features',
|
|
50
|
+
{ 'data-count': String(count % 4 === 0 ? 4 : Math.min(count, 3)) },
|
|
51
|
+
'div',
|
|
52
|
+
sectionHead('featureGrid', block.title),
|
|
61
53
|
h(
|
|
62
54
|
'ul',
|
|
63
|
-
{ class: '
|
|
64
|
-
block.items.map((item) =>
|
|
55
|
+
{ class: 'cd-features__items' },
|
|
56
|
+
block.items.map((item) => entry(item, ctx, tag)),
|
|
65
57
|
),
|
|
66
58
|
)
|
|
67
59
|
}
|
|
@@ -1,39 +1,43 @@
|
|
|
1
1
|
import type { GalleryBlock } 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
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
6
|
+
* A set of screenshots or diagrams, each in the hairline frame.
|
|
7
|
+
*
|
|
8
|
+
* - `grid`: two or three columns, every frame cropped to the same 16:10 so
|
|
9
|
+
* the rows stay level.
|
|
10
|
+
* - `masonry`: three columns that keep each picture's own proportions.
|
|
11
|
+
* - `carousel`: one row that scrolls sideways inside the container, with
|
|
12
|
+
* scroll snapping and no script, named so a screen reader announces it as
|
|
13
|
+
* a scrollable group.
|
|
9
14
|
*/
|
|
10
15
|
export function renderGallery(block: GalleryBlock, ctx: RenderContext): HtmlElement {
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
const carousel = block.layout === 'carousel'
|
|
17
|
+
return section(
|
|
18
|
+
'div',
|
|
19
|
+
'gallery',
|
|
20
|
+
'cd-gallery',
|
|
21
|
+
{ 'data-layout': block.layout, 'data-count': String(Math.min(block.items.length, 6)) },
|
|
22
|
+
'div',
|
|
23
|
+
h(
|
|
24
|
+
'ul',
|
|
25
|
+
{
|
|
26
|
+
class: 'cd-gallery__items',
|
|
27
|
+
...(carousel
|
|
28
|
+
? { role: 'region', 'aria-label': ctx.t('gallery.carousel'), tabindex: 0 }
|
|
29
|
+
: {}),
|
|
30
|
+
},
|
|
31
|
+
block.items.map((item) =>
|
|
32
|
+
h(
|
|
33
|
+
'li',
|
|
34
|
+
{ class: 'cd-gallery__item cd-frame' },
|
|
35
|
+
image(ctx, item.media, {
|
|
36
|
+
className: 'cd-gallery__image cd-frame__image',
|
|
37
|
+
sizes: '(min-width: 64rem) 25rem, (min-width: 40rem) 50vw, 100vw',
|
|
38
|
+
}),
|
|
39
|
+
),
|
|
19
40
|
),
|
|
20
41
|
),
|
|
21
42
|
)
|
|
22
|
-
|
|
23
|
-
return h(
|
|
24
|
-
'section',
|
|
25
|
-
{ class: 'cg-block cg-gallery', 'data-block': 'gallery', 'data-layout': block.layout },
|
|
26
|
-
block.layout === 'carousel'
|
|
27
|
-
? h(
|
|
28
|
-
'div',
|
|
29
|
-
{
|
|
30
|
-
class: 'cg-gallery__viewport',
|
|
31
|
-
role: 'region',
|
|
32
|
-
'aria-label': ctx.t('gallery.carousel'),
|
|
33
|
-
tabindex: '0',
|
|
34
|
-
},
|
|
35
|
-
items,
|
|
36
|
-
)
|
|
37
|
-
: items,
|
|
38
|
-
)
|
|
39
43
|
}
|
|
@@ -1,61 +1,57 @@
|
|
|
1
1
|
import type { HeroBlock } from '@cogenta/blocks'
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
type HtmlElement,
|
|
6
|
-
h,
|
|
7
|
-
heading,
|
|
8
|
-
image,
|
|
9
|
-
type RenderContext,
|
|
10
|
-
renderIcon,
|
|
11
|
-
} from '@cogenta/theme-kit'
|
|
2
|
+
import { actionList, type HtmlElement, h, image, type RenderContext } from '@cogenta/theme-kit'
|
|
3
|
+
import { optionalText } from '../layout.js'
|
|
4
|
+
import { renderSearchForm } from '../search.js'
|
|
12
5
|
|
|
13
6
|
/**
|
|
14
|
-
* The
|
|
15
|
-
* `renderPage` relies on it to avoid emitting a second one.
|
|
7
|
+
* The opening of a documentation site: a clear statement and the search.
|
|
16
8
|
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
9
|
+
* Left-aligned on the grid, never centred. An eyebrow, when there is one, is
|
|
10
|
+
* a quiet line above the title (a product and its version), never a badge.
|
|
11
|
+
* The title is short and set large on the first eight columns, the subtitle
|
|
12
|
+
* says in two sentences what the documentation covers, and under it the
|
|
13
|
+
* search field at its large size: a real `GET /search` form, the first thing
|
|
14
|
+
* a reader of documentation reaches for. The actions follow, the primary one
|
|
15
|
+
* as the small teal control and the rest as underlined arrow links.
|
|
16
|
+
*
|
|
17
|
+
* Media, when an editor adds one, is a diagram or a screenshot on the last
|
|
18
|
+
* five columns in the hairline frame, loaded eagerly: it is above the fold by
|
|
19
|
+
* construction. Nothing decorative stands in for it when there is none.
|
|
24
20
|
*/
|
|
25
21
|
export function renderHero(block: HeroBlock, ctx: RenderContext): HtmlElement {
|
|
26
|
-
const
|
|
22
|
+
const actions = actionList(ctx, block.actions, ctx.t('hero.actions'))
|
|
23
|
+
const media = block.media !== undefined
|
|
24
|
+
|
|
27
25
|
return h(
|
|
28
26
|
'section',
|
|
29
|
-
{ class: '
|
|
27
|
+
{ class: 'cd-section cd-hero', 'data-block': 'hero', 'data-media': media ? 'true' : 'false' },
|
|
30
28
|
h(
|
|
31
29
|
'div',
|
|
32
|
-
{ class: '
|
|
33
|
-
block.eyebrow === undefined
|
|
34
|
-
? null
|
|
35
|
-
: h('p', { class: 'cg-hero__eyebrow', 'data-field': 'eyebrow' }, block.eyebrow),
|
|
36
|
-
heading(tag, { class: 'cg-hero__title', 'data-field': 'title' }, block.title),
|
|
37
|
-
block.subtitle === undefined
|
|
38
|
-
? null
|
|
39
|
-
: h('p', { class: 'cg-hero__subtitle', 'data-field': 'subtitle' }, block.subtitle),
|
|
40
|
-
actionList(ctx, block.actions, ctx.t('hero.actions')),
|
|
30
|
+
{ class: 'cd-container cd-hero__inner' },
|
|
41
31
|
h(
|
|
42
32
|
'div',
|
|
43
|
-
{ class: '
|
|
44
|
-
|
|
45
|
-
h('
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
),
|
|
49
|
-
block.media === undefined
|
|
50
|
-
? null
|
|
51
|
-
: h(
|
|
33
|
+
{ class: 'cd-hero__copy' },
|
|
34
|
+
optionalText('p', 'cd-hero__eyebrow', block.eyebrow, { 'data-field': 'eyebrow' }),
|
|
35
|
+
h('h1', { class: 'cd-hero__title', 'data-field': 'title' }, block.title),
|
|
36
|
+
optionalText('p', 'cd-hero__subtitle', block.subtitle, { 'data-field': 'subtitle' }),
|
|
37
|
+
h(
|
|
52
38
|
'div',
|
|
53
|
-
{ class: '
|
|
54
|
-
|
|
55
|
-
className: 'cg-hero__media',
|
|
56
|
-
loading: 'eager',
|
|
57
|
-
sizes: '(min-width: 64rem) 32vw, 100vw',
|
|
58
|
-
}),
|
|
39
|
+
{ class: 'cd-hero__search' },
|
|
40
|
+
renderSearchForm(ctx.locale, 'cd-search-hero', 'large'),
|
|
59
41
|
),
|
|
42
|
+
actions === null ? null : h('div', { class: 'cd-hero__actions' }, actions),
|
|
43
|
+
),
|
|
44
|
+
block.media === undefined
|
|
45
|
+
? null
|
|
46
|
+
: h(
|
|
47
|
+
'figure',
|
|
48
|
+
{ class: 'cd-hero__media cd-frame' },
|
|
49
|
+
image(ctx, block.media, {
|
|
50
|
+
className: 'cd-hero__image cd-frame__image',
|
|
51
|
+
loading: 'eager',
|
|
52
|
+
sizes: '(min-width: 64rem) 30rem, 100vw',
|
|
53
|
+
}),
|
|
54
|
+
),
|
|
55
|
+
),
|
|
60
56
|
)
|
|
61
57
|
}
|
|
@@ -1,31 +1,31 @@
|
|
|
1
|
-
import type { LogoStripBlock
|
|
1
|
+
import type { LogoStripBlock } from '@cogenta/blocks'
|
|
2
2
|
import { type HtmlElement, h, image, type RenderContext } from '@cogenta/theme-kit'
|
|
3
|
+
import { optionalText, section } from '../layout.js'
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
6
|
+
* A strip of wordmarks ("Runs in production at"): the caption on its own
|
|
7
|
+
* line above, then one row of marks at one height in grey, wrapping to three
|
|
8
|
+
* and then two to a row on smaller screens. A hairline above separates the
|
|
9
|
+
* strip from what precedes it.
|
|
9
10
|
*/
|
|
10
|
-
function renderItem(item: LogoStripItem, _ctx: RenderContext): HtmlElement {
|
|
11
|
-
return h(
|
|
12
|
-
'li',
|
|
13
|
-
{ class: 'cg-logo-band__item' },
|
|
14
|
-
image(_ctx, item.media, { className: 'cg-logo-band__image', variant: { fit: 'contain' } }),
|
|
15
|
-
)
|
|
16
|
-
}
|
|
17
|
-
|
|
18
11
|
export function renderLogoStrip(block: LogoStripBlock, ctx: RenderContext): HtmlElement {
|
|
19
|
-
return
|
|
20
|
-
'
|
|
21
|
-
|
|
12
|
+
return section(
|
|
13
|
+
'div',
|
|
14
|
+
'logoStrip',
|
|
15
|
+
'cd-strip',
|
|
16
|
+
{ 'data-count': String(Math.min(block.logos.length, 6)) },
|
|
17
|
+
'div',
|
|
18
|
+
optionalText('p', 'cd-strip__caption', block.caption, { 'data-field': 'caption' }),
|
|
22
19
|
h(
|
|
23
20
|
'ul',
|
|
24
|
-
{ class: '
|
|
25
|
-
block.logos.map((
|
|
21
|
+
{ class: 'cd-strip__items' },
|
|
22
|
+
block.logos.map((logo) =>
|
|
23
|
+
h(
|
|
24
|
+
'li',
|
|
25
|
+
{ class: 'cd-strip__item' },
|
|
26
|
+
image(ctx, logo.media, { className: 'cd-strip__image cd-mark', sizes: '9rem' }),
|
|
27
|
+
),
|
|
28
|
+
),
|
|
26
29
|
),
|
|
27
|
-
block.caption === undefined
|
|
28
|
-
? null
|
|
29
|
-
: h('figcaption', { class: 'cg-logo-band__caption', 'data-field': 'caption' }, block.caption),
|
|
30
30
|
)
|
|
31
31
|
}
|
|
@@ -1,52 +1,42 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
type HtmlElement,
|
|
5
|
-
h,
|
|
6
|
-
heading,
|
|
7
|
-
image,
|
|
8
|
-
type RenderContext,
|
|
9
|
-
} from '@cogenta/theme-kit'
|
|
1
|
+
import type { LogosBlock } from '@cogenta/blocks'
|
|
2
|
+
import { type HtmlElement, h, image, type RenderContext } from '@cogenta/theme-kit'
|
|
3
|
+
import { section, sectionHead } from '../layout.js'
|
|
10
4
|
|
|
11
5
|
/**
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
6
|
+
* Named organisations (the companies running the product, the platforms it
|
|
7
|
+
* integrates with) as a ruled grid: hairlines between cells, each wordmark in
|
|
8
|
+
* grey at one height, linked when the block gives an address. The
|
|
9
|
+
* organisation's name is the image's accessible name when the media library
|
|
10
|
+
* has no alt text.
|
|
11
|
+
*
|
|
12
|
+
* Wordmarks are shown in grey in light and inverted in dark, so a logo drawn
|
|
13
|
+
* in dark ink stays legible on the dark ground.
|
|
15
14
|
*/
|
|
16
|
-
function renderItem(item: LogoItem, ctx: RenderContext): HtmlElement {
|
|
17
|
-
const logo = image(ctx, item.media, {
|
|
18
|
-
className: 'cg-logo__image',
|
|
19
|
-
altFrom: item.name,
|
|
20
|
-
variant: { fit: 'contain' },
|
|
21
|
-
})
|
|
22
|
-
return h(
|
|
23
|
-
'li',
|
|
24
|
-
{ class: 'cg-logo' },
|
|
25
|
-
item.url === undefined
|
|
26
|
-
? logo
|
|
27
|
-
: h(
|
|
28
|
-
'a',
|
|
29
|
-
{ class: 'cg-logo__link', href: ctx.link(item.url), rel: 'noopener noreferrer' },
|
|
30
|
-
logo,
|
|
31
|
-
),
|
|
32
|
-
)
|
|
33
|
-
}
|
|
34
|
-
|
|
35
15
|
export function renderLogos(block: LogosBlock, ctx: RenderContext): HtmlElement {
|
|
36
|
-
return
|
|
16
|
+
return section(
|
|
37
17
|
'section',
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
{ class: 'cg-logos__title', 'data-field': 'title' },
|
|
44
|
-
block.title,
|
|
45
|
-
),
|
|
18
|
+
'logos',
|
|
19
|
+
'cd-logos',
|
|
20
|
+
{ 'data-count': String(Math.min(block.items.length, 6)) },
|
|
21
|
+
'div',
|
|
22
|
+
sectionHead('logos', block.title),
|
|
46
23
|
h(
|
|
47
24
|
'ul',
|
|
48
|
-
{ class: '
|
|
49
|
-
block.items.map((item) =>
|
|
25
|
+
{ class: 'cd-logos__items' },
|
|
26
|
+
block.items.map((item) => {
|
|
27
|
+
const mark = image(ctx, item.media, {
|
|
28
|
+
className: 'cd-logos__image cd-mark',
|
|
29
|
+
altFrom: item.name,
|
|
30
|
+
sizes: '10rem',
|
|
31
|
+
})
|
|
32
|
+
return h(
|
|
33
|
+
'li',
|
|
34
|
+
{ class: 'cd-logos__item' },
|
|
35
|
+
item.url === undefined
|
|
36
|
+
? mark
|
|
37
|
+
: h('a', { class: 'cd-logos__link', href: ctx.link(item.url), rel: 'noopener' }, mark),
|
|
38
|
+
)
|
|
39
|
+
}),
|
|
50
40
|
),
|
|
51
41
|
)
|
|
52
42
|
}
|
|
@@ -1,36 +1,58 @@
|
|
|
1
1
|
import type { MediaFigureBlock } from '@cogenta/blocks'
|
|
2
2
|
import { aspectRatio, type HtmlElement, h, image, type RenderContext } from '@cogenta/theme-kit'
|
|
3
|
+
import { optionalText } from '../layout.js'
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
6
|
+
* A diagram, a screenshot or a photograph, in the hairline frame, with its
|
|
7
|
+
* caption and credit under it in the secondary ink.
|
|
8
|
+
*
|
|
9
|
+
* `align` (contract B) places the frame: `wide` takes the whole container
|
|
10
|
+
* (or the whole reading column on a documentation page), `center` the middle
|
|
11
|
+
* eight columns, `start` and `end` eight columns on either side, and `full`
|
|
12
|
+
* runs to the edges of the window, without a frame.
|
|
13
|
+
*
|
|
14
|
+
* `ratio` crops from the top edge, so an interface keeps its title bar; a
|
|
15
|
+
* focal point set in the media library still wins.
|
|
9
16
|
*/
|
|
17
|
+
const SIZES: Readonly<Record<string, string>> = {
|
|
18
|
+
full: '100vw',
|
|
19
|
+
wide: '(min-width: 80rem) 76rem, 100vw',
|
|
20
|
+
center: '(min-width: 64rem) 50rem, 100vw',
|
|
21
|
+
start: '(min-width: 64rem) 50rem, 100vw',
|
|
22
|
+
end: '(min-width: 64rem) 50rem, 100vw',
|
|
23
|
+
}
|
|
24
|
+
|
|
10
25
|
export function renderMediaFigure(block: MediaFigureBlock, ctx: RenderContext): HtmlElement {
|
|
26
|
+
const align = block.align ?? 'wide'
|
|
11
27
|
const ratio = aspectRatio(block.ratio)
|
|
12
28
|
const hasCaption = block.caption !== undefined || block.credit !== undefined
|
|
29
|
+
|
|
13
30
|
return h(
|
|
14
|
-
'
|
|
15
|
-
{
|
|
16
|
-
|
|
17
|
-
'
|
|
18
|
-
'
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
'
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
31
|
+
'div',
|
|
32
|
+
{ class: 'cd-section cd-figure', 'data-block': 'mediaFigure', 'data-align': align },
|
|
33
|
+
h(
|
|
34
|
+
'figure',
|
|
35
|
+
{ class: 'cd-container cd-figure__inner' },
|
|
36
|
+
h(
|
|
37
|
+
'div',
|
|
38
|
+
{
|
|
39
|
+
class: align === 'full' ? 'cd-figure__media' : 'cd-figure__media cd-frame',
|
|
40
|
+
style: ratio === undefined ? undefined : `aspect-ratio:${ratio}`,
|
|
41
|
+
'data-ratio': ratio === undefined ? 'original' : 'fixed',
|
|
42
|
+
},
|
|
43
|
+
image(ctx, block.media, {
|
|
44
|
+
className: 'cd-figure__image cd-frame__image',
|
|
45
|
+
sizes: SIZES[align] ?? '100vw',
|
|
46
|
+
}),
|
|
47
|
+
),
|
|
48
|
+
hasCaption
|
|
49
|
+
? h(
|
|
50
|
+
'figcaption',
|
|
51
|
+
{ class: 'cd-figure__caption' },
|
|
52
|
+
optionalText('span', 'cd-figure__text', block.caption, { 'data-field': 'caption' }),
|
|
53
|
+
optionalText('span', 'cd-figure__credit', block.credit, { 'data-field': 'credit' }),
|
|
54
|
+
)
|
|
55
|
+
: null,
|
|
56
|
+
),
|
|
35
57
|
)
|
|
36
58
|
}
|