@tenphi/tasty 0.0.0-snapshot.05c1c22
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/LICENSE +21 -0
- package/README.md +629 -0
- package/dist/_virtual/_rolldown/runtime.js +7 -0
- package/dist/chunks/cacheKey.d.ts +1 -0
- package/dist/chunks/cacheKey.js +77 -0
- package/dist/chunks/cacheKey.js.map +1 -0
- package/dist/chunks/definitions.d.ts +37 -0
- package/dist/chunks/definitions.js +258 -0
- package/dist/chunks/definitions.js.map +1 -0
- package/dist/chunks/index.d.ts +1 -0
- package/dist/chunks/renderChunk.d.ts +1 -0
- package/dist/chunks/renderChunk.js +59 -0
- package/dist/chunks/renderChunk.js.map +1 -0
- package/dist/config.d.ts +366 -0
- package/dist/config.js +503 -0
- package/dist/config.js.map +1 -0
- package/dist/core/index.d.ts +33 -0
- package/dist/core/index.js +26 -0
- package/dist/counter-style/index.js +51 -0
- package/dist/counter-style/index.js.map +1 -0
- package/dist/debug.d.ts +89 -0
- package/dist/debug.js +453 -0
- package/dist/debug.js.map +1 -0
- package/dist/font-face/index.js +63 -0
- package/dist/font-face/index.js.map +1 -0
- package/dist/hooks/index.d.ts +7 -0
- package/dist/hooks/resolve-ssr-collector.js +14 -0
- package/dist/hooks/resolve-ssr-collector.js.map +1 -0
- package/dist/hooks/useCounterStyle.d.ts +50 -0
- package/dist/hooks/useCounterStyle.js +46 -0
- package/dist/hooks/useCounterStyle.js.map +1 -0
- package/dist/hooks/useFontFace.d.ts +43 -0
- package/dist/hooks/useFontFace.js +70 -0
- package/dist/hooks/useFontFace.js.map +1 -0
- package/dist/hooks/useGlobalStyles.d.ts +30 -0
- package/dist/hooks/useGlobalStyles.js +78 -0
- package/dist/hooks/useGlobalStyles.js.map +1 -0
- package/dist/hooks/useKeyframes.d.ts +56 -0
- package/dist/hooks/useKeyframes.js +64 -0
- package/dist/hooks/useKeyframes.js.map +1 -0
- package/dist/hooks/useProperty.d.ts +79 -0
- package/dist/hooks/useProperty.js +109 -0
- package/dist/hooks/useProperty.js.map +1 -0
- package/dist/hooks/useRawCSS.d.ts +53 -0
- package/dist/hooks/useRawCSS.js +35 -0
- package/dist/hooks/useRawCSS.js.map +1 -0
- package/dist/hooks/useStyles.d.ts +45 -0
- package/dist/hooks/useStyles.js +237 -0
- package/dist/hooks/useStyles.js.map +1 -0
- package/dist/index.d.ts +50 -0
- package/dist/index.js +35 -0
- package/dist/injector/index.d.ts +183 -0
- package/dist/injector/index.js +179 -0
- package/dist/injector/index.js.map +1 -0
- package/dist/injector/injector.d.ts +166 -0
- package/dist/injector/injector.js +464 -0
- package/dist/injector/injector.js.map +1 -0
- package/dist/injector/sheet-manager.d.ts +136 -0
- package/dist/injector/sheet-manager.js +733 -0
- package/dist/injector/sheet-manager.js.map +1 -0
- package/dist/injector/types.d.ts +204 -0
- package/dist/keyframes/index.js +206 -0
- package/dist/keyframes/index.js.map +1 -0
- package/dist/parser/classify.js +319 -0
- package/dist/parser/classify.js.map +1 -0
- package/dist/parser/const.js +49 -0
- package/dist/parser/const.js.map +1 -0
- package/dist/parser/lru.js +109 -0
- package/dist/parser/lru.js.map +1 -0
- package/dist/parser/parser.d.ts +25 -0
- package/dist/parser/parser.js +115 -0
- package/dist/parser/parser.js.map +1 -0
- package/dist/parser/tokenizer.js +69 -0
- package/dist/parser/tokenizer.js.map +1 -0
- package/dist/parser/types.d.ts +51 -0
- package/dist/parser/types.js +46 -0
- package/dist/parser/types.js.map +1 -0
- package/dist/pipeline/conditions.d.ts +134 -0
- package/dist/pipeline/conditions.js +406 -0
- package/dist/pipeline/conditions.js.map +1 -0
- package/dist/pipeline/exclusive.js +230 -0
- package/dist/pipeline/exclusive.js.map +1 -0
- package/dist/pipeline/index.d.ts +55 -0
- package/dist/pipeline/index.js +708 -0
- package/dist/pipeline/index.js.map +1 -0
- package/dist/pipeline/materialize.js +1103 -0
- package/dist/pipeline/materialize.js.map +1 -0
- package/dist/pipeline/parseStateKey.d.ts +15 -0
- package/dist/pipeline/parseStateKey.js +446 -0
- package/dist/pipeline/parseStateKey.js.map +1 -0
- package/dist/pipeline/simplify.js +515 -0
- package/dist/pipeline/simplify.js.map +1 -0
- package/dist/pipeline/warnings.js +18 -0
- package/dist/pipeline/warnings.js.map +1 -0
- package/dist/plugins/index.d.ts +2 -0
- package/dist/plugins/okhsl-plugin.d.ts +35 -0
- package/dist/plugins/okhsl-plugin.js +97 -0
- package/dist/plugins/okhsl-plugin.js.map +1 -0
- package/dist/plugins/types.d.ts +76 -0
- package/dist/properties/index.js +222 -0
- package/dist/properties/index.js.map +1 -0
- package/dist/properties/property-type-resolver.d.ts +24 -0
- package/dist/properties/property-type-resolver.js +90 -0
- package/dist/properties/property-type-resolver.js.map +1 -0
- package/dist/ssr/astro.d.ts +29 -0
- package/dist/ssr/astro.js +64 -0
- package/dist/ssr/astro.js.map +1 -0
- package/dist/ssr/async-storage.d.ts +17 -0
- package/dist/ssr/async-storage.js +34 -0
- package/dist/ssr/async-storage.js.map +1 -0
- package/dist/ssr/collect-auto-properties.js +39 -0
- package/dist/ssr/collect-auto-properties.js.map +1 -0
- package/dist/ssr/collector.d.ts +102 -0
- package/dist/ssr/collector.js +226 -0
- package/dist/ssr/collector.js.map +1 -0
- package/dist/ssr/context.d.ts +8 -0
- package/dist/ssr/context.js +13 -0
- package/dist/ssr/context.js.map +1 -0
- package/dist/ssr/format-global-rules.js +22 -0
- package/dist/ssr/format-global-rules.js.map +1 -0
- package/dist/ssr/format-keyframes.js +69 -0
- package/dist/ssr/format-keyframes.js.map +1 -0
- package/dist/ssr/format-property.js +49 -0
- package/dist/ssr/format-property.js.map +1 -0
- package/dist/ssr/format-rules.js +73 -0
- package/dist/ssr/format-rules.js.map +1 -0
- package/dist/ssr/hydrate.d.ts +22 -0
- package/dist/ssr/hydrate.js +49 -0
- package/dist/ssr/hydrate.js.map +1 -0
- package/dist/ssr/index.d.ts +5 -0
- package/dist/ssr/index.js +11 -0
- package/dist/ssr/index.js.map +1 -0
- package/dist/ssr/next.d.ts +45 -0
- package/dist/ssr/next.js +69 -0
- package/dist/ssr/next.js.map +1 -0
- package/dist/ssr/ssr-collector-ref.js +12 -0
- package/dist/ssr/ssr-collector-ref.js.map +1 -0
- package/dist/states/index.d.ts +49 -0
- package/dist/states/index.js +170 -0
- package/dist/states/index.js.map +1 -0
- package/dist/static/index.d.ts +5 -0
- package/dist/static/index.js +4 -0
- package/dist/static/inject.d.ts +5 -0
- package/dist/static/inject.js +17 -0
- package/dist/static/inject.js.map +1 -0
- package/dist/static/tastyStatic.d.ts +46 -0
- package/dist/static/tastyStatic.js +30 -0
- package/dist/static/tastyStatic.js.map +1 -0
- package/dist/static/types.d.ts +49 -0
- package/dist/static/types.js +24 -0
- package/dist/static/types.js.map +1 -0
- package/dist/styles/align.d.ts +15 -0
- package/dist/styles/align.js +14 -0
- package/dist/styles/align.js.map +1 -0
- package/dist/styles/border.d.ts +25 -0
- package/dist/styles/border.js +113 -0
- package/dist/styles/border.js.map +1 -0
- package/dist/styles/color.d.ts +14 -0
- package/dist/styles/color.js +26 -0
- package/dist/styles/color.js.map +1 -0
- package/dist/styles/createStyle.js +79 -0
- package/dist/styles/createStyle.js.map +1 -0
- package/dist/styles/dimension.js +96 -0
- package/dist/styles/dimension.js.map +1 -0
- package/dist/styles/display.d.ts +37 -0
- package/dist/styles/display.js +66 -0
- package/dist/styles/display.js.map +1 -0
- package/dist/styles/fade.d.ts +15 -0
- package/dist/styles/fade.js +57 -0
- package/dist/styles/fade.js.map +1 -0
- package/dist/styles/fill.d.ts +42 -0
- package/dist/styles/fill.js +51 -0
- package/dist/styles/fill.js.map +1 -0
- package/dist/styles/flow.d.ts +16 -0
- package/dist/styles/flow.js +12 -0
- package/dist/styles/flow.js.map +1 -0
- package/dist/styles/gap.d.ts +31 -0
- package/dist/styles/gap.js +36 -0
- package/dist/styles/gap.js.map +1 -0
- package/dist/styles/height.d.ts +17 -0
- package/dist/styles/height.js +19 -0
- package/dist/styles/height.js.map +1 -0
- package/dist/styles/index.d.ts +1 -0
- package/dist/styles/index.js +8 -0
- package/dist/styles/index.js.map +1 -0
- package/dist/styles/inset.d.ts +52 -0
- package/dist/styles/inset.js +149 -0
- package/dist/styles/inset.js.map +1 -0
- package/dist/styles/justify.d.ts +15 -0
- package/dist/styles/justify.js +14 -0
- package/dist/styles/justify.js.map +1 -0
- package/dist/styles/list.d.ts +16 -0
- package/dist/styles/list.js +98 -0
- package/dist/styles/list.js.map +1 -0
- package/dist/styles/margin.d.ts +24 -0
- package/dist/styles/margin.js +103 -0
- package/dist/styles/margin.js.map +1 -0
- package/dist/styles/outline.d.ts +29 -0
- package/dist/styles/outline.js +64 -0
- package/dist/styles/outline.js.map +1 -0
- package/dist/styles/padding.d.ts +24 -0
- package/dist/styles/padding.js +103 -0
- package/dist/styles/padding.js.map +1 -0
- package/dist/styles/predefined.d.ts +71 -0
- package/dist/styles/predefined.js +237 -0
- package/dist/styles/predefined.js.map +1 -0
- package/dist/styles/preset.d.ts +52 -0
- package/dist/styles/preset.js +126 -0
- package/dist/styles/preset.js.map +1 -0
- package/dist/styles/radius.d.ts +12 -0
- package/dist/styles/radius.js +71 -0
- package/dist/styles/radius.js.map +1 -0
- package/dist/styles/scrollbar.d.ts +25 -0
- package/dist/styles/scrollbar.js +46 -0
- package/dist/styles/scrollbar.js.map +1 -0
- package/dist/styles/shadow.d.ts +14 -0
- package/dist/styles/shadow.js +23 -0
- package/dist/styles/shadow.js.map +1 -0
- package/dist/styles/transition.d.ts +14 -0
- package/dist/styles/transition.js +157 -0
- package/dist/styles/transition.js.map +1 -0
- package/dist/styles/types.d.ts +549 -0
- package/dist/styles/width.d.ts +17 -0
- package/dist/styles/width.js +19 -0
- package/dist/styles/width.js.map +1 -0
- package/dist/tasty.d.ts +119 -0
- package/dist/tasty.js +231 -0
- package/dist/tasty.js.map +1 -0
- package/dist/types.d.ts +184 -0
- package/dist/utils/cache-wrapper.js +21 -0
- package/dist/utils/cache-wrapper.js.map +1 -0
- package/dist/utils/case-converter.js +8 -0
- package/dist/utils/case-converter.js.map +1 -0
- package/dist/utils/color-math.d.ts +46 -0
- package/dist/utils/color-math.js +749 -0
- package/dist/utils/color-math.js.map +1 -0
- package/dist/utils/color-space.d.ts +5 -0
- package/dist/utils/color-space.js +228 -0
- package/dist/utils/color-space.js.map +1 -0
- package/dist/utils/colors.d.ts +5 -0
- package/dist/utils/colors.js +10 -0
- package/dist/utils/colors.js.map +1 -0
- package/dist/utils/css-types.d.ts +7 -0
- package/dist/utils/dotize.d.ts +26 -0
- package/dist/utils/dotize.js +122 -0
- package/dist/utils/dotize.js.map +1 -0
- package/dist/utils/filter-base-props.d.ts +15 -0
- package/dist/utils/filter-base-props.js +45 -0
- package/dist/utils/filter-base-props.js.map +1 -0
- package/dist/utils/get-display-name.d.ts +7 -0
- package/dist/utils/get-display-name.js +10 -0
- package/dist/utils/get-display-name.js.map +1 -0
- package/dist/utils/has-keys.js +13 -0
- package/dist/utils/has-keys.js.map +1 -0
- package/dist/utils/is-dev-env.js +19 -0
- package/dist/utils/is-dev-env.js.map +1 -0
- package/dist/utils/is-valid-element-type.js +15 -0
- package/dist/utils/is-valid-element-type.js.map +1 -0
- package/dist/utils/merge-styles.d.ts +7 -0
- package/dist/utils/merge-styles.js +145 -0
- package/dist/utils/merge-styles.js.map +1 -0
- package/dist/utils/mod-attrs.d.ts +6 -0
- package/dist/utils/mod-attrs.js +20 -0
- package/dist/utils/mod-attrs.js.map +1 -0
- package/dist/utils/process-tokens.d.ts +21 -0
- package/dist/utils/process-tokens.js +90 -0
- package/dist/utils/process-tokens.js.map +1 -0
- package/dist/utils/resolve-recipes.d.ts +17 -0
- package/dist/utils/resolve-recipes.js +146 -0
- package/dist/utils/resolve-recipes.js.map +1 -0
- package/dist/utils/selector-transform.js +32 -0
- package/dist/utils/selector-transform.js.map +1 -0
- package/dist/utils/string.js +8 -0
- package/dist/utils/string.js.map +1 -0
- package/dist/utils/styles.d.ts +99 -0
- package/dist/utils/styles.js +220 -0
- package/dist/utils/styles.js.map +1 -0
- package/dist/utils/typography.d.ts +47 -0
- package/dist/utils/typography.js +51 -0
- package/dist/utils/typography.js.map +1 -0
- package/dist/utils/warnings.d.ts +16 -0
- package/dist/utils/warnings.js +16 -0
- package/dist/utils/warnings.js.map +1 -0
- package/dist/zero/babel.d.ts +182 -0
- package/dist/zero/babel.js +438 -0
- package/dist/zero/babel.js.map +1 -0
- package/dist/zero/css-writer.d.ts +45 -0
- package/dist/zero/css-writer.js +73 -0
- package/dist/zero/css-writer.js.map +1 -0
- package/dist/zero/extractor.d.ts +24 -0
- package/dist/zero/extractor.js +266 -0
- package/dist/zero/extractor.js.map +1 -0
- package/dist/zero/index.d.ts +3 -0
- package/dist/zero/index.js +3 -0
- package/dist/zero/next.d.ts +86 -0
- package/dist/zero/next.js +143 -0
- package/dist/zero/next.js.map +1 -0
- package/docs/PIPELINE.md +519 -0
- package/docs/README.md +31 -0
- package/docs/adoption.md +296 -0
- package/docs/comparison.md +420 -0
- package/docs/configuration.md +326 -0
- package/docs/debug.md +318 -0
- package/docs/design-system.md +424 -0
- package/docs/dsl.md +673 -0
- package/docs/getting-started.md +217 -0
- package/docs/injector.md +528 -0
- package/docs/methodology.md +567 -0
- package/docs/runtime.md +485 -0
- package/docs/ssr.md +384 -0
- package/docs/styles.md +582 -0
- package/docs/tasty-static.md +520 -0
- package/package.json +215 -0
- package/tasty.config.ts +14 -0
package/docs/runtime.md
ADDED
|
@@ -0,0 +1,485 @@
|
|
|
1
|
+
# Runtime API
|
|
2
|
+
|
|
3
|
+
The React-specific `tasty()` component factory, component props, and hooks. For the shared style language (state maps, tokens, units, extending semantics), see [Style DSL](dsl.md). For global configuration, see [Configuration](configuration.md). For the broader docs map, see the [Docs Hub](README.md).
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Component Creation
|
|
8
|
+
|
|
9
|
+
### Create a new component
|
|
10
|
+
|
|
11
|
+
```jsx
|
|
12
|
+
import { tasty } from '@tenphi/tasty';
|
|
13
|
+
|
|
14
|
+
const Card = tasty({
|
|
15
|
+
as: 'div',
|
|
16
|
+
styles: {
|
|
17
|
+
padding: '4x',
|
|
18
|
+
fill: '#white',
|
|
19
|
+
border: true,
|
|
20
|
+
radius: true,
|
|
21
|
+
},
|
|
22
|
+
styleProps: ['padding', 'fill'],
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
<Card>Hello World</Card>
|
|
26
|
+
<Card padding="6x" fill="#gray.05">Custom Card</Card>
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### Extend an existing component
|
|
30
|
+
|
|
31
|
+
```jsx
|
|
32
|
+
const PrimaryButton = tasty(Button, {
|
|
33
|
+
styles: {
|
|
34
|
+
fill: '#purple',
|
|
35
|
+
color: '#white',
|
|
36
|
+
padding: '2x 4x',
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Style maps merge intelligently — see [Style DSL — Extending vs. Replacing State Maps](dsl.md#extending-vs-replacing-state-maps) for extend mode, replace mode, `@inherit`, `null`, and `false` tombstones.
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## Style Props
|
|
46
|
+
|
|
47
|
+
Use `styleProps` to expose style properties as direct component props:
|
|
48
|
+
|
|
49
|
+
```jsx
|
|
50
|
+
const FlexibleBox = tasty({
|
|
51
|
+
as: 'div',
|
|
52
|
+
styles: {
|
|
53
|
+
display: 'flex',
|
|
54
|
+
padding: '2x',
|
|
55
|
+
},
|
|
56
|
+
styleProps: ['gap', 'align', 'placeContent', 'fill'],
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
<FlexibleBox gap="2x" align="center" fill="#surface">
|
|
60
|
+
Content
|
|
61
|
+
</FlexibleBox>
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Style props accept state maps, so responsive values work through the same API:
|
|
65
|
+
|
|
66
|
+
```jsx
|
|
67
|
+
<FlexibleBox
|
|
68
|
+
gap={{ '': '2x', '@tablet': '4x' }}
|
|
69
|
+
fill={{ '': '#surface', '@dark': '#surface-dark' }}
|
|
70
|
+
>
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
For predefined style prop lists (`FLOW_STYLES`, `POSITION_STYLES`, `DIMENSION_STYLES`, etc.) and guidance on which props to expose per component category, see [Methodology — styleProps as the public API](methodology.md#styleprops-as-the-public-api).
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## Mod Props
|
|
78
|
+
|
|
79
|
+
Use `modProps` to expose modifier keys as direct component props instead of requiring the `mods` object:
|
|
80
|
+
|
|
81
|
+
```jsx
|
|
82
|
+
// Before: mods object
|
|
83
|
+
<Button mods={{ isLoading: true, size: 'large' }}>Submit</Button>
|
|
84
|
+
|
|
85
|
+
// After: mod props
|
|
86
|
+
<Button isLoading size="large">Submit</Button>
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Array form
|
|
90
|
+
|
|
91
|
+
List modifier key names. Types default to `ModValue` (`boolean | string | number | undefined | null`):
|
|
92
|
+
|
|
93
|
+
```jsx
|
|
94
|
+
const Button = tasty({
|
|
95
|
+
modProps: ['isLoading', 'isSelected'] as const,
|
|
96
|
+
styles: {
|
|
97
|
+
fill: { '': '#surface', isLoading: '#surface.5' },
|
|
98
|
+
border: { '': '1bw solid #outline', isSelected: '2bw solid #primary' },
|
|
99
|
+
},
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
<Button isLoading isSelected>Submit</Button>
|
|
103
|
+
// Renders: <button data-is-loading="" data-is-selected="">Submit</button>
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Object form (typed)
|
|
107
|
+
|
|
108
|
+
Map modifier names to type descriptors for precise TypeScript types:
|
|
109
|
+
|
|
110
|
+
```tsx
|
|
111
|
+
const Button = tasty({
|
|
112
|
+
modProps: {
|
|
113
|
+
isLoading: Boolean, // isLoading?: boolean
|
|
114
|
+
isSelected: Boolean, // isSelected?: boolean
|
|
115
|
+
size: ['small', 'medium', 'large'] as const, // size?: 'small' | 'medium' | 'large'
|
|
116
|
+
},
|
|
117
|
+
styles: {
|
|
118
|
+
padding: { '': '2x 4x', 'size=small': '1x 2x', 'size=large': '3x 6x' },
|
|
119
|
+
fill: { '': '#surface', isLoading: '#surface.5' },
|
|
120
|
+
},
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
<Button isLoading size="large">Submit</Button>
|
|
124
|
+
// Renders: <button data-is-loading="" data-size="large">Submit</button>
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Available type descriptors:
|
|
128
|
+
|
|
129
|
+
| Descriptor | TypeScript type | Example |
|
|
130
|
+
|---|---|---|
|
|
131
|
+
| `Boolean` | `boolean` | `isLoading: Boolean` |
|
|
132
|
+
| `String` | `string` | `label: String` |
|
|
133
|
+
| `Number` | `number` | `count: Number` |
|
|
134
|
+
| `['a', 'b'] as const` | `'a' \| 'b'` | `size: ['sm', 'md', 'lg'] as const` |
|
|
135
|
+
|
|
136
|
+
### Merge with `mods`
|
|
137
|
+
|
|
138
|
+
Mod props and the `mods` object can be used together. Mod props take precedence:
|
|
139
|
+
|
|
140
|
+
```jsx
|
|
141
|
+
<Button mods={{ isLoading: false, extra: true }} isLoading>
|
|
142
|
+
// isLoading=true wins (from mod prop), extra=true preserved from mods
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### When to use `modProps` vs `mods`
|
|
146
|
+
|
|
147
|
+
| Use case | Recommendation |
|
|
148
|
+
|---|---|
|
|
149
|
+
| Component has a fixed set of known modifiers | `modProps` — cleaner API, better TypeScript autocomplete |
|
|
150
|
+
| Component needs arbitrary/dynamic modifiers | `mods` — open-ended `Record<string, ModValue>` |
|
|
151
|
+
| Both fixed and dynamic | Combine: `modProps` for known keys, `mods` for ad-hoc |
|
|
152
|
+
|
|
153
|
+
For architecture guidance on when to use modifiers vs `styleProps`, see [Methodology — modProps and mods](methodology.md#modprops-and-mods).
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
## Variants
|
|
158
|
+
|
|
159
|
+
Define named style variations. Only CSS for variants actually used at runtime is injected:
|
|
160
|
+
|
|
161
|
+
```jsx
|
|
162
|
+
const Button = tasty({
|
|
163
|
+
styles: {
|
|
164
|
+
padding: '2x 4x',
|
|
165
|
+
border: true,
|
|
166
|
+
},
|
|
167
|
+
variants: {
|
|
168
|
+
default: { fill: '#blue', color: '#white' },
|
|
169
|
+
danger: { fill: '#red', color: '#white' },
|
|
170
|
+
outline: { fill: 'transparent', color: '#blue', border: '1bw solid #blue' },
|
|
171
|
+
},
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
<Button variant="danger">Delete</Button>
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### Extending Variants with Base State Maps
|
|
178
|
+
|
|
179
|
+
When base `styles` contain an extend-mode state map (an object **without** a `''` key), it is applied **after** the variant merge. This lets you add or override states across all variants without repeating yourself:
|
|
180
|
+
|
|
181
|
+
```jsx
|
|
182
|
+
const Badge = tasty({
|
|
183
|
+
styles: {
|
|
184
|
+
padding: '1x 2x',
|
|
185
|
+
border: {
|
|
186
|
+
'type=primary': '#clear',
|
|
187
|
+
},
|
|
188
|
+
},
|
|
189
|
+
variants: {
|
|
190
|
+
primary: {
|
|
191
|
+
border: { '': '#white.2', pressed: '#primary-text', disabled: '#clear' },
|
|
192
|
+
fill: { '': '#white #primary', hovered: '#white #primary-text' },
|
|
193
|
+
},
|
|
194
|
+
secondary: {
|
|
195
|
+
border: { '': '#primary.15', pressed: '#primary.3' },
|
|
196
|
+
fill: '#primary.10',
|
|
197
|
+
},
|
|
198
|
+
},
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
// Both variants get 'type=primary': '#clear' appended to their border map
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
Properties that are **not** extend-mode (simple values, state maps with `''`, `null`, `false`, selectors, sub-elements) merge with variants as before — the variant can fully replace them.
|
|
205
|
+
|
|
206
|
+
---
|
|
207
|
+
|
|
208
|
+
## Sub-element Styling
|
|
209
|
+
|
|
210
|
+
Sub-elements are inner parts of a compound component, styled via capitalized keys in `styles` and identified by `data-element` attributes in the DOM.
|
|
211
|
+
|
|
212
|
+
> Use the `elements` prop to declare sub-element components. This gives you typed, reusable sub-components (`Card.Title`, `Card.Content`) instead of manually writing `data-element` attributes.
|
|
213
|
+
|
|
214
|
+
```jsx
|
|
215
|
+
const Card = tasty({
|
|
216
|
+
styles: {
|
|
217
|
+
padding: '4x',
|
|
218
|
+
Title: { preset: 'h3', color: '#primary' },
|
|
219
|
+
Content: { color: '#text' },
|
|
220
|
+
},
|
|
221
|
+
elements: {
|
|
222
|
+
Title: 'h3',
|
|
223
|
+
Content: 'div',
|
|
224
|
+
},
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
<Card>
|
|
228
|
+
<Card.Title>Card Title</Card.Title>
|
|
229
|
+
<Card.Content>Card content</Card.Content>
|
|
230
|
+
</Card>
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
Each entry in `elements` can be a tag name string or a config object:
|
|
234
|
+
|
|
235
|
+
```jsx
|
|
236
|
+
elements: {
|
|
237
|
+
Title: 'h3', // shorthand: tag name only
|
|
238
|
+
Icon: { as: 'span', qa: 'card-icon' }, // full form: tag + QA attribute
|
|
239
|
+
}
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
The sub-components produced by `elements` support `mods`, `tokens`, `isDisabled`, `isHidden`, and `isChecked` props — the same modifier interface as the root component.
|
|
243
|
+
|
|
244
|
+
If you don't need sub-components (e.g., the inner elements are already rendered by a third-party library), you can still style them by key alone — just omit `elements` and apply `data-element` manually:
|
|
245
|
+
|
|
246
|
+
```jsx
|
|
247
|
+
const Card = tasty({
|
|
248
|
+
styles: {
|
|
249
|
+
padding: '4x',
|
|
250
|
+
Title: { preset: 'h3', color: '#primary' },
|
|
251
|
+
},
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
<Card>
|
|
255
|
+
<div data-element="Title">Card Title</div>
|
|
256
|
+
</Card>
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
### Selector Affix (`$`)
|
|
260
|
+
|
|
261
|
+
The `$` property inside a sub-element's styles controls how its selector attaches to the root selector — combinators, HTML tags, pseudo-elements, the `@` placeholder, and more. For the full reference table and injection rules, see [DSL — Selector Affix](dsl.md#selector-affix-).
|
|
262
|
+
|
|
263
|
+
For the mental model behind sub-elements — how they share root state context and how this differs from BEM — see [Methodology — Component architecture](methodology.md#component-architecture-root--sub-elements).
|
|
264
|
+
|
|
265
|
+
---
|
|
266
|
+
|
|
267
|
+
## Hooks
|
|
268
|
+
|
|
269
|
+
### useStyles
|
|
270
|
+
|
|
271
|
+
Generate a className from a style object:
|
|
272
|
+
|
|
273
|
+
```tsx
|
|
274
|
+
import { useStyles } from '@tenphi/tasty';
|
|
275
|
+
|
|
276
|
+
function MyComponent() {
|
|
277
|
+
const { className } = useStyles({
|
|
278
|
+
padding: '2x',
|
|
279
|
+
fill: '#surface',
|
|
280
|
+
radius: '1r',
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
return <div className={className}>Styled content</div>;
|
|
284
|
+
}
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
### useGlobalStyles
|
|
288
|
+
|
|
289
|
+
Inject global styles for a CSS selector:
|
|
290
|
+
|
|
291
|
+
```tsx
|
|
292
|
+
import { useGlobalStyles } from '@tenphi/tasty';
|
|
293
|
+
|
|
294
|
+
function ThemeStyles() {
|
|
295
|
+
useGlobalStyles('.card', {
|
|
296
|
+
padding: '4x',
|
|
297
|
+
fill: '#surface',
|
|
298
|
+
radius: '1r',
|
|
299
|
+
});
|
|
300
|
+
|
|
301
|
+
return null;
|
|
302
|
+
}
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
### useRawCSS
|
|
306
|
+
|
|
307
|
+
Inject raw CSS strings:
|
|
308
|
+
|
|
309
|
+
```tsx
|
|
310
|
+
import { useRawCSS } from '@tenphi/tasty';
|
|
311
|
+
|
|
312
|
+
function GlobalReset() {
|
|
313
|
+
useRawCSS(`
|
|
314
|
+
body { margin: 0; padding: 0; }
|
|
315
|
+
`);
|
|
316
|
+
|
|
317
|
+
return null;
|
|
318
|
+
}
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
### useKeyframes
|
|
322
|
+
|
|
323
|
+
Inject `@keyframes` rules and return the generated animation name:
|
|
324
|
+
|
|
325
|
+
```tsx
|
|
326
|
+
import { useKeyframes } from '@tenphi/tasty';
|
|
327
|
+
|
|
328
|
+
function Spinner() {
|
|
329
|
+
const spin = useKeyframes(
|
|
330
|
+
{
|
|
331
|
+
from: { transform: 'rotate(0deg)' },
|
|
332
|
+
to: { transform: 'rotate(360deg)' },
|
|
333
|
+
},
|
|
334
|
+
{ name: 'spin' }
|
|
335
|
+
);
|
|
336
|
+
|
|
337
|
+
return <div style={{ animation: `${spin} 1s linear infinite` }} />;
|
|
338
|
+
}
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
`useKeyframes()` also supports a factory function with dependencies:
|
|
342
|
+
|
|
343
|
+
```tsx
|
|
344
|
+
function Pulse({ scale }: { scale: number }) {
|
|
345
|
+
const pulse = useKeyframes(
|
|
346
|
+
() => ({
|
|
347
|
+
'0%': { transform: 'scale(1)' },
|
|
348
|
+
'100%': { transform: `scale(${scale})` },
|
|
349
|
+
}),
|
|
350
|
+
[scale]
|
|
351
|
+
);
|
|
352
|
+
|
|
353
|
+
return <div style={{ animation: `${pulse} 500ms ease-in-out alternate infinite` }} />;
|
|
354
|
+
}
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
### useProperty
|
|
358
|
+
|
|
359
|
+
Register a CSS `@property` rule so a custom property can animate smoothly:
|
|
360
|
+
|
|
361
|
+
```tsx
|
|
362
|
+
import { useProperty } from '@tenphi/tasty';
|
|
363
|
+
|
|
364
|
+
function Spinner() {
|
|
365
|
+
useProperty('$rotation', {
|
|
366
|
+
syntax: '<angle>',
|
|
367
|
+
inherits: false,
|
|
368
|
+
initialValue: '0deg',
|
|
369
|
+
});
|
|
370
|
+
|
|
371
|
+
return <div style={{ transform: 'rotate(var(--rotation))' }} />;
|
|
372
|
+
}
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
`useProperty()` accepts Tasty token syntax for the property name:
|
|
376
|
+
|
|
377
|
+
- `$name` defines `--name`
|
|
378
|
+
- `#name` defines `--name-color` and auto-infers `<color>`
|
|
379
|
+
- `--name` is also supported for existing CSS variables
|
|
380
|
+
|
|
381
|
+
### useFontFace
|
|
382
|
+
|
|
383
|
+
Inject `@font-face` rules for custom fonts. Permanent — no cleanup on unmount. Deduplicates by content.
|
|
384
|
+
|
|
385
|
+
```tsx
|
|
386
|
+
import { useFontFace } from '@tenphi/tasty';
|
|
387
|
+
|
|
388
|
+
function App() {
|
|
389
|
+
useFontFace('Brand Sans', {
|
|
390
|
+
src: 'url("/fonts/brand-sans.woff2") format("woff2")',
|
|
391
|
+
fontWeight: '400 700',
|
|
392
|
+
fontDisplay: 'swap',
|
|
393
|
+
});
|
|
394
|
+
|
|
395
|
+
return <div style={{ fontFamily: '"Brand Sans", sans-serif' }}>Hello</div>;
|
|
396
|
+
}
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
For multiple weights/styles, pass an array:
|
|
400
|
+
|
|
401
|
+
```tsx
|
|
402
|
+
useFontFace('Brand Sans', [
|
|
403
|
+
{ src: 'url("/fonts/brand-regular.woff2") format("woff2")', fontWeight: 400, fontDisplay: 'swap' },
|
|
404
|
+
{ src: 'url("/fonts/brand-bold.woff2") format("woff2")', fontWeight: 700, fontDisplay: 'swap' },
|
|
405
|
+
]);
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
Signature:
|
|
409
|
+
|
|
410
|
+
```ts
|
|
411
|
+
function useFontFace(family: string, input: FontFaceInput): void;
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
### useCounterStyle
|
|
415
|
+
|
|
416
|
+
Inject a `@counter-style` rule and get back the counter style name. Permanent — no cleanup on unmount. Deduplicates by name.
|
|
417
|
+
|
|
418
|
+
```tsx
|
|
419
|
+
import { useCounterStyle } from '@tenphi/tasty';
|
|
420
|
+
|
|
421
|
+
function EmojiList() {
|
|
422
|
+
const styleName = useCounterStyle({
|
|
423
|
+
system: 'cyclic',
|
|
424
|
+
symbols: '"👍"',
|
|
425
|
+
suffix: '" "',
|
|
426
|
+
}, { name: 'thumbs' });
|
|
427
|
+
|
|
428
|
+
return (
|
|
429
|
+
<ol style={{ listStyleType: styleName }}>
|
|
430
|
+
<li>First</li>
|
|
431
|
+
<li>Second</li>
|
|
432
|
+
</ol>
|
|
433
|
+
);
|
|
434
|
+
}
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
Factory form with dependencies:
|
|
438
|
+
|
|
439
|
+
```tsx
|
|
440
|
+
function DynamicList({ marker }: { marker: string }) {
|
|
441
|
+
const styleName = useCounterStyle(
|
|
442
|
+
() => ({
|
|
443
|
+
system: 'cyclic',
|
|
444
|
+
symbols: `"${marker}"`,
|
|
445
|
+
suffix: '" "',
|
|
446
|
+
}),
|
|
447
|
+
[marker],
|
|
448
|
+
);
|
|
449
|
+
|
|
450
|
+
return <ol style={{ listStyleType: styleName }}>...</ol>;
|
|
451
|
+
}
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
Signatures:
|
|
455
|
+
|
|
456
|
+
```ts
|
|
457
|
+
function useCounterStyle(
|
|
458
|
+
descriptors: CounterStyleDescriptors,
|
|
459
|
+
options?: { name?: string; root?: Document | ShadowRoot },
|
|
460
|
+
): string;
|
|
461
|
+
|
|
462
|
+
function useCounterStyle(
|
|
463
|
+
factory: () => CounterStyleDescriptors,
|
|
464
|
+
deps: readonly unknown[],
|
|
465
|
+
options?: { name?: string; root?: Document | ShadowRoot },
|
|
466
|
+
): string;
|
|
467
|
+
```
|
|
468
|
+
|
|
469
|
+
### Troubleshooting
|
|
470
|
+
|
|
471
|
+
- Styles are not updating: make sure `configure()` runs before first render, and verify the generated class name or global rule with [Debug Utilities](debug.md).
|
|
472
|
+
- SSR output looks wrong: check the [SSR guide](ssr.md) because the hooks integrate with SSR collectors differently than the client-only runtime path.
|
|
473
|
+
- Animation/custom property issues: prefer `useKeyframes()` and `useProperty()` over raw CSS when you want Tasty to manage injection and SSR collection for you.
|
|
474
|
+
|
|
475
|
+
---
|
|
476
|
+
|
|
477
|
+
## Learn more
|
|
478
|
+
|
|
479
|
+
- **[Style DSL](dsl.md)** — State maps, tokens, units, extending semantics, keyframes, @property
|
|
480
|
+
- **[Methodology](methodology.md)** — Recommended patterns: root + sub-elements, styleProps, tokens, wrapping
|
|
481
|
+
- **[Configuration](configuration.md)** — Tokens, recipes, custom units, style handlers, TypeScript extensions
|
|
482
|
+
- **[Style Properties](styles.md)** — Complete reference for all enhanced style properties
|
|
483
|
+
- **[Zero Runtime (tastyStatic)](tasty-static.md)** — Build-time static styling with Babel plugin
|
|
484
|
+
- **[Server-Side Rendering](ssr.md)** — SSR setup for Next.js, Astro, and generic frameworks
|
|
485
|
+
- **[Debug Utilities](debug.md)** — Inspect injected CSS, cache state, and active styles at runtime
|