@cogenta/theme-canonical 1.1.3 → 1.3.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 (71) hide show
  1. package/dist/src/index.d.ts +1 -0
  2. package/dist/src/index.d.ts.map +1 -1
  3. package/dist/src/index.js +1 -0
  4. package/dist/src/index.js.map +1 -1
  5. package/dist/src/render/arrow-link.d.ts +11 -0
  6. package/dist/src/render/arrow-link.d.ts.map +1 -0
  7. package/dist/src/render/arrow-link.js +29 -0
  8. package/dist/src/render/arrow-link.js.map +1 -0
  9. package/dist/src/render/blocks/collection-list.d.ts +15 -5
  10. package/dist/src/render/blocks/collection-list.d.ts.map +1 -1
  11. package/dist/src/render/blocks/collection-list.js +36 -13
  12. package/dist/src/render/blocks/collection-list.js.map +1 -1
  13. package/dist/src/render/blocks/embed.d.ts.map +1 -1
  14. package/dist/src/render/blocks/embed.js +3 -2
  15. package/dist/src/render/blocks/embed.js.map +1 -1
  16. package/dist/src/render/blocks/gallery.d.ts.map +1 -1
  17. package/dist/src/render/blocks/gallery.js +4 -1
  18. package/dist/src/render/blocks/gallery.js.map +1 -1
  19. package/dist/src/render/blocks/hero.d.ts.map +1 -1
  20. package/dist/src/render/blocks/hero.js +9 -2
  21. package/dist/src/render/blocks/hero.js.map +1 -1
  22. package/dist/src/render/blocks/pricing-table.d.ts.map +1 -1
  23. package/dist/src/render/blocks/pricing-table.js +17 -4
  24. package/dist/src/render/blocks/pricing-table.js.map +1 -1
  25. package/dist/src/render/chrome.d.ts +40 -1
  26. package/dist/src/render/chrome.d.ts.map +1 -1
  27. package/dist/src/render/chrome.js +103 -71
  28. package/dist/src/render/chrome.js.map +1 -1
  29. package/dist/src/render/dates.d.ts +9 -0
  30. package/dist/src/render/dates.d.ts.map +1 -0
  31. package/dist/src/render/dates.js +16 -0
  32. package/dist/src/render/dates.js.map +1 -0
  33. package/dist/src/render/render-block.d.ts.map +1 -1
  34. package/dist/src/render/render-block.js +7 -1
  35. package/dist/src/render/render-block.js.map +1 -1
  36. package/dist/src/render/strings.d.ts +25 -0
  37. package/dist/src/render/strings.d.ts.map +1 -0
  38. package/dist/src/render/strings.js +26 -0
  39. package/dist/src/render/strings.js.map +1 -0
  40. package/dist/src/render/term-archive.d.ts +5 -5
  41. package/dist/src/render/term-archive.d.ts.map +1 -1
  42. package/dist/src/render/term-archive.js +14 -12
  43. package/dist/src/render/term-archive.js.map +1 -1
  44. package/dist/src/render/widget-areas.d.ts +20 -0
  45. package/dist/src/render/widget-areas.d.ts.map +1 -0
  46. package/dist/src/render/widget-areas.js +40 -0
  47. package/dist/src/render/widget-areas.js.map +1 -0
  48. package/package.json +5 -5
  49. package/src/index.ts +1 -0
  50. package/src/render/arrow-link.ts +27 -0
  51. package/src/render/blocks/collection-list.ts +53 -15
  52. package/src/render/blocks/embed.ts +3 -2
  53. package/src/render/blocks/gallery.ts +4 -1
  54. package/src/render/blocks/hero.ts +9 -2
  55. package/src/render/blocks/pricing-table.ts +22 -4
  56. package/src/render/chrome.ts +156 -70
  57. package/src/render/dates.ts +14 -0
  58. package/src/render/render-block.ts +6 -0
  59. package/src/render/strings.ts +30 -0
  60. package/src/render/term-archive.ts +54 -32
  61. package/src/render/widget-areas.ts +44 -0
  62. package/src/styles/archive.css +66 -20
  63. package/src/styles/base.css +266 -680
  64. package/src/styles/blocks.css +678 -811
  65. package/src/styles/chrome.css +469 -0
  66. package/src/styles/listings.css +183 -0
  67. package/src/styles/theme.css +28 -14
  68. package/src/styles/tokens.css +192 -205
  69. package/src/styles/utility.css +295 -0
  70. package/src/styles/widgets.css +1064 -0
  71. package/tokens.json +15 -15
@@ -1,21 +1,23 @@
1
1
  import { type HtmlElement, h, type TermArchiveInput } from '@cogenta/theme-kit'
2
+ import { arrowWords } from './arrow-link.js'
3
+ import { formatEntryDate } from './dates.js'
2
4
 
3
5
  /**
4
6
  * The taxonomy-term archive (contract D `theme@1.3`).
5
7
  *
6
- * Built from this theme's *own* entry-card classes — the same `cg-entry`
7
- * markup `collectionList` already renders — rather than a new set of
8
- * archive-only classes: an archive of articles should look like a list of
9
- * articles on this theme, and reusing the classes is what guarantees that
10
- * without a second stylesheet to keep in step.
8
+ * A header in the page frame (the breadcrumb, the term as the page's title,
9
+ * the sub-terms), then the classified entries as this theme's index: the
10
+ * same `cg-collection`/`cg-entry` markup a `collectionList` block renders in
11
+ * its `list` layout, so an archive of articles reads exactly like a list of
12
+ * articles anywhere else on the site, from one set of rules.
11
13
  */
12
14
  export function renderTermArchive(input: TermArchiveInput): HtmlElement {
13
15
  const items = input.entries.map((entry) =>
14
16
  h(
15
17
  'li',
16
- { class: 'cg-entry' },
18
+ { class: 'cg-entry', 'data-picture': 'false' },
17
19
  h(
18
- 'div',
20
+ 'article',
19
21
  { class: 'cg-entry__body' },
20
22
  h(
21
23
  'h2',
@@ -29,7 +31,7 @@ export function renderTermArchive(input: TermArchiveInput): HtmlElement {
29
31
  : h(
30
32
  'time',
31
33
  { class: 'cg-entry__date', datetime: entry.publishedAt },
32
- entry.publishedAt.slice(0, 10),
34
+ formatEntryDate(entry.publishedAt, input.locale),
33
35
  ),
34
36
  entry.summary === null ? null : h('p', { class: 'cg-entry__excerpt' }, entry.summary),
35
37
  ),
@@ -39,29 +41,41 @@ export function renderTermArchive(input: TermArchiveInput): HtmlElement {
39
41
  return h(
40
42
  'main',
41
43
  { class: 'cg-main cg-archive', id: 'cg-main' },
42
- input.ancestors.length === 0
43
- ? null
44
- : h(
45
- 'nav',
46
- { class: 'cg-archive__breadcrumb', 'aria-label': input.labels.breadcrumb },
47
- h(
48
- 'ol',
49
- {},
50
- ...input.ancestors.map((link) => h('li', {}, h('a', { href: link.href }, link.label))),
44
+ h(
45
+ 'div',
46
+ { class: 'cg-archive__head' },
47
+ input.ancestors.length === 0
48
+ ? null
49
+ : h(
50
+ 'nav',
51
+ { class: 'cg-archive__breadcrumb', 'aria-label': input.labels.breadcrumb },
52
+ h(
53
+ 'ol',
54
+ {},
55
+ ...input.ancestors.map((link) =>
56
+ h('li', {}, h('a', { href: link.href }, link.label)),
57
+ ),
58
+ ),
51
59
  ),
52
- ),
53
- h('h1', { class: 'cg-page__title' }, input.term.label),
54
- input.children.length === 0
55
- ? null
56
- : h(
57
- 'ul',
58
- { class: 'cg-archive__children', 'aria-label': input.labels.subterms },
59
- ...input.children.map((child) => h('li', {}, h('a', { href: child.href }, child.label))),
60
- ),
61
- items.length === 0
62
- ? h('p', { class: 'cg-collection__empty' }, input.labels.empty)
63
- : h('ul', { class: 'cg-collection__items' }, ...items),
64
- renderPager(input),
60
+ h('h1', { class: 'cg-page__title' }, input.term.label),
61
+ input.children.length === 0
62
+ ? null
63
+ : h(
64
+ 'ul',
65
+ { class: 'cg-archive__children', 'aria-label': input.labels.subterms },
66
+ ...input.children.map((child) =>
67
+ h('li', {}, h('a', { href: child.href }, child.label)),
68
+ ),
69
+ ),
70
+ ),
71
+ h(
72
+ 'section',
73
+ { class: 'cg-collection cg-archive__list', 'data-layout': 'list' },
74
+ items.length === 0
75
+ ? h('p', { class: 'cg-collection__empty' }, input.labels.empty)
76
+ : h('ul', { class: 'cg-collection__items' }, ...items),
77
+ renderPager(input),
78
+ ),
65
79
  )
66
80
  }
67
81
 
@@ -77,9 +91,17 @@ function renderPager(input: TermArchiveInput): HtmlElement | null {
77
91
  { class: 'cg-archive__pager', 'aria-label': input.labels.pagination },
78
92
  input.page.previousHref === null
79
93
  ? null
80
- : h('a', { rel: 'prev', href: input.page.previousHref }, input.labels.previous),
94
+ : h(
95
+ 'a',
96
+ { class: 'cg-arrow-link', rel: 'prev', href: input.page.previousHref },
97
+ arrowWords(input.labels.previous, 'back'),
98
+ ),
81
99
  input.page.nextHref === null
82
100
  ? null
83
- : h('a', { rel: 'next', href: input.page.nextHref }, input.labels.next),
101
+ : h(
102
+ 'a',
103
+ { class: 'cg-arrow-link', rel: 'next', href: input.page.nextHref },
104
+ arrowWords(input.labels.next),
105
+ ),
84
106
  )
85
107
  }
@@ -0,0 +1,44 @@
1
+ /**
2
+ * The widget areas this theme names (contract D `theme@1.6`).
3
+ *
4
+ * Exporting `widgetAreas` is what tells the host that this theme draws the
5
+ * footer columns (`footer-1`..`footer-4`) inside its own footer, where
6
+ * `renderChrome` places them between the footer menu and the legal line. The
7
+ * page areas (`content-before`, `content-after`, `sidebar`) are placed by the
8
+ * host in the one `cg-sidebar-layout` markup every theme styles; this theme
9
+ * sets it on its twelve-column grid in `styles/widgets.css`.
10
+ *
11
+ * A third-party theme can copy this file as it is: a theme that adds an area
12
+ * of its own lists it here too, and renders it itself with
13
+ * `renderWidgetArea` from `@cogenta/theme-kit`.
14
+ */
15
+ export const widgetAreas: readonly {
16
+ readonly id: string
17
+ readonly label: string
18
+ readonly description?: string
19
+ }[] = [
20
+ {
21
+ id: 'sidebar',
22
+ label: 'Sidebar',
23
+ description:
24
+ 'Beside an entry, an archive or search results on a wide screen; under the content on a phone and on the home page.',
25
+ },
26
+ {
27
+ id: 'content-before',
28
+ label: 'Before the content',
29
+ description: 'At the top of the page, under the header.',
30
+ },
31
+ {
32
+ id: 'content-after',
33
+ label: 'After the content',
34
+ description: 'Under the page’s own content, before the comments.',
35
+ },
36
+ {
37
+ id: 'footer-1',
38
+ label: 'Footer, column 1',
39
+ description: 'In the footer, between the footer menu and the legal line.',
40
+ },
41
+ { id: 'footer-2', label: 'Footer, column 2' },
42
+ { id: 'footer-3', label: 'Footer, column 3' },
43
+ { id: 'footer-4', label: 'Footer, column 4' },
44
+ ]
@@ -1,40 +1,86 @@
1
1
  /*
2
- * The taxonomy-term archive (contract D `theme@1.3`).
3
- *
4
- * Only the three things an archive adds beyond what `collectionList` already
5
- * styles — a breadcrumb, a sub-term row, a prev/next pager. The entry list
6
- * itself reuses the `cg-entry`/`cg-collection__items` rules, on purpose: an
7
- * archive of articles must look like this theme's list of articles, and a
8
- * second set of card rules is exactly how those two drift apart.
2
+ * The taxonomy-term archive (contract D `theme@1.3`): a breadcrumb, the term
3
+ * as the page title, its sub-terms, then the entries as the index of
4
+ * `listings.css`, and a previous/next pager.
9
5
  */
10
6
 
11
- .cg-archive {
12
- max-inline-size: var(--cg-page);
13
- margin-inline: auto;
14
- padding: var(--cg-s10) var(--cg-gutter);
7
+ .cg-archive__head {
8
+ padding-block: calc(var(--cg-section) * 0.6) calc(var(--cg-section) / 4);
9
+ padding-inline: var(--cg-inset);
15
10
  }
16
11
 
17
- .cg-archive__breadcrumb ol,
18
- .cg-archive__children {
12
+ .cg-archive__head .cg-page__title {
13
+ padding: 0;
14
+ }
15
+
16
+ .cg-archive__breadcrumb ol {
19
17
  display: flex;
20
18
  flex-wrap: wrap;
21
- gap: var(--cg-s3);
22
- margin: 0 0 var(--cg-s4);
19
+ gap: var(--cg-s1) var(--cg-s3);
20
+ margin: 0 0 var(--cg-s6);
23
21
  padding: 0;
24
22
  list-style: none;
23
+ color: var(--cg-ink-muted);
25
24
  font-size: var(--cg-text-sm);
26
25
  }
27
26
 
27
+ .cg-archive__breadcrumb li:not(:last-child)::after {
28
+ content: "/" / "";
29
+ margin-inline-start: var(--cg-s3);
30
+ }
31
+
32
+ .cg-archive__breadcrumb a {
33
+ color: var(--cg-ink-muted);
34
+ }
35
+
36
+ .cg-archive__breadcrumb a:hover {
37
+ color: var(--cg-accent);
38
+ }
39
+
28
40
  .cg-archive__children {
29
- margin-block: var(--cg-s4) var(--cg-s8);
41
+ display: flex;
42
+ flex-wrap: wrap;
43
+ gap: var(--cg-s1) var(--cg-s6);
44
+ margin: var(--cg-s8) 0 0;
45
+ padding: 0;
46
+ list-style: none;
47
+ }
48
+
49
+ .cg-archive__children a {
50
+ display: inline-block;
51
+ padding-block: var(--cg-s2);
52
+ color: var(--cg-ink);
53
+ font-weight: var(--cg-weight-medium);
54
+ text-decoration-color: var(--cg-underline);
55
+ }
56
+
57
+ .cg-archive__children a:hover {
58
+ color: var(--cg-accent);
59
+ text-decoration-color: currentColor;
60
+ }
61
+
62
+ .cg-archive__list {
63
+ display: grid;
64
+ grid-template-columns: repeat(var(--cg-columns), minmax(0, 1fr));
65
+ column-gap: var(--cg-column-gap);
66
+ align-content: start;
67
+ padding-block: calc(var(--cg-section) / 4) calc(var(--cg-section) / 2);
68
+ padding-inline: var(--cg-inset);
69
+ }
70
+
71
+ .cg-archive__list > * {
72
+ grid-column: 1 / -1;
73
+ min-inline-size: 0;
30
74
  }
31
75
 
32
76
  .cg-archive__pager {
33
77
  display: flex;
78
+ flex-wrap: wrap;
34
79
  justify-content: space-between;
35
80
  gap: var(--cg-s4);
36
- margin-block-start: var(--cg-s10);
37
- padding-block-start: var(--cg-s5);
38
- border-block-start: 1px solid var(--cg-line-soft);
39
- font-weight: var(--cg-weight-semibold);
81
+ margin-block-start: var(--cg-s8);
82
+ }
83
+
84
+ .cg-archive__pager a[rel="next"] {
85
+ margin-inline-start: auto;
40
86
  }