@docpensieve/theme 0.4.0-beta.1 → 0.4.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@docpensieve/theme",
3
- "version": "0.4.0-beta.1",
3
+ "version": "0.4.0",
4
4
  "description": "DocPensieve theme system: composable providers (Tailwind, custom)",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -20,7 +20,7 @@
20
20
  "types"
21
21
  ],
22
22
  "dependencies": {
23
- "@docpensieve/shared": "0.4.0-beta.1",
23
+ "@docpensieve/shared": "0.4.0",
24
24
  "tailwindcss": "^4.3.3"
25
25
  },
26
26
  "keywords": [
@@ -22,6 +22,14 @@ export const DEFAULT_TOKENS = Object.freeze({
22
22
  '--dp-rule': '#e8ebef',
23
23
  '--dp-accent': '#5b57d1',
24
24
  '--dp-accent-soft': '#f0effc',
25
+ // Meaning, not decoration: a tip, a caution and a danger. A component never
26
+ // writes a colour, so the three come from here.
27
+ '--dp-tip': '#0f7a5a',
28
+ '--dp-tip-soft': '#eaf7f2',
29
+ '--dp-attention': '#9a6400',
30
+ '--dp-attention-soft': '#fdf4e3',
31
+ '--dp-danger': '#b42318',
32
+ '--dp-danger-soft': '#fdf0ef',
25
33
  '--dp-shadow': 'rgba(20, 24, 34, 0.12)',
26
34
  '--dp-radius': '6px',
27
35
  '--dp-font': 'system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif',
@@ -30,6 +30,13 @@ const TAILWIND_TOKENS = Object.freeze({
30
30
  '--dp-rule': 'oklch(92.9% 0.013 255.508)',
31
31
  '--dp-accent': 'oklch(51.1% 0.262 276.966)',
32
32
  '--dp-accent-soft': 'oklch(96.2% 0.018 272.314)',
33
+ // Meaning, not decoration: a tip, a caution and a danger.
34
+ '--dp-tip': 'oklch(50.8% 0.118 165.612)',
35
+ '--dp-tip-soft': 'oklch(97.9% 0.021 166.113)',
36
+ '--dp-attention': 'oklch(55.5% 0.123 66.442)',
37
+ '--dp-attention-soft': 'oklch(98% 0.016 73.684)',
38
+ '--dp-danger': 'oklch(50.5% 0.213 27.518)',
39
+ '--dp-danger-soft': 'oklch(97.1% 0.013 17.38)',
33
40
  '--dp-shadow': 'rgba(15, 23, 42, 0.12)',
34
41
  '--dp-radius': '0.375rem',
35
42
  '--dp-font': 'var(--font-sans, ui-sans-serif, system-ui, sans-serif)',
@@ -49,9 +56,14 @@ const TAILWIND_TOKENS = Object.freeze({
49
56
  const TAILWIND_CLASSES = Object.freeze({
50
57
  header:
51
58
  'dp-header border-b border-slate-200 bg-white/90 backdrop-blur dark:border-slate-800 dark:bg-slate-950/90',
59
+ // The same dress, without what holds it to the top of the screen.
60
+ headerStatic:
61
+ 'dp-header dp-header--static border-b border-slate-200 bg-white dark:border-slate-800 dark:bg-slate-950',
52
62
  brand: 'dp-brand font-semibold tracking-tight text-slate-900 no-underline dark:text-slate-100',
53
63
  versionsList:
54
64
  'dp-versions-list rounded-md border border-slate-200 bg-white p-1 shadow-lg dark:border-slate-800 dark:bg-slate-900',
65
+ languagesList:
66
+ 'dp-languages-list rounded-md border border-slate-200 bg-white p-1 shadow-lg dark:border-slate-800 dark:bg-slate-900',
55
67
  sidebar: 'dp-sidebar text-sm',
56
68
  navLink:
57
69
  'dp-nav-link block rounded px-2 py-1 no-underline text-slate-600 hover:bg-slate-100 hover:text-slate-900 aria-[current=page]:bg-indigo-50 aria-[current=page]:font-medium aria-[current=page]:text-indigo-700 dark:text-slate-400 dark:hover:bg-slate-800 dark:hover:text-slate-100 dark:aria-[current=page]:bg-slate-800 dark:aria-[current=page]:text-indigo-300',
package/styles/custom.css CHANGED
@@ -30,6 +30,12 @@
30
30
  --dp-rule: #262a32;
31
31
  --dp-accent: #9b97f0;
32
32
  --dp-accent-soft: #1e1d33;
33
+ --dp-tip: #4cc79a;
34
+ --dp-tip-soft: #10241d;
35
+ --dp-attention: #e0a85a;
36
+ --dp-attention-soft: #241c10;
37
+ --dp-danger: #f2837a;
38
+ --dp-danger-soft: #2a1513;
33
39
  --dp-shadow: rgba(0, 0, 0, 0.45);
34
40
  }
35
41
  }
@@ -44,6 +50,12 @@
44
50
  --dp-rule: #262a32;
45
51
  --dp-accent: #9b97f0;
46
52
  --dp-accent-soft: #1e1d33;
53
+ --dp-tip: #4cc79a;
54
+ --dp-tip-soft: #10241d;
55
+ --dp-attention: #e0a85a;
56
+ --dp-attention-soft: #241c10;
57
+ --dp-danger: #f2837a;
58
+ --dp-danger-soft: #2a1513;
47
59
  --dp-shadow: rgba(0, 0, 0, 0.45);
48
60
  }
49
61
 
@@ -148,6 +160,35 @@ a {
148
160
  font-weight: 560;
149
161
  }
150
162
 
163
+ /* The language switcher wears the same dress; a language this page has not
164
+ been translated into is dimmed rather than removed. */
165
+ .dp-languages-list {
166
+ padding: 0.3rem;
167
+ background: var(--dp-bg);
168
+ border: 1px solid var(--dp-border);
169
+ border-radius: var(--dp-radius);
170
+ box-shadow: 0 8px 24px var(--dp-shadow);
171
+ }
172
+ .dp-languages-list a,
173
+ .dp-languages-list span {
174
+ display: block;
175
+ padding: 0.3rem 0.55rem;
176
+ border-radius: 4px;
177
+ font-size: 0.86rem;
178
+ color: var(--dp-text);
179
+ text-decoration: none;
180
+ }
181
+ .dp-languages-list a:hover {
182
+ background: var(--dp-bg-soft);
183
+ }
184
+ .dp-languages-list a[aria-current] {
185
+ color: var(--dp-accent);
186
+ font-weight: 560;
187
+ }
188
+ .dp-languages-list span {
189
+ color: var(--dp-text-soft);
190
+ }
191
+
151
192
  /* --- Side columns -------------------------------------------------------- */
152
193
 
153
194
  .dp-sidebar,
package/styles/prose.css CHANGED
@@ -161,6 +161,31 @@
161
161
  color: var(--dp-text);
162
162
  }
163
163
 
164
+ /* A folded category of the menu, and the menu of a narrow screen. */
165
+ .dp-nav-summary {
166
+ display: block;
167
+ padding: 0.25rem 0.5rem;
168
+ color: var(--dp-text-soft);
169
+ font-weight: 600;
170
+ }
171
+
172
+ .dp-nav-summary:hover {
173
+ color: var(--dp-text);
174
+ }
175
+
176
+ .dp-sidebar-menu > summary {
177
+ border: 1px solid var(--dp-border);
178
+ border-radius: var(--dp-radius);
179
+ color: var(--dp-text-soft);
180
+ font-weight: 500;
181
+ }
182
+
183
+ .dp-sidebar-menu[open] > summary,
184
+ .dp-sidebar-menu > summary:hover {
185
+ border-color: var(--dp-text-soft);
186
+ color: var(--dp-text);
187
+ }
188
+
164
189
  /* The links of the header, and the menu that holds them on a narrow screen. */
165
190
  .dp-header-links a {
166
191
  color: var(--dp-text-soft);
@@ -172,6 +197,49 @@
172
197
  color: var(--dp-text);
173
198
  }
174
199
 
200
+ .dp-mega > summary {
201
+ color: var(--dp-text-soft);
202
+ font-weight: 500;
203
+ }
204
+
205
+ .dp-mega > summary:hover,
206
+ .dp-mega[open] > summary {
207
+ color: var(--dp-text);
208
+ }
209
+
210
+ .dp-mega-panel {
211
+ border: 1px solid var(--dp-border);
212
+ border-radius: var(--dp-radius);
213
+ background: var(--dp-bg);
214
+ box-shadow: 0 8px 24px var(--dp-shadow);
215
+ }
216
+
217
+ .dp-mega-title {
218
+ color: var(--dp-text-soft);
219
+ font-size: 0.75rem;
220
+ font-weight: 600;
221
+ letter-spacing: 0.04em;
222
+ text-transform: uppercase;
223
+ }
224
+
225
+ .dp-mega-panel a {
226
+ color: var(--dp-text);
227
+ text-decoration: none;
228
+ }
229
+
230
+ .dp-mega-panel a:hover {
231
+ color: var(--dp-accent);
232
+ }
233
+
234
+ /* Inside the menu of a narrow screen, the panel is part of the list. */
235
+ .dp-menu-panel .dp-mega-panel {
236
+ border: 0;
237
+ border-inline-start: 1px solid var(--dp-border);
238
+ border-radius: 0;
239
+ background: transparent;
240
+ box-shadow: none;
241
+ }
242
+
175
243
  .dp-menu > summary {
176
244
  border: 1px solid var(--dp-border);
177
245
  border-radius: var(--dp-radius);
@@ -22,6 +22,14 @@ html {
22
22
  scroll-padding-top: 4.5rem;
23
23
  }
24
24
 
25
+ /*
26
+ * Nothing covers the top of the page once the header scrolls away: kept, the
27
+ * padding would leave a blank band above every heading reached by a link.
28
+ */
29
+ html:has(.dp-header--static) {
30
+ scroll-padding-top: 0;
31
+ }
32
+
25
33
  body {
26
34
  margin: 0;
27
35
  }
@@ -139,6 +147,15 @@ body {
139
147
  padding: 0 1.5rem;
140
148
  }
141
149
 
150
+ /*
151
+ * Scrolls away with the page, giving its height back to the text. Written
152
+ * after the rule above, which it undoes: the element carries both classes,
153
+ * and of two rules of equal weight the last one wins.
154
+ */
155
+ .dp-header--static {
156
+ position: static;
157
+ }
158
+
142
159
  /* The version switcher is a <details>: it opens without JavaScript. */
143
160
  .dp-versions {
144
161
  position: relative;
@@ -160,6 +177,32 @@ body {
160
177
  list-style: none;
161
178
  }
162
179
 
180
+ /* The language switcher works exactly like it, and is narrower: it holds
181
+ codes, not version numbers. */
182
+ .dp-languages {
183
+ position: relative;
184
+ }
185
+ .dp-languages > summary {
186
+ cursor: pointer;
187
+ list-style: none;
188
+ user-select: none;
189
+ }
190
+ .dp-languages > summary::-webkit-details-marker {
191
+ display: none;
192
+ }
193
+ .dp-languages-list {
194
+ position: absolute;
195
+ top: calc(100% + 0.4rem);
196
+ left: 0;
197
+ min-width: 5rem;
198
+ margin: 0;
199
+ list-style: none;
200
+ }
201
+ /* A language this page was never translated into: shown, never offered. */
202
+ .dp-languages-list [aria-disabled='true'] {
203
+ cursor: not-allowed;
204
+ }
205
+
163
206
  /*
164
207
  * What the header offers beyond the brand — versions, links, search — is
165
208
  * written twice, and shown once: in a row on a wide screen, behind a menu
@@ -185,6 +228,59 @@ body {
185
228
  margin-inline-start: 0;
186
229
  }
187
230
 
231
+ /*
232
+ * A header entry that opens a panel of links instead of leading anywhere.
233
+ * Its look is in prose.css.
234
+ */
235
+ .dp-mega {
236
+ position: relative;
237
+ }
238
+
239
+ .dp-mega > summary {
240
+ cursor: pointer;
241
+ list-style: none;
242
+ }
243
+
244
+ .dp-mega > summary::-webkit-details-marker {
245
+ display: none;
246
+ }
247
+
248
+ .dp-mega-panel {
249
+ position: absolute;
250
+ top: calc(100% + 0.5rem);
251
+ left: 0;
252
+ display: grid;
253
+ grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr));
254
+ gap: 1.25rem;
255
+ min-inline-size: 22rem;
256
+ padding: 1.1rem 1.25rem;
257
+ }
258
+
259
+ .dp-mega-panel ul {
260
+ display: flex;
261
+ flex-direction: column;
262
+ gap: 0.4rem;
263
+ margin: 0;
264
+ padding: 0;
265
+ list-style: none;
266
+ }
267
+
268
+ .dp-mega-title {
269
+ margin: 0 0 0.5rem;
270
+ }
271
+
272
+ /*
273
+ * Inside the menu of a narrow screen, the panel unfolds in place: laid over
274
+ * it, it would open outside the screen.
275
+ */
276
+ .dp-menu-panel .dp-mega-panel {
277
+ position: static;
278
+ grid-template-columns: minmax(0, 1fr);
279
+ gap: 0.75rem;
280
+ min-inline-size: 0;
281
+ padding: 0.5rem 0 0 0.75rem;
282
+ }
283
+
188
284
  .dp-menu {
189
285
  display: none;
190
286
  position: relative;
@@ -310,6 +406,59 @@ body {
310
406
  font-weight: 600;
311
407
  }
312
408
 
409
+ /*
410
+ * A folded category: a native details, whose handle carries the marker. Its
411
+ * look is in prose.css.
412
+ */
413
+ .dp-nav-group > summary {
414
+ cursor: pointer;
415
+ list-style: none;
416
+ }
417
+
418
+ .dp-nav-group > summary::-webkit-details-marker {
419
+ display: none;
420
+ }
421
+
422
+ /* The marker turns with the fold, and never takes the focus on its own. */
423
+ .dp-nav-group > summary::after {
424
+ content: '';
425
+ display: inline-block;
426
+ inline-size: 0.35rem;
427
+ block-size: 0.35rem;
428
+ margin-inline-start: 0.4rem;
429
+ border-inline-end: 1px solid currentColor;
430
+ border-block-end: 1px solid currentColor;
431
+ rotate: -45deg;
432
+ translate: 0 -0.1rem;
433
+ }
434
+
435
+ .dp-nav-group[open] > summary::after {
436
+ rotate: 45deg;
437
+ translate: 0 -0.15rem;
438
+ }
439
+
440
+ /*
441
+ * The menu of a narrow screen: folded above the content, where the column
442
+ * cannot stand. Shown instead of the column, never beside it.
443
+ */
444
+ .dp-sidebar-menu {
445
+ display: none;
446
+ margin-block-end: 1.5rem;
447
+ }
448
+
449
+ .dp-sidebar-menu > summary {
450
+ display: inline-flex;
451
+ align-items: center;
452
+ gap: 0.4rem;
453
+ padding: 0.5rem 0.9rem;
454
+ cursor: pointer;
455
+ list-style: none;
456
+ }
457
+
458
+ .dp-sidebar-menu > summary::-webkit-details-marker {
459
+ display: none;
460
+ }
461
+
313
462
  .dp-sidebar,
314
463
  .dp-toc {
315
464
  position: sticky;
@@ -398,13 +547,15 @@ body {
398
547
  padding: 1.5rem 25px 4rem;
399
548
  }
400
549
  /*
401
- * On a small screen the menu moves above the content and stops being
402
- * sticky: a fixed column would eat half of the useful surface.
550
+ * On a small screen the column gives way to the folded menu above the
551
+ * content: open, it would eat the first screen before a word is read.
403
552
  */
404
553
  .dp-sidebar {
405
- position: static;
406
- max-height: none;
407
- padding-bottom: 1.25rem;
554
+ display: none;
555
+ }
556
+
557
+ .dp-sidebar-menu {
558
+ display: block;
408
559
  }
409
560
  }
410
561
 
@@ -28,6 +28,12 @@
28
28
  --dp-rule: oklch(27.9% 0.041 260.031);
29
29
  --dp-accent: oklch(78.5% 0.115 274.713);
30
30
  --dp-accent-soft: oklch(20.8% 0.042 265.755);
31
+ --dp-tip: oklch(76.5% 0.177 163.223);
32
+ --dp-tip-soft: oklch(26.2% 0.051 172.552);
33
+ --dp-attention: oklch(82.8% 0.189 84.429);
34
+ --dp-attention-soft: oklch(27.9% 0.077 45.635);
35
+ --dp-danger: oklch(70.4% 0.191 22.216);
36
+ --dp-danger-soft: oklch(25.8% 0.092 26.042);
31
37
  --dp-shadow: rgba(0, 0, 0, 0.45);
32
38
  }
33
39
  }
@@ -42,6 +48,12 @@
42
48
  --dp-rule: oklch(27.9% 0.041 260.031);
43
49
  --dp-accent: oklch(78.5% 0.115 274.713);
44
50
  --dp-accent-soft: oklch(20.8% 0.042 265.755);
51
+ --dp-tip: oklch(76.5% 0.177 163.223);
52
+ --dp-tip-soft: oklch(26.2% 0.051 172.552);
53
+ --dp-attention: oklch(82.8% 0.189 84.429);
54
+ --dp-attention-soft: oklch(27.9% 0.077 45.635);
55
+ --dp-danger: oklch(70.4% 0.191 22.216);
56
+ --dp-danger-soft: oklch(25.8% 0.092 26.042);
45
57
  --dp-shadow: rgba(0, 0, 0, 0.45);
46
58
  }
47
59
 
@@ -19,6 +19,12 @@ export declare const DEFAULT_TOKENS: Readonly<{
19
19
  '--dp-rule': "#e8ebef";
20
20
  '--dp-accent': "#5b57d1";
21
21
  '--dp-accent-soft': "#f0effc";
22
+ '--dp-tip': "#0f7a5a";
23
+ '--dp-tip-soft': "#eaf7f2";
24
+ '--dp-attention': "#9a6400";
25
+ '--dp-attention-soft': "#fdf4e3";
26
+ '--dp-danger': "#b42318";
27
+ '--dp-danger-soft': "#fdf0ef";
22
28
  '--dp-shadow': "rgba(20, 24, 34, 0.12)";
23
29
  '--dp-radius': "6px";
24
30
  '--dp-font': "system-ui, -apple-system, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif";
@@ -38,6 +44,12 @@ export declare class CustomProvider extends BaseThemeProvider {
38
44
  '--dp-rule': "#e8ebef";
39
45
  '--dp-accent': "#5b57d1";
40
46
  '--dp-accent-soft': "#f0effc";
47
+ '--dp-tip': "#0f7a5a";
48
+ '--dp-tip-soft': "#eaf7f2";
49
+ '--dp-attention': "#9a6400";
50
+ '--dp-attention-soft': "#fdf4e3";
51
+ '--dp-danger': "#b42318";
52
+ '--dp-danger-soft': "#fdf0ef";
41
53
  '--dp-shadow': "rgba(20, 24, 34, 0.12)";
42
54
  '--dp-radius': "6px";
43
55
  '--dp-font': "system-ui, -apple-system, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif";
@@ -16,6 +16,12 @@ export declare class TailwindProvider extends BaseThemeProvider {
16
16
  '--dp-rule': "oklch(92.9% 0.013 255.508)";
17
17
  '--dp-accent': "oklch(51.1% 0.262 276.966)";
18
18
  '--dp-accent-soft': "oklch(96.2% 0.018 272.314)";
19
+ '--dp-tip': "oklch(50.8% 0.118 165.612)";
20
+ '--dp-tip-soft': "oklch(97.9% 0.021 166.113)";
21
+ '--dp-attention': "oklch(55.5% 0.123 66.442)";
22
+ '--dp-attention-soft': "oklch(98% 0.016 73.684)";
23
+ '--dp-danger': "oklch(50.5% 0.213 27.518)";
24
+ '--dp-danger-soft': "oklch(97.1% 0.013 17.38)";
19
25
  '--dp-shadow': "rgba(15, 23, 42, 0.12)";
20
26
  '--dp-radius': "0.375rem";
21
27
  '--dp-font': "var(--font-sans, ui-sans-serif, system-ui, sans-serif)";