@tenphi/cookbook 0.17.0 → 0.18.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/dist/cli.js +39 -9
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +2 -2
- package/dist/content.d.ts +3 -0
- package/dist/content.js +3 -0
- package/dist/eslint-plugin.d.ts +2 -2
- package/dist/eslint-plugin.js +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/docs/ai-agents.md +15 -4
- package/docs/authoring.mdx +42 -8
- package/docs/cli.md +43 -1
- package/docs/configuration.md +77 -15
- package/docs/content-sources.md +26 -0
- package/docs/customization-rules.md +8 -0
- package/docs/deployment.md +20 -3
- package/docs/examples.md +5 -2
- package/docs/getting-started.md +9 -6
- package/docs/index.md +21 -10
- package/docs/migration.md +98 -5
- package/docs/plugins.md +120 -0
- package/docs/publishing.md +153 -0
- package/docs/quality-checks.md +71 -0
- package/docs/recipes.md +116 -0
- package/docs/theme-and-components.md +481 -70
- package/docs/troubleshooting.md +89 -0
- package/package.json +7 -3
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
title: Theme
|
|
2
|
+
title: Theme reference
|
|
3
3
|
description: Build an accessible Glaze palette, customize Tasty tokens, and use the supported Astro components.
|
|
4
4
|
sidebar:
|
|
5
5
|
order: 5
|
|
@@ -26,20 +26,25 @@ cover the configuration language accepted by `theme.styles`:
|
|
|
26
26
|
* [Tasty methodology](./upstream/tasty/docs/methodology.md) for the design-system
|
|
27
27
|
patterns behind roots, sub-elements, and controlled overrides.
|
|
28
28
|
|
|
29
|
+
For the short brand, logo, and font path, start with the
|
|
30
|
+
[configuration recipes](./recipes.md). This reference covers semantic colors,
|
|
31
|
+
typography, tokens, every configurable style tree, and custom components. Read
|
|
32
|
+
the [customization rules](./customization-rules.md) before adding styles.
|
|
33
|
+
|
|
29
34
|
## Brand color
|
|
30
35
|
|
|
31
36
|
The default brand is a calm blue with 68% OKHSL saturation. Set a brand color
|
|
32
37
|
with Glaze's `from` declaration:
|
|
33
38
|
|
|
34
39
|
```ts
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
+
import { defineDocsConfig } from "@tenphi/cookbook/config";
|
|
41
|
+
|
|
42
|
+
export default defineDocsConfig({
|
|
43
|
+
theme: { brand: { from: "#2f5bff" } },
|
|
44
|
+
});
|
|
40
45
|
```
|
|
41
46
|
|
|
42
|
-
Add a contrast target when the brand appears as text
|
|
47
|
+
Add a contrast target when the brand appears as text:
|
|
43
48
|
|
|
44
49
|
```ts
|
|
45
50
|
theme: {
|
|
@@ -50,9 +55,12 @@ theme: {
|
|
|
50
55
|
}
|
|
51
56
|
```
|
|
52
57
|
|
|
53
|
-
The
|
|
54
|
-
|
|
55
|
-
|
|
58
|
+
The brand supplies the hue and saturation seed. Cookbook derives separate text,
|
|
59
|
+
filled-control, and focus roles from it. Small accent text and filled controls
|
|
60
|
+
use stronger default APCA floors (75 normally, 90 in high contrast), and diagnostics
|
|
61
|
+
also enforce WCAG 4.5:1 / 7:1 on their actual backgrounds. Higher authored brand
|
|
62
|
+
targets are retained. Glaze adjusts tones only as far as these floors require;
|
|
63
|
+
dark and high-contrast schemes resolve independently.
|
|
56
64
|
|
|
57
65
|
Cookbook rejects a normal APCA target below 45 unless
|
|
58
66
|
`unsafeContrast: true` is present. That escape hatch is intentionally visible
|
|
@@ -72,13 +80,19 @@ theme: {
|
|
|
72
80
|
surface: { tone: 98, saturation: 0.05 },
|
|
73
81
|
text: {
|
|
74
82
|
base: "surface",
|
|
75
|
-
tone:
|
|
83
|
+
tone: 0,
|
|
84
|
+
saturation: 0,
|
|
85
|
+
contrast: { wcag: [7, 10] }
|
|
86
|
+
},
|
|
87
|
+
heading: {
|
|
88
|
+
base: "surface",
|
|
89
|
+
tone: [4, 0],
|
|
76
90
|
saturation: 0,
|
|
77
91
|
contrast: { wcag: [7, 10] }
|
|
78
92
|
},
|
|
79
93
|
textSoft: {
|
|
80
94
|
base: "surface",
|
|
81
|
-
tone:
|
|
95
|
+
tone: [25, 10],
|
|
82
96
|
saturation: 0.05,
|
|
83
97
|
contrast: { wcag: [4.5, 7] }
|
|
84
98
|
}
|
|
@@ -88,8 +102,19 @@ theme: {
|
|
|
88
102
|
```
|
|
89
103
|
|
|
90
104
|
Glaze resolves each declaration for light, dark, normal, and high-contrast
|
|
91
|
-
modes.
|
|
92
|
-
high contrast.
|
|
105
|
+
modes. In a tone or contrast pair, the first value applies to normal mode;
|
|
106
|
+
the second applies to high contrast. Use absolute tones for reading text:
|
|
107
|
+
`text` starts at tone 0 and `heading` at tone 4, giving headings only a slight
|
|
108
|
+
reduction in contrast. Glaze applies its tone boundaries in normal mode, so
|
|
109
|
+
body text is not pure black, then inverts the tones for dark mode. High-contrast
|
|
110
|
+
mode uses the full range. `textSoft` is reserved for secondary text.
|
|
111
|
+
`heading` follows an explicitly configured `text` declaration unless it has
|
|
112
|
+
its own declaration, preserving existing custom palettes.
|
|
113
|
+
Contrast requirements are minimum safeguards: Glaze preserves the authored
|
|
114
|
+
tone when it already meets the floor. A small relative tone step from the
|
|
115
|
+
surface would instead leave the solver to produce text at that minimum.
|
|
116
|
+
|
|
117
|
+
Palette declarations inherit the brand hue and saturation:
|
|
93
118
|
`saturation` is a 0–1 factor of that seed, and `tone` is 0–100. They can set
|
|
94
119
|
an absolute tone or a tone relative to `base`. Use `from` on a palette role
|
|
95
120
|
when it needs its own color seed; otherwise relative declarations keep its
|
|
@@ -100,9 +125,9 @@ Cookbook keeps literal surface seeds desaturated in the dark scheme so a nearly
|
|
|
100
125
|
white tint does not become vivid dark chrome when its tone is inverted.
|
|
101
126
|
|
|
102
127
|
Components consume semantic colors consistently: `surface`, `header`, `surface-2`,
|
|
103
|
-
`surface-3`, `text`, `text-soft`, `border`, `border-strong`, `accent-text`,
|
|
104
|
-
`accent-surface`, `accent-surface-text`, and `focus`.
|
|
105
|
-
these as `#surface`, `#text`, `#border`, and so on; the Astro shell consumes the
|
|
128
|
+
`surface-3`, `text`, `heading`, `text-soft`, `border`, `border-strong`, `accent-text`,
|
|
129
|
+
`accent-surface`, `accent-surface-text`, `logo-surface`, `logo-mark`, and `focus`.
|
|
130
|
+
Tasty components can use these as `#surface`, `#text`, `#border`, and so on; the Astro shell consumes the
|
|
106
131
|
same resolved values. Glaze also generates hover and pressed states, subtle
|
|
107
132
|
accent fills, overlays, shadows, and the orange, green, blue, purple, and red
|
|
108
133
|
roles used by Starlight content components. No browser color mixes or
|
|
@@ -189,15 +214,20 @@ theme: {
|
|
|
189
214
|
}
|
|
190
215
|
```
|
|
191
216
|
|
|
192
|
-
The short form
|
|
193
|
-
|
|
217
|
+
The short form follows the regular and strong weights in your configured
|
|
218
|
+
presets, including heading and custom preset references. It requests normal and
|
|
219
|
+
italic styles, prefers a variable range, and falls back to real static weights
|
|
220
|
+
when ranges are unavailable. A font without italics produces a build warning;
|
|
221
|
+
choose another family or select only its supported styles. To control the
|
|
222
|
+
request exactly, list weights or ascending variable ranges and styles. Google
|
|
223
|
+
Fonts must support them; see the
|
|
194
224
|
[Google Fonts CSS API](https://developers.google.com/fonts/docs/css2) for its
|
|
195
225
|
available styles and weight syntax.
|
|
196
226
|
|
|
197
227
|
```ts
|
|
198
228
|
theme: {
|
|
199
229
|
fonts: {
|
|
200
|
-
body: { google: "Inter", weights: [400,
|
|
230
|
+
body: { google: "Inter", weights: ["400 750"], styles: ["normal", "italic"] }
|
|
201
231
|
}
|
|
202
232
|
}
|
|
203
233
|
```
|
|
@@ -223,10 +253,38 @@ theme: {
|
|
|
223
253
|
|
|
224
254
|
The `body` role also feeds navigation and small text. `heading` feeds `h1`
|
|
225
255
|
through `h6`, while `code` covers code text. Each role has a system fallback.
|
|
226
|
-
Cookbook emits
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
256
|
+
Cookbook emits font faces through Tasty with `font-display: swap`. Google CSS
|
|
257
|
+
and font files are downloaded at build time and cached in
|
|
258
|
+
`<Astro cacheDir>/cookbook-fonts`. Files are served from your own site's
|
|
259
|
+
`_cookbook/fonts/` path by default, including the deployment base. Visitors make
|
|
260
|
+
no Google Fonts requests. Existing local-file definitions keep working.
|
|
261
|
+
|
|
262
|
+
```ts
|
|
263
|
+
theme: {
|
|
264
|
+
fonts: { body: "Inter" },
|
|
265
|
+
fontLoading: {
|
|
266
|
+
google: "self-hosted", // or "remote" to keep Google's font CDN URLs
|
|
267
|
+
cache: "reuse", // "refresh" to fetch again; "offline" to forbid network
|
|
268
|
+
display: "swap" // also auto, block, fallback, optional
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
The first build requires network access. Preserve the Astro cache between CI
|
|
274
|
+
runs; `offline` fails with an actionable message when an entry is missing or
|
|
275
|
+
corrupt. Cache entries are content-verified and keyed by the exact request.
|
|
276
|
+
`refresh` deliberately updates them. For a fully checked-in font source, copy
|
|
277
|
+
licensed files into `public/fonts/` and use the local form. Only `wght` and
|
|
278
|
+
`ital` axes are requested; use local variable files and Tasty typography styles
|
|
279
|
+
for other axes. Styles and weights that do not exist are rejected for explicit
|
|
280
|
+
requests. For static fonts, browsers select their nearest real weight;
|
|
281
|
+
intermediate weights require a variable font.
|
|
282
|
+
|
|
283
|
+
Migration: name-only Google font configuration now downloads the required
|
|
284
|
+
weights and italics and serves them locally. This increases the initial build's
|
|
285
|
+
font downloads and removes visitors' external font dependency. Set
|
|
286
|
+
`fontLoading.google: "remote"` to retain CDN delivery. Existing CSS-variable
|
|
287
|
+
weights that cannot be resolved from presets require explicit `weights`.
|
|
230
288
|
|
|
231
289
|
### Adjust presets
|
|
232
290
|
|
|
@@ -341,42 +399,62 @@ is merged into the base inside Cookbook.
|
|
|
341
399
|
Every configurable surface accepts styles at the root plus these named Tasty
|
|
342
400
|
sub-elements:
|
|
343
401
|
|
|
344
|
-
| Configuration name | Named sub-elements
|
|
345
|
-
| ----------------------- |
|
|
346
|
-
| `Card` | `Heading2`, `Heading3`, `Paragraph`
|
|
347
|
-
| `Callout` | `Title`, `Body`, `Tip`, `Caution`, `Danger`
|
|
348
|
-
| `CodeGroup` | `Caption`, `Pre`, `Code`
|
|
349
|
-
| `Tab` | `Heading`, `Hidden`, `HiddenHeading`
|
|
350
|
-
| `
|
|
351
|
-
| `
|
|
352
|
-
| `
|
|
353
|
-
| `
|
|
354
|
-
| `
|
|
355
|
-
| `
|
|
356
|
-
| `
|
|
357
|
-
| `
|
|
358
|
-
| `
|
|
359
|
-
| `
|
|
360
|
-
| `
|
|
361
|
-
| `
|
|
362
|
-
| `
|
|
363
|
-
| `
|
|
364
|
-
| `
|
|
365
|
-
| `
|
|
366
|
-
| `
|
|
367
|
-
| `
|
|
368
|
-
| `
|
|
369
|
-
| `
|
|
370
|
-
| `
|
|
371
|
-
| `
|
|
372
|
-
| `
|
|
373
|
-
| `
|
|
374
|
-
| `
|
|
375
|
-
| `
|
|
376
|
-
| `
|
|
377
|
-
| `
|
|
378
|
-
| `
|
|
379
|
-
| `
|
|
402
|
+
| Configuration name | Named sub-elements |
|
|
403
|
+
| ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
404
|
+
| `Card` | `Heading2`, `Heading3`, `Paragraph` |
|
|
405
|
+
| `Callout` | `Title`, `Body`, `Tip`, `Caution`, `Danger` |
|
|
406
|
+
| `CodeGroup` | `Caption`, `Pre`, `Code` |
|
|
407
|
+
| `Tab` | `Heading`, `Hidden`, `HiddenHeading` |
|
|
408
|
+
| `MobileTableOfContents` | `Summary`, `List`, `NestedList`, `Item`, `Link`, `HoverLink`, `Focus` |
|
|
409
|
+
| `PageActions` | `Control`, `Hover`, `Focus`, `Pending`, `Status` |
|
|
410
|
+
| `Footer` | `Meta`, `LoneMetaItem`, `MetaLink`, `HoverMetaLink`, `Credit`, `CreditLink`, `HoverCreditLink` |
|
|
411
|
+
| `Hero` | `Visual`, `Stack`, `Copy`, `Title`, `Tagline`, `Actions`, `Action`, `HoverAction`, `PrimaryAction`, `SecondaryAction`, `MinimalAction`, `ActionIcon` |
|
|
412
|
+
| `LanguageSelect` | `Label`, `HoverLabel`, `LabelIcon`, `Select`, `Caret`, `Option` |
|
|
413
|
+
| `Logo` | `Svg`, `Mark` |
|
|
414
|
+
| `SiteLogo` | `Image`, `Light`, `Dark` |
|
|
415
|
+
| `MarkdownCodeBlock` | `Pre`, `CopyButton`, `HoverCopyButton`, `CopiedButton`, `CopyIcon`, `CopiedIcon`, `Code`, `Diff`, `DiffCode`, `DiffLine`, `EmptyDiffLine`, `InsertedLine`, `DeletedLine` |
|
|
416
|
+
| `MarkdownHeading` | `Heading`, `Heading1`, `Heading2`, `Heading3`, `Heading4`, `Heading5`, `Heading6`, `Link`, `RevealedLink`, `HoverLink`, `LinkIcon`, `CopiedLink`, `CopiedLinkIcon`, `CopiedIcon` |
|
|
417
|
+
| `MarkdownInlineCode` | None |
|
|
418
|
+
| `MarkdownTable` | `Table`, `Cell`, `LastBodyRowCell`, `HeaderCell`, `Scroll` |
|
|
419
|
+
| `Mermaid` | `Diagram`, `Text`, `MonoText` |
|
|
420
|
+
| `MobileMenuFooter` | `Social` |
|
|
421
|
+
| `MobileMenuToggle` | `Control`, `Icon`, `Section`, `Page`, `HoverControl`, `ActiveControl` |
|
|
422
|
+
| `MobileNavigationTabs` | `Trigger`, `Marker`, `Caret`, `ExpandedCaret`, `Label`, `List`, `Item`, `Link`, `HoverLink`, `CurrentLink` |
|
|
423
|
+
| `MobileTableOfContents` | `Item`, `Link`, `LinkLabel`, `HoverLink`, `CurrentLink`, `CurrentIndicator` |
|
|
424
|
+
| `PackageVersion` | None |
|
|
425
|
+
| `VersionSwitcher` | `Trigger`, `Panel`, `OpenPanel`, `Link`, `CurrentLink` |
|
|
426
|
+
| `Preview` | `Caption`, `Stage`, `Frame`, `Code`, `Summary`, `Pre` |
|
|
427
|
+
| `Sidebar` | `Backdrop`, `OpenBackdrop`, `MobileHeading`, `HomeLink`, `HomeLogo`, `HomeLabel`, `Close`, `HoverClose`, `CloseIcon`, `CurrentLink`, `OpenPane`, `EnteredPane`, `Content`, `Tree`, `List`, `Item`, `TopLevelSpacing`, `GroupSpacing`, `NestedItem`, `SectionHeading`, `Control`, `Summary`, `GroupLabel`, `GroupLabelText`, `Link`, `LinkLabel`, `InteractiveControl`, `SummaryMarker`, `Caret`, `ExpandedCaret`, `LinkedSummary`, `GroupLink`, `LinkedSectionHeading`, `SectionLink`, `Badge`, `TopLevelLink` |
|
|
428
|
+
| `SocialIcons` | `Link`, `HoverLink`, `Icon` |
|
|
429
|
+
| `StarlightHeader` | `Primary`, `TitleAndSearch`, `Title`, `LogoLink`, `Logo`, `SiteTitle`, `Search`, `SearchElement`, `Tools`, `ToolItem`, `Social`, `MobileTheme` |
|
|
430
|
+
| `TableOfContentsLayout` | `WithMobile`, `Content` |
|
|
431
|
+
| `SearchButton` | `PendingShortcut`, `Label`, `Shortcut`, `Hover`, `Active`, `NativeIcon`, `Icon` |
|
|
432
|
+
| `Layout` | `Islands`, `LockedPage`, `Light`, `Auto` |
|
|
433
|
+
| `HeaderLinks` | `Desktop`, `DesktopLink`, `Link`, `HoverLink`, `PrimaryLink`, `HoverPrimaryLink`, `Trigger`, `HoverTrigger`, `Panel`, `PanelNavigation`, `PanelLink`, `FirstPanelLink`, `Close`, `HoverClose` |
|
|
434
|
+
| `Heading` | `Level1`, `Level2`, `Level3`, `Level4`, `Level5`, `Level6`, `PageTitle` |
|
|
435
|
+
| `HeaderFrame` | None |
|
|
436
|
+
| `PageFrame` | `MainFrame`, `SidebarFrame`, `Columns` |
|
|
437
|
+
| `Steps` | `Item`, `Marker` |
|
|
438
|
+
| `Tabs` | `List`, `Button`, `SelectedButton`, `FocusedButton` |
|
|
439
|
+
| `TableOfContents` | `Heading`, `List`, `Item`, `Link`, `LinkLabel`, `HoverLink`, `CurrentLink` |
|
|
440
|
+
| `ThemeSelect` | `Trigger`, `HoverTrigger`, `ActiveTrigger`, `Icon`, `Panel`, `OpenPanel`, `Section`, `SectionSpacing`, `SectionLabel`, `Option`, `HoverOption`, `CheckedOption`, `FocusedOption`, `Input`, `OptionIcon`, `Checkmark`, `SelectedCheckmark` |
|
|
441
|
+
| `TopNavigation` | `Scrollbar`, `Link`, `HoverLink`, `CurrentLink`, `ActiveIndicator` |
|
|
442
|
+
| `Document` | `All`, `Body`, `Control`, `Pointer`, `ResponsiveWidth`, `ResponsiveHeight`, `Hidden`, `DesktopBlock`, `DesktopFlex`, `ScreenReaderOnly`, `Strong`, `Link`, `NarrowBlock`, `MobileBlock`, `Code`, `FocusRing`, `CurrentLink`, `SearchOpen` |
|
|
443
|
+
| `MainPane` | `WithSidebars` |
|
|
444
|
+
| `MainContent` | `ContentSpacing`, `Container`, `Panel`, `FirstPanel`, `BodyPanel` |
|
|
445
|
+
| `Banner` | `Link` |
|
|
446
|
+
| `SkipLink` | `Focus` |
|
|
447
|
+
| `Search` | `Status`, `Dialog`, `CloseIcon`, `OpenDialog`, `Backdrop`, `Frame`, `Container`, `Close`, `HoverClose`, `ActiveClose` |
|
|
448
|
+
| `Pagination` | `Link`, `NextLink`, `NextIcon`, `NextLabel`, `HoverLink`, `ActiveLink`, `Title`, `LoneNextLink`, `NativeIcon`, `Icon`, `PreviousIconRtl`, `NextIconRtl` |
|
|
449
|
+
| `Markdown` | `Block`, `BlockSpacing`, `HeadingSpacing`, `List`, `CompactItem`, `ListItem`, `DefinitionTerm`, `DefinitionDescription`, `Link`, `HoverLink`, `Quote`, `Rule`, `Details`, `HoverDetails`, `Summary`, `OpenSummary`, `SummaryMarker`, `SummaryIcon`, `OpenSummaryIcon`, `Code` |
|
|
450
|
+
| `MermaidSource` | None |
|
|
451
|
+
| `StarlightAside` | `Note`, `Tip`, `Caution`, `Danger`, `Title`, `Icon`, `FirstContent` |
|
|
452
|
+
| `StarlightCard` | `Title` |
|
|
453
|
+
| `StarlightLinkCard` | `Hover`, `Stack`, `Link`, `LinkOverlay`, `DescriptionAndIcon` |
|
|
454
|
+
| `StarlightBadge` | None |
|
|
455
|
+
| `StarlightSteps` | `Item`, `Counter`, `Connector` |
|
|
456
|
+
| `SyntaxHighlight` | `Scroll`, `Wrap`, `Marker`, `Comment`, `Punctuation`, `Keyword`, `String`, `Token`, `Property`, `Number`, `Function`, `Value`, `Operator`, `Text`, `Bg`, `Inserted`, `Deleted`, `Italic`, `Strong`, `Underline` |
|
|
457
|
+
| `SearchResults` | `Form`, `Input`, `Clear`, `Results`, `Result`, `ResultLink`, `SearchIcon`, `ClearIcon`, `SuppressedClear`, `Message`, `List`, `Title`, `Excerpt`, `NestedResult`, `Match`, `More`, `HoverMore` |
|
|
380
458
|
|
|
381
459
|
`COOKBOOK_COMPONENT_NAMES` publishes the configuration names, and
|
|
382
460
|
`COOKBOOK_COMPONENT_SUB_ELEMENTS` publishes the complete sub-element lists for
|
|
@@ -458,8 +536,8 @@ import { Card, Logo, Preview, Steps, Tabs } from "@tenphi/cookbook/components";
|
|
|
458
536
|
|
|
459
537
|
See [Authoring components](./authoring.mdx) for complete examples and props.
|
|
460
538
|
|
|
461
|
-
* `Preview` isolates HTML and
|
|
462
|
-
|
|
539
|
+
* `Preview` isolates HTML, CSS, and optional JavaScript in a sandboxed iframe.
|
|
540
|
+
The frame never receives same-origin access to the documentation page.
|
|
463
541
|
|
|
464
542
|
Use MDX only for repository content you control. Locked package content remains
|
|
465
543
|
Markdown-only unless the consumer explicitly sets `trust: "mdx"` for that
|
|
@@ -487,7 +565,84 @@ is needed for static components. Set shared tokens, presets, and states in
|
|
|
487
565
|
`docs.config.ts` before rendering. Import the styling entry point in component
|
|
488
566
|
modules; configuration files should use the main `@tenphi/cookbook` entry point.
|
|
489
567
|
|
|
490
|
-
### A
|
|
568
|
+
### A shared site logo
|
|
569
|
+
|
|
570
|
+
Set `site.logo` once to use your artwork in the header and mobile drawer:
|
|
571
|
+
|
|
572
|
+
```ts
|
|
573
|
+
site: {
|
|
574
|
+
title: "Acme",
|
|
575
|
+
logo: "./assets/acme.svg"
|
|
576
|
+
}
|
|
577
|
+
```
|
|
578
|
+
|
|
579
|
+
Paths are local files relative to the resolved project root, just like
|
|
580
|
+
`site.favicon`. Cookbook reads the intrinsic dimensions and copies the image to
|
|
581
|
+
a content-hashed URL under the deployment base. SVG, PNG, JPEG, WebP, AVIF, and
|
|
582
|
+
GIF are supported. Missing or invalid files fail during setup.
|
|
583
|
+
|
|
584
|
+
```ts
|
|
585
|
+
site: {
|
|
586
|
+
title: "Acme",
|
|
587
|
+
logo: {
|
|
588
|
+
light: "./assets/acme-light.svg",
|
|
589
|
+
dark: "./assets/acme-dark.svg",
|
|
590
|
+
alt: "Acme documentation",
|
|
591
|
+
href: "/",
|
|
592
|
+
decorative: true
|
|
593
|
+
},
|
|
594
|
+
favicon: "./assets/acme-icon.svg"
|
|
595
|
+
}
|
|
596
|
+
```
|
|
597
|
+
|
|
598
|
+
Use `src` for one image, or both `light` and `dark`. Variants follow the
|
|
599
|
+
appearance control and the system preference in Auto mode. They must share an
|
|
600
|
+
aspect ratio to prevent layout shifts. Optional `width` and `height` describe
|
|
601
|
+
intrinsic dimensions; Tasty controls display size. Customize
|
|
602
|
+
`theme.styles.SiteLogo` and its complete anatomy: `Image`, `Light`, and `Dark`.
|
|
603
|
+
Wide wordmarks retain their proportions within the header.
|
|
604
|
+
|
|
605
|
+
The logo is decorative by default because the neighboring title labels the
|
|
606
|
+
site. Set `decorative: false` and `alt` when the image itself carries meaningful
|
|
607
|
+
text. The header logo link still has a name when the image is decorative.
|
|
608
|
+
`href` defaults to the localized documentation home; it accepts a root-relative
|
|
609
|
+
documentation route or HTTP(S) destination. The header title and drawer use the
|
|
610
|
+
same destination. `site.logo: false` removes the mark from both locations.
|
|
611
|
+
|
|
612
|
+
A logo does not change the favicon or touch icons. Configure `site.favicon`
|
|
613
|
+
separately for square artwork; the default Cookbook icon set remains in place
|
|
614
|
+
until changed. `Logo` remains available as the standalone Cookbook book mark.
|
|
615
|
+
|
|
616
|
+
The built-in mark uses `theme.palette["logo-surface"]` and `theme.palette["logo-mark"]`.
|
|
617
|
+
Both default to Glaze `mode: "fixed"`: the brand background and light book keep
|
|
618
|
+
their polarity in dark mode while respecting Glaze's tone boundaries and
|
|
619
|
+
high-contrast settings. The mark-to-background contrast floor is 3:1 normally
|
|
620
|
+
and 4.5:1 in high contrast. These colors are separate from interactive accents.
|
|
621
|
+
For example, to customize the logo background while retaining brand hue:
|
|
622
|
+
|
|
623
|
+
```ts
|
|
624
|
+
theme: {
|
|
625
|
+
brand: { from: "#315efb" },
|
|
626
|
+
palette: {
|
|
627
|
+
"logo-surface": {
|
|
628
|
+
base: "logo-mark",
|
|
629
|
+
tone: 40,
|
|
630
|
+
saturation: 0.8,
|
|
631
|
+
mode: "fixed",
|
|
632
|
+
contrast: { wcag: [3, 4.5] },
|
|
633
|
+
},
|
|
634
|
+
"logo-mark": { tone: 100, saturation: 0, mode: "fixed" },
|
|
635
|
+
},
|
|
636
|
+
}
|
|
637
|
+
```
|
|
638
|
+
|
|
639
|
+
Custom image assets keep their authored colors; use `light`/`dark` files when
|
|
640
|
+
you want distinct artwork. Header and drawer home links center logos with the
|
|
641
|
+
site title regardless of their aspect ratio. Use `theme.styles.SiteLogo` for
|
|
642
|
+
image size and `theme.styles.StarlightHeader.SiteTitle` / `Sidebar.HomeLink`
|
|
643
|
+
for typography; they do not need baseline offsets for a different preset.
|
|
644
|
+
|
|
645
|
+
### Advanced site title markup
|
|
491
646
|
|
|
492
647
|
To put your own logo and title in one home link, create
|
|
493
648
|
`docs/components/site-title.ts`:
|
|
@@ -541,20 +696,20 @@ const { siteTitle, siteTitleHref } = Astro.locals.starlightRoute;
|
|
|
541
696
|
</SiteTitleRoot>
|
|
542
697
|
```
|
|
543
698
|
|
|
544
|
-
Register the replacement in `docs.config.ts` and
|
|
699
|
+
Register the replacement in `docs.config.ts` and disable the shared mark.
|
|
700
|
+
A `SiteTitle` override affects the header; use `site.logo` above for ordinary
|
|
701
|
+
branding shared with the drawer. For custom drawer markup, override `Sidebar`.
|
|
545
702
|
The custom component supports root styles plus its complete list of named
|
|
546
703
|
sub-elements: `Logo` and `Label`.
|
|
547
704
|
|
|
548
705
|
```ts
|
|
706
|
+
site: { logo: false },
|
|
549
707
|
components: {
|
|
550
708
|
overrides: {
|
|
551
709
|
SiteTitle: "./docs/components/SiteTitle.astro"
|
|
552
710
|
}
|
|
553
711
|
},
|
|
554
712
|
theme: {
|
|
555
|
-
styles: {
|
|
556
|
-
StarlightHeader: { LogoLink: { hide: true } }
|
|
557
|
-
},
|
|
558
713
|
customStyles: {
|
|
559
714
|
ProjectSiteTitle: { Logo: { color: "#text" } }
|
|
560
715
|
}
|
|
@@ -738,8 +893,264 @@ left-aligned navigation links with a `1bw` gap, without primary button variants.
|
|
|
738
893
|
`HeaderLinks.PanelLink` styles the menu rows; `FirstPanelLink` reserves space
|
|
739
894
|
for the close button. The inset divider above the tabs belongs to `TopNavigation`.
|
|
740
895
|
|
|
741
|
-
The table of contents is hidden below 72rem
|
|
742
|
-
`
|
|
743
|
-
|
|
896
|
+
The desktop table of contents is hidden below 72rem. Set
|
|
897
|
+
`tableOfContents: { mobile: true }` to show an optional compact disclosure there.
|
|
898
|
+
`MobileTableOfContents` owns its summary and links; `TableOfContentsLayout`
|
|
899
|
+
controls placement. `Layout` controls shared
|
|
744
900
|
navigation dimensions and the drawer's scroll lock; `PageFrame` styles the
|
|
745
901
|
page container and content columns.
|
|
902
|
+
|
|
903
|
+
### Header control shape
|
|
904
|
+
|
|
905
|
+
Header buttons and the mobile drawer close button use the independent
|
|
906
|
+
`$header-control-radius` token, which defaults to `999px` for pill and circular
|
|
907
|
+
shapes. Set it to `8px` for the same corners as the default content controls:
|
|
908
|
+
|
|
909
|
+
```ts
|
|
910
|
+
theme: {
|
|
911
|
+
tokens: { "$header-control-radius": "8px" }
|
|
912
|
+
}
|
|
913
|
+
```
|
|
914
|
+
|
|
915
|
+
`$radius` continues to control code-copy buttons, navigation items, and other
|
|
916
|
+
content controls. Individual `theme.styles` overrides still take precedence.
|
|
917
|
+
The mobile header divider spans the viewport while its content keeps the
|
|
918
|
+
configured horizontal padding.
|
|
919
|
+
|
|
920
|
+
### Add palette colors and reference other roles
|
|
921
|
+
|
|
922
|
+
Every `theme.palette` entry participates in one Glaze color graph. Use lowercase
|
|
923
|
+
names with hyphens; a role named `review-panel` becomes the Tasty token
|
|
924
|
+
`#review-panel`. Declaration order does not matter. References can target custom
|
|
925
|
+
colors or built-in roles, including header, border, overlay, and syntax colors.
|
|
926
|
+
|
|
927
|
+
```ts
|
|
928
|
+
theme: {
|
|
929
|
+
brand: { from: "#315efb" },
|
|
930
|
+
palette: {
|
|
931
|
+
"review-ink": {
|
|
932
|
+
base: "review-panel",
|
|
933
|
+
tone: [4, 0],
|
|
934
|
+
saturation: 0.05,
|
|
935
|
+
contrast: { wcag: [7, 10] },
|
|
936
|
+
},
|
|
937
|
+
"review-panel": { base: "surface", tone: "-2", saturation: 0.05 },
|
|
938
|
+
},
|
|
939
|
+
styles: {
|
|
940
|
+
Callout: { fill: "#review-panel", color: "#review-ink" },
|
|
941
|
+
},
|
|
942
|
+
},
|
|
943
|
+
```
|
|
944
|
+
|
|
945
|
+
Relative and absolute declarations inherit the brand's hue and saturation.
|
|
946
|
+
Use saturation factors from `0` (neutral) to `1` (full seed saturation), and
|
|
947
|
+
`hue` to choose a different hue. All roles resolve for light, dark, and both
|
|
948
|
+
high-contrast modes. Configuration diagnostics and rendering use the same graph.
|
|
949
|
+
Missing references and cycles fail with the color name; layered configurations
|
|
950
|
+
resolve references after merging.
|
|
951
|
+
|
|
952
|
+
`textSoft` remains an alias for `text-soft`. Use either spelling, but do not
|
|
953
|
+
configure both. The names `current`, `constructor`, and `prototype` are reserved.
|
|
954
|
+
Declaring a built-in name intentionally overrides that role; use a project
|
|
955
|
+
prefix for additional roles to avoid future naming collisions.
|
|
956
|
+
|
|
957
|
+
When a status role such as `info` uses a mix or shadow definition, its derived
|
|
958
|
+
`info-text` defaults to neutral, contrast-corrected text. Override `info-text`
|
|
959
|
+
explicitly for a colored label; the mix/shadow dependency graph stays intact.
|
|
960
|
+
A shadow status also uses a neutral derived surface, because Glaze does not allow
|
|
961
|
+
a shadow to be a mix target. Override the surface separately when needed.
|
|
962
|
+
|
|
963
|
+
### Register units and recipes
|
|
964
|
+
|
|
965
|
+
Register custom units and flat recipes in `theme`; Cookbook configures Tasty
|
|
966
|
+
before evaluating your components:
|
|
967
|
+
|
|
968
|
+
```ts
|
|
969
|
+
theme: {
|
|
970
|
+
brand: { from: "#315efb" },
|
|
971
|
+
palette: {
|
|
972
|
+
"review-panel": { base: "surface", tone: "-2", saturation: 0.05 },
|
|
973
|
+
"review-ink": { base: "review-panel", tone: 0, contrast: { wcag: [7, 10] } },
|
|
974
|
+
},
|
|
975
|
+
units: { rh: "6px" },
|
|
976
|
+
recipes: {
|
|
977
|
+
"review-panel": {
|
|
978
|
+
fill: "#review-panel",
|
|
979
|
+
color: "#review-ink",
|
|
980
|
+
padding: "2rh",
|
|
981
|
+
radius: "3px",
|
|
982
|
+
},
|
|
983
|
+
},
|
|
984
|
+
customStyles: { DemoBadge: { Label: { color: "#review-ink" } } },
|
|
985
|
+
},
|
|
986
|
+
```
|
|
987
|
+
|
|
988
|
+
```ts
|
|
989
|
+
import { defineComponent } from "@tenphi/cookbook/styling";
|
|
990
|
+
|
|
991
|
+
export const DemoBadge = defineComponent("DemoBadge", {
|
|
992
|
+
as: "aside",
|
|
993
|
+
elements: { Label: "strong" },
|
|
994
|
+
styles: {
|
|
995
|
+
display: "block",
|
|
996
|
+
recipe: "review-panel",
|
|
997
|
+
Label: { preset: "h4" },
|
|
998
|
+
},
|
|
999
|
+
});
|
|
1000
|
+
```
|
|
1001
|
+
|
|
1002
|
+
Use `<DemoBadge><DemoBadge.Label>Review ready</DemoBadge.Label></DemoBadge>` in
|
|
1003
|
+
MDX. Keep these styled components server-rendered: their CSS is extracted at
|
|
1004
|
+
build time. Add behavior with a small client script targeting the rendered
|
|
1005
|
+
markup. This recipe produces 12px padding. Units merge by name, with the later
|
|
1006
|
+
configuration winning. Recipes merge using Tasty `mergeStyles`, including state
|
|
1007
|
+
maps. Recipes are flat: define named sub-elements on the owning component, and
|
|
1008
|
+
compose recipes with `recipe: "base elevated"` rather than referencing a recipe
|
|
1009
|
+
inside another recipe. `none` is a reserved recipe name. Cookbook's built-in
|
|
1010
|
+
units are `x`, `r`, `cr`, and `bw`; overriding one changes its meaning globally.
|
|
1011
|
+
|
|
1012
|
+
Keep editor and linter validation synchronized with your configuration:
|
|
1013
|
+
|
|
1014
|
+
```ts
|
|
1015
|
+
// tasty.config.ts
|
|
1016
|
+
import { createValidationConfig } from "@tenphi/cookbook/eslint-plugin";
|
|
1017
|
+
import docs from "./docs.config";
|
|
1018
|
+
export default createValidationConfig(docs.theme);
|
|
1019
|
+
```
|
|
1020
|
+
|
|
1021
|
+
### Configure Glaze adaptation
|
|
1022
|
+
|
|
1023
|
+
`theme.glaze` accepts `lightTone`, `darkTone`, `darkDesaturation`, `autoFlip`,
|
|
1024
|
+
`pastel`, `inferRole`, and `shadowTuning`. Tone windows accept `[lo, hi]`, `false`
|
|
1025
|
+
for the full range, or the advanced `{ lo, hi, eps }` form. Continue to use
|
|
1026
|
+
`theme.contrastLevel` for manual contrast interpolation. Cookbook always emits
|
|
1027
|
+
all four appearance variants.
|
|
1028
|
+
|
|
1029
|
+
```ts
|
|
1030
|
+
theme: {
|
|
1031
|
+
glaze: { lightTone: [10, 100], darkTone: [15, 95] },
|
|
1032
|
+
palette: {
|
|
1033
|
+
"accent-surface-subtle": {
|
|
1034
|
+
type: "mix", base: "surface", target: "accent-surface", value: [12, 20],
|
|
1035
|
+
},
|
|
1036
|
+
shadow: {
|
|
1037
|
+
type: "shadow", bg: "surface", fg: "text", intensity: [12, 24],
|
|
1038
|
+
tuning: { alphaMax: 0.3 },
|
|
1039
|
+
},
|
|
1040
|
+
},
|
|
1041
|
+
},
|
|
1042
|
+
```
|
|
1043
|
+
|
|
1044
|
+
Palette roles accept Glaze's regular, mix, and shadow declarations. Mix and
|
|
1045
|
+
shadow references use the same graph as other roles. Native Glaze restrictions
|
|
1046
|
+
still apply, including the requirement for shadow backgrounds and foregrounds
|
|
1047
|
+
to reference non-shadow colors. `shadowTuning` exposes `saturationFactor`,
|
|
1048
|
+
`maxSaturation`, `lightnessFactor`, `lightnessBounds`, `minGapTarget`, `alphaMax`,
|
|
1049
|
+
and `bgHueBlend`; a role's own `tuning` takes precedence.
|
|
1050
|
+
|
|
1051
|
+
### Built-in palette inventory
|
|
1052
|
+
|
|
1053
|
+
Every generated role below can be overridden in `theme.palette`. Names map
|
|
1054
|
+
directly to Tasty `#name` tokens. `COOKBOOK_PALETTE_NAMES`, exported from
|
|
1055
|
+
`@tenphi/docs`, lists the same roles for tooling.
|
|
1056
|
+
|
|
1057
|
+
| Area | Roles |
|
|
1058
|
+
| ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
1059
|
+
| Surfaces | `surface`, `header`, `overlay`, `surface-2`, `surface-3`, `surface-2-hover`, `surface-2-pressed`, `surface-3-hover`, `surface-3-pressed` |
|
|
1060
|
+
| Reading | `text`, `heading`, `text-soft` (alias `textSoft`), `text-muted` |
|
|
1061
|
+
| Brand and focus | `accent-text`, `accent-surface`, `accent-surface-text`, `accent-surface-subtle`, `accent-surface-2-subtle`, `logo-surface`, `logo-mark`, `focus` |
|
|
1062
|
+
| Borders and effects | `border`, `border-strong`, `shadow`, `clear` |
|
|
1063
|
+
| Status | `info`, `success`, `warning`, `danger`, each with `-text` and `-surface` variants |
|
|
1064
|
+
| Additional hues | `orange`, `green`, `blue`, `purple`, `red`, each with `-text` and `-surface` variants |
|
|
1065
|
+
| Syntax | `syntax-bg`, `syntax-text`, `syntax-comment`, `syntax-punctuation`, `syntax-keyword`, `syntax-string`, `syntax-token`, `syntax-property`, `syntax-number`, `syntax-function`, `syntax-value`, `syntax-operator` |
|
|
1066
|
+
|
|
1067
|
+
## Contrast checks and troubleshooting
|
|
1068
|
+
|
|
1069
|
+
Cookbook checks text, headings, muted reading text, brand links, filled-control
|
|
1070
|
+
labels, status text on its tinted surface, focus rings on each elevated
|
|
1071
|
+
surface, and every palette declaration with a contrast floor. The same Glaze
|
|
1072
|
+
resolution powers rendering and `cookbook doctor`, in light, dark, and both
|
|
1073
|
+
high-contrast modes. Manual `theme.contrastLevel` targets interpolate with
|
|
1074
|
+
Glaze's contrast level.
|
|
1075
|
+
|
|
1076
|
+
`resolveDocsTheme(theme).contrastChecks` lists each foreground/background pair,
|
|
1077
|
+
mode, metric, target, measured value, and pass result. APCA uses display-channel
|
|
1078
|
+
luminance; WCAG ratios use the sRGB transfer function. Transparent foregrounds
|
|
1079
|
+
are composited onto their background before measuring. These checks cover
|
|
1080
|
+
Cookbook's semantic pairs; test actual pages after changing component styles,
|
|
1081
|
+
backgrounds, typography, or layout.
|
|
1082
|
+
|
|
1083
|
+
A `DOCS_SEMANTIC_CONTRAST_UNMET` or `DOCS_BRAND_CONTRAST_UNMET` error names the
|
|
1084
|
+
pair, mode, and required target. Adjust that pair's `theme.palette` declarations:
|
|
1085
|
+
use an absolute tone for reading text, reduce saturation when needed, and keep
|
|
1086
|
+
`autoFlip` enabled when the solver needs to cross its base. A fixed middle-tone
|
|
1087
|
+
button fill may make its label's contrast impossible. Cookbook's default
|
|
1088
|
+
brand fill adapts to avoid this, including for orange, yellow, and pale brands.
|
|
1089
|
+
Focus uses a WCAG 3:1 floor (4.5:1 in high contrast) against the surface ramp.
|
|
1090
|
+
|
|
1091
|
+
Keep contrast requirements when adjusting colors. Extreme custom tone windows,
|
|
1092
|
+
fixed colors, or opacity can prevent a requested floor from being met. A palette
|
|
1093
|
+
check does not replace keyboard, screen-reader, and rendered-page testing.
|
|
1094
|
+
|
|
1095
|
+
## Customize shared page surfaces
|
|
1096
|
+
|
|
1097
|
+
Each bridge has a complete base style tree; supply only the properties you
|
|
1098
|
+
want to change. Sub-elements keep their selectors and all other defaults.
|
|
1099
|
+
For example, a compact search dialog and quieter pagination need no CSS:
|
|
1100
|
+
|
|
1101
|
+
```ts
|
|
1102
|
+
theme: {
|
|
1103
|
+
styles: {
|
|
1104
|
+
Search: { Dialog: { inlineSize: "max 32rem" } },
|
|
1105
|
+
SearchResults: { ResultLink: { color: "#accent-text" } },
|
|
1106
|
+
Pagination: { Link: { padding: "1.5x", fill: "#surface" } },
|
|
1107
|
+
Banner: { padding: "1x 2x" },
|
|
1108
|
+
Markdown: { Quote: { color: "#text", inlinePadding: "3x start" } },
|
|
1109
|
+
},
|
|
1110
|
+
}
|
|
1111
|
+
```
|
|
1112
|
+
|
|
1113
|
+
`Document` owns resets, base typography, generic controls, responsive media,
|
|
1114
|
+
and accessibility utilities. `MainPane` and `MainContent` own the content
|
|
1115
|
+
layout. `Markdown` owns prose, lists, links, quotations, and disclosure
|
|
1116
|
+
anatomy. `Search` owns the dialog; `SearchResults` owns the Pagefind UI.
|
|
1117
|
+
The `Starlight*` trees style compatible upstream component markup; Cookbook's
|
|
1118
|
+
own `Card`, `Callout`, and `Steps` use their respective trees.
|
|
1119
|
+
|
|
1120
|
+
Custom components created with `defineComponent()` receive `theme.customStyles`
|
|
1121
|
+
overrides during server rendering. Units, recipes, states, and presets are
|
|
1122
|
+
resolved there and emitted as static CSS. Cookbook ships no Tasty/Glaze browser
|
|
1123
|
+
runtime, theme configuration, or style hydration setup. Browser scripts and
|
|
1124
|
+
`client:*` islands must not import Cookbook styling, Tasty, or Glaze; the build
|
|
1125
|
+
rejects these imports. Attach small interaction scripts to server-rendered markup
|
|
1126
|
+
or pass already-styled static markup into a client island.
|
|
1127
|
+
|
|
1128
|
+
Code fences and `CodeGroup` use the same `MarkdownCodeBlock` style tree. Its
|
|
1129
|
+
root `$copy-button-size` defaults to `2rem`; the copy control and vertical
|
|
1130
|
+
padding share it, keeping equal top, right, and bottom insets on one-line
|
|
1131
|
+
snippets. The padding follows the `code` preset's line height. Override it with
|
|
1132
|
+
`theme.styles.MarkdownCodeBlock` when changing the control size or code layout.
|
|
1133
|
+
|
|
1134
|
+
### Syntax highlighting and isolated previews
|
|
1135
|
+
|
|
1136
|
+
Shiki classifies code; Tasty renders every token using Glaze's semantic syntax
|
|
1137
|
+
colors. Customize token rules with `theme.styles.SyntaxHighlight`, or their
|
|
1138
|
+
colors with `theme.palette` (for example `syntax-keyword`). Code fences, including
|
|
1139
|
+
MDX and diff blocks, use classes without inline style attributes. Custom Shiki
|
|
1140
|
+
transformers should emit classes; unsupported inline declarations fail with a
|
|
1141
|
+
configuration hint.
|
|
1142
|
+
|
|
1143
|
+
The production build rejects style attributes, style blocks (including inside
|
|
1144
|
+
shadow-root templates), and non-Tasty stylesheets throughout documentation HTML.
|
|
1145
|
+
It parses actual markup, so escaped examples and strings in scripts are allowed.
|
|
1146
|
+
The explicit exception is the separate document in a sandboxed `Preview` iframe;
|
|
1147
|
+
it cannot access its parent's origin. Configure its size with
|
|
1148
|
+
`theme.styles.Preview.Frame`. The documentation shell supports the CSP directive
|
|
1149
|
+
`style-src-attr 'none'`. A host's CSP may also restrict the preview document; when
|
|
1150
|
+
using that directive, authored previews must use style blocks rather than style
|
|
1151
|
+
attributes.
|
|
1152
|
+
|
|
1153
|
+
Search uses an owned, keyboard-accessible dialog with Pagefind's indexing and
|
|
1154
|
+
results UI. Its clear-button sizing is adapted to `SearchResults.Input` styles,
|
|
1155
|
+
so the browser does not need inline layout declarations. The adapter is checked
|
|
1156
|
+
against the pinned Pagefind UI version during builds.
|