vunor 0.1.2 → 0.1.4
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 +6 -11
- package/dist/AppLayout.mjs +0 -0
- package/dist/AppToasts.mjs +4 -8
- package/dist/Button.mjs +5 -10
- package/dist/ButtonBase.mjs +4 -8
- package/dist/Calendar.mjs +10 -14
- package/dist/Card.mjs +4 -9
- package/dist/CardHeader.mjs +5 -10
- package/dist/CardInner.mjs +4 -9
- package/dist/Checkbox.mjs +4 -8
- package/dist/Combobox.d.mts +9 -9
- package/dist/Combobox.mjs +5 -9
- package/dist/DatePicker.d.mts +9 -9
- package/dist/DatePicker.mjs +12 -17
- package/dist/DatePickerBase.d.mts +9 -9
- package/dist/DatePickerBase.mjs +13 -17
- package/dist/DatePickerInner.mjs +5 -9
- package/dist/DatePickerPopup.mjs +4 -8
- package/dist/DelayedSwitch.mjs +4 -9
- package/dist/DevTools.mjs +583 -150
- package/dist/Dialog.d.mts +6 -6
- package/dist/Dialog.mjs +4 -8
- package/dist/Icon.mjs +4 -9
- package/dist/InnerLoading.mjs +4 -8
- package/dist/Input.d.mts +13 -13
- package/dist/Input.mjs +4 -8
- package/dist/InputBase.d.mts +9 -9
- package/dist/InputBase.mjs +4 -8
- package/dist/Label.mjs +1 -4
- package/dist/LoadingIndicator.mjs +4 -8
- package/dist/Menu.d.mts +2 -2
- package/dist/Menu.mjs +5 -14
- package/dist/MenuItem.mjs +4 -9
- package/dist/OverflowContainer.mjs +4 -8
- package/dist/Pagination.mjs +4 -9
- package/dist/Popover.mjs +4 -9
- package/dist/ProgressBar.mjs +4 -9
- package/dist/RadioGroup.mjs +4 -8
- package/dist/Select.d.mts +9 -9
- package/dist/Select.mjs +4 -9
- package/dist/SelectBase.mjs +4 -8
- package/dist/Slider.mjs +4 -8
- package/dist/Tabs.mjs +4 -9
- package/dist/nuxt.mjs +1 -3
- package/dist/theme.d.mts +35 -0
- package/dist/theme.mjs +313 -336
- package/dist/utils-6bTTIoaw.js +40 -0
- package/dist/utils.d.mts +2 -2
- package/dist/utils.mjs +1 -4
- package/dist/vite.mjs +1 -2
- package/dist/vunor.d.mts +13 -13
- package/dist/vunor.mjs +1 -6
- package/package.json +30 -37
- package/scripts/setup-skills.js +0 -78
- package/skills/vunor/SKILL.md +0 -115
- package/skills/vunor/components.md +0 -320
- package/skills/vunor/core.md +0 -173
- package/skills/vunor/forms.md +0 -348
- package/skills/vunor/palette.md +0 -223
- package/skills/vunor/rules.md +0 -263
- package/skills/vunor/shortcuts.md +0 -239
- package/skills/vunor/typography.md +0 -204
package/skills/vunor/rules.md
DELETED
|
@@ -1,263 +0,0 @@
|
|
|
1
|
-
# UnoCSS custom rules — vunor
|
|
2
|
-
|
|
3
|
-
> All 15 custom UnoCSS rules provided by `presetVunor`: palette/scope/current-color rules, spacing/typography/card/fingertip rules, and i8 input styling rules.
|
|
4
|
-
|
|
5
|
-
## Concepts
|
|
6
|
-
|
|
7
|
-
Vunor's `presetVunor()` registers custom UnoCSS rules that power the color scope system, typography-aware spacing, card sizing, touch targets, and input styling. These rules generate CSS custom properties that compose together — e.g., `scope-primary` sets palette variables, `current-bg-scope-color-500` reads them, and `bg-current` applies the result.
|
|
8
|
-
|
|
9
|
-
Rules are organized in three groups:
|
|
10
|
-
1. **Palette rules** (8) — color scoping, current-color system, icon utilities
|
|
11
|
-
2. **Spacing rules** (4) — text margins, card spacing, fingertip sizing
|
|
12
|
-
3. **Input rules** (3) — i8 border/bg/outline configuration
|
|
13
|
-
|
|
14
|
-
## Palette rules
|
|
15
|
-
|
|
16
|
-
### `scope-{color}`
|
|
17
|
-
|
|
18
|
-
Sets `--scope-color-*` CSS custom properties for the entire subtree.
|
|
19
|
-
|
|
20
|
-
**Pattern:** `/^scope-(.*)$/`
|
|
21
|
-
|
|
22
|
-
Generates variables for all 10 main shades (50–900), 5 light layers (0–4), 5 dark layers (0–4), and sets `--current-hl` to the 500 shade. Valid colors: `primary`, `secondary`, `good`, `warn`, `error`, `grey`, `neutral`.
|
|
23
|
-
|
|
24
|
-
```html
|
|
25
|
-
<div class="scope-primary">
|
|
26
|
-
<!-- --scope-color-50 through --scope-color-900 are now set -->
|
|
27
|
-
<!-- --scope-light-0 through --scope-light-4 -->
|
|
28
|
-
<!-- --scope-dark-0 through --scope-dark-4 -->
|
|
29
|
-
<!-- --current-hl = primary-500 -->
|
|
30
|
-
</div>
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
### `current-{target}-{source}`
|
|
34
|
-
|
|
35
|
-
Sets a `--current-{target}` CSS variable to a specific color.
|
|
36
|
-
|
|
37
|
-
**Pattern:** `/^current-(text|bg|icon|border|outline|caret|hl)-(.+)$/`
|
|
38
|
-
|
|
39
|
-
| Source type | Example | Result |
|
|
40
|
-
|-------------|---------|--------|
|
|
41
|
-
| Scope reference | `current-bg-scope-color-500` | `--current-bg: var(--scope-color-500)` |
|
|
42
|
-
| Highlight alias | `current-text-hl` | `--current-text: var(--current-hl)` |
|
|
43
|
-
| Theme color | `current-bg-primary-500` | `--current-bg: <rgb values>` |
|
|
44
|
-
|
|
45
|
-
```html
|
|
46
|
-
<div class="current-bg-primary-500 current-text-primary-50">
|
|
47
|
-
<div class="bg-current text-current">Styled via CSS vars</div>
|
|
48
|
-
</div>
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
### `{target}-current` / `{target}-current-{source}` / `{target}-current/{opacity}`
|
|
52
|
-
|
|
53
|
-
Applies a `--current-*` color to a CSS property.
|
|
54
|
-
|
|
55
|
-
**Pattern:** `/^(text|bg|icon|border|outline|caret|fill|shadow|ring)-current(-text|-bg|-icon|-border|-outline|-caret|-hl)?(\/\d{1,3})?$/`
|
|
56
|
-
|
|
57
|
-
```html
|
|
58
|
-
<div class="text-current"> <!-- color: rgb(var(--current-text) / 1) -->
|
|
59
|
-
<div class="bg-current/50"> <!-- background-color: rgb(var(--current-bg) / 0.5) -->
|
|
60
|
-
<div class="border-current-hl"> <!-- border-color uses --current-hl -->
|
|
61
|
-
<div class="icon-current"> <!-- sets --un-icon-opacity: 1 -->
|
|
62
|
-
<div class="shadow-current-border"> <!-- --un-shadow-color from --current-border -->
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
Special behavior for `icon` target: sets `--un-icon-opacity` but applies color through the `icon-color` rule, not directly.
|
|
66
|
-
|
|
67
|
-
### `{target}-scope-{source}` / `{target}-scope-{source}/{opacity}`
|
|
68
|
-
|
|
69
|
-
Applies a scoped palette color directly to a CSS property without going through `--current-*`.
|
|
70
|
-
|
|
71
|
-
**Pattern:** `/^(bg|text|fill|stroke|border|outline|icon|caret)-scope-((?:color|dark|light|text|bg|white|black|icon)(?:-\d+)?)(\/\d{1,3})?$/`
|
|
72
|
-
|
|
73
|
-
```html
|
|
74
|
-
<div class="bg-scope-color-100"> <!-- background: --scope-color-100 -->
|
|
75
|
-
<div class="text-scope-dark-2"> <!-- color: --scope-dark-2 -->
|
|
76
|
-
<div class="border-scope-light-1/50"> <!-- border: --scope-light-1 at 50% -->
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
### `icon-opacity-{0-100}`
|
|
80
|
-
|
|
81
|
-
Sets `--un-icon-opacity`.
|
|
82
|
-
|
|
83
|
-
**Pattern:** `/^icon-opacity-(\d{1,3})$/`
|
|
84
|
-
|
|
85
|
-
```html
|
|
86
|
-
<div class="icon-opacity-50"> <!-- --un-icon-opacity: 0.5 -->
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
### `icon-color`
|
|
90
|
-
|
|
91
|
-
Applies the current icon color with icon opacity.
|
|
92
|
-
|
|
93
|
-
**Pattern:** exact match `icon-color`
|
|
94
|
-
|
|
95
|
-
```css
|
|
96
|
-
.icon-color { color: rgb(var(--current-icon) / var(--un-icon-opacity, 1)); }
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
### `icon-size-{value}` / `icon-size`
|
|
100
|
-
|
|
101
|
-
Sets or applies icon dimensions.
|
|
102
|
-
|
|
103
|
-
**Pattern:** `/^icon-size-(.*)$/` and exact match `icon-size`
|
|
104
|
-
|
|
105
|
-
| Class | Result |
|
|
106
|
-
|-------|--------|
|
|
107
|
-
| `icon-size-[2em]` | `--icon-size: 2em` |
|
|
108
|
-
| `icon-size-4` | `--icon-size: 1rem` (from theme.spacing) |
|
|
109
|
-
| `icon-size` | `width/height: var(--icon-size, 1em)` |
|
|
110
|
-
|
|
111
|
-
## Spacing rules
|
|
112
|
-
|
|
113
|
-
### `text-m{t|b|y}-{size}`
|
|
114
|
-
|
|
115
|
-
Text margins with line-height compensation. Adjusts top/bottom margins using `--font-tc` (top correction) and `--font-bc` (bottom correction) so spacing between typographic elements is optically correct.
|
|
116
|
-
|
|
117
|
-
**Pattern:** `/^text-m([bty])?-(.*)$/`
|
|
118
|
-
|
|
119
|
-
| Suffix | Applies to |
|
|
120
|
-
|--------|-----------|
|
|
121
|
-
| `t` | top only |
|
|
122
|
-
| `b` | bottom only |
|
|
123
|
-
| `y` | top and bottom |
|
|
124
|
-
| _(none)_ | all four sides |
|
|
125
|
-
|
|
126
|
-
```html
|
|
127
|
-
<h1 class="text-h1 text-mb-$m">Title</h1>
|
|
128
|
-
<!-- margin-bottom: calc(1em + var(--font-bc)) -->
|
|
129
|
-
|
|
130
|
-
<p class="text-body text-mt-$s">Paragraph</p>
|
|
131
|
-
<!-- margin-top: calc(0.62em + var(--font-tc)) -->
|
|
132
|
-
```
|
|
133
|
-
|
|
134
|
-
Size values: spacing tokens (`$s`, `$m`, `$l`...), theme spacing keys, or numbers (multiplied by 0.25rem if unitless).
|
|
135
|
-
|
|
136
|
-
### `card-dense`
|
|
137
|
-
|
|
138
|
-
Switches card spacing to the dense variant.
|
|
139
|
-
|
|
140
|
-
**Pattern:** exact match `card-dense`
|
|
141
|
-
|
|
142
|
-
```css
|
|
143
|
-
.card-dense { --card-spacing: var(--card-spacing-dense); }
|
|
144
|
-
```
|
|
145
|
-
|
|
146
|
-
### `card-{typography}`
|
|
147
|
-
|
|
148
|
-
Sets `--card-spacing` proportional to a typography level's corrected font size.
|
|
149
|
-
|
|
150
|
-
**Pattern:** `/^card-(.*)$/` (matches any valid `theme.fontSize` key)
|
|
151
|
-
|
|
152
|
-
```html
|
|
153
|
-
<div class="card-h3">
|
|
154
|
-
<!-- --card-spacing: <h3 corrected size * cardSpacingFactor.regular> -->
|
|
155
|
-
<!-- --card-spacing-dense: <h3 corrected size * cardSpacingFactor.dense> -->
|
|
156
|
-
<!-- --card-heading-size, --card-heading-bold, etc. also set -->
|
|
157
|
-
<!-- padding: var(--card-spacing) -->
|
|
158
|
-
</div>
|
|
159
|
-
```
|
|
160
|
-
|
|
161
|
-
Valid keys: `h1`–`h6`, `subheading`, `body`, `body-l`, `body-s`, `callout`, `label`, `caption`, `overline`.
|
|
162
|
-
|
|
163
|
-
### `fingertip-{size}`
|
|
164
|
-
|
|
165
|
-
Sets touch target height via `--v-fingertip` and `--v-fingertip-half`.
|
|
166
|
-
|
|
167
|
-
**Pattern:** `/^fingertip-(.*)/`
|
|
168
|
-
|
|
169
|
-
| Class | Source |
|
|
170
|
-
|-------|--------|
|
|
171
|
-
| `fingertip-xs` / `s` / `m` / `l` / `xl` | Named sizes from preset config |
|
|
172
|
-
| `fingertip-4` | `theme.spacing['4']` |
|
|
173
|
-
| `fingertip-[2.5rem]` | Bracket value used directly |
|
|
174
|
-
|
|
175
|
-
```css
|
|
176
|
-
.fingertip-m { --v-fingertip: 3em; --v-fingertip-half: 1.5em; }
|
|
177
|
-
```
|
|
178
|
-
|
|
179
|
-
## Input (i8) rules
|
|
180
|
-
|
|
181
|
-
### `i8-{target}-{value}`
|
|
182
|
-
|
|
183
|
-
Configures input border, outline, or background via CSS custom properties.
|
|
184
|
-
|
|
185
|
-
**Pattern:** `/^i8-(border|outline|bg)-(.+)$/`
|
|
186
|
-
|
|
187
|
-
| Value type | Example | CSS generated |
|
|
188
|
-
|-----------|---------|---------------|
|
|
189
|
-
| `none` | `i8-border-none` | `--i8-border-width: 0` |
|
|
190
|
-
| `transparent` | `i8-bg-transparent` | `--i8-bg-color: 0` |
|
|
191
|
-
| Scope ref | `i8-border-scope-color-500` | `--i8-border-color: var(--scope-color-500)` |
|
|
192
|
-
| Theme color | `i8-border-primary` | `--i8-border-color: <rgb>` |
|
|
193
|
-
| Width (px/em/rem) | `i8-border-2px` | `--i8-border-width: 2px` |
|
|
194
|
-
| Bracket color | `i8-outline-[#ff0000]` | `--i8-outline-color: #ff0000` |
|
|
195
|
-
| Bracket width | `i8-border-[0.5em]` | `--i8-border-width: 0.5em` |
|
|
196
|
-
|
|
197
|
-
### `i8-{target}-opacity-{0-100}`
|
|
198
|
-
|
|
199
|
-
Sets opacity for input border, outline, or background.
|
|
200
|
-
|
|
201
|
-
**Pattern:** `/^i8-(border|outline|bg)-opacity-(\d{1,3})$/`
|
|
202
|
-
|
|
203
|
-
```html
|
|
204
|
-
<div class="i8-border-opacity-50"> <!-- --i8-border-opacity: 0.5 -->
|
|
205
|
-
```
|
|
206
|
-
|
|
207
|
-
### `i8-apply-{target}`
|
|
208
|
-
|
|
209
|
-
Applies the configured i8 values to actual CSS properties. This is the final rendering step — used internally by `i8-flat`, `i8-filled`, `i8-round` shortcuts.
|
|
210
|
-
|
|
211
|
-
**Pattern:** `/^i8-apply-(border|outline|bg)$/`
|
|
212
|
-
|
|
213
|
-
| Class | CSS | Defaults |
|
|
214
|
-
|-------|-----|----------|
|
|
215
|
-
| `i8-apply-bg` | `background-color: rgb(var(--i8-bg-color, var(--current-bg)) / var(--i8-bg-opacity, 1))` | opacity: 1 |
|
|
216
|
-
| `i8-apply-border` | `border-color: rgb(...)` + `border-width: var(--i8-border-width, 1px)` | opacity: 0.2, width: 1px |
|
|
217
|
-
| `i8-apply-outline` | `outline-color: rgb(...)` + `outline-width: var(--i8-outline-width, 2px)` | opacity: 0.5, width: 2px |
|
|
218
|
-
|
|
219
|
-
## CSS custom properties reference
|
|
220
|
-
|
|
221
|
-
Properties set by these rules:
|
|
222
|
-
|
|
223
|
-
| Variable | Set by | Used by |
|
|
224
|
-
|----------|--------|---------|
|
|
225
|
-
| `--scope-color-{step}` | `scope-*` | `current-*-scope-*`, `*-scope-*` |
|
|
226
|
-
| `--scope-light-{0-4}` | `scope-*` | `layer-*`, `*-scope-light-*` |
|
|
227
|
-
| `--scope-dark-{0-4}` | `scope-*` | `layer-*`, `*-scope-dark-*` |
|
|
228
|
-
| `--current-text` | `current-text-*` | `text-current` |
|
|
229
|
-
| `--current-bg` | `current-bg-*` | `bg-current` |
|
|
230
|
-
| `--current-icon` | `current-icon-*` | `icon-current`, `icon-color` |
|
|
231
|
-
| `--current-border` | `current-border-*` | `border-current` |
|
|
232
|
-
| `--current-hl` | `scope-*`, `current-hl-*` | `*-current-hl` |
|
|
233
|
-
| `--font-tc` / `--font-bc` | `text-*` typography utilities | `text-mt-*`, `text-mb-*` |
|
|
234
|
-
| `--card-spacing` | `card-*` | Card component padding |
|
|
235
|
-
| `--card-spacing-dense` | `card-*` | `card-dense` |
|
|
236
|
-
| `--v-fingertip` | `fingertip-*` | `h-fingertip`, button/input heights |
|
|
237
|
-
| `--v-fingertip-half` | `fingertip-*` | `px-fingertip-half`, rounded buttons |
|
|
238
|
-
| `--i8-border-color` | `i8-border-*` | `i8-apply-border` |
|
|
239
|
-
| `--i8-border-width` | `i8-border-*` | `i8-apply-border` |
|
|
240
|
-
| `--i8-border-opacity` | `i8-border-opacity-*` | `i8-apply-border` |
|
|
241
|
-
| `--i8-bg-color` | `i8-bg-*` | `i8-apply-bg` |
|
|
242
|
-
| `--i8-bg-opacity` | `i8-bg-opacity-*` | `i8-apply-bg` |
|
|
243
|
-
| `--i8-outline-color` | `i8-outline-*` | `i8-apply-outline` |
|
|
244
|
-
| `--i8-outline-width` | `i8-outline-*` | `i8-apply-outline` |
|
|
245
|
-
| `--i8-outline-opacity` | `i8-outline-opacity-*` | `i8-apply-outline` |
|
|
246
|
-
| `--un-icon-opacity` | `icon-opacity-*`, `icon-current` | `icon-color` |
|
|
247
|
-
| `--icon-size` | `icon-size-*` | `icon-size` |
|
|
248
|
-
|
|
249
|
-
## Best practices
|
|
250
|
-
|
|
251
|
-
- Use `scope-{color}` at the highest ancestor that shares a palette — avoids redundant variable declarations.
|
|
252
|
-
- Prefer `text-mt-*` / `text-mb-*` over plain `mt-*` / `mb-*` between typographic elements — the font corrections produce optically correct spacing.
|
|
253
|
-
- The `i8-*` rules are low-level — most of the time, use `i8-flat` / `i8-filled` / `i8-round` shortcuts which compose these rules internally.
|
|
254
|
-
- `card-{typography}` sets `padding` directly — don't add extra padding classes on the same element.
|
|
255
|
-
|
|
256
|
-
## Gotchas
|
|
257
|
-
|
|
258
|
-
- `scope-{color}` only sets CSS variables — it doesn't apply any visible styles. You need `layer-*`, `surface-*`, `bg-current`, or `*-scope-*` classes to consume the scope.
|
|
259
|
-
- `icon-current` does **not** set `color` directly — it sets `--un-icon-opacity`. Use `icon-color` alongside it, or use the `icon-color icon-size` classes that components already include.
|
|
260
|
-
- `i8-apply-border` defaults to `border-opacity: 0.2` and `width: 1px`. If you set `i8-border-primary` but see no visible border, check that `border-style` (e.g. `border-solid`) is also applied.
|
|
261
|
-
- `text-m-$m` applies margins to **all four sides** (not just top/bottom). Use `text-my-$m` for vertical-only.
|
|
262
|
-
- `fingertip-m` sets the CSS variable but doesn't apply height — use `h-fingertip` to consume it.
|
|
263
|
-
- `card-dense` requires a `card-{typography}` rule on the same element (or ancestor) to have set `--card-spacing-dense`.
|
|
@@ -1,239 +0,0 @@
|
|
|
1
|
-
# Shortcut objects — vunor
|
|
2
|
-
|
|
3
|
-
> The structured shortcut system for defining and customizing component styles: defineShortcuts, mergeVunorShortcuts, c8/i8 style systems, and overriding built-in styles.
|
|
4
|
-
|
|
5
|
-
## Concepts
|
|
6
|
-
|
|
7
|
-
Instead of flat UnoCSS shortcut strings, Vunor uses **structured nested objects** where keys are variant prefixes and values are the classes to apply. This makes styles readable, deeply mergeable, and surgically overridable.
|
|
8
|
-
|
|
9
|
-
The key insight: when two shortcut objects define the same key, `mergeVunorShortcuts()` deep-merges them with later entries winning. You can override a single variant of a built-in style without rewriting the whole shortcut.
|
|
10
|
-
|
|
11
|
-
### How it works
|
|
12
|
-
|
|
13
|
-
```
|
|
14
|
-
defineShortcuts({ ... }) → Shortcut object (nested)
|
|
15
|
-
↓
|
|
16
|
-
toUnoShortcut(obj) → Flat UnoCSS string
|
|
17
|
-
↓
|
|
18
|
-
mergeVunorShortcuts([...]) → Merged array (later wins)
|
|
19
|
-
↓
|
|
20
|
-
vunorShortcuts(overrides) → Final UnoCSS shortcuts config
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
## API Reference
|
|
24
|
-
|
|
25
|
-
### `defineShortcuts(obj)`
|
|
26
|
-
|
|
27
|
-
Creates a typed shortcut object. Keys are shortcut names (CSS classes), values are variant-prefix objects.
|
|
28
|
-
|
|
29
|
-
```ts
|
|
30
|
-
import { defineShortcuts } from 'vunor/theme'
|
|
31
|
-
|
|
32
|
-
const shortcuts = defineShortcuts({
|
|
33
|
-
'btn': {
|
|
34
|
-
'': 'h-fingertip flex items-center', // base classes (no prefix)
|
|
35
|
-
'hover:': 'bg-current/05', // → "hover:bg-current/05"
|
|
36
|
-
'dark:': 'text-white', // → "dark:text-white"
|
|
37
|
-
'[&.btn-round]:': 'rounded-full', // → "[&.btn-round]:rounded-full"
|
|
38
|
-
},
|
|
39
|
-
})
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
Each key is a **variant prefix** that gets prepended to every class in the value.
|
|
43
|
-
|
|
44
|
-
### Compound variants
|
|
45
|
-
|
|
46
|
-
Nesting goes deeper for compound states:
|
|
47
|
-
|
|
48
|
-
```ts
|
|
49
|
-
defineShortcuts({
|
|
50
|
-
'c8-filled': {
|
|
51
|
-
'': 'current-bg-scope-color-500 text-white rounded-base',
|
|
52
|
-
'hover:': 'current-bg-scope-color-400',
|
|
53
|
-
'dark:': {
|
|
54
|
-
'': 'text-white/90',
|
|
55
|
-
'hover:': 'current-bg-scope-color-600 border-solid',
|
|
56
|
-
// produces: "dark:text-white/90 dark:hover:current-bg-scope-color-600 dark:hover:border-solid"
|
|
57
|
-
},
|
|
58
|
-
},
|
|
59
|
-
})
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
### `toUnoShortcut(obj)`
|
|
63
|
-
|
|
64
|
-
Flattens a shortcut object into a single UnoCSS string. Called internally but can be used directly for debugging.
|
|
65
|
-
|
|
66
|
-
```ts
|
|
67
|
-
import { toUnoShortcut } from 'vunor/theme'
|
|
68
|
-
|
|
69
|
-
const flat = toUnoShortcut({
|
|
70
|
-
'': 'flex items-center',
|
|
71
|
-
'hover:': 'bg-blue-100',
|
|
72
|
-
})
|
|
73
|
-
// → "flex items-center hover:bg-blue-100"
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
### `mergeVunorShortcuts(arrays)`
|
|
77
|
-
|
|
78
|
-
Deep-merges multiple shortcut arrays. Later arrays win on conflict.
|
|
79
|
-
|
|
80
|
-
```ts
|
|
81
|
-
import { mergeVunorShortcuts } from 'vunor/theme'
|
|
82
|
-
|
|
83
|
-
const merged = mergeVunorShortcuts([defaultShortcuts, myOverrides])
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
### `vunorShortcuts(overrides?, baseShortcuts?)`
|
|
87
|
-
|
|
88
|
-
Returns the final merged shortcuts for UnoCSS config. This is what you put in `shortcuts: [...]`.
|
|
89
|
-
|
|
90
|
-
```ts
|
|
91
|
-
import { vunorShortcuts } from 'vunor/theme'
|
|
92
|
-
|
|
93
|
-
// Default styles
|
|
94
|
-
shortcuts: [vunorShortcuts()]
|
|
95
|
-
|
|
96
|
-
// With overrides (overrides take priority)
|
|
97
|
-
shortcuts: [vunorShortcuts(myCustomShortcuts)]
|
|
98
|
-
```
|
|
99
|
-
|
|
100
|
-
## Built-in style systems
|
|
101
|
-
|
|
102
|
-
### c8 — Clickable styles
|
|
103
|
-
|
|
104
|
-
Four visual variants for buttons and interactive elements. Use with `scope-{color}` to set the palette.
|
|
105
|
-
|
|
106
|
-
| Class | Description |
|
|
107
|
-
|-------|-------------|
|
|
108
|
-
| `c8-filled` | Solid background, white text |
|
|
109
|
-
| `c8-flat` | Transparent background, colored text, subtle hover |
|
|
110
|
-
| `c8-outlined` | Border + colored text, transparent fill |
|
|
111
|
-
| `c8-light` | Light tinted background, colored text |
|
|
112
|
-
|
|
113
|
-
Each includes hover, active, focus, and disabled states.
|
|
114
|
-
|
|
115
|
-
```html
|
|
116
|
-
<button class="scope-primary c8-filled">Save</button>
|
|
117
|
-
<button class="scope-error c8-flat">Cancel</button>
|
|
118
|
-
<button class="scope-good c8-outlined">Confirm</button>
|
|
119
|
-
<button class="scope-warn c8-light">Warning</button>
|
|
120
|
-
```
|
|
121
|
-
|
|
122
|
-
### i8 — Input styles
|
|
123
|
-
|
|
124
|
-
Three visual variants for form inputs.
|
|
125
|
-
|
|
126
|
-
| Class | Description |
|
|
127
|
-
|-------|-------------|
|
|
128
|
-
| `i8-flat` | Bottom border only (minimal) |
|
|
129
|
-
| `i8-filled` | Full border with background |
|
|
130
|
-
| `i8-round` | Pill-shaped (fully rounded) |
|
|
131
|
-
|
|
132
|
-
Sub-shortcuts used within input components:
|
|
133
|
-
|
|
134
|
-
| Class | Purpose |
|
|
135
|
-
|-------|---------|
|
|
136
|
-
| `i8-input` | The `<input>` element itself |
|
|
137
|
-
| `i8-textarea` | The `<textarea>` element |
|
|
138
|
-
| `i8-label` | Floating label |
|
|
139
|
-
| `i8-label-wrapper` | Label container for positioning |
|
|
140
|
-
| `i8-hint` | Hint text below input |
|
|
141
|
-
| `i8-counter` | Character counter |
|
|
142
|
-
| `i8-prepend` / `i8-append` | Side icons/content (inside border) |
|
|
143
|
-
| `i8-before` / `i8-after` | Side content (outside border) |
|
|
144
|
-
| `i8-underline` | Bottom border element |
|
|
145
|
-
|
|
146
|
-
### Other built-in shortcuts
|
|
147
|
-
|
|
148
|
-
| Prefix | Components |
|
|
149
|
-
|--------|-----------|
|
|
150
|
-
| `btn` | Button — `btn`, `btn-round`, `btn-square`, `btn-icon`, `btn-label` |
|
|
151
|
-
| `card` | Card — `card`, `card-header`, `card-dense` |
|
|
152
|
-
| `checkbox` | Checkbox — `checkbox-root`, `checkbox`, `checkbox-indicator`, `checkbox-icon`, `checkbox-label` |
|
|
153
|
-
| `rb` | RadioGroup — `rb-container`, `rb-root`, `rb-item`, `rb-item-indicator`, `rb-item-label` |
|
|
154
|
-
| `select` | Select — `select-content`, `select-item`, `select-grp-label`, `select-separator` |
|
|
155
|
-
| `dialog` | Dialog — `dialog-overlay`, `dialog-card`, `dialog-header`, `dialog-title`, `dialog-close`, `dialog-footer` |
|
|
156
|
-
| `tabs` | Tabs — `tabs-indicator`, `tab` |
|
|
157
|
-
| `menu` | Menu — `menu-root`, `menu-item` |
|
|
158
|
-
| `loading` | Loading — `loading-indicator`, `loading-indicator-wrapper`, `inner-loading` |
|
|
159
|
-
| `toast` | Toasts — `toast-root`, `toasts-viewport` |
|
|
160
|
-
| `progress` | ProgressBar — `progress-bar` |
|
|
161
|
-
|
|
162
|
-
## Common patterns
|
|
163
|
-
|
|
164
|
-
### Pattern: Override a single variant
|
|
165
|
-
|
|
166
|
-
Change only the base classes of `c8-filled` while keeping all hover/dark/active variants intact:
|
|
167
|
-
|
|
168
|
-
```ts
|
|
169
|
-
import { vunorShortcuts, defineShortcuts } from 'vunor/theme'
|
|
170
|
-
|
|
171
|
-
const myOverrides = defineShortcuts({
|
|
172
|
-
'c8-filled': {
|
|
173
|
-
'': 'rounded-full', // only overrides base — hover, dark, etc. stay
|
|
174
|
-
},
|
|
175
|
-
})
|
|
176
|
-
|
|
177
|
-
export default defineConfig({
|
|
178
|
-
presets: [presetVunor()],
|
|
179
|
-
shortcuts: [vunorShortcuts(myOverrides)],
|
|
180
|
-
})
|
|
181
|
-
```
|
|
182
|
-
|
|
183
|
-
### Pattern: Override input underline style
|
|
184
|
-
|
|
185
|
-
```ts
|
|
186
|
-
const myOverrides = defineShortcuts({
|
|
187
|
-
'i8-flat': {
|
|
188
|
-
'': 'border-b-2', // thicker bottom border
|
|
189
|
-
},
|
|
190
|
-
})
|
|
191
|
-
```
|
|
192
|
-
|
|
193
|
-
### Pattern: Add a new shortcut
|
|
194
|
-
|
|
195
|
-
```ts
|
|
196
|
-
const myShortcuts = defineShortcuts({
|
|
197
|
-
'badge': {
|
|
198
|
-
'': 'inline-flex items-center px-$xs py-$xxs text-caption rounded-full',
|
|
199
|
-
'dark:': 'bg-white/10',
|
|
200
|
-
},
|
|
201
|
-
})
|
|
202
|
-
|
|
203
|
-
shortcuts: [vunorShortcuts(myShortcuts)]
|
|
204
|
-
```
|
|
205
|
-
|
|
206
|
-
### Pattern: Override component-specific shortcuts
|
|
207
|
-
|
|
208
|
-
```ts
|
|
209
|
-
const myOverrides = defineShortcuts({
|
|
210
|
-
'btn': {
|
|
211
|
-
'': 'uppercase tracking-wider', // make all buttons uppercase
|
|
212
|
-
},
|
|
213
|
-
'card': {
|
|
214
|
-
'': 'shadow-lg', // add shadow to all cards
|
|
215
|
-
},
|
|
216
|
-
})
|
|
217
|
-
```
|
|
218
|
-
|
|
219
|
-
## Integration
|
|
220
|
-
|
|
221
|
-
- Shortcuts are consumed by UnoCSS — they expand to utility classes at build time.
|
|
222
|
-
- The `c8-*` and `i8-*` systems are used internally by Vunor components (`VuButton` uses `c8-*`, `VuInput` uses `i8-*`).
|
|
223
|
-
- You can use `c8-*` and `i8-*` classes on any HTML element, not just Vunor components.
|
|
224
|
-
- `scope-{color}` must be set on an ancestor (or the element itself) for `c8-*` and `i8-*` to pick up colors.
|
|
225
|
-
|
|
226
|
-
## Best practices
|
|
227
|
-
|
|
228
|
-
- Always pass overrides through `vunorShortcuts(overrides)` — don't try to manually merge with the defaults.
|
|
229
|
-
- Override at the most specific variant level possible. Replacing `''` (base) is safe; replacing the entire shortcut object loses all variant handling.
|
|
230
|
-
- Use `defineShortcuts()` for type safety — it validates the structure at the TypeScript level.
|
|
231
|
-
- Keep custom shortcuts in a separate file (e.g., `shortcuts.custom.ts`) for clarity.
|
|
232
|
-
|
|
233
|
-
## Gotchas
|
|
234
|
-
|
|
235
|
-
- Shortcut keys are **variant prefixes**, not CSS pseudo-classes. The key `'hover:'` (with colon) prepends `hover:` to each class in the value string.
|
|
236
|
-
- The empty string key `''` is the base (no-prefix) classes. It's required for every shortcut.
|
|
237
|
-
- `mergeVunorShortcuts` does **deep merge**, not replacement. If you need to completely replace a shortcut, set every key explicitly.
|
|
238
|
-
- Shortcut names become CSS class names. Adding a shortcut `'my-card'` means you use `class="my-card"`.
|
|
239
|
-
- The `i8` rules (`i8-border-*`, `i8-bg-*`, `i8-outline-*`) are separate UnoCSS rules, not shortcuts. They set CSS custom properties (`--i8-border-color`, `--i8-bg-color`) consumed by the `i8-*` shortcuts.
|