@tenphi/cookbook 0.28.0 → 0.30.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.
Files changed (54) hide show
  1. package/README.md +13 -11
  2. package/dist/index.d.ts +2 -2
  3. package/dist/index.js +2 -2
  4. package/docs/ai-agents.md +5 -3
  5. package/docs/architecture.md +10 -7
  6. package/docs/authoring.mdx +94 -36
  7. package/docs/cli.md +92 -33
  8. package/docs/component-styles.md +286 -282
  9. package/docs/configuration.md +232 -153
  10. package/docs/content-sources.md +39 -21
  11. package/docs/custom-components.md +117 -169
  12. package/docs/customization-rules.md +23 -14
  13. package/docs/deployment.md +101 -53
  14. package/docs/es/getting-started.md +7 -5
  15. package/docs/es/index.md +1 -1
  16. package/docs/examples.md +65 -28
  17. package/docs/fonts-and-typography.md +32 -27
  18. package/docs/getting-started.md +17 -10
  19. package/docs/ja/getting-started.md +7 -5
  20. package/docs/ja/index.md +1 -1
  21. package/docs/migration.md +188 -65
  22. package/docs/plugins.md +28 -16
  23. package/docs/publishing.md +3 -2
  24. package/docs/quality-checks.md +18 -42
  25. package/docs/recipes.md +38 -54
  26. package/docs/ru/getting-started.md +7 -5
  27. package/docs/ru/index.md +1 -1
  28. package/docs/site-navigation.md +47 -47
  29. package/docs/theme-and-components.md +126 -59
  30. package/docs/troubleshooting.md +4 -3
  31. package/docs/upstream/manifest.json +2 -2
  32. package/docs/upstream/tasty/README.md +404 -381
  33. package/docs/upstream/tasty/docs/README.md +4 -1
  34. package/docs/upstream/tasty/docs/adoption.md +25 -17
  35. package/docs/upstream/tasty/docs/ai-agents.md +42 -34
  36. package/docs/upstream/tasty/docs/comparison.md +9 -8
  37. package/docs/upstream/tasty/docs/configuration.md +187 -69
  38. package/docs/upstream/tasty/docs/debug.md +3 -2
  39. package/docs/upstream/tasty/docs/design-system.md +117 -15
  40. package/docs/upstream/tasty/docs/dsl.md +211 -117
  41. package/docs/upstream/tasty/docs/getting-started.md +81 -24
  42. package/docs/upstream/tasty/docs/injector.md +41 -40
  43. package/docs/upstream/tasty/docs/methodology.md +46 -21
  44. package/docs/upstream/tasty/docs/migration-v3.md +3 -3
  45. package/docs/upstream/tasty/docs/pipeline.md +111 -116
  46. package/docs/upstream/tasty/docs/plugins.md +21 -41
  47. package/docs/upstream/tasty/docs/react-api.md +73 -10
  48. package/docs/upstream/tasty/docs/runtime-benchmarks.md +46 -46
  49. package/docs/upstream/tasty/docs/ssr.md +92 -66
  50. package/docs/upstream/tasty/docs/styles.md +37 -17
  51. package/docs/upstream/tasty/docs/tasty-static.md +175 -57
  52. package/docs/zh/getting-started.md +7 -5
  53. package/docs/zh/index.md +1 -1
  54. package/package.json +3 -3
@@ -2,58 +2,22 @@
2
2
  title: Component styles
3
3
  description: Customize built-in UI surfaces through partial Tasty style objects and named sub-elements.
4
4
  ---
5
- For color roles and design tokens, start with the
5
+ Change Cookbook's built-in interface through `theme.styles`. Each surface has a
6
+ public name, such as `Sidebar` or `SearchResults`, and named parts, such as
7
+ `Sidebar.LinkLabel`. This page explains how overrides merge, lists every name
8
+ and part, and describes the shared states you can use in style maps. For color
9
+ roles and design tokens, start with the
6
10
  [theme overview](./theme-and-components.md). For your own components, see
7
11
  [Custom components](./custom-components.md).
8
12
 
9
- Owned markup uses Tasty's built-in `data-element` identities for its named parts.
10
- For example, Header's `Logo` styles target `data-element="Logo"` directly;
11
- no anatomy class or separate marker is required. A configured image logo owns
12
- its dimensions under `SiteLogo`.
13
-
14
- Heading levels are states of the same element. Customize them through a root
15
- property map such as `Heading: { textWrap: { "": "balance", ":is(h1)": "pretty" } }`.
16
- Markdown heading wrappers use `level=h1` through `level=h6` as root states.
17
-
18
- Block spacing uses `$margin-block-start` and `$margin-block-end` tokens. The
19
- owning `blockMargin` consumes both tokens, and a surrounding prose/layout rule
20
- changes only the start token. For example, `Callout: { "$margin-block-end": "3x" }`
21
- changes the end spacing while retaining Markdown's spacing before the callout.
22
- Document foundations reset these tokens on every element to prevent inheritance
23
- into nested content. For content-panel padding, use `MainContent.Panel`'s
24
- `$padding-block-start` and `$padding-block-end` tokens in the same way.
25
-
26
13
  ## Style customization
27
14
 
28
- Cookbook-owned interface elements use `defineComponent()` to create Tasty components
29
- and merge their named theme overrides. Shared bases use `extendComponent()`.
30
- Cookbook components and generated Markdown surfaces use Tasty style trees.
31
- Customize them by name under `theme.styles`; the configuration is resolved
32
- before CSS generation, so this is not a selector-based CSS override.
33
-
34
- Cookbook merges your partial style object with the component's base styles
35
- before Tasty extracts CSS. The generated stylesheet contains the resolved
36
- style, so you can change an element without copying its full defaults.
37
-
38
- Each surface is registered by its owning component or generated-content bridge.
39
- Fonts and document defaults belong to the page shell, so replacing Header
40
- preserves the rest of the site's styling. Component-specific CSS is collected
41
- when its owner renders. See [Component ownership](./architecture.md#component-ownership)
42
- for the renderer authoring convention.
43
-
44
- Start with the area you want to change, then use the complete sub-element
45
- inventory below to find its exact anatomy:
46
-
47
- | Page area | Style names to inspect |
48
- | ----------------------------- | ------------------------------------------------------------------------------------ |
49
- | Header, title, and navigation | `HeaderFrame`, `Header`, `SiteLogo`, `HeaderLinks`, `TopNavigation` |
50
- | Sidebar and mobile menu | `Sidebar`, `MobileMenuToggle`, `MobileNavigationTabs`, `MobileMenuFooter` |
51
- | Article text and headings | `Markdown`, `MarkdownHeading`, `Heading`, `MainContent` |
52
- | Code and diagrams | `MarkdownCodeBlock`, `MarkdownInlineCode`, `SyntaxHighlight`, `CodeGroup`, `Mermaid` |
53
- | Search | `SearchButton`, `Search`, `SearchResults` |
54
- | Table of contents | `TableOfContents`, `MobileTableOfContents`, `TableOfContentsLayout` |
55
- | Cards, notes, and tabs | `Card`, `Callout`, `MarkdownAlert`, `Tabs` |
56
- | Footer and page controls | `Footer`, `Pagination`, `PageActions`, `ThemeSelect` |
15
+ Supply a partial Tasty style object under `theme.styles.<ComponentName>`.
16
+ Cookbook merges it into that component's complete base style object before
17
+ Tasty extracts CSS, so the generated stylesheet contains the resolved style.
18
+ This is not a selector-based CSS override: you change an element without
19
+ copying its full defaults, adding a second stylesheet, or using `!important`.
20
+ No merge helper or base style object is required in user configuration.
57
21
 
58
22
  For example, this changes a typography role and one named element without
59
23
  copying a component's full style tree:
@@ -77,11 +41,141 @@ tokens and presets keep the component aligned with the rest of the site, while
77
41
  Glaze resolves semantic colors across the configured schemes and contrast
78
42
  modes.
79
43
 
44
+ Root properties customize each surface's container. Overriding
45
+ `Sidebar.LinkLabel.whiteSpace` keeps the other base `LinkLabel` properties
46
+ because the configured object is merged. See
47
+ [state maps](#state-maps-and-validation) for how conditional values merge.
48
+
49
+ Built-in names belong in `theme.styles`, which rejects unknown names and
50
+ misspelled sub-elements. Register your own components in `theme.customStyles`;
51
+ the name must match the string passed to `defineComponent()`,
52
+ `extendComponent()`, or `resolveComponentStyles()`. A production build warns
53
+ when a configured custom name has no matching component style resolver.
54
+ `components.overrides` remains the structural escape hatch for replacing an
55
+ Astro component; prefer `theme.styles` when the markup and behavior stay the
56
+ same. Fonts and document defaults belong to the page shell, so replacing
57
+ `Header` keeps the rest of the site's styling.
58
+
59
+ ### Find the right name
60
+
61
+ Start with the area you want to change, then use the
62
+ [complete component anatomy](#complete-component-anatomy) to find its exact
63
+ parts:
64
+
65
+ | Page area | Style names to inspect |
66
+ | ----------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
67
+ | Header, title, and navigation | `HeaderFrame`, `Header`, `SiteLogo`, `HeaderLinks`, `TopNavigation`, `LanguageSelect`, `VersionSwitcher`, `SocialIcons` |
68
+ | Sidebar and mobile menu | `Sidebar`, `MobileMenuToggle`, `MobileNavigationTabs`, `MobileMenuFooter` |
69
+ | Article text and headings | `Markdown`, `MarkdownHeading`, `MarkdownTable`, `Heading`, `MainContent`, `Banner` |
70
+ | Code and diagrams | `MarkdownCodeBlock`, `MarkdownInlineCode`, `SyntaxHighlight`, `CodeGroup`, `Mermaid` |
71
+ | Search | `SearchButton`, `Search`, `SearchResults` |
72
+ | Table of contents | `TableOfContents`, `MobileTableOfContents`, `TableOfContentsLayout` |
73
+ | Cards, notes, and tabs | `Card`, `Callout`, `MarkdownAlert`, `Tabs`, `Tab`, `Steps`, `Preview` |
74
+ | Home page hero | `Hero` |
75
+ | Page layout | `PageFrame`, `Layout`, `MainPane` |
76
+ | Footer and page controls | `Footer`, `Pagination`, `PageActions`, `ThemeSelect` |
77
+
78
+ Owned markup uses Tasty's built-in `data-element` identities for its named
79
+ parts. For example, Header's `Logo` styles target `data-element="Logo"`
80
+ directly; no anatomy class or separate marker is required. A configured image
81
+ logo owns its dimensions under `SiteLogo`. `SocialIcons` styles the shared
82
+ icon-button links in the header and mobile menu, and `ThemeSelect` styles the
83
+ combined Appearance panel.
84
+
85
+ ### Complete component anatomy
86
+
87
+ Every configurable surface accepts styles at the root plus the named Tasty
88
+ sub-elements below. The list is generated from the public component registry so
89
+ it stays complete when a surface changes.
90
+
91
+ <!-- component-anatomy:start -->
92
+
93
+ #### Page shell
94
+
95
+ * `Document`: `All`, `BlockSpacing`, `Body`, `Control`, `Pointer`, `ResponsiveWidth`, `ResponsiveHeight`, `Hidden`, `PrintHidden`, `DesktopBlock`, `DesktopFlex`, `ScreenReaderOnly`, `RouteAnnouncer`, `Strong`, `Link`, `NarrowBlock`, `MobileBlock`, `Code`, `FocusRing`, `CurrentLink`, `SearchOpen`
96
+ * `Layout`: `Islands`
97
+ * `PageFrame`: `MainFrame`, `SidebarFrame`, `Columns`
98
+ * `MainPane`: None
99
+ * `MainContent`: `ContentSpacing`, `Container`, `Panel`
100
+ * `HeaderFrame`: None
101
+ * `Heading`: None
102
+ * `Banner`: `Link`
103
+ * `SkipLink`: None
104
+
105
+ #### Navigation and controls
106
+
107
+ * `Header`: `Primary`, `Title`, `LogoLink`, `Logo`, `SiteTitle`, `Search`, `SearchElement`, `Tools`, `Social`, `MobileTheme`, `MobileLanguage`
108
+ * `HeaderLinks`: `Desktop`, `DesktopLink`, `Link`, `HoverLink`, `PrimaryLink`, `HoverPrimaryLink`, `Trigger`, `HoverTrigger`, `Panel`, `OpenPanel`, `PanelNavigation`, `PanelLink`, `FirstPanelLink`, `Close`, `HoverClose`
109
+ * `SearchButton`: `PendingShortcut`, `Label`, `Shortcut`, `NativeIcon`, `Icon`
110
+ * `Button`: None
111
+ * `Sidebar`: `Backdrop`, `OpenBackdrop`, `MobileHeading`, `HomeLink`, `HomeLogo`, `HomeLabel`, `Close`, `HoverClose`, `CloseIcon`, `CurrentLink`, `Content`, `Tree`, `List`, `Item`, `TopLevelSpacing`, `GroupSpacing`, `NestedItem`, `SectionHeading`, `Control`, `Summary`, `GroupLabel`, `GroupLabelText`, `Link`, `LinkLabel`, `InteractiveControl`, `SummaryMarker`, `Caret`, `ExpandedCaret`, `LinkedSummary`, `GroupLink`, `LinkedSectionHeading`, `SectionLink`, `Badge`, `TopLevelLink`
112
+ * `MobileMenuToggle`: `Icon`, `Section`, `Page`
113
+ * `MobileNavigationTabs`: `Trigger`, `Marker`, `Caret`, `ExpandedCaret`, `Label`, `List`, `Item`, `Link`, `HoverLink`, `CurrentLink`
114
+ * `MobileMenuFooter`: `Social`
115
+ * `TopNavigation`: `Scrollbar`, `Link`, `HoverLink`, `CurrentLink`, `ActiveIndicator`
116
+ * `TableOfContentsLayout`: `Content`
117
+ * `TableOfContents`: `Heading`, `List`, `Item`, `Link`, `LinkLabel`, `HoverLink`, `CurrentLink`
118
+ * `MobileTableOfContents`: `Summary`, `List`, `NestedList`, `Item`, `Link`, `HoverLink`, `Focus`
119
+ * `Pagination`: `Link`, `PreviousLink`, `NextLink`, `NextIcon`, `NextLabel`, `HoverLink`, `ActiveLink`, `Title`, `LoneNextLink`, `Icon`, `PreviousIconRtl`, `NextIconRtl`
120
+ * `VersionSwitcher`: `Trigger`, `HoverTrigger`, `TriggerLabel`, `Caret`, `Panel`, `OpenPanel`, `PanelTitle`, `Options`, `Link`, `HoverLink`, `CurrentLink`, `Checkmark`, `SelectedCheckmark`
121
+ * `LanguageSelect`: `Trigger`, `HoverTrigger`, `ActiveTrigger`, `LabelIcon`, `TriggerLabel`, `Caret`, `CompactTrigger`, `CompactLabel`, `CompactCaret`, `Label`, `HoverLabel`, `Select`, `CompactSelect`, `CompactLabelIcon`, `SidebarTrigger`, `Panel`, `SidebarPanel`, `OpenPanel`, `PanelTitle`, `Options`, `Option`, `HoverOption`, `CurrentOption`, `Fallback`, `Checkmark`, `SelectedCheckmark`
122
+ * `SocialIcons`: `Link`, `HoverLink`, `Icon`
123
+ * `ThemeSelect`: `Trigger`, `HoverTrigger`, `ActiveTrigger`, `Icon`, `Panel`, `OpenPanel`, `Section`, `SectionSpacing`, `SectionLabel`, `Option`, `HoverOption`, `CheckedOption`, `FocusedOption`, `Input`, `OptionIcon`, `Checkmark`, `SelectedCheckmark`
124
+
125
+ #### Rendered content
126
+
127
+ * `Markdown`: `Block`, `BlockSpacing`, `HeadingSpacing`, `List`, `CompactItem`, `ListItem`, `DefinitionTerm`, `DefinitionDescription`, `Link`, `HoverLink`, `Quote`, `Rule`, `Details`, `HoverDetails`, `Summary`, `OpenSummary`, `SummaryMarker`, `SummaryIcon`, `OpenSummaryIcon`, `Code`
128
+ * `MarkdownHeading`: `Heading`, `Link`, `RevealedLink`, `HoverLink`, `LinkIcon`, `CopiedLink`, `CopiedLinkIcon`, `CopiedIcon`
129
+ * `MarkdownCodeBlock`: `Pre`, `CopyButton`, `HoverCopyButton`, `CopiedButton`, `CopyIcon`, `CopiedIcon`, `Code`, `Diff`, `DiffCode`, `DiffLine`, `EmptyDiffLine`, `InsertedLine`, `DeletedLine`
130
+ * `MarkdownInlineCode`: None
131
+ * `MarkdownTable`: `Table`, `Cell`, `LastBodyRowCell`, `HeaderCell`, `Scroll`
132
+ * `MarkdownAlert`: `Title`, `FirstContent`
133
+ * `SyntaxHighlight`: `Marker`, `Comment`, `Punctuation`, `Keyword`, `String`, `Token`, `Property`, `Number`, `Function`, `Value`, `Operator`, `Text`, `Bg`, `Inserted`, `Deleted`, `Italic`, `Strong`, `Underline`
134
+ * `Mermaid`: `Diagram`, `Text`, `MonoText`
135
+ * `MermaidSource`: None
136
+
137
+ #### Authoring components
138
+
139
+ * `Card`: `Heading2`, `Heading3`, `Paragraph`
140
+ * `Callout`: `Title`, `Body`
141
+ * `CodeGroup`: `Caption`, `Pre`, `Code`
142
+ * `Tab`: `Heading`, `HiddenHeading`
143
+ * `Tabs`: `List`, `Button`, `SelectedButton`, `FocusedButton`
144
+ * `Steps`: `Item`, `Marker`
145
+ * `Hero`: `Visual`, `DarkVisual`, `LightVisual`, `Stack`, `Copy`, `Title`, `Tagline`, `Actions`, `Action`, `HoverAction`, `PrimaryAction`, `SecondaryAction`, `MinimalAction`, `ActionIcon`
146
+ * `Preview`: `Caption`, `Stage`, `Frame`, `Code`, `Summary`, `HoverSummary`, `ActiveSummary`, `Pre`
147
+ * `SiteLogo`: `Image`, `Light`, `Dark`
148
+ * `Logo`: `Svg`, `Mark`
149
+ * `PageActions`: `Control`, `Hover`, `Focus`, `Pending`, `Status`
150
+ * `Footer`: `Meta`, `MetaLink`, `MetaUpdated`, `Credit`, `CreditLink`
151
+ * `PackageVersion`: None
152
+
153
+ #### Search
154
+
155
+ * `Search`: `Status`, `Dialog`, `CloseIcon`, `OpenDialog`, `EnteredDialog`, `Backdrop`, `EnteredBackdrop`, `Frame`, `Container`, `Close`, `HoverClose`, `ActiveClose`
156
+ * `SearchResults`: `UI`, `Form`, `Field`, `EngineControls`, `Drawer`, `Input`, `Clear`, `Results`, `Result`, `ResultLink`, `SearchIcon`, `ClearIcon`, `SuppressedClear`, `Message`, `List`, `Title`, `Excerpt`, `NestedResult`, `Match`, `More`, `HoverMore`
157
+
158
+ <!-- component-anatomy:end -->
159
+
160
+ For theme editors and other tooling, `@tenphi/cookbook` exports
161
+ `COOKBOOK_COMPONENT_NAMES`, which publishes the
162
+ configuration names and `COOKBOOK_COMPONENT_SUB_ELEMENTS` publishes the
163
+ complete sub-element lists. The corresponding TypeScript types are
164
+ `CookbookComponentName`, `CookbookComponentSubElementName`,
165
+ `CookbookComponentStyles`, `ComponentStyleConfig`, and `ComponentStylesConfig`.
166
+ Known configuration names provide editor suggestions for their named
167
+ sub-elements.
168
+
169
+ ## States in style maps
170
+
171
+ Cookbook registers shared Tasty state aliases for `theme.styles`, custom
172
+ components, and recipes. Use the default state key `""` for the value outside a
173
+ condition.
174
+
80
175
  ### Responsive states
81
176
 
82
- Cookbook registers these Tasty state aliases for `theme.styles`, custom
83
- components, and recipes. Widths use CSS `rem` units; their pixel values depend
84
- on the browser's font-size settings.
177
+ Widths use CSS `rem` units; their pixel values depend on the browser's
178
+ font-size settings.
85
179
 
86
180
  | State | Condition | Typical use |
87
181
  | ----- | ------------- | ---------------------------------------------- |
@@ -94,13 +188,11 @@ pagination, `!@md` for mobile, and `!@lg` when the contents panel does not fit
94
188
  beside the page. Combine states when needed, for example `@md & !@lg` for the
95
189
  intermediate layout. Component-specific
96
190
  thresholds use direct media conditions, such as `@media(w <= 23rem)` for
97
- PackageVersion. Use the default state key `""` for the value outside a condition.
98
- Add your own aliases with `theme.states`; redefining a built-in alias also
191
+ PackageVersion. Add your own aliases with `theme.states`; redefining a built-in alias also
99
192
  changes the renderer's responsive layout, so check the whole site when doing so.
100
193
 
101
- Native pseudo-classes need no alias. Use `:is(:popover-open)` on a root or
102
- `@own(:is(:popover-open))` for a selected descendant; the `:is()` wrapper is
103
- needed because the pinned linter's simple pseudo-class list omits `:popover-open`.
194
+ Native pseudo-classes need no alias. Use `:popover-open` on a root or
195
+ `@own(:popover-open)` for a selected descendant.
104
196
 
105
197
  ### Appearance and motion states
106
198
 
@@ -114,12 +206,23 @@ Use these shared aliases to match the site's appearance or respect motion prefer
114
206
  | `@system-light` | `prefers-color-scheme: light` | Read the system preference directly |
115
207
  | `@system-dark` | `prefers-color-scheme: dark` | Read the system preference directly |
116
208
 
117
- Use `@light` and `@dark` in component styles. They check the page root's
118
- `data-theme` attribute and use the system preference only when that attribute
119
- is absent. Document rules that style the root itself use `@system-light` and
120
- `@system-dark` within their automatic-theme branch. Keep scheme media queries
209
+ Use `@light` and `@dark` in component styles and in document rules that style
210
+ the root itself. They check the page root's `data-theme` attribute and use the
211
+ system preference only when that attribute is absent. Keep scheme media queries
121
212
  in the shared state definitions instead of repeating them in style objects.
122
213
 
214
+ ### Prose states
215
+
216
+ Markdown styles share three conditions that skip elements inside isolated
217
+ sections marked `data-not-content`, while preserving surrounding prose in the
218
+ same Markdown root:
219
+
220
+ | State | Selects |
221
+ | ---------------- | ------------------------------------------------------------------------- |
222
+ | `@prose` | Any selected element outside isolated sections |
223
+ | `@prose-block` | A block that follows block content, including linked Cards (`data-block`) |
224
+ | `@prose-heading` | A heading that follows non-heading content |
225
+
123
226
  ### State maps and validation
124
227
 
125
228
  In a generated site, run `npm run validate` (or the matching package manager's
@@ -141,14 +244,7 @@ selectors, and syntax wrapping. Use Tasty element names such as `Primary > Searc
141
244
  instead of spelling out `[data-element="Primary"] > [data-element="Search"]`.
142
245
  For a state on the owning root, use a plain key: `DiffCode: { display: { "diff": "block" } }`.
143
246
  Use `@own(:first-child)` when a structurally selected link needs its own condition,
144
- instead of repeating its `Panel a` selector. `@prose` uses
145
- `@own(!:is([data-not-content] *))` to exclude selected elements inside isolated
146
- sections while preserving surrounding prose in the same Markdown root.
147
-
148
- Markdown also shares `@prose-block` for a block following block content
149
- (including linked Cards marked `data-block`), and `@prose-heading` for a heading
150
- following non-heading content. Both preserve the same isolated-content condition
151
- as `@prose`.
247
+ instead of repeating its `Panel a` selector.
152
248
 
153
249
  A scalar override replaces the property's
154
250
  whole state map; use the matching state key without a default entry to change
@@ -158,18 +254,25 @@ conditional `display`, `"": null` is also supported, including styles with
158
254
 
159
255
  For a compact language selector, customize the root with
160
256
  `LanguageSelect: { border: { "[data-compact]": "4px solid #border" } }`.
161
- The former `Compact` hook is now a root state. Likewise, customize code wrapping
257
+ Likewise, customize code wrapping
162
258
  with `SyntaxHighlight: { whiteSpace: { "[data-syntax-wrap]": "pre-wrap" } }`.
163
259
  Syntax category sub-elements such as `Keyword` target descendant spans; use
164
260
  `SyntaxHighlight.color["[data-syntax-keyword]"]` when customizing the containing
165
261
  code element itself.
166
262
 
167
- Cookbook temporarily retains selectors for pseudo-element states that Tasty
168
- cannot yet compile correctly and four empty legacy customization hooks whose
263
+ A sub-element whose selector ends in a pseudo-element, such as
264
+ `Pagination.NextIcon` (`a[rel="next"]::before`), keeps the conditions on the
265
+ element it belongs to in that selector. Its `@own(...)` states describe the
266
+ pseudo-element itself, so Tasty ignores modifier, attribute, and tree-position
267
+ states there. Cookbook also retains four empty legacy customization hooks whose
169
268
  conditional override scopes must remain compatible. Each has a narrow lint
170
269
  exception in its owning style module. Use state maps for new definitions.
171
270
 
172
- For example:
271
+ Heading levels are states of the same element. Customize them through a root
272
+ property map such as `Heading: { textWrap: { "": "balance", ":is(h1)": "pretty" } }`.
273
+ Markdown heading wrappers use `level=h1` through `level=h6` as root states.
274
+
275
+ For example, these overrides combine plain values with a descendant state:
173
276
 
174
277
  ```ts
175
278
  theme: {
@@ -200,140 +303,132 @@ theme: {
200
303
  }
201
304
  ```
202
305
 
203
- No merge helper or base style object is required in user configuration. Style
204
- customization has one behavior: every supplied object is a partial override and
205
- is merged into the base inside Cookbook.
306
+ ## Common customizations
206
307
 
207
- Every configurable surface accepts styles at the root plus the named Tasty
208
- sub-elements below. The list is generated from the public component registry so
209
- it stays complete when a surface changes.
308
+ ### Header control shape
210
309
 
211
- ### Complete component anatomy
310
+ Header buttons and the mobile drawer close button use the independent
311
+ `$header-control-radius` token, which defaults to `999px` for pill and circular
312
+ shapes. Set it to `8px` for the same corners as the default content controls:
212
313
 
213
- <!-- component-anatomy:start -->
314
+ ```ts
315
+ theme: {
316
+ tokens: { "$header-control-radius": "8px" }
317
+ }
318
+ ```
214
319
 
215
- #### Page shell
320
+ `$radius` continues to control code-copy buttons, navigation items, and other
321
+ content controls. Individual `theme.styles` overrides still take precedence.
322
+ The mobile header divider spans the viewport while its content keeps the
323
+ configured horizontal padding.
216
324
 
217
- * `Document`: `All`, `BlockSpacing`, `Body`, `Control`, `Pointer`, `ResponsiveWidth`, `ResponsiveHeight`, `Hidden`, `PrintHidden`, `DesktopBlock`, `DesktopFlex`, `ScreenReaderOnly`, `RouteAnnouncer`, `Strong`, `Link`, `NarrowBlock`, `MobileBlock`, `Code`, `FocusRing`, `CurrentLink`, `SearchOpen`
218
- * `Layout`: `Islands`
219
- * `PageFrame`: `MainFrame`, `SidebarFrame`, `Columns`
220
- * `MainPane`: None
221
- * `MainContent`: `ContentSpacing`, `Container`, `Panel`
222
- * `HeaderFrame`: None
223
- * `Heading`: None
224
- * `Banner`: `Link`
225
- * `SkipLink`: None
325
+ ### Shared page surfaces
226
326
 
227
- #### Navigation and controls
327
+ Each bridge has a complete base style tree; supply only the properties you
328
+ want to change. Sub-elements keep their selectors and all other defaults.
329
+ For example, a compact search dialog and quieter pagination need no CSS:
228
330
 
229
- * `Header`: `Primary`, `Title`, `LogoLink`, `Logo`, `SiteTitle`, `Search`, `SearchElement`, `Tools`, `Social`, `MobileTheme`, `MobileLanguage`
230
- * `HeaderLinks`: `Desktop`, `DesktopLink`, `Link`, `HoverLink`, `PrimaryLink`, `HoverPrimaryLink`, `Trigger`, `HoverTrigger`, `Panel`, `OpenPanel`, `PanelNavigation`, `PanelLink`, `FirstPanelLink`, `Close`, `HoverClose`
231
- * `SearchButton`: `PendingShortcut`, `Label`, `Shortcut`, `NativeIcon`, `Icon`
232
- * `Button`: None
233
- * `Sidebar`: `Backdrop`, `OpenBackdrop`, `MobileHeading`, `HomeLink`, `HomeLogo`, `HomeLabel`, `Close`, `HoverClose`, `CloseIcon`, `CurrentLink`, `Content`, `Tree`, `List`, `Item`, `TopLevelSpacing`, `GroupSpacing`, `NestedItem`, `SectionHeading`, `Control`, `Summary`, `GroupLabel`, `GroupLabelText`, `Link`, `LinkLabel`, `InteractiveControl`, `SummaryMarker`, `Caret`, `ExpandedCaret`, `LinkedSummary`, `GroupLink`, `LinkedSectionHeading`, `SectionLink`, `Badge`, `TopLevelLink`
234
- * `MobileMenuToggle`: `Icon`, `Section`, `Page`
235
- * `MobileNavigationTabs`: `Trigger`, `Marker`, `Caret`, `ExpandedCaret`, `Label`, `List`, `Item`, `Link`, `HoverLink`, `CurrentLink`
236
- * `MobileMenuFooter`: `Social`
237
- * `TopNavigation`: `Scrollbar`, `Link`, `HoverLink`, `CurrentLink`, `ActiveIndicator`
238
- * `TableOfContentsLayout`: `Content`
239
- * `TableOfContents`: `Heading`, `List`, `Item`, `Link`, `LinkLabel`, `HoverLink`, `CurrentLink`
240
- * `MobileTableOfContents`: `Summary`, `List`, `NestedList`, `Item`, `Link`, `HoverLink`, `Focus`
241
- * `Pagination`: `Link`, `PreviousLink`, `NextLink`, `NextIcon`, `NextLabel`, `HoverLink`, `ActiveLink`, `Title`, `LoneNextLink`, `Icon`, `PreviousIconRtl`, `NextIconRtl`
242
- * `VersionSwitcher`: `Trigger`, `HoverTrigger`, `TriggerLabel`, `Caret`, `Panel`, `OpenPanel`, `PanelTitle`, `Options`, `Link`, `HoverLink`, `CurrentLink`, `Checkmark`, `SelectedCheckmark`
243
- * `LanguageSelect`: `Trigger`, `HoverTrigger`, `ActiveTrigger`, `LabelIcon`, `TriggerLabel`, `Caret`, `CompactTrigger`, `CompactLabel`, `CompactCaret`, `Label`, `HoverLabel`, `Select`, `CompactSelect`, `CompactLabelIcon`, `SidebarTrigger`, `Panel`, `SidebarPanel`, `OpenPanel`, `PanelTitle`, `Options`, `Option`, `HoverOption`, `CurrentOption`, `Fallback`, `Checkmark`, `SelectedCheckmark`
244
- * `SocialIcons`: `Link`, `HoverLink`, `Icon`
245
- * `ThemeSelect`: `Trigger`, `HoverTrigger`, `ActiveTrigger`, `Icon`, `Panel`, `OpenPanel`, `Section`, `SectionSpacing`, `SectionLabel`, `Option`, `HoverOption`, `CheckedOption`, `FocusedOption`, `Input`, `OptionIcon`, `Checkmark`, `SelectedCheckmark`
331
+ ```ts
332
+ theme: {
333
+ styles: {
334
+ Search: { Dialog: { inlineSize: { "": "0 90% 32rem", "!@md": "100%" } } },
335
+ SearchResults: { ResultLink: { color: "#accent-text" } },
336
+ Pagination: { Link: { padding: "1.5x", fill: "#surface" } },
337
+ Banner: { padding: "1x 2x" },
338
+ Markdown: {
339
+ Quote: {
340
+ color: { "@prose": "#text" },
341
+ inlinePadding: { "@prose": "3x start" },
342
+ },
343
+ },
344
+ },
345
+ }
346
+ ```
246
347
 
247
- #### Rendered content
348
+ `Document` owns resets, base typography, generic controls, responsive media,
349
+ and accessibility utilities. `MainPane` and `MainContent` own the content
350
+ layout. `Markdown` owns prose, lists, links, quotations, and disclosure
351
+ anatomy. `Search` owns the dialog; `SearchResults` owns the search field and
352
+ Pagefind results UI.
353
+ `MarkdownAlert` styles rendered alert blockquotes; `Card`, `Callout`, and
354
+ `Steps` style Cookbook components. `Callout` reads its colors from the root
355
+ `#callout-border`, `#callout-text`, and `#callout-surface` tokens, which change
356
+ per kind through `[data-kind="tip"]`, `"caution"`, and `"danger"` states.
248
357
 
249
- * `Markdown`: `Block`, `BlockSpacing`, `HeadingSpacing`, `List`, `CompactItem`, `ListItem`, `DefinitionTerm`, `DefinitionDescription`, `Link`, `HoverLink`, `Quote`, `Rule`, `Details`, `HoverDetails`, `Summary`, `OpenSummary`, `SummaryMarker`, `SummaryIcon`, `OpenSummaryIcon`, `Code`
250
- * `MarkdownHeading`: `Heading`, `Link`, `RevealedLink`, `HoverLink`, `LinkIcon`, `CopiedLink`, `CopiedLinkIcon`, `CopiedIcon`
251
- * `MarkdownCodeBlock`: `Pre`, `CopyButton`, `HoverCopyButton`, `CopiedButton`, `CopyIcon`, `CopiedIcon`, `Code`, `Diff`, `DiffCode`, `DiffLine`, `EmptyDiffLine`, `InsertedLine`, `DeletedLine`
252
- * `MarkdownInlineCode`: None
253
- * `MarkdownTable`: `Table`, `Cell`, `LastBodyRowCell`, `HeaderCell`, `Scroll`
254
- * `MarkdownAlert`: `Title`, `FirstContent`
255
- * `SyntaxHighlight`: `Marker`, `Comment`, `Punctuation`, `Keyword`, `String`, `Token`, `Property`, `Number`, `Function`, `Value`, `Operator`, `Text`, `Bg`, `Inserted`, `Deleted`, `Italic`, `Strong`, `Underline`
256
- * `Mermaid`: `Diagram`, `Text`, `MonoText`
257
- * `MermaidSource`: None
358
+ ### Block spacing
258
359
 
259
- #### Authoring components
360
+ Block spacing uses `$margin-block-start` and `$margin-block-end` tokens. The
361
+ owning `blockMargin` consumes both tokens, and a surrounding prose/layout rule
362
+ changes only the start token. For example, `Callout: { "$margin-block-end": "3x" }`
363
+ changes the end spacing while retaining Markdown's spacing before the callout.
364
+ Document foundations reset these tokens on every element to prevent inheritance
365
+ into nested content. For content-panel padding, use `MainContent.Panel`'s
366
+ `$padding-block-start` and `$padding-block-end` tokens in the same way.
260
367
 
261
- * `Card`: `Heading2`, `Heading3`, `Paragraph`
262
- * `Callout`: `Title`, `Body`
263
- * `CodeGroup`: `Caption`, `Pre`, `Code`
264
- * `Tab`: `Heading`, `HiddenHeading`
265
- * `Tabs`: `List`, `Button`, `SelectedButton`, `FocusedButton`
266
- * `Steps`: `Item`, `Marker`
267
- * `Hero`: `Visual`, `DarkVisual`, `LightVisual`, `Stack`, `Copy`, `Title`, `Tagline`, `Actions`, `Action`, `HoverAction`, `PrimaryAction`, `SecondaryAction`, `MinimalAction`, `ActionIcon`
268
- * `Preview`: `Caption`, `Stage`, `Frame`, `Code`, `Summary`, `HoverSummary`, `ActiveSummary`, `Pre`
269
- * `SiteLogo`: `Image`, `Light`, `Dark`
270
- * `Logo`: `Svg`, `Mark`
271
- * `PageActions`: `Control`, `Hover`, `Focus`, `Pending`, `Status`
272
- * `Footer`: `Meta`, `MetaLink`, `MetaUpdated`, `Credit`, `CreditLink`
273
- * `PackageVersion`: None
368
+ ### Code blocks and syntax highlighting
274
369
 
275
- #### Search
370
+ Code fences and `CodeGroup` use the same `MarkdownCodeBlock` style tree. Its
371
+ root `$copy-button-size` defaults to `2rem`; the copy control and vertical
372
+ padding share it, keeping equal top, right, and bottom insets on one-line
373
+ snippets. The padding follows the `code` preset's line height. Override it with
374
+ `theme.styles.MarkdownCodeBlock` when changing the control size or code layout.
276
375
 
277
- * `Search`: `Status`, `Dialog`, `CloseIcon`, `OpenDialog`, `EnteredDialog`, `Backdrop`, `EnteredBackdrop`, `Frame`, `Container`, `Close`, `HoverClose`, `ActiveClose`
278
- * `SearchResults`: `UI`, `Form`, `Field`, `EngineControls`, `Drawer`, `Input`, `Clear`, `Results`, `Result`, `ResultLink`, `SearchIcon`, `ClearIcon`, `SuppressedClear`, `Message`, `List`, `Title`, `Excerpt`, `NestedResult`, `Match`, `More`, `HoverMore`
376
+ Shiki classifies code; Tasty renders every token using Glaze's semantic syntax
377
+ colors. Customize token rules with `theme.styles.SyntaxHighlight`, or their
378
+ colors with `theme.palette` (for example `syntax-keyword`). The default
379
+ `syntax-bg` stays white in light mode and takes a slight brand-hued tint, close
380
+ to the page background's saturation, in dark mode. Set
381
+ `theme.palette["syntax-bg"]` to give code its own color seed;
382
+ syntax text and token contrast resolve against that surface. Code fences, including
383
+ MDX and diff blocks, use the `.tasty-code` root class, `data-syntax-*` modifiers, and
384
+ `data-diff` on the owning code-block wrapper. Diff lines carry
385
+ `data-inserted`/`data-deleted` with `data-element="Line"`. Custom Shiki
386
+ transformers may add root classes; token anatomy and state use identities or
387
+ modifiers. Unsupported token classes or inline declarations fail with a
388
+ configuration hint.
279
389
 
280
- <!-- component-anatomy:end -->
390
+ ### Heading links
281
391
 
282
- `COOKBOOK_COMPONENT_NAMES` publishes the configuration names, and
283
- `COOKBOOK_COMPONENT_SUB_ELEMENTS` publishes the complete sub-element lists for
284
- theme editors and other tooling. The corresponding TypeScript types are
285
- `CookbookComponentName`, `CookbookComponentSubElementName`,
286
- `CookbookComponentStyles`, `ComponentStyleConfig`, and `ComponentStylesConfig`.
287
- Known configuration names provide editor suggestions for their named
288
- sub-elements. `ThemeSelect` styles the combined Appearance panel; replace old
289
- `Select` and `Picker` overrides with `Trigger` and `Panel`. The separate
290
- `ContrastSelect` surface is replaced by the same `ThemeSelect` panel and option
291
- sub-elements. `SocialIcons` styles the shared icon-button links in the header
292
- and mobile menu. On wider layouts, heading permalinks sit to the left of the
293
- heading and are revealed on heading hover or keyboard focus. On mobile they
294
- stay visible and inline so the target is not clipped by the narrower content
295
- gutter. Customize the behavior with `MarkdownHeading.Link`,
296
- `MarkdownHeading.RevealedLink`, and `MarkdownHeading.LinkIcon`. The `#` icon
297
- scales with its heading and stays centered in the link target across heading
298
- levels and screen widths. Activating a heading link copies the full page URL
299
- with that section’s fragment without scrolling or changing the current URL. A
300
- checkmark and screen-reader status confirm the copy; clipboard failures are
301
- announced. Modified clicks and links
302
- without JavaScript retain native anchor behavior. Customize the confirmation
303
- with `MarkdownHeading.CopiedLink`, `MarkdownHeading.CopiedLinkIcon` (the hidden
304
- original icon), and `MarkdownHeading.CopiedIcon` (the checkmark).
305
-
306
- Root properties customize each navigation container. For example, overriding
307
- `Sidebar.LinkLabel.whiteSpace` keeps the other base `LinkLabel` properties
308
- because the configured object is merged by default.
309
- By default, the footer credit uses the primary body text color, while its
310
- Cookbook link uses the semantic brand link color.
392
+ On wider layouts, heading permalinks sit to the left of the heading and are
393
+ revealed on heading hover or keyboard focus. On mobile they stay visible and
394
+ inline so the target is not clipped by the narrower content gutter. Customize
395
+ the behavior with `MarkdownHeading.Link`, `MarkdownHeading.RevealedLink`, and
396
+ `MarkdownHeading.LinkIcon`. The `#` icon scales with its heading and stays
397
+ centered in the link target across heading levels and screen widths.
311
398
 
312
- `components.overrides` remains the structural escape hatch for replacing an
313
- Astro component. Prefer `theme.styles` when the markup and behavior remain the
314
- same.
315
-
316
- Register custom names and their partial Tasty objects in `theme.customStyles`.
317
- Built-in names belong in `theme.styles` and reject misspelled sub-elements.
318
- The name must match the string passed to `defineComponent()`, `extendComponent()`, or
319
- `resolveComponentStyles()`. A production
320
- build warns when a configured custom name has no matching component style
321
- resolver.
322
-
323
- The default renderer runs Tasty in Astro extract mode. Direct components and
324
- the remaining document/vendor bridge styles are collected into shared static
325
- CSS during the build, while appearance controls add only the small client
326
- behavior needed to persist selected theme and contrast modes. The compact
327
- Cookbook logo is shown beside the project title in the default top bar, links
328
- to the localized home page, and is also the default generated favicon. Use
329
- [`site.favicon`](./configuration.md#site-icons) to generate the complete icon
330
- set from project artwork.
399
+ Activating a heading link copies the full page URL with that section's fragment
400
+ without scrolling or changing the current URL. A checkmark and screen-reader
401
+ status confirm the copy; clipboard failures are announced. Modified clicks and
402
+ links without JavaScript retain native anchor behavior. Customize the
403
+ confirmation with `MarkdownHeading.CopiedLink`, `MarkdownHeading.CopiedLinkIcon`
404
+ (the hidden original icon), and `MarkdownHeading.CopiedIcon` (the checkmark).
405
+
406
+ ### Previews and the style boundary
407
+
408
+ The production build rejects style attributes, style blocks (including inside
409
+ shadow-root templates), and non-Tasty stylesheets throughout documentation HTML.
410
+ It parses actual markup, so escaped examples and strings in scripts are allowed.
411
+ The explicit exception is the separate document in a sandboxed `Preview` iframe;
412
+ it cannot access its parent's origin. Configure its size with
413
+ `theme.styles.Preview.Frame`, or one preview's minimum height with its `height`
414
+ prop. For a preview that runs scripts, a client script sets the frame's
415
+ `height` to its content plus its `buffer` prop, within the frame's `min-height`
416
+ and `max-height` (by default `10rem` and the window's height). The
417
+ documentation shell works under the CSP directive `style-src-attr 'none'`: it
418
+ blocks style attributes in markup, not the script's style changes. A host's CSP
419
+ may also restrict the preview document; when using that directive, authored
420
+ previews must use style blocks rather than style attributes.
331
421
 
332
422
  ## Static behavior
333
423
 
334
424
  Documentation content, navigation, headings, code, and images remain readable
335
425
  without client JavaScript. Search, mobile navigation, copy controls, appearance
336
- persistence, and executable previews enhance the static output.
426
+ persistence, and executable previews enhance the static output. Cookbook runs
427
+ Tasty in Astro extract mode and ships no Tasty or Glaze browser runtime, theme
428
+ configuration, or style hydration setup. Browser scripts and `client:*` islands
429
+ must not import Cookbook styling, Tasty, or Glaze; the build rejects these
430
+ imports. Attach small interaction scripts to server-rendered markup or pass
431
+ already-styled static markup into a client island.
337
432
 
338
433
  ### Appearance and navigation
339
434
 
@@ -367,20 +462,22 @@ at the end.
367
462
  ### Responsive header and navigation
368
463
 
369
464
  The header uses `#header`, generated from `theme.palette.header` (or the page
370
- surface) at 70% opacity in all four appearance modes, with a 16px backdrop blur.
465
+ surface) at 70% opacity in all four appearance modes, with a backdrop blur set
466
+ by the root `$backdrop-blur` token (default `16px`).
371
467
  Customize the outer bar with `theme.styles.HeaderFrame`, its contents with
372
468
  `Header`, and header buttons with `HeaderLinks` and `SearchButton`.
373
469
 
374
470
  Below 50rem, page navigation moves into a header row and opens a left drawer.
375
471
  `MobileMenuToggle.Section` and `Page` style its breadcrumb labels. The drawer
376
472
  contains the complete active section, a collapsible `MobileNavigationTabs`
377
- selector, and a close button. The drawer slides in and out over 120ms and
473
+ selector, and a close button. The drawer slides in and out over the root
474
+ `$sidebar-transition` duration (default `120ms`) and
378
475
  disables motion when the reader prefers reduced motion. Its mobile shadow uses
379
476
  the Glaze `shadow`-typed `#shadow` token. Customize the movement and shadow through
380
477
  `theme.styles.Sidebar`, and the underlay through `Sidebar.Backdrop` and
381
478
  `OpenBackdrop`. `theme.palette.overlay` supplies the underlay declaration, which defaults
382
- to black at 50% opacity. Glaze resolves it in fixed mode with tone remapping
383
- disabled, so it stays black in dark and high-contrast schemes.
479
+ to black at 50% opacity. Glaze resolves it in `static` mode, which skips scheme
480
+ adaptation, so it stays black in dark and high-contrast schemes.
384
481
  Icon buttons retain their plain desktop appearance on mobile. More uses
385
482
  left-aligned navigation links with a `1bw` gap, without primary button variants.
386
483
  `HeaderLinks.PanelLink` styles the menu rows; `FirstPanelLink` reserves space
@@ -396,92 +493,7 @@ controls placement. `Layout` controls shared
396
493
  navigation dimensions and the drawer's scroll lock; `PageFrame` styles the
397
494
  page container and content columns.
398
495
 
399
- ### Header control shape
400
-
401
- Header buttons and the mobile drawer close button use the independent
402
- `$header-control-radius` token, which defaults to `999px` for pill and circular
403
- shapes. Set it to `8px` for the same corners as the default content controls:
404
-
405
- ```ts
406
- theme: {
407
- tokens: { "$header-control-radius": "8px" }
408
- }
409
- ```
410
-
411
- `$radius` continues to control code-copy buttons, navigation items, and other
412
- content controls. Individual `theme.styles` overrides still take precedence.
413
- The mobile header divider spans the viewport while its content keeps the
414
- configured horizontal padding.
415
-
416
- ## Customize shared page surfaces
417
-
418
- Each bridge has a complete base style tree; supply only the properties you
419
- want to change. Sub-elements keep their selectors and all other defaults.
420
- For example, a compact search dialog and quieter pagination need no CSS:
421
-
422
- ```ts
423
- theme: {
424
- styles: {
425
- Search: { Dialog: { inlineSize: "max 32rem" } },
426
- SearchResults: { ResultLink: { color: "#accent-text" } },
427
- Pagination: { Link: { padding: "1.5x", fill: "#surface" } },
428
- Banner: { padding: "1x 2x" },
429
- Markdown: { Quote: { color: "#text", inlinePadding: "3x start" } },
430
- },
431
- }
432
- ```
433
-
434
- `Document` owns resets, base typography, generic controls, responsive media,
435
- and accessibility utilities. `MainPane` and `MainContent` own the content
436
- layout. `Markdown` owns prose, lists, links, quotations, and disclosure
437
- anatomy. `Search` owns the dialog; `SearchResults` owns the search field and
438
- Pagefind results UI.
439
- `MarkdownAlert` styles rendered alert blockquotes; `Card`, `Callout`, and
440
- `Steps` style Cookbook components.
441
-
442
- Custom components created with `defineComponent()` receive `theme.customStyles`
443
- overrides during server rendering. Units, recipes, states, and presets are
444
- resolved there and emitted as static CSS. Cookbook ships no Tasty/Glaze browser
445
- runtime, theme configuration, or style hydration setup. Browser scripts and
446
- `client:*` islands must not import Cookbook styling, Tasty, or Glaze; the build
447
- rejects these imports. Attach small interaction scripts to server-rendered markup
448
- or pass already-styled static markup into a client island.
449
-
450
- Code fences and `CodeGroup` use the same `MarkdownCodeBlock` style tree. Its
451
- root `$copy-button-size` defaults to `2rem`; the copy control and vertical
452
- padding share it, keeping equal top, right, and bottom insets on one-line
453
- snippets. The padding follows the `code` preset's line height. Override it with
454
- `theme.styles.MarkdownCodeBlock` when changing the control size or code layout.
455
-
456
- ### Syntax highlighting and isolated previews
457
-
458
- Shiki classifies code; Tasty renders every token using Glaze's semantic syntax
459
- colors. Customize token rules with `theme.styles.SyntaxHighlight`, or their
460
- colors with `theme.palette` (for example `syntax-keyword`). The default
461
- `syntax-bg` stays white in light mode and takes a slight brand-hued tint, close
462
- to the page background's saturation, in dark mode. Set
463
- `theme.palette["syntax-bg"]` to give code its own color seed;
464
- syntax text and token contrast resolve against that surface. Code fences, including
465
- MDX and diff blocks, use the `.tasty-code` root class, `data-syntax-*` modifiers, and
466
- `data-diff` on the owning code-block wrapper. Diff lines carry
467
- `data-inserted`/`data-deleted` with `data-element="Line"`. Custom Shiki
468
- transformers may add root classes; token anatomy and state use identities or
469
- modifiers. Unsupported token classes or inline declarations fail with a
470
- configuration hint.
471
-
472
- The production build rejects style attributes, style blocks (including inside
473
- shadow-root templates), and non-Tasty stylesheets throughout documentation HTML.
474
- It parses actual markup, so escaped examples and strings in scripts are allowed.
475
- The explicit exception is the separate document in a sandboxed `Preview` iframe;
476
- it cannot access its parent's origin. Configure its size with
477
- `theme.styles.Preview.Frame`, or one preview's minimum height with its `height`
478
- prop. For a preview that runs scripts, a client script sets the frame's
479
- `height` to its content plus its `buffer` prop, within the frame's `min-height`
480
- and `max-height` (by default `10rem` and the window's height). The
481
- documentation shell supports the CSP directive `style-src-attr 'none'`, which
482
- allows that script's style changes. A host's CSP may also restrict the preview
483
- document; when using that directive, authored previews must use style blocks
484
- rather than style attributes.
496
+ ### Search dialog
485
497
 
486
498
  Search uses an owned, keyboard-accessible dialog and server-rendered input so
487
499
  the first opening can focus the field immediately on mobile. Pagefind's indexing
@@ -490,11 +502,3 @@ and results UI load lazily. Customize the field with `SearchResults.Field`,
490
502
  Closing waits for the dialog's fade transition, with reduced motion respected.
491
503
  The fullscreen mobile dialog has no dimmed or blurred backdrop; the backdrop
492
504
  transition applies only to wider layouts.
493
- The Pagefind sizing adapter prevents inline layout declarations and is checked
494
- against the pinned UI version during builds.
495
-
496
- Root selectors may use stable classes (for example `.cookbook-markdown-content`,
497
- `.td-code-block`, and `.tasty-code`) or `data-component`. `data-element` identifies
498
- structural anatomy and must not serve as a variant or modifier. Use data modifiers
499
- for states; authored sub-element classes remain only in the Pagefind bridge because
500
- the library owns and updates its UI markup.