@tenphi/cookbook 0.20.3 → 0.20.5
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/README.md +5 -4
- package/docs/authoring.mdx +77 -3
- package/docs/comparison.md +4 -4
- package/docs/component-styles.md +399 -0
- package/docs/configuration.md +58 -25
- package/docs/custom-components.md +369 -0
- package/docs/customization-rules.md +6 -5
- package/docs/es/getting-started.md +109 -0
- package/docs/es/index.md +63 -0
- package/docs/fonts-and-typography.md +157 -0
- package/docs/getting-started.md +4 -3
- package/docs/index.md +6 -0
- package/docs/ja/getting-started.md +109 -0
- package/docs/ja/index.md +63 -0
- package/docs/migration.md +18 -4
- package/docs/plugins.md +2 -2
- package/docs/quality-checks.md +1 -1
- package/docs/recipes.md +30 -4
- package/docs/ru/getting-started.md +109 -0
- package/docs/ru/index.md +63 -0
- package/docs/site-navigation.md +77 -0
- package/docs/theme-and-components.md +142 -975
- package/docs/troubleshooting.md +1 -1
- package/docs/zh/getting-started.md +109 -0
- package/docs/zh/index.md +63 -0
- package/package.json +3 -3
|
@@ -1,35 +1,29 @@
|
|
|
1
1
|
---
|
|
2
|
-
title: Theme
|
|
3
|
-
description:
|
|
2
|
+
title: Theme and components
|
|
3
|
+
description: Choose a brand, build a semantic palette, set design tokens, and find the right customization guide.
|
|
4
4
|
sidebar:
|
|
5
5
|
order: 5
|
|
6
6
|
---
|
|
7
|
-
Cookbook
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
patterns behind roots, sub-elements, and controlled overrides.
|
|
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.
|
|
7
|
+
Cookbook resolves Glaze colors and Tasty styles during the build, then ships
|
|
8
|
+
static CSS. Start with a brand color; add semantic palette roles, typography,
|
|
9
|
+
and component overrides only where the default needs to change. The
|
|
10
|
+
[configuration recipes](./recipes.md) show complete, build-checked starting
|
|
11
|
+
points. Read the [customization rules](./customization-rules.md) before writing
|
|
12
|
+
new styles.
|
|
13
|
+
|
|
14
|
+
| To change | Start here |
|
|
15
|
+
| ------------------------------------- | ------------------------------------------------- |
|
|
16
|
+
| Brand, color roles, and design tokens | This page |
|
|
17
|
+
| Font files, families, and typography | [Fonts and typography](./fonts-and-typography.md) |
|
|
18
|
+
| Built-in UI surfaces and named parts | [Component styles](./component-styles.md) |
|
|
19
|
+
| Your own Astro or MDX components | [Custom components](./custom-components.md) |
|
|
20
|
+
| Complete configuration fields | [Configuration reference](./configuration.md) |
|
|
21
|
+
|
|
22
|
+
Glaze derives light, dark, and high-contrast values from the brand and palette
|
|
23
|
+
inputs. Tasty applies those values through semantic tokens. See the
|
|
24
|
+
[Glaze reference](./upstream/glaze/README.md) for color declarations and the
|
|
25
|
+
[Tasty style DSL](./upstream/tasty/docs/dsl.md) for state maps, tokens, units,
|
|
26
|
+
and sub-elements.
|
|
33
27
|
|
|
34
28
|
## Brand color
|
|
35
29
|
|
|
@@ -142,842 +136,6 @@ Borders stay intentionally quiet: Glaze derives their hue from `brand` but
|
|
|
142
136
|
uses only one quarter of the brand saturation. Normal and high-contrast modes
|
|
143
137
|
change border tone, not that restrained saturation relationship.
|
|
144
138
|
|
|
145
|
-
The Appearance button in the desktop and mobile header opens one panel with
|
|
146
|
-
Color scheme and Contrast sections. Color scheme offers Light, Dark, and Auto;
|
|
147
|
-
Contrast offers Normal, High, and Auto. Each preference is independent, and
|
|
148
|
-
selections are saved in the browser. The panel supports keyboard navigation,
|
|
149
|
-
Escape, and outside-click dismissal. The popover fades and scales vertically
|
|
150
|
-
from 96% to 100% over 120ms using native entry and exit transitions. Reduced
|
|
151
|
-
motion disables the transition. Customize these states with
|
|
152
|
-
`theme.styles.ThemeSelect.Panel` and `OpenPanel`; the root `$popover-transition`
|
|
153
|
-
token controls the duration. Contrast can follow the system, force the
|
|
154
|
-
normal palette, or activate the Glaze high-contrast palette.
|
|
155
|
-
System mode responds to `prefers-contrast: more`; an explicit selection is
|
|
156
|
-
persisted and takes precedence over that media query.
|
|
157
|
-
|
|
158
|
-
Interactive controls step up exactly one surface level: a control on `surface`
|
|
159
|
-
uses `surface-2`, while a control on `surface-2` uses `surface-3`. Hover and
|
|
160
|
-
pressed states build on that elevated surface without changing the border.
|
|
161
|
-
Inputs stay on their surrounding surface so their border remains the visual
|
|
162
|
-
boundary. Primary buttons and selected navigation use the fixed-mode
|
|
163
|
-
`accent-surface` and its paired light `accent-surface-text`. The brand fill
|
|
164
|
-
keeps its polarity in dark mode while Glaze adjusts it to preserve label
|
|
165
|
-
contrast.
|
|
166
|
-
|
|
167
|
-
Page navigation keeps Next first in the keyboard order. It appears above
|
|
168
|
-
Previous on narrow screens; wider layouts show Previous at the start and Next
|
|
169
|
-
at the end.
|
|
170
|
-
|
|
171
|
-
## Design tokens
|
|
172
|
-
|
|
173
|
-
Token names follow Tasty's
|
|
174
|
-
[token and unit syntax](./upstream/tasty/docs/dsl.md#built-in-units): `$name`
|
|
175
|
-
becomes the CSS custom property `--name`. Existing `--name` keys are still
|
|
176
|
-
accepted for compatibility.
|
|
177
|
-
|
|
178
|
-
```ts
|
|
179
|
-
theme: {
|
|
180
|
-
tokens: {
|
|
181
|
-
"$gap": "0.5rem",
|
|
182
|
-
"$radius": "8px",
|
|
183
|
-
"$card-radius": "16px",
|
|
184
|
-
"$border-width": "1px",
|
|
185
|
-
"$outline-width": "2px",
|
|
186
|
-
"$outline-offset": "2px",
|
|
187
|
-
"$control-height": "2.5rem",
|
|
188
|
-
"$layout-width": "87.5rem",
|
|
189
|
-
"$content-width": "58rem",
|
|
190
|
-
"$sidebar-width": "17.5rem"
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
```
|
|
194
|
-
|
|
195
|
-
`layout-width` caps and centers the complete documentation shell, while
|
|
196
|
-
`content-width` limits the reading column inside it. `radius` is the control
|
|
197
|
-
and navigation radius; `card-radius` is the larger surface radius. Keeping
|
|
198
|
-
those roles separate makes a sharp control theme or a soft card theme possible
|
|
199
|
-
without one-off component overrides.
|
|
200
|
-
|
|
201
|
-
## Typography presets
|
|
202
|
-
|
|
203
|
-
The built-in [typography presets](./upstream/tasty/docs/styles.md#preset) are
|
|
204
|
-
`body`, `heading`, `h1` through `h6`, `navigation`, `small`, and `code`. Onest
|
|
205
|
-
is self-hosted and used for body and heading text by default; JetBrains Mono is
|
|
206
|
-
self-hosted for code.
|
|
207
|
-
|
|
208
|
-
### Change font families
|
|
209
|
-
|
|
210
|
-
Set `theme.fonts` to load fonts and apply them to the matching presets. A Google
|
|
211
|
-
Fonts family needs only its name:
|
|
212
|
-
|
|
213
|
-
```ts
|
|
214
|
-
theme: {
|
|
215
|
-
fonts: {
|
|
216
|
-
body: "Inter",
|
|
217
|
-
heading: "Newsreader"
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
```
|
|
221
|
-
|
|
222
|
-
The short form follows the regular and strong weights in your configured
|
|
223
|
-
presets, including heading and custom preset references. It requests normal and
|
|
224
|
-
italic styles, prefers a variable range, and falls back to real static weights
|
|
225
|
-
when ranges are unavailable. A font without italics produces a build warning;
|
|
226
|
-
choose another family or select only its supported styles. To control the
|
|
227
|
-
request exactly, list weights or ascending variable ranges and styles. Google
|
|
228
|
-
Fonts must support them; see the
|
|
229
|
-
[Google Fonts CSS API](https://developers.google.com/fonts/docs/css2) for its
|
|
230
|
-
available styles and weight syntax.
|
|
231
|
-
|
|
232
|
-
```ts
|
|
233
|
-
theme: {
|
|
234
|
-
fonts: {
|
|
235
|
-
body: { google: "Inter", weights: ["400 750"], styles: ["normal", "italic"] }
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
```
|
|
239
|
-
|
|
240
|
-
For a font you own, put its files in `public/fonts/` and give Cookbook their
|
|
241
|
-
public paths. Cookbook checks that each file exists during the build and adjusts
|
|
242
|
-
its URL for the Astro `base` path. A variable font can cover a weight range;
|
|
243
|
-
use separate entries for regular and italic files when needed:
|
|
244
|
-
|
|
245
|
-
```ts
|
|
246
|
-
theme: {
|
|
247
|
-
fonts: {
|
|
248
|
-
body: {
|
|
249
|
-
family: "Acme Sans",
|
|
250
|
-
files: [
|
|
251
|
-
{ src: "/fonts/acme-sans.woff2", weight: "100 900" },
|
|
252
|
-
{ src: "/fonts/acme-sans-italic.woff2", weight: "100 900", style: "italic" }
|
|
253
|
-
]
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
```
|
|
258
|
-
|
|
259
|
-
The `body` role also feeds navigation and small text. `heading` feeds `h1`
|
|
260
|
-
through `h6`, while `code` covers code text. Each role has a system fallback.
|
|
261
|
-
Cookbook emits font faces through Tasty with `font-display: swap`. Google CSS
|
|
262
|
-
and font files are downloaded at build time and cached in
|
|
263
|
-
`<Astro cacheDir>/cookbook-fonts`. Files are served from your own site's
|
|
264
|
-
`_cookbook/fonts/` path by default, including the deployment base. Visitors make
|
|
265
|
-
no Google Fonts requests. Existing local-file definitions keep working.
|
|
266
|
-
|
|
267
|
-
```ts
|
|
268
|
-
theme: {
|
|
269
|
-
fonts: { body: "Inter" },
|
|
270
|
-
fontLoading: {
|
|
271
|
-
google: "self-hosted", // or "remote" to keep Google's font CDN URLs
|
|
272
|
-
cache: "reuse", // "refresh" to fetch again; "offline" to forbid network
|
|
273
|
-
display: "swap" // also auto, block, fallback, optional
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
```
|
|
277
|
-
|
|
278
|
-
The first build requires network access. Preserve the Astro cache between CI
|
|
279
|
-
runs; `offline` fails with an actionable message when an entry is missing or
|
|
280
|
-
corrupt. Cache entries are content-verified and keyed by the exact request.
|
|
281
|
-
`refresh` deliberately updates them. For a fully checked-in font source, copy
|
|
282
|
-
licensed files into `public/fonts/` and use the local form. Only `wght` and
|
|
283
|
-
`ital` axes are requested; use local variable files and Tasty typography styles
|
|
284
|
-
for other axes. Styles and weights that do not exist are rejected for explicit
|
|
285
|
-
requests. For static fonts, browsers select their nearest real weight;
|
|
286
|
-
intermediate weights require a variable font.
|
|
287
|
-
|
|
288
|
-
Migration: name-only Google font configuration now downloads the required
|
|
289
|
-
weights and italics and serves them locally. This increases the initial build's
|
|
290
|
-
font downloads and removes visitors' external font dependency. Set
|
|
291
|
-
`fontLoading.google: "remote"` to retain CDN delivery. Existing CSS-variable
|
|
292
|
-
weights that cannot be resolved from presets require explicit `weights`.
|
|
293
|
-
|
|
294
|
-
### Adjust presets
|
|
295
|
-
|
|
296
|
-
Presets merge property-by-property, so changing size, weight, or line height
|
|
297
|
-
does not require copying the rest of the preset. `theme.presets` takes precedence
|
|
298
|
-
over `theme.fonts` for an explicitly set `fontFamily`:
|
|
299
|
-
|
|
300
|
-
```ts
|
|
301
|
-
theme: {
|
|
302
|
-
presets: {
|
|
303
|
-
body: {
|
|
304
|
-
boldFontWeight: 680
|
|
305
|
-
},
|
|
306
|
-
heading: {
|
|
307
|
-
fontWeight: 650,
|
|
308
|
-
boldFontWeight: 740
|
|
309
|
-
},
|
|
310
|
-
h1: {
|
|
311
|
-
fontSize: "3rem",
|
|
312
|
-
letterSpacing: "-0.02em"
|
|
313
|
-
},
|
|
314
|
-
code: { fontSize: "0.9rem" }
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
```
|
|
318
|
-
|
|
319
|
-
For a system or already loaded font, set its CSS family directly with
|
|
320
|
-
`theme.presets.<role>.fontFamily`. This does not load a font file. Additional
|
|
321
|
-
named presets are available to custom MDX components.
|
|
322
|
-
|
|
323
|
-
Heading presets reference the `heading` family and weights; body, navigation,
|
|
324
|
-
and controls reference `body`. Semantic `strong` and `b` elements use Tasty's
|
|
325
|
-
`strong` modifier, so their weight comes from the active preset's
|
|
326
|
-
`boldFontWeight` instead of a separate element-specific value. `strong` is a
|
|
327
|
-
reserved modifier keyword, not a named preset; the modifier-only form is
|
|
328
|
-
equivalent to `inherit / strong`. Body text uses a regular `400` weight and
|
|
329
|
-
neutral tracking, while
|
|
330
|
-
headings use a medium `610` weight and progressively gentle negative tracking.
|
|
331
|
-
The separate `720` heading bold weight keeps emphasized heading text distinct.
|
|
332
|
-
Navigation uses a lighter `450` weight with `580` for the current sidebar page,
|
|
333
|
-
while smaller group labels establish hierarchy without oversized bold text.
|
|
334
|
-
Inactive sidebar links use `sidebar-text`, a slightly softer blend of `text-soft`
|
|
335
|
-
and the surface. In high-contrast mode it matches `text-soft`. Set
|
|
336
|
-
`theme.palette['sidebar-text']` to adjust that color without changing other
|
|
337
|
-
secondary text, or `theme.styles.Sidebar.Control` to customize the control.
|
|
338
|
-
Top-level sidebar groups are always-visible section headings with their direct
|
|
339
|
-
links aligned beneath them. Deeper groups expand on click or keyboard activation;
|
|
340
|
-
the current group and its ancestors start open. Groups can have a parent-page
|
|
341
|
-
`link`; activating an unselected linked header selects that page and keeps its
|
|
342
|
-
children open. Activating the selected header toggles its children.
|
|
343
|
-
The current group can stay collapsed because its header remains visible. Only
|
|
344
|
-
the current page is highlighted; ancestors receive no extra emphasis. Explicit expansion choices are
|
|
345
|
-
remembered for the browser tab; automatically revealing the current page does
|
|
346
|
-
not overwrite them. Desktop scroll position is restored independently of mobile
|
|
347
|
-
menu scrolling, and the current page's ancestors remain open after navigation.
|
|
348
|
-
Nested groups use indentation without vertical rails. Customize section headings
|
|
349
|
-
with `theme.styles.Sidebar.SectionHeading`, indentation with `NestedItem`, and
|
|
350
|
-
disclosure icons with `Caret` and `ExpandedCaret`.
|
|
351
|
-
Adjacent sidebar items have a `1bw` gap. Inline code scales to `0.875em` of its
|
|
352
|
-
surrounding text, including smaller table text; code blocks keep the `code` preset
|
|
353
|
-
size. Customize inline code through `theme.styles.MarkdownInlineCode`.
|
|
354
|
-
Cookbook applies each semantic typography role through its complete Tasty
|
|
355
|
-
`preset`, so configured fields such as `fontStyle` and `textTransform` are not
|
|
356
|
-
silently omitted.
|
|
357
|
-
|
|
358
|
-
The exported `DEFAULT_THEME_TOKENS` and `DEFAULT_TYPOGRAPHY_PRESETS` constants
|
|
359
|
-
are useful when building a theme editor or presenting a reset action.
|
|
360
|
-
|
|
361
|
-
## Style customization
|
|
362
|
-
|
|
363
|
-
Cookbook-owned interface elements are direct `tasty()` components. Supported
|
|
364
|
-
Cookbook components and generated Markdown surfaces use Tasty style trees.
|
|
365
|
-
Customize them by name under `theme.styles`; the configuration is resolved
|
|
366
|
-
before CSS generation, so this is not a selector-based CSS override.
|
|
367
|
-
|
|
368
|
-
> **Direct styles, without a specificity battle.** Cookbook merges your partial
|
|
369
|
-
> style object with the component's base styles before Tasty extracts CSS. The
|
|
370
|
-
> generated stylesheet reflects that result; changing a supported property
|
|
371
|
-
> does not add a competing rule just to beat the original. You can customize
|
|
372
|
-
> existing elements without long selectors or `!important`.
|
|
373
|
-
|
|
374
|
-
Start with the area you want to change, then use the complete sub-element table
|
|
375
|
-
below to find its exact anatomy:
|
|
376
|
-
|
|
377
|
-
| Page area | Style names to inspect |
|
|
378
|
-
| ----------------------------- | ------------------------------------------------------------------------------------ |
|
|
379
|
-
| Header, title, and navigation | `HeaderFrame`, `Header`, `SiteLogo`, `HeaderLinks`, `TopNavigation` |
|
|
380
|
-
| Sidebar and mobile menu | `Sidebar`, `MobileMenuToggle`, `MobileNavigationTabs`, `MobileMenuFooter` |
|
|
381
|
-
| Article text and headings | `Markdown`, `MarkdownHeading`, `Heading`, `MainContent` |
|
|
382
|
-
| Code and diagrams | `MarkdownCodeBlock`, `MarkdownInlineCode`, `SyntaxHighlight`, `CodeGroup`, `Mermaid` |
|
|
383
|
-
| Search | `SearchButton`, `Search`, `SearchResults` |
|
|
384
|
-
| Table of contents | `TableOfContents`, `MobileTableOfContents`, `TableOfContentsLayout` |
|
|
385
|
-
| Cards, notes, and tabs | `Card`, `Callout`, `MarkdownAlert`, `Tabs` |
|
|
386
|
-
| Footer and page controls | `Footer`, `Pagination`, `PageActions`, `ThemeSelect` |
|
|
387
|
-
|
|
388
|
-
For example, this changes a typography role and one named element without
|
|
389
|
-
copying a component's full style tree:
|
|
390
|
-
|
|
391
|
-
```ts
|
|
392
|
-
theme: {
|
|
393
|
-
presets: { h2: { fontSize: "1.75rem" } },
|
|
394
|
-
styles: {
|
|
395
|
-
Sidebar: {
|
|
396
|
-
LinkLabel: {
|
|
397
|
-
preset: "body",
|
|
398
|
-
whiteSpace: { "": "nowrap", "@mobile": "normal" }
|
|
399
|
-
}
|
|
400
|
-
}
|
|
401
|
-
}
|
|
402
|
-
}
|
|
403
|
-
```
|
|
404
|
-
|
|
405
|
-
The `@mobile` value sits with the default value in one Tasty state map. Shared
|
|
406
|
-
tokens and presets keep the component aligned with the rest of the site, while
|
|
407
|
-
Glaze resolves semantic colors across the configured schemes and contrast
|
|
408
|
-
modes.
|
|
409
|
-
|
|
410
|
-
In a generated site, run `npm run validate` (or the matching package manager's
|
|
411
|
-
command) after editing `docs.config.ts`. It checks TypeScript theme properties,
|
|
412
|
-
then runs Cookbook's preflight and production output checks. A misspelled
|
|
413
|
-
preset or built-in sub-element property fails type checking.
|
|
414
|
-
|
|
415
|
-
Provide only the root and named
|
|
416
|
-
[sub-element](./upstream/tasty/docs/dsl.md#sub-element) properties you want to
|
|
417
|
-
override. Cookbook deep-merges that partial style object into the complete
|
|
418
|
-
base style object inside the renderer, following Tasty's
|
|
419
|
-
[state-map merge semantics](./upstream/tasty/docs/dsl.md#extending-vs-replacing-state-maps):
|
|
420
|
-
|
|
421
|
-
```ts
|
|
422
|
-
theme: {
|
|
423
|
-
styles: {
|
|
424
|
-
ThemeSelect: {
|
|
425
|
-
Trigger: {
|
|
426
|
-
border: "#border-strong"
|
|
427
|
-
},
|
|
428
|
-
Panel: {
|
|
429
|
-
padding: "1x",
|
|
430
|
-
shadow: "0 1rem 3rem #shadow"
|
|
431
|
-
}
|
|
432
|
-
},
|
|
433
|
-
TopNavigation: {
|
|
434
|
-
Link: { preset: "body" },
|
|
435
|
-
CurrentLink: { color: "#accent-text" }
|
|
436
|
-
},
|
|
437
|
-
Sidebar: {
|
|
438
|
-
LinkLabel: { whiteSpace: "normal" }
|
|
439
|
-
},
|
|
440
|
-
TableOfContents: {
|
|
441
|
-
LinkLabel: { whiteSpace: "normal" }
|
|
442
|
-
},
|
|
443
|
-
MobileMenuToggle: {
|
|
444
|
-
Page: { color: "#accent-text" }
|
|
445
|
-
}
|
|
446
|
-
}
|
|
447
|
-
}
|
|
448
|
-
```
|
|
449
|
-
|
|
450
|
-
No merge helper or base style object is required in user configuration. Style
|
|
451
|
-
customization has one behavior: every supplied object is a partial override and
|
|
452
|
-
is merged into the base inside Cookbook.
|
|
453
|
-
|
|
454
|
-
Every configurable surface accepts styles at the root plus these named Tasty
|
|
455
|
-
sub-elements:
|
|
456
|
-
|
|
457
|
-
| Configuration name | Named sub-elements |
|
|
458
|
-
| ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
459
|
-
| `Card` | `Heading2`, `Heading3`, `Paragraph` |
|
|
460
|
-
| `Callout` | `Title`, `Body`, `Tip`, `Caution`, `Danger` |
|
|
461
|
-
| `CodeGroup` | `Caption`, `Pre`, `Code` |
|
|
462
|
-
| `Tab` | `Heading`, `Hidden`, `HiddenHeading` |
|
|
463
|
-
| `MobileTableOfContents` | `Summary`, `List`, `NestedList`, `Item`, `Link`, `HoverLink`, `Focus` |
|
|
464
|
-
| `PageActions` | `Control`, `Hover`, `Focus`, `Pending`, `Status` |
|
|
465
|
-
| `Footer` | `Meta`, `LoneMetaItem`, `MetaLink`, `HoverMetaLink`, `Credit`, `CreditLink`, `HoverCreditLink` |
|
|
466
|
-
| `Hero` | `Visual`, `DarkVisual`, `LightVisual`, `Stack`, `Copy`, `Title`, `Tagline`, `Actions`, `Action`, `HoverAction`, `PrimaryAction`, `SecondaryAction`, `MinimalAction`, `ActionIcon` |
|
|
467
|
-
| `LanguageSelect` | `Label`, `HoverLabel`, `LabelIcon`, `Select`, `Caret`, `Option` |
|
|
468
|
-
| `Logo` | `Svg`, `Mark` |
|
|
469
|
-
| `SiteLogo` | `Image`, `Light`, `Dark` |
|
|
470
|
-
| `MarkdownCodeBlock` | `Pre`, `CopyButton`, `HoverCopyButton`, `CopiedButton`, `CopyIcon`, `CopiedIcon`, `Code`, `Diff`, `DiffCode`, `DiffLine`, `EmptyDiffLine`, `InsertedLine`, `DeletedLine` |
|
|
471
|
-
| `MarkdownHeading` | `Heading`, `Heading1`, `Heading2`, `Heading3`, `Heading4`, `Heading5`, `Heading6`, `Link`, `RevealedLink`, `HoverLink`, `LinkIcon`, `CopiedLink`, `CopiedLinkIcon`, `CopiedIcon` |
|
|
472
|
-
| `MarkdownInlineCode` | None |
|
|
473
|
-
| `MarkdownTable` | `Table`, `Cell`, `LastBodyRowCell`, `HeaderCell`, `Scroll` |
|
|
474
|
-
| `Mermaid` | `Diagram`, `Text`, `MonoText` |
|
|
475
|
-
| `MobileMenuFooter` | `Social` |
|
|
476
|
-
| `MobileMenuToggle` | `Control`, `Icon`, `Section`, `Page`, `HoverControl`, `ActiveControl` |
|
|
477
|
-
| `MobileNavigationTabs` | `Trigger`, `Marker`, `Caret`, `ExpandedCaret`, `Label`, `List`, `Item`, `Link`, `HoverLink`, `CurrentLink` |
|
|
478
|
-
| `MobileTableOfContents` | `Item`, `Link`, `LinkLabel`, `HoverLink`, `CurrentLink`, `CurrentIndicator` |
|
|
479
|
-
| `PackageVersion` | None |
|
|
480
|
-
| `VersionSwitcher` | `Trigger`, `Panel`, `OpenPanel`, `Link`, `CurrentLink` |
|
|
481
|
-
| `Preview` | `Caption`, `Stage`, `Frame`, `Code`, `Summary`, `Pre` |
|
|
482
|
-
| `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` |
|
|
483
|
-
| `SocialIcons` | `Link`, `HoverLink`, `Icon` |
|
|
484
|
-
| `Header` | `Primary`, `TitleAndSearch`, `Title`, `LogoLink`, `Logo`, `SiteTitle`, `Search`, `SearchElement`, `Tools`, `ToolItem`, `Social`, `MobileTheme` |
|
|
485
|
-
| `TableOfContentsLayout` | `WithMobile`, `Content` |
|
|
486
|
-
| `SearchButton` | `PendingShortcut`, `Label`, `Shortcut`, `Hover`, `Active`, `NativeIcon`, `Icon` |
|
|
487
|
-
| `Layout` | `Islands`, `LockedPage`, `Light`, `Auto` |
|
|
488
|
-
| `HeaderLinks` | `Desktop`, `DesktopLink`, `Link`, `HoverLink`, `PrimaryLink`, `HoverPrimaryLink`, `Trigger`, `HoverTrigger`, `Panel`, `PanelNavigation`, `PanelLink`, `FirstPanelLink`, `Close`, `HoverClose` |
|
|
489
|
-
| `Heading` | `Level1`, `Level2`, `Level3`, `Level4`, `Level5`, `Level6`, `PageTitle` |
|
|
490
|
-
| `HeaderFrame` | None |
|
|
491
|
-
| `PageFrame` | `MainFrame`, `SidebarFrame`, `Columns` |
|
|
492
|
-
| `Steps` | `Item`, `Marker` |
|
|
493
|
-
| `Tabs` | `List`, `Button`, `SelectedButton`, `FocusedButton` |
|
|
494
|
-
| `TableOfContents` | `Heading`, `List`, `Item`, `Link`, `LinkLabel`, `HoverLink`, `CurrentLink` |
|
|
495
|
-
| `ThemeSelect` | `Trigger`, `HoverTrigger`, `ActiveTrigger`, `Icon`, `Panel`, `OpenPanel`, `Section`, `SectionSpacing`, `SectionLabel`, `Option`, `HoverOption`, `CheckedOption`, `FocusedOption`, `Input`, `OptionIcon`, `Checkmark`, `SelectedCheckmark` |
|
|
496
|
-
| `TopNavigation` | `Scrollbar`, `Link`, `HoverLink`, `CurrentLink`, `ActiveIndicator` |
|
|
497
|
-
| `Document` | `All`, `Body`, `Control`, `Pointer`, `ResponsiveWidth`, `ResponsiveHeight`, `Hidden`, `PrintHidden`, `DesktopBlock`, `DesktopFlex`, `ScreenReaderOnly`, `Strong`, `Link`, `NarrowBlock`, `MobileBlock`, `Code`, `FocusRing`, `CurrentLink`, `SearchOpen` |
|
|
498
|
-
| `MainPane` | `WithSidebars` |
|
|
499
|
-
| `MainContent` | `ContentSpacing`, `Container`, `Panel`, `FirstPanel`, `BodyPanel` |
|
|
500
|
-
| `Banner` | `Link` |
|
|
501
|
-
| `SkipLink` | `Focus` |
|
|
502
|
-
| `Search` | `Status`, `Dialog`, `CloseIcon`, `OpenDialog`, `Backdrop`, `Frame`, `Container`, `Close`, `HoverClose`, `ActiveClose` |
|
|
503
|
-
| `Pagination` | `Link`, `PreviousLink`, `NextLink`, `NextIcon`, `NextLabel`, `HoverLink`, `ActiveLink`, `Title`, `LoneNextLink`, `Icon`, `PreviousIconRtl`, `NextIconRtl` |
|
|
504
|
-
| `Markdown` | `Block`, `BlockSpacing`, `HeadingSpacing`, `List`, `CompactItem`, `ListItem`, `DefinitionTerm`, `DefinitionDescription`, `Link`, `HoverLink`, `Quote`, `Rule`, `Details`, `HoverDetails`, `Summary`, `OpenSummary`, `SummaryMarker`, `SummaryIcon`, `OpenSummaryIcon`, `Code` |
|
|
505
|
-
| `MermaidSource` | None |
|
|
506
|
-
| `MarkdownAlert` | `Note`, `Tip`, `Caution`, `Danger`, `Title`, `FirstContent` |
|
|
507
|
-
| `SyntaxHighlight` | `Scroll`, `Wrap`, `Marker`, `Comment`, `Punctuation`, `Keyword`, `String`, `Token`, `Property`, `Number`, `Function`, `Value`, `Operator`, `Text`, `Bg`, `Inserted`, `Deleted`, `Italic`, `Strong`, `Underline` |
|
|
508
|
-
| `SearchResults` | `Form`, `Input`, `Clear`, `Results`, `Result`, `ResultLink`, `SearchIcon`, `ClearIcon`, `SuppressedClear`, `Message`, `List`, `Title`, `Excerpt`, `NestedResult`, `Match`, `More`, `HoverMore` |
|
|
509
|
-
|
|
510
|
-
`COOKBOOK_COMPONENT_NAMES` publishes the configuration names, and
|
|
511
|
-
`COOKBOOK_COMPONENT_SUB_ELEMENTS` publishes the complete sub-element lists for
|
|
512
|
-
theme editors and other tooling. The corresponding TypeScript types are
|
|
513
|
-
`CookbookComponentName`, `CookbookComponentSubElementName`,
|
|
514
|
-
`CookbookComponentStyles`, `ComponentStyleConfig`, and `ComponentStylesConfig`.
|
|
515
|
-
Known configuration names provide editor suggestions for their named
|
|
516
|
-
sub-elements. `ThemeSelect` styles the combined Appearance panel; replace old
|
|
517
|
-
`Select` and `Picker` overrides with `Trigger` and `Panel`. The separate
|
|
518
|
-
`ContrastSelect` surface is replaced by the same `ThemeSelect` panel and option
|
|
519
|
-
sub-elements. `SocialIcons` styles the shared icon-button links in the header
|
|
520
|
-
and mobile menu. On wider layouts, heading permalinks sit to the left of the
|
|
521
|
-
heading and are revealed on heading hover or keyboard focus. On mobile they
|
|
522
|
-
stay visible and inline so the target is not clipped by the narrower content
|
|
523
|
-
gutter. Customize the behavior with `MarkdownHeading.Link`,
|
|
524
|
-
`MarkdownHeading.RevealedLink`, and `MarkdownHeading.LinkIcon`. The `#` icon
|
|
525
|
-
scales with its heading and stays centered in the link target across heading
|
|
526
|
-
levels and screen widths. Activating a heading link copies the full page URL
|
|
527
|
-
with that section’s fragment without scrolling or changing the current URL. A
|
|
528
|
-
checkmark and screen-reader status confirm the copy; clipboard failures are
|
|
529
|
-
announced. Modified clicks and links
|
|
530
|
-
without JavaScript retain native anchor behavior. Customize the confirmation
|
|
531
|
-
with `MarkdownHeading.CopiedLink`, `MarkdownHeading.CopiedLinkIcon` (the hidden
|
|
532
|
-
original icon), and `MarkdownHeading.CopiedIcon` (the checkmark).
|
|
533
|
-
|
|
534
|
-
Root properties customize each navigation container. For example, overriding
|
|
535
|
-
`Sidebar.LinkLabel.whiteSpace` keeps the other base `LinkLabel` properties
|
|
536
|
-
because the configured object is merged by default.
|
|
537
|
-
By default, the footer credit uses the primary body text color, while its
|
|
538
|
-
Cookbook link uses the semantic brand link color.
|
|
539
|
-
|
|
540
|
-
`components.overrides` remains the structural escape hatch for replacing an
|
|
541
|
-
Astro component. Prefer `theme.styles` when the markup and behavior remain the
|
|
542
|
-
same.
|
|
543
|
-
|
|
544
|
-
Register custom names and their partial Tasty objects in `theme.customStyles`.
|
|
545
|
-
Built-in names belong in `theme.styles` and reject misspelled sub-elements.
|
|
546
|
-
Custom names can also target a matching user-authored `data-tasty-anatomy` attribute.
|
|
547
|
-
The name must match the string passed to `defineComponent()` or
|
|
548
|
-
`resolveComponentStyles()`, or the `data-tasty-anatomy` value. A production
|
|
549
|
-
build warns when a configured custom name has no matching component style
|
|
550
|
-
resolver or rendered anatomy attribute.
|
|
551
|
-
|
|
552
|
-
The default renderer runs Tasty in Astro extract mode. Direct components and
|
|
553
|
-
the remaining document/vendor bridge styles are collected into shared static
|
|
554
|
-
CSS during the build, while appearance controls add only the small client
|
|
555
|
-
behavior needed to persist selected theme and contrast modes. The compact
|
|
556
|
-
Cookbook logo is shown beside the project title in the default top bar, links
|
|
557
|
-
to the localized home page, and is also the default generated favicon. Use
|
|
558
|
-
[`site.favicon`](./configuration.md#site-icons) to generate the complete icon
|
|
559
|
-
set from project artwork.
|
|
560
|
-
|
|
561
|
-
## Diff snippets
|
|
562
|
-
|
|
563
|
-
Use a `diff` code fence to highlight changed lines. Insertions and deletions
|
|
564
|
-
receive subtle theme-aware backgrounds while their `+` and `-` markers remain
|
|
565
|
-
visible for readers who do not distinguish the colors.
|
|
566
|
-
|
|
567
|
-
```diff
|
|
568
|
-
-formatOkhsl(v.h, v.s * 100, l * 100);
|
|
569
|
-
+formatOkhsl(v.h, v.s, l);
|
|
570
|
-
|
|
571
|
-
-formatOkhst(v.h, v.s * 100, v.t * 100);
|
|
572
|
-
+formatOkhst(v.h, v.s, v.t);
|
|
573
|
-
```
|
|
574
|
-
|
|
575
|
-
## Astro and MDX components
|
|
576
|
-
|
|
577
|
-
The facade exposes supported components from `@tenphi/cookbook/components`:
|
|
578
|
-
|
|
579
|
-
```mdx
|
|
580
|
-
import { Card, Logo, Preview, Steps, Tabs } from "@tenphi/cookbook/components";
|
|
581
|
-
|
|
582
|
-
<Card title="Package-first" href="/getting-started/">
|
|
583
|
-
Generate a site from a locked npm artifact.
|
|
584
|
-
</Card>
|
|
585
|
-
```
|
|
586
|
-
|
|
587
|
-
* `Card` renders a titled article or link.
|
|
588
|
-
* `Logo` renders the Cookbook mark using the active brand color.
|
|
589
|
-
* `Steps` provides an ordered steps container.
|
|
590
|
-
* `Tabs` and `Tab` provide accessible tabbed panels.
|
|
591
|
-
* `Callout` renders a note, tip, caution, or danger block.
|
|
592
|
-
* `CodeGroup` renders labeled source strings in tabs.
|
|
593
|
-
|
|
594
|
-
See [Authoring components](./authoring.mdx) for complete examples and props.
|
|
595
|
-
|
|
596
|
-
* `Preview` isolates HTML, CSS, and optional JavaScript in a sandboxed iframe.
|
|
597
|
-
The frame never receives same-origin access to the documentation page.
|
|
598
|
-
|
|
599
|
-
Use MDX only for repository content you control. Locked package content remains
|
|
600
|
-
Markdown-only unless the consumer explicitly sets `trust: "mdx"` for that
|
|
601
|
-
source.
|
|
602
|
-
|
|
603
|
-
## Authoring custom components
|
|
604
|
-
|
|
605
|
-
Import styling tools from `@tenphi/cookbook/styling`. They use the same Tasty
|
|
606
|
-
runtime as Cookbook, with its semantic colors, typography presets, units, and
|
|
607
|
-
responsive states. The renderer package also exposes them from
|
|
608
|
-
`@tenphi/renderer/styling`.
|
|
609
|
-
|
|
610
|
-
| Export | Purpose |
|
|
611
|
-
| ------------------------ | ---------------------------------------------------------------------------------- |
|
|
612
|
-
| `defineComponent` | Create a named Tasty component with its `theme.customStyles[name]` overrides. |
|
|
613
|
-
| `tasty` | Use Tasty directly without binding a component to `theme.customStyles`. |
|
|
614
|
-
| `useGlobalStyles` | Collect a global Tasty style tree while rendering a page. |
|
|
615
|
-
| `resolveComponentStyles` | Merge `theme.customStyles[name]` into a complete base style tree for global rules. |
|
|
616
|
-
| `mergeStyles` | Compose your own base styles with Tasty's deep-merge semantics. |
|
|
617
|
-
| `Styles` | TypeScript type for a Tasty style object. |
|
|
618
|
-
|
|
619
|
-
Cookbook supplies the React renderer and extracts these styles into its static
|
|
620
|
-
CSS. No additional Tasty dependency, Astro integration, or `client:*` directive
|
|
621
|
-
is needed for static components. Set shared tokens, presets, and states in
|
|
622
|
-
`docs.config.ts` before rendering. Import the styling entry point in component
|
|
623
|
-
modules; configuration files should use the main `@tenphi/cookbook` entry point.
|
|
624
|
-
|
|
625
|
-
### A shared site logo
|
|
626
|
-
|
|
627
|
-
Set `site.logo` once to use your artwork in the header and mobile drawer:
|
|
628
|
-
|
|
629
|
-
```ts
|
|
630
|
-
site: {
|
|
631
|
-
title: "Acme",
|
|
632
|
-
logo: "./assets/acme.svg"
|
|
633
|
-
}
|
|
634
|
-
```
|
|
635
|
-
|
|
636
|
-
Paths are local files relative to the resolved project root, just like
|
|
637
|
-
`site.favicon`. Cookbook reads the intrinsic dimensions and copies the image to
|
|
638
|
-
a content-hashed URL under the deployment base. SVG, PNG, JPEG, WebP, AVIF, and
|
|
639
|
-
GIF are supported. Missing or invalid files fail during setup.
|
|
640
|
-
|
|
641
|
-
```ts
|
|
642
|
-
site: {
|
|
643
|
-
title: "Acme",
|
|
644
|
-
logo: {
|
|
645
|
-
light: "./assets/acme-light.svg",
|
|
646
|
-
dark: "./assets/acme-dark.svg",
|
|
647
|
-
alt: "Acme documentation",
|
|
648
|
-
href: "/",
|
|
649
|
-
decorative: true
|
|
650
|
-
},
|
|
651
|
-
favicon: "./assets/acme-icon.svg"
|
|
652
|
-
}
|
|
653
|
-
```
|
|
654
|
-
|
|
655
|
-
Use `src` for one image, or both `light` and `dark`. Variants follow the
|
|
656
|
-
appearance control and the system preference in Auto mode. They must share an
|
|
657
|
-
aspect ratio to prevent layout shifts. Optional `width` and `height` describe
|
|
658
|
-
intrinsic dimensions; Tasty controls display size. Customize
|
|
659
|
-
`theme.styles.SiteLogo` and its complete anatomy: `Image`, `Light`, and `Dark`.
|
|
660
|
-
Wide wordmarks retain their proportions within the header.
|
|
661
|
-
|
|
662
|
-
The logo is decorative by default because the neighboring title labels the
|
|
663
|
-
site. Set `decorative: false` and `alt` when the image itself carries meaningful
|
|
664
|
-
text. The header logo link still has a name when the image is decorative.
|
|
665
|
-
`href` defaults to the localized documentation home; it accepts a root-relative
|
|
666
|
-
documentation route or HTTP(S) destination. The header title and drawer use the
|
|
667
|
-
same destination. `site.logo: false` removes the mark from both locations.
|
|
668
|
-
|
|
669
|
-
A logo does not change the favicon or touch icons. Configure `site.favicon`
|
|
670
|
-
separately for square artwork; the default Cookbook icon set remains in place
|
|
671
|
-
until changed. `Logo` remains available as the standalone Cookbook book mark.
|
|
672
|
-
|
|
673
|
-
The built-in mark uses `theme.palette["logo-surface"]` and `theme.palette["logo-mark"]`.
|
|
674
|
-
The default homepage hero artwork also uses `logo-surface` for its brand fill.
|
|
675
|
-
Both default to Glaze `mode: "fixed"`: the brand background and light book keep
|
|
676
|
-
their polarity in dark mode while respecting Glaze's tone boundaries and
|
|
677
|
-
high-contrast settings. The mark-to-background contrast floor is 3:1 normally
|
|
678
|
-
and 4.5:1 in high contrast. These colors are separate from interactive accents.
|
|
679
|
-
For example, to customize the logo background while retaining brand hue:
|
|
680
|
-
|
|
681
|
-
```ts
|
|
682
|
-
theme: {
|
|
683
|
-
brand: { from: "#315efb" },
|
|
684
|
-
palette: {
|
|
685
|
-
"logo-surface": {
|
|
686
|
-
base: "logo-mark",
|
|
687
|
-
tone: 40,
|
|
688
|
-
saturation: 0.8,
|
|
689
|
-
mode: "fixed",
|
|
690
|
-
contrast: { wcag: [3, 4.5] },
|
|
691
|
-
},
|
|
692
|
-
"logo-mark": { tone: 100, saturation: 0, mode: "fixed" },
|
|
693
|
-
},
|
|
694
|
-
}
|
|
695
|
-
```
|
|
696
|
-
|
|
697
|
-
Custom image assets keep their authored colors; use `light`/`dark` files when
|
|
698
|
-
you want distinct artwork. Header and drawer home links center logos with the
|
|
699
|
-
site title regardless of their aspect ratio. Use `theme.styles.SiteLogo` for
|
|
700
|
-
image size and `theme.styles.Header.SiteTitle` / `Sidebar.HomeLink`
|
|
701
|
-
for typography; they do not need baseline offsets for a different preset.
|
|
702
|
-
|
|
703
|
-
### Advanced site title markup
|
|
704
|
-
|
|
705
|
-
To put your own logo and title in one home link, create
|
|
706
|
-
`docs/components/site-title.ts`:
|
|
707
|
-
|
|
708
|
-
```ts
|
|
709
|
-
import { defineComponent } from "@tenphi/cookbook/styling";
|
|
710
|
-
|
|
711
|
-
export const SiteTitleRoot = defineComponent("ProjectSiteTitle", {
|
|
712
|
-
as: "a",
|
|
713
|
-
styles: {
|
|
714
|
-
display: "flex",
|
|
715
|
-
alignItems: "center",
|
|
716
|
-
gap: "1x",
|
|
717
|
-
inlineSize: "min 0",
|
|
718
|
-
color: "#text",
|
|
719
|
-
preset: { "": "h4 / strong", "@mobile": "h5 / strong" },
|
|
720
|
-
textDecoration: "none",
|
|
721
|
-
Logo: {
|
|
722
|
-
$: "> svg",
|
|
723
|
-
display: "block",
|
|
724
|
-
flexShrink: "0",
|
|
725
|
-
inlineSize: { "": "2rem", "@mobile": "1.75rem" },
|
|
726
|
-
blockSize: { "": "2rem", "@mobile": "1.75rem" },
|
|
727
|
-
color: "#accent-text",
|
|
728
|
-
},
|
|
729
|
-
Label: {
|
|
730
|
-
$: "> span",
|
|
731
|
-
inlineSize: "min 0",
|
|
732
|
-
overflow: "hidden",
|
|
733
|
-
textOverflow: "ellipsis",
|
|
734
|
-
whiteSpace: "nowrap",
|
|
735
|
-
},
|
|
736
|
-
},
|
|
737
|
-
});
|
|
738
|
-
```
|
|
739
|
-
|
|
740
|
-
Then create `docs/components/SiteTitle.astro`, using an SVG whose paths use
|
|
741
|
-
`currentColor` to follow the semantic accent color:
|
|
742
|
-
|
|
743
|
-
```astro
|
|
744
|
-
---
|
|
745
|
-
import ProjectLogo from "../../public/logo.svg";
|
|
746
|
-
import { SiteTitleRoot } from "./site-title.js";
|
|
747
|
-
|
|
748
|
-
const { siteTitle, siteTitleHref } = Astro.locals.cookbookRoute;
|
|
749
|
-
---
|
|
750
|
-
|
|
751
|
-
<SiteTitleRoot href={siteTitleHref}>
|
|
752
|
-
<ProjectLogo aria-hidden="true" focusable="false" />
|
|
753
|
-
<span translate="no">{siteTitle}</span>
|
|
754
|
-
</SiteTitleRoot>
|
|
755
|
-
```
|
|
756
|
-
|
|
757
|
-
Register the replacement in `docs.config.ts` and disable the shared mark.
|
|
758
|
-
A `SiteTitle` override affects the header; use `site.logo` above for ordinary
|
|
759
|
-
branding shared with the drawer. For custom drawer markup, override `Sidebar`.
|
|
760
|
-
The custom component supports root styles plus its complete list of named
|
|
761
|
-
sub-elements: `Logo` and `Label`.
|
|
762
|
-
|
|
763
|
-
```ts
|
|
764
|
-
site: { logo: false },
|
|
765
|
-
components: {
|
|
766
|
-
overrides: {
|
|
767
|
-
SiteTitle: "./docs/components/SiteTitle.astro"
|
|
768
|
-
}
|
|
769
|
-
},
|
|
770
|
-
theme: {
|
|
771
|
-
customStyles: {
|
|
772
|
-
ProjectSiteTitle: { Logo: { color: "#text" } }
|
|
773
|
-
}
|
|
774
|
-
}
|
|
775
|
-
```
|
|
776
|
-
|
|
777
|
-
`defineComponent(name, options)` accepts Tasty factory options and a name for
|
|
778
|
-
`theme.customStyles[name]`. It merges the configured partial style object before
|
|
779
|
-
creating the component, retaining the other base properties and responsive
|
|
780
|
-
states. Tasty options such as `elements`, `variants`, `styleProps`, `modProps`,
|
|
781
|
-
and `tokenProps` keep their behavior and inferred types, including generated
|
|
782
|
-
subcomponents such as `Component.Label`.
|
|
783
|
-
Configured styles become the component's defaults; variants and styles passed
|
|
784
|
-
at render time follow Tasty's usual precedence.
|
|
785
|
-
|
|
786
|
-
Use `defineComponent` when authoring a component that should support
|
|
787
|
-
`theme.customStyles`. Use `tasty` directly for ordinary Tasty creation or composition
|
|
788
|
-
that does not need a configuration name. To define a named component around
|
|
789
|
-
an existing React component that forwards `className`, pass it as `as` in the options. Use `className`
|
|
790
|
-
when passing a class to a Tasty component from Astro.
|
|
791
|
-
|
|
792
|
-
### Global style trees
|
|
793
|
-
|
|
794
|
-
For markup you do not render through a Tasty component, call
|
|
795
|
-
`useGlobalStyles()` during rendering. For example, this Astro component
|
|
796
|
-
supports root styles and a `Label` sub-element through `theme.customStyles.ProjectNote`:
|
|
797
|
-
|
|
798
|
-
```astro
|
|
799
|
-
---
|
|
800
|
-
import {
|
|
801
|
-
resolveComponentStyles,
|
|
802
|
-
useGlobalStyles,
|
|
803
|
-
} from "@tenphi/cookbook/styling";
|
|
804
|
-
|
|
805
|
-
useGlobalStyles(
|
|
806
|
-
".project-note",
|
|
807
|
-
resolveComponentStyles("ProjectNote", {
|
|
808
|
-
padding: "2x",
|
|
809
|
-
fill: "#surface-2",
|
|
810
|
-
Label: { $: "> strong", color: "#text", preset: "strong" },
|
|
811
|
-
}),
|
|
812
|
-
);
|
|
813
|
-
---
|
|
814
|
-
|
|
815
|
-
<aside class="project-note"><strong>Note</strong><slot /></aside>
|
|
816
|
-
```
|
|
817
|
-
|
|
818
|
-
`defineComponent` and `resolveComponentStyles` read the same `theme.customStyles`
|
|
819
|
-
configuration; user configuration contains only the properties to change. They do not require a
|
|
820
|
-
`data-tasty-anatomy` attribute. That attribute remains available for older
|
|
821
|
-
components using the compatibility bridge described above.
|
|
822
|
-
|
|
823
|
-
## Linting custom styles
|
|
824
|
-
|
|
825
|
-
`@tenphi/cookbook/eslint-plugin` re-exports the Tasty ESLint plugin together with
|
|
826
|
-
Cookbook's `validationConfig`. The renderer offers the same exports from
|
|
827
|
-
`@tenphi/renderer/eslint-plugin`. Keep style definitions in `.ts` or `.tsx`
|
|
828
|
-
modules, as in the site title example above, to lint them with either ESLint or
|
|
829
|
-
oxlint.
|
|
830
|
-
|
|
831
|
-
Create `tasty.config.ts` at your project root:
|
|
832
|
-
|
|
833
|
-
```ts
|
|
834
|
-
export default {
|
|
835
|
-
extends: "@tenphi/cookbook",
|
|
836
|
-
};
|
|
837
|
-
```
|
|
838
|
-
|
|
839
|
-
Renderer-only consumers can use `extends: "@tenphi/renderer"` instead.
|
|
840
|
-
The preset registers both Cookbook styling import paths, its built-in tokens,
|
|
841
|
-
units, responsive states, and typography presets. It also describes
|
|
842
|
-
`defineComponent`, `resolveComponentStyles`, and `mergeStyles`, so their inline
|
|
843
|
-
style objects, variants, and named sub-elements receive the same checks as
|
|
844
|
-
`tasty()` calls. Partial overrides passed to `mergeStyles` may omit default state
|
|
845
|
-
values and retain the plugin's safeguards against fixes that replace base styles.
|
|
846
|
-
|
|
847
|
-
### ESLint
|
|
848
|
-
|
|
849
|
-
Install ESLint and a TypeScript parser:
|
|
850
|
-
|
|
851
|
-
```sh
|
|
852
|
-
pnpm add -D eslint @typescript-eslint/parser
|
|
853
|
-
```
|
|
854
|
-
|
|
855
|
-
Add the plugin to `eslint.config.mjs`:
|
|
856
|
-
|
|
857
|
-
```js
|
|
858
|
-
import parser from "@typescript-eslint/parser";
|
|
859
|
-
import tasty from "@tenphi/cookbook/eslint-plugin";
|
|
860
|
-
|
|
861
|
-
export default [
|
|
862
|
-
{
|
|
863
|
-
...tasty.configs.recommended,
|
|
864
|
-
files: ["**/*.{ts,tsx}"],
|
|
865
|
-
languageOptions: { parser },
|
|
866
|
-
},
|
|
867
|
-
];
|
|
868
|
-
```
|
|
869
|
-
|
|
870
|
-
Run `pnpm exec eslint docs/components --max-warnings 0`. Use
|
|
871
|
-
`tasty.configs.strict` for additional checks, including custom property names and
|
|
872
|
-
runtime style values. The named `recommended` and `strict` exports contain rule
|
|
873
|
-
maps for configurations that register the plugin themselves.
|
|
874
|
-
|
|
875
|
-
### oxlint
|
|
876
|
-
|
|
877
|
-
Install oxlint:
|
|
878
|
-
|
|
879
|
-
```sh
|
|
880
|
-
pnpm add -D oxlint
|
|
881
|
-
```
|
|
882
|
-
|
|
883
|
-
Create `oxlint.config.mjs` using its JavaScript plugin support:
|
|
884
|
-
|
|
885
|
-
```js
|
|
886
|
-
import { recommended } from "@tenphi/cookbook/eslint-plugin";
|
|
887
|
-
|
|
888
|
-
export default {
|
|
889
|
-
jsPlugins: [{ name: "tasty", specifier: "@tenphi/cookbook/eslint-plugin" }],
|
|
890
|
-
rules: recommended,
|
|
891
|
-
};
|
|
892
|
-
```
|
|
893
|
-
|
|
894
|
-
Run `pnpm exec oxlint --config oxlint.config.mjs docs/components --deny-warnings`.
|
|
895
|
-
The `tasty` alias keeps rule names such as `tasty/known-property` consistent with
|
|
896
|
-
ESLint. Import `strict` instead of `recommended` to enable the stricter rule map.
|
|
897
|
-
Both presets are tested with oxlint 1.83.0; JavaScript plugin support is experimental.
|
|
898
|
-
|
|
899
|
-
### Custom theme names
|
|
900
|
-
|
|
901
|
-
Add names introduced by your `docs.config.ts` theme to the validation config.
|
|
902
|
-
For example, after defining `theme.tokens["$project-gap"]`, `theme.states["@project-wide"]`,
|
|
903
|
-
and `theme.presets["project-title"]`:
|
|
904
|
-
|
|
905
|
-
```ts
|
|
906
|
-
import type { TastyValidationConfig } from "@tenphi/cookbook/eslint-plugin";
|
|
907
|
-
|
|
908
|
-
export default {
|
|
909
|
-
extends: "@tenphi/cookbook",
|
|
910
|
-
tokens: ["$project-gap"],
|
|
911
|
-
states: ["@project-wide"],
|
|
912
|
-
presets: ["project-title"],
|
|
913
|
-
} satisfies TastyValidationConfig;
|
|
914
|
-
```
|
|
915
|
-
|
|
916
|
-
`extends` merges and deduplicates these arrays with the inherited configuration,
|
|
917
|
-
so list only your additions. It also inherits the styling helper signatures;
|
|
918
|
-
entries you add to `styleFunctions` override inherited signatures by function name.
|
|
919
|
-
The exported `validationConfig` object remains available for programmatic use.
|
|
920
|
-
The entry point also exports the upstream `StyleFunctionConfig` and
|
|
921
|
-
`ResolvedConfig` types for shared lint configurations. Additional imported
|
|
922
|
-
helpers can be registered in `styleFunctions`; use `partial: true` for helpers
|
|
923
|
-
that merge overrides into existing styles.
|
|
924
|
-
|
|
925
|
-
## Static behavior
|
|
926
|
-
|
|
927
|
-
Documentation content, navigation, headings, code, and images remain readable
|
|
928
|
-
without client JavaScript. Search, mobile navigation, copy controls, appearance
|
|
929
|
-
persistence, and executable previews can progressively enhance the static
|
|
930
|
-
output.
|
|
931
|
-
|
|
932
|
-
### Responsive header and navigation
|
|
933
|
-
|
|
934
|
-
The header uses `#header`, generated from `theme.palette.header` (or the page
|
|
935
|
-
surface) at 70% opacity in all four appearance modes, with a 16px backdrop blur.
|
|
936
|
-
Customize the outer bar with `theme.styles.HeaderFrame`, its contents with
|
|
937
|
-
`Header`, and header buttons with `HeaderLinks` and `SearchButton`.
|
|
938
|
-
|
|
939
|
-
Below 50rem, page navigation moves into a header row and opens a left drawer.
|
|
940
|
-
`MobileMenuToggle.Section` and `Page` style its breadcrumb labels. The drawer
|
|
941
|
-
contains the complete active section, a collapsible `MobileNavigationTabs`
|
|
942
|
-
selector, and a close button. The drawer slides in and out over 120ms and
|
|
943
|
-
disables motion when the reader prefers reduced motion. Its mobile shadow uses
|
|
944
|
-
the Glaze `shadow`-typed `#shadow` token. Customize the movement and shadow through
|
|
945
|
-
`theme.styles.Sidebar`, and the underlay through `Sidebar.Backdrop` and
|
|
946
|
-
`OpenBackdrop`. `theme.palette.overlay` supplies the underlay declaration, which defaults
|
|
947
|
-
to black at 50% opacity. Glaze resolves it in fixed mode with tone remapping
|
|
948
|
-
disabled, so it stays black in dark and high-contrast schemes.
|
|
949
|
-
Icon buttons retain their plain desktop appearance on mobile. More uses
|
|
950
|
-
left-aligned navigation links with a `1bw` gap, without primary button variants.
|
|
951
|
-
`HeaderLinks.PanelLink` styles the menu rows; `FirstPanelLink` reserves space
|
|
952
|
-
for the close button. The inset divider above the tabs belongs to `TopNavigation`.
|
|
953
|
-
|
|
954
|
-
The desktop table of contents is hidden below 72rem. Set
|
|
955
|
-
`tableOfContents: { mobile: true }` to show an optional compact disclosure there.
|
|
956
|
-
On desktop, the current section is marked as the page scrolls and its link stays
|
|
957
|
-
visible in a long contents list. Customize its appearance with
|
|
958
|
-
`theme.styles.TableOfContents.CurrentLink`.
|
|
959
|
-
`MobileTableOfContents` owns its summary and links; `TableOfContentsLayout`
|
|
960
|
-
controls placement. `Layout` controls shared
|
|
961
|
-
navigation dimensions and the drawer's scroll lock; `PageFrame` styles the
|
|
962
|
-
page container and content columns.
|
|
963
|
-
|
|
964
|
-
### Header control shape
|
|
965
|
-
|
|
966
|
-
Header buttons and the mobile drawer close button use the independent
|
|
967
|
-
`$header-control-radius` token, which defaults to `999px` for pill and circular
|
|
968
|
-
shapes. Set it to `8px` for the same corners as the default content controls:
|
|
969
|
-
|
|
970
|
-
```ts
|
|
971
|
-
theme: {
|
|
972
|
-
tokens: { "$header-control-radius": "8px" }
|
|
973
|
-
}
|
|
974
|
-
```
|
|
975
|
-
|
|
976
|
-
`$radius` continues to control code-copy buttons, navigation items, and other
|
|
977
|
-
content controls. Individual `theme.styles` overrides still take precedence.
|
|
978
|
-
The mobile header divider spans the viewport while its content keeps the
|
|
979
|
-
configured horizontal padding.
|
|
980
|
-
|
|
981
139
|
### Add palette colors and reference other roles
|
|
982
140
|
|
|
983
141
|
Every `theme.palette` entry participates in one Glaze color graph. Use lowercase
|
|
@@ -1021,64 +179,6 @@ explicitly for a colored label; the mix/shadow dependency graph stays intact.
|
|
|
1021
179
|
A shadow status also uses a neutral derived surface, because Glaze does not allow
|
|
1022
180
|
a shadow to be a mix target. Override the surface separately when needed.
|
|
1023
181
|
|
|
1024
|
-
### Register units and recipes
|
|
1025
|
-
|
|
1026
|
-
Register custom units and flat recipes in `theme`; Cookbook configures Tasty
|
|
1027
|
-
before evaluating your components:
|
|
1028
|
-
|
|
1029
|
-
```ts
|
|
1030
|
-
theme: {
|
|
1031
|
-
brand: { from: "#315efb" },
|
|
1032
|
-
palette: {
|
|
1033
|
-
"review-panel": { base: "surface", tone: "-2", saturation: 0.05 },
|
|
1034
|
-
"review-ink": { base: "review-panel", tone: 0, contrast: { wcag: [7, 10] } },
|
|
1035
|
-
},
|
|
1036
|
-
units: { rh: "6px" },
|
|
1037
|
-
recipes: {
|
|
1038
|
-
"review-panel": {
|
|
1039
|
-
fill: "#review-panel",
|
|
1040
|
-
color: "#review-ink",
|
|
1041
|
-
padding: "2rh",
|
|
1042
|
-
radius: "3px",
|
|
1043
|
-
},
|
|
1044
|
-
},
|
|
1045
|
-
customStyles: { DemoBadge: { Label: { color: "#review-ink" } } },
|
|
1046
|
-
},
|
|
1047
|
-
```
|
|
1048
|
-
|
|
1049
|
-
```ts
|
|
1050
|
-
import { defineComponent } from "@tenphi/cookbook/styling";
|
|
1051
|
-
|
|
1052
|
-
export const DemoBadge = defineComponent("DemoBadge", {
|
|
1053
|
-
as: "aside",
|
|
1054
|
-
elements: { Label: "strong" },
|
|
1055
|
-
styles: {
|
|
1056
|
-
display: "block",
|
|
1057
|
-
recipe: "review-panel",
|
|
1058
|
-
Label: { preset: "h4" },
|
|
1059
|
-
},
|
|
1060
|
-
});
|
|
1061
|
-
```
|
|
1062
|
-
|
|
1063
|
-
Use `<DemoBadge><DemoBadge.Label>Review ready</DemoBadge.Label></DemoBadge>` in
|
|
1064
|
-
MDX. Keep these styled components server-rendered: their CSS is extracted at
|
|
1065
|
-
build time. Add behavior with a small client script targeting the rendered
|
|
1066
|
-
markup. This recipe produces 12px padding. Units merge by name, with the later
|
|
1067
|
-
configuration winning. Recipes merge using Tasty `mergeStyles`, including state
|
|
1068
|
-
maps. Recipes are flat: define named sub-elements on the owning component, and
|
|
1069
|
-
compose recipes with `recipe: "base elevated"` rather than referencing a recipe
|
|
1070
|
-
inside another recipe. `none` is a reserved recipe name. Cookbook's built-in
|
|
1071
|
-
units are `x`, `r`, `cr`, and `bw`; overriding one changes its meaning globally.
|
|
1072
|
-
|
|
1073
|
-
Keep editor and linter validation synchronized with your configuration:
|
|
1074
|
-
|
|
1075
|
-
```ts
|
|
1076
|
-
// tasty.config.ts
|
|
1077
|
-
import { createValidationConfig } from "@tenphi/cookbook/eslint-plugin";
|
|
1078
|
-
import docs from "./docs.config";
|
|
1079
|
-
export default createValidationConfig(docs.theme);
|
|
1080
|
-
```
|
|
1081
|
-
|
|
1082
182
|
### Configure Glaze adaptation
|
|
1083
183
|
|
|
1084
184
|
`theme.glaze` accepts `lightTone`, `darkTone`, `darkDesaturation`, `autoFlip`,
|
|
@@ -1125,7 +225,7 @@ directly to Tasty `#name` tokens. `COOKBOOK_PALETTE_NAMES`, exported from
|
|
|
1125
225
|
| Additional hues | `orange`, `green`, `blue`, `purple`, `red`, each with `-text` and `-surface` variants |
|
|
1126
226
|
| 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` |
|
|
1127
227
|
|
|
1128
|
-
|
|
228
|
+
### Contrast checks and troubleshooting
|
|
1129
229
|
|
|
1130
230
|
Cookbook checks text, headings, muted reading text, brand links, filled-control
|
|
1131
231
|
labels, status text on its tinted surface, focus rings on each elevated
|
|
@@ -1154,69 +254,136 @@ Keep contrast requirements when adjusting colors. Extreme custom tone windows,
|
|
|
1154
254
|
fixed colors, or opacity can prevent a requested floor from being met. A palette
|
|
1155
255
|
check does not replace keyboard, screen-reader, and rendered-page testing.
|
|
1156
256
|
|
|
1157
|
-
##
|
|
257
|
+
## Design tokens
|
|
258
|
+
|
|
259
|
+
Token names follow Tasty's
|
|
260
|
+
[token and unit syntax](./upstream/tasty/docs/dsl.md#built-in-units): `$name`
|
|
261
|
+
becomes the CSS custom property `--name`. Existing `--name` keys are still
|
|
262
|
+
accepted for compatibility.
|
|
263
|
+
|
|
264
|
+
```ts
|
|
265
|
+
theme: {
|
|
266
|
+
tokens: {
|
|
267
|
+
"$gap": "0.5rem",
|
|
268
|
+
"$radius": "8px",
|
|
269
|
+
"$card-radius": "16px",
|
|
270
|
+
"$border-width": "1px",
|
|
271
|
+
"$outline-width": "2px",
|
|
272
|
+
"$outline-offset": "2px",
|
|
273
|
+
"$control-height": "2.5rem",
|
|
274
|
+
"$layout-width": "87.5rem",
|
|
275
|
+
"$content-width": "58rem",
|
|
276
|
+
"$sidebar-width": "17.5rem"
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
`layout-width` caps and centers the complete documentation shell, while
|
|
282
|
+
`content-width` limits the reading column inside it. `radius` is the control
|
|
283
|
+
and navigation radius; `card-radius` is the larger surface radius. Keeping
|
|
284
|
+
those roles separate makes a sharp control theme or a soft card theme possible
|
|
285
|
+
without one-off component overrides.
|
|
286
|
+
|
|
287
|
+
### Register units and recipes
|
|
1158
288
|
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
For example, a compact search dialog and quieter pagination need no CSS:
|
|
289
|
+
Register custom units and flat recipes in `theme`; Cookbook configures Tasty
|
|
290
|
+
before evaluating your components:
|
|
1162
291
|
|
|
1163
292
|
```ts
|
|
1164
293
|
theme: {
|
|
294
|
+
brand: { from: "#315efb" },
|
|
295
|
+
palette: {
|
|
296
|
+
"review-panel": { base: "surface", tone: "-2", saturation: 0.05 },
|
|
297
|
+
"review-ink": { base: "review-panel", tone: 0, contrast: { wcag: [7, 10] } },
|
|
298
|
+
},
|
|
299
|
+
units: { rh: "6px" },
|
|
300
|
+
recipes: {
|
|
301
|
+
"review-panel": {
|
|
302
|
+
fill: "#review-panel",
|
|
303
|
+
color: "#review-ink",
|
|
304
|
+
padding: "2rh",
|
|
305
|
+
radius: "3px",
|
|
306
|
+
},
|
|
307
|
+
},
|
|
308
|
+
customStyles: { DemoBadge: { Label: { color: "#review-ink" } } },
|
|
309
|
+
},
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
```ts
|
|
313
|
+
import { defineComponent } from "@tenphi/cookbook/styling";
|
|
314
|
+
|
|
315
|
+
export const DemoBadge = defineComponent("DemoBadge", {
|
|
316
|
+
as: "aside",
|
|
317
|
+
elements: { Label: "strong" },
|
|
1165
318
|
styles: {
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
Banner: { padding: "1x 2x" },
|
|
1170
|
-
Markdown: { Quote: { color: "#text", inlinePadding: "3x start" } },
|
|
319
|
+
display: "block",
|
|
320
|
+
recipe: "review-panel",
|
|
321
|
+
Label: { preset: "h4" },
|
|
1171
322
|
},
|
|
1172
|
-
}
|
|
323
|
+
});
|
|
1173
324
|
```
|
|
1174
325
|
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
326
|
+
Use `<DemoBadge><DemoBadge.Label>Review ready</DemoBadge.Label></DemoBadge>` in
|
|
327
|
+
MDX. Keep these styled components server-rendered: their CSS is extracted at
|
|
328
|
+
build time. Add behavior with a small client script targeting the rendered
|
|
329
|
+
markup. This recipe produces 12px padding. Units merge by name, with the later
|
|
330
|
+
configuration winning. Recipes merge using Tasty `mergeStyles`, including state
|
|
331
|
+
maps. Recipes are flat: define named sub-elements on the owning component, and
|
|
332
|
+
compose recipes with `recipe: "base elevated"` rather than referencing a recipe
|
|
333
|
+
inside another recipe. `none` is a reserved recipe name. Cookbook's built-in
|
|
334
|
+
units are `x`, `r`, `cr`, and `bw`; overriding one changes its meaning globally.
|
|
1181
335
|
|
|
1182
|
-
|
|
1183
|
-
overrides during server rendering. Units, recipes, states, and presets are
|
|
1184
|
-
resolved there and emitted as static CSS. Cookbook ships no Tasty/Glaze browser
|
|
1185
|
-
runtime, theme configuration, or style hydration setup. Browser scripts and
|
|
1186
|
-
`client:*` islands must not import Cookbook styling, Tasty, or Glaze; the build
|
|
1187
|
-
rejects these imports. Attach small interaction scripts to server-rendered markup
|
|
1188
|
-
or pass already-styled static markup into a client island.
|
|
336
|
+
Keep editor and linter validation synchronized with your configuration:
|
|
1189
337
|
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
338
|
+
```ts
|
|
339
|
+
// tasty.config.ts
|
|
340
|
+
import { createValidationConfig } from "@tenphi/cookbook/eslint-plugin";
|
|
341
|
+
import docs from "./docs.config";
|
|
342
|
+
export default createValidationConfig(docs.theme);
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
## Typography presets
|
|
1195
346
|
|
|
1196
|
-
|
|
347
|
+
Cookbook supplies semantic `body`, `heading`, `h1`–`h6`, `navigation`, `small`,
|
|
348
|
+
and `code` presets. Change their families, sizes, and weights through
|
|
349
|
+
`theme.fonts` and `theme.presets`. See [Fonts and typography](./fonts-and-typography.md)
|
|
350
|
+
for local and Google font examples, cache behavior, and preset details.
|
|
1197
351
|
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
`theme.palette["syntax-bg"]` to give code its own color seed;
|
|
1204
|
-
syntax text and token contrast resolve against that surface. Code fences, including
|
|
1205
|
-
MDX and diff blocks, use classes without inline style attributes. Custom Shiki
|
|
1206
|
-
transformers should emit classes; unsupported inline declarations fail with a
|
|
1207
|
-
configuration hint.
|
|
352
|
+
### Change font families
|
|
353
|
+
|
|
354
|
+
Use `theme.fonts` to load Google families by name or local font files. The
|
|
355
|
+
[font guide](./fonts-and-typography.md#change-font-families) explains both
|
|
356
|
+
paths and how to select weights and styles.
|
|
1208
357
|
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
358
|
+
## Style customization
|
|
359
|
+
|
|
360
|
+
Use a partial Tasty style object at `theme.styles.<ComponentName>` to change a
|
|
361
|
+
built-in surface. Cookbook merges it with the complete base style object before
|
|
362
|
+
CSS extraction. The [component styles reference](./component-styles.md) gives
|
|
363
|
+
examples and the complete list of named sub-elements for every surface.
|
|
364
|
+
|
|
365
|
+
## Authoring custom components
|
|
366
|
+
|
|
367
|
+
Use `defineComponent()` for a configurable component root and
|
|
368
|
+
`resolveComponentStyles()` for an owned global style tree. Keep styling on the
|
|
369
|
+
server so the browser receives extracted CSS. The
|
|
370
|
+
[custom component guide](./custom-components.md) covers both patterns.
|
|
371
|
+
|
|
372
|
+
### A shared site logo
|
|
373
|
+
|
|
374
|
+
For ordinary branding, set `site.logo` once for the header and mobile drawer.
|
|
375
|
+
Use the [logo guide](./custom-components.md#a-shared-site-logo) for image
|
|
376
|
+
variants, accessibility, and advanced title markup.
|
|
377
|
+
|
|
378
|
+
## Linting custom styles
|
|
379
|
+
|
|
380
|
+
Adopt Cookbook's Tasty validation preset and register your additional names.
|
|
381
|
+
See [Linting custom styles](./custom-components.md#linting-custom-styles) for
|
|
382
|
+
ESLint and oxlint examples.
|
|
383
|
+
|
|
384
|
+
## Static behavior
|
|
1218
385
|
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
386
|
+
The page content remains readable without client JavaScript. Search, menus,
|
|
387
|
+
copy controls, and appearance persistence enhance the static HTML. See
|
|
388
|
+
[Component styles](./component-styles.md#static-behavior) for the boundary and
|
|
389
|
+
responsive UI behavior.
|