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.
Files changed (62) hide show
  1. package/README.md +6 -11
  2. package/dist/AppLayout.mjs +0 -0
  3. package/dist/AppToasts.mjs +4 -8
  4. package/dist/Button.mjs +5 -10
  5. package/dist/ButtonBase.mjs +4 -8
  6. package/dist/Calendar.mjs +10 -14
  7. package/dist/Card.mjs +4 -9
  8. package/dist/CardHeader.mjs +5 -10
  9. package/dist/CardInner.mjs +4 -9
  10. package/dist/Checkbox.mjs +4 -8
  11. package/dist/Combobox.d.mts +9 -9
  12. package/dist/Combobox.mjs +5 -9
  13. package/dist/DatePicker.d.mts +9 -9
  14. package/dist/DatePicker.mjs +12 -17
  15. package/dist/DatePickerBase.d.mts +9 -9
  16. package/dist/DatePickerBase.mjs +13 -17
  17. package/dist/DatePickerInner.mjs +5 -9
  18. package/dist/DatePickerPopup.mjs +4 -8
  19. package/dist/DelayedSwitch.mjs +4 -9
  20. package/dist/DevTools.mjs +583 -150
  21. package/dist/Dialog.d.mts +6 -6
  22. package/dist/Dialog.mjs +4 -8
  23. package/dist/Icon.mjs +4 -9
  24. package/dist/InnerLoading.mjs +4 -8
  25. package/dist/Input.d.mts +13 -13
  26. package/dist/Input.mjs +4 -8
  27. package/dist/InputBase.d.mts +9 -9
  28. package/dist/InputBase.mjs +4 -8
  29. package/dist/Label.mjs +1 -4
  30. package/dist/LoadingIndicator.mjs +4 -8
  31. package/dist/Menu.d.mts +2 -2
  32. package/dist/Menu.mjs +5 -14
  33. package/dist/MenuItem.mjs +4 -9
  34. package/dist/OverflowContainer.mjs +4 -8
  35. package/dist/Pagination.mjs +4 -9
  36. package/dist/Popover.mjs +4 -9
  37. package/dist/ProgressBar.mjs +4 -9
  38. package/dist/RadioGroup.mjs +4 -8
  39. package/dist/Select.d.mts +9 -9
  40. package/dist/Select.mjs +4 -9
  41. package/dist/SelectBase.mjs +4 -8
  42. package/dist/Slider.mjs +4 -8
  43. package/dist/Tabs.mjs +4 -9
  44. package/dist/nuxt.mjs +1 -3
  45. package/dist/theme.d.mts +35 -0
  46. package/dist/theme.mjs +313 -336
  47. package/dist/utils-6bTTIoaw.js +40 -0
  48. package/dist/utils.d.mts +2 -2
  49. package/dist/utils.mjs +1 -4
  50. package/dist/vite.mjs +1 -2
  51. package/dist/vunor.d.mts +13 -13
  52. package/dist/vunor.mjs +1 -6
  53. package/package.json +30 -37
  54. package/scripts/setup-skills.js +0 -78
  55. package/skills/vunor/SKILL.md +0 -115
  56. package/skills/vunor/components.md +0 -320
  57. package/skills/vunor/core.md +0 -173
  58. package/skills/vunor/forms.md +0 -348
  59. package/skills/vunor/palette.md +0 -223
  60. package/skills/vunor/rules.md +0 -263
  61. package/skills/vunor/shortcuts.md +0 -239
  62. package/skills/vunor/typography.md +0 -204
@@ -0,0 +1,40 @@
1
+ import { computed, getCurrentInstance } from "vue";
2
+ //#region src/components/Input/utils.ts
3
+ function useInputProps() {
4
+ const instance = getCurrentInstance();
5
+ if (instance) {
6
+ const props = instance.props;
7
+ return computed(() => ({
8
+ label: props.label,
9
+ stackLabel: props.stackLabel,
10
+ placeholder: props.placeholder,
11
+ design: props.design,
12
+ readonly: props.readonly,
13
+ disabled: props.disabled,
14
+ iconPrepend: props.iconPrepend,
15
+ iconAppend: props.iconAppend,
16
+ groupItem: props.groupItem,
17
+ type: props.type,
18
+ rows: props.type === "textarea" ? props.rows : void 0,
19
+ autoGrow: props.autoGrow,
20
+ maxlength: props.maxlength,
21
+ required: props.required,
22
+ active: props.active,
23
+ loading: props.loading,
24
+ onAppendClick: props.onAppendClick,
25
+ onPrependClick: props.onPrependClick,
26
+ onBlur: props.onBlur,
27
+ onFocus: props.onFocus,
28
+ iconBefore: props.iconBefore,
29
+ iconAfter: props.iconAfter,
30
+ error: props.error,
31
+ hint: props.hint,
32
+ autocomplete: props.autocomplete,
33
+ onBeforeClick: props.onBeforeClick,
34
+ onAfterClick: props.onAfterClick,
35
+ onClick: props.onClick
36
+ }));
37
+ }
38
+ }
39
+ //#endregion
40
+ export { useInputProps as t };
package/dist/utils.d.mts CHANGED
@@ -13,11 +13,11 @@ type TVueCssClass = string | string[] | Record<string, boolean | undefined>;
13
13
  declare function mergeCssClasses(...args: Array<TVueCssClass | undefined>): Record<string, boolean>;
14
14
  //#endregion
15
15
  //#region src/components/utils/provide-inject.d.ts
16
- declare const useProvideInject: <PA extends any[], IA extends any[], PR, INJ>(key: string, init: () => TProvideInjectBody<PA, IA, PR, INJ>) => {
16
+ declare const useProvideInject: <PA extends unknown[], IA extends unknown[], PR, INJ>(key: string, init: () => TProvideInjectBody<PA, IA, PR, INJ>) => {
17
17
  provide: (...args: PA) => PR;
18
18
  inject: (...args: IA) => INJ | undefined;
19
19
  };
20
- interface TProvideInjectBody<PA extends any[], IA extends any[], PR, INJ> {
20
+ interface TProvideInjectBody<PA extends unknown[], IA extends unknown[], PR, INJ> {
21
21
  _provide: (...args: PA) => PR;
22
22
  _inject: (...args: IA) => INJ;
23
23
  }
package/dist/utils.mjs CHANGED
@@ -1,5 +1,4 @@
1
1
  import { inject, provide } from "vue";
2
-
3
2
  //#region src/components/utils/merge-class.ts
4
3
  /**
5
4
  * Merges CSS classes from various input types into a single object.
@@ -17,7 +16,6 @@ function mergeCssClasses(...args) {
17
16
  }
18
17
  return result;
19
18
  }
20
-
21
19
  //#endregion
22
20
  //#region src/components/utils/provide-inject.ts
23
21
  const useProvideInject = (key, init) => {
@@ -47,6 +45,5 @@ useProvideInject("key", () => {
47
45
  _inject: () => a
48
46
  };
49
47
  });
50
-
51
48
  //#endregion
52
- export { mergeCssClasses, useProvideInject };
49
+ export { mergeCssClasses, useProvideInject };
package/dist/vite.mjs CHANGED
@@ -6,6 +6,5 @@ const VunorVueResolver = (componentName) => {
6
6
  from: `vunor/${componentName.slice(2)}`
7
7
  };
8
8
  };
9
-
10
9
  //#endregion
11
- export { VunorVueResolver };
10
+ export { VunorVueResolver };
package/dist/vunor.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import * as vue from "vue";
1
+ import * as _$vue from "vue";
2
2
  import { ComputedRef, Ref } from "vue";
3
3
 
4
4
  //#region src/components/AppToasts/app-toasts.d.ts
@@ -19,7 +19,7 @@ type TToastInternal = TAppToast & {
19
19
  };
20
20
  declare function useAppToasts(): {
21
21
  create: (toast: TAppToast) => () => void;
22
- toasts: vue.Ref<{
22
+ toasts: _$vue.Ref<{
23
23
  title: string;
24
24
  message: string;
25
25
  duration?: number | undefined;
@@ -50,7 +50,7 @@ declare function useAppToasts(): {
50
50
  //#region src/components/Card/pi.d.ts
51
51
  declare const useCardPI: () => {
52
52
  provide: () => {
53
- headerLevel: vue.Ref<string, string>;
53
+ headerLevel: _$vue.Ref<string, string>;
54
54
  };
55
55
  inject: () => void | undefined;
56
56
  };
@@ -58,7 +58,7 @@ declare const useCardPI: () => {
58
58
  //#region src/components/Input/pi.d.ts
59
59
  declare const useInputPi: () => {
60
60
  provide: () => {
61
- focused: vue.ComputedRef<boolean>;
61
+ focused: _$vue.ComputedRef<boolean>;
62
62
  };
63
63
  inject: (a: Ref<boolean, boolean>) => void | undefined;
64
64
  };
@@ -96,10 +96,10 @@ interface TInputBaseProps extends Omit<TInputAttrs, 'data-has-prepend' | 'data-h
96
96
  active?: boolean;
97
97
  loading?: boolean;
98
98
  noUnderline?: boolean;
99
- onAppendClick?: (event: MouseEvent) => any;
100
- onPrependClick?: (event: MouseEvent) => any;
101
- onBlur?: (event: FocusEvent) => any;
102
- onFocus?: (event: FocusEvent) => any;
99
+ onAppendClick?: (event: MouseEvent) => void;
100
+ onPrependClick?: (event: MouseEvent) => void;
101
+ onBlur?: (event: FocusEvent) => void;
102
+ onFocus?: (event: FocusEvent) => void;
103
103
  }
104
104
  interface TInputProps extends TInputBaseProps {
105
105
  iconBefore?: string;
@@ -108,11 +108,11 @@ interface TInputProps extends TInputBaseProps {
108
108
  hint?: string;
109
109
  groupTemplate?: string;
110
110
  stackLabel?: boolean;
111
- onBeforeClick?: (event: MouseEvent) => any;
112
- onAfterClick?: (event: MouseEvent) => any;
113
- onClick?: (event: MouseEvent) => any;
114
- onBlur?: (event: FocusEvent) => any;
115
- onFocus?: (event: FocusEvent) => any;
111
+ onBeforeClick?: (event: MouseEvent) => void;
112
+ onAfterClick?: (event: MouseEvent) => void;
113
+ onClick?: (event: MouseEvent) => void;
114
+ onBlur?: (event: FocusEvent) => void;
115
+ onFocus?: (event: FocusEvent) => void;
116
116
  }
117
117
  interface TInputBaseEmits {
118
118
  (e: 'prependClick' | 'appendClick', event: MouseEvent): void;
package/dist/vunor.mjs CHANGED
@@ -1,6 +1,5 @@
1
1
  import { computed, getCurrentInstance, onMounted, onUnmounted, ref, watch } from "vue";
2
2
  import { useProvideInject } from "vunor/utils";
3
-
4
3
  //#region src/components/AppToasts/app-toasts.ts
5
4
  const toasts = ref([]);
6
5
  function useAppToasts() {
@@ -28,7 +27,6 @@ function useAppToasts() {
28
27
  close
29
28
  };
30
29
  }
31
-
32
30
  //#endregion
33
31
  //#region src/components/Card/pi.ts
34
32
  const safeTag = (t) => t && /^h[1-6]$/.test(t) ? t : "";
@@ -56,7 +54,6 @@ const useCardPI = () => useProvideInject("__vunor_card_PI", () => {
56
54
  }
57
55
  };
58
56
  });
59
-
60
57
  //#endregion
61
58
  //#region src/components/Input/pi.ts
62
59
  const useInputPi = () => useProvideInject("__vunor_input_PI", () => {
@@ -72,7 +69,6 @@ const useInputPi = () => useProvideInject("__vunor_input_PI", () => {
72
69
  }
73
70
  };
74
71
  });
75
-
76
72
  //#endregion
77
73
  //#region src/components/Input/utils.ts
78
74
  function useHtmlInputAttrs() {
@@ -168,6 +164,5 @@ function useInputDataAttrs() {
168
164
  "aria-disabled": instance?.props.disabled ? true : void 0
169
165
  }));
170
166
  }
171
-
172
167
  //#endregion
173
- export { useAppToasts, useCardPI, useHtmlInputAttrs, useInputBaseProps, useInputDataAttrs, useInputPi, useInputProps };
168
+ export { useAppToasts, useCardPI, useHtmlInputAttrs, useInputBaseProps, useInputDataAttrs, useInputPi, useInputProps };
package/package.json CHANGED
@@ -1,13 +1,8 @@
1
1
  {
2
2
  "name": "vunor",
3
- "version": "0.1.2",
4
- "bin": {
5
- "setup-skills": "./scripts/setup-skills.js"
6
- },
3
+ "version": "0.1.4",
7
4
  "files": [
8
- "dist",
9
- "skills",
10
- "scripts/setup-skills.js"
5
+ "dist"
11
6
  ],
12
7
  "type": "module",
13
8
  "exports": {
@@ -183,43 +178,41 @@
183
178
  "pub": "npm publish --access public",
184
179
  "type-check": "vue-tsc --build --force",
185
180
  "test": "vitest run && playwright test",
186
- "test:e2e": "playwright test",
187
- "setup-skills": "node ./scripts/setup-skills.js",
188
- "postinstall": "node ./scripts/setup-skills.js --postinstall"
181
+ "test:e2e": "playwright test"
189
182
  },
190
183
  "dependencies": {
191
- "@internationalized/date": "^3.11.0",
192
- "@prostojs/palitra": "^0.0.3",
193
- "@unocss/preset-mini": "^66.6.0",
194
- "defu": "^6.1.4",
195
- "reka-ui": "^2.0.0",
196
- "unocss": "^66.6.0",
197
- "vue": "^3.5.28"
184
+ "@internationalized/date": "^3.12.1",
185
+ "@prostojs/palitra": "^0.0.4",
186
+ "@unocss/preset-mini": "^66.6.8",
187
+ "defu": "^6.1.7",
188
+ "reka-ui": "^2.9.6",
189
+ "unocss": "^66.6.8",
190
+ "vue": "^3.5.32"
198
191
  },
199
192
  "devDependencies": {
200
193
  "@iconify/utils": "^3.1.0",
201
- "@nuxt/kit": "^3.21.1",
202
- "@nuxt/schema": "^3.21.1",
203
- "@playwright/test": "^1.58.2",
204
- "@types/node": "^22.19.11",
205
- "@unocss/preset-icons": "^66.6.0",
194
+ "@nuxt/kit": "^4.4.2",
195
+ "@nuxt/schema": "^4.4.2",
196
+ "@playwright/test": "^1.59.1",
197
+ "@types/node": "^25.6.0",
198
+ "@unocss/preset-icons": "^66.6.8",
206
199
  "@unocss/preset-mini": "^66.6.0",
207
- "@unocss/preset-wind": "^66.6.0",
208
- "@unocss/reset": "^66.6.0",
209
- "@vitejs/plugin-vue": "^6.0.4",
210
- "@vue/tsconfig": "^0.7.0",
211
- "@vueuse/core": "^13.9.0",
212
- "rolldown": "1.0.0-rc.5",
213
- "rolldown-plugin-dts": "^0.22.1",
200
+ "@unocss/preset-wind": "^66.6.8",
201
+ "@unocss/reset": "^66.6.8",
202
+ "@vitejs/plugin-vue": "^6.0.6",
203
+ "@vue/tsconfig": "^0.9.1",
204
+ "@vueuse/core": "^14.2.1",
205
+ "rolldown": "1.0.0-rc.16",
206
+ "rolldown-plugin-dts": "^0.23.2",
214
207
  "tsx": "^4.21.0",
215
- "typescript": "^5.9.3",
208
+ "typescript": "^6.0.3",
216
209
  "unocss": "^66.6.0",
217
- "unocss-preset-scrollbar": "^3.2.0",
218
- "unplugin-auto-import": "^19.3.0",
219
- "unplugin-vue-components": "^28.8.0",
220
- "vite": "^7.3.1",
221
- "vitest": "^3.2.4",
222
- "vue-router": "^4.6.4",
223
- "vue-tsc": "^3.2.4"
210
+ "unocss-preset-scrollbar": "^4.0.0",
211
+ "unplugin-auto-import": "^21.0.0",
212
+ "unplugin-vue-components": "^32.0.0",
213
+ "vite": "^8.0.8",
214
+ "vitest": "^4.1.4",
215
+ "vue-router": "^5.0.4",
216
+ "vue-tsc": "^3.2.6"
224
217
  }
225
218
  }
@@ -1,78 +0,0 @@
1
- #!/usr/bin/env node
2
- /* prettier-ignore */
3
- import fs from 'fs'
4
- import path from 'path'
5
- import os from 'os'
6
- import { fileURLToPath } from 'url'
7
-
8
- const __dirname = path.dirname(fileURLToPath(import.meta.url))
9
-
10
- const SKILL_NAME = 'vunor'
11
- const SKILL_SRC = path.join(__dirname, '..', 'skills', SKILL_NAME)
12
-
13
- if (!fs.existsSync(SKILL_SRC)) {
14
- console.error(`No skills found at ${SKILL_SRC}`)
15
- console.error('Add your SKILL.md files to the skills/' + SKILL_NAME + '/ directory first.')
16
- process.exit(1)
17
- }
18
-
19
- const AGENTS = {
20
- 'Claude Code': { dir: '.claude/skills', global: path.join(os.homedir(), '.claude', 'skills') },
21
- 'Cursor': { dir: '.cursor/skills', global: path.join(os.homedir(), '.cursor', 'skills') },
22
- 'Windsurf': { dir: '.windsurf/skills', global: path.join(os.homedir(), '.windsurf', 'skills') },
23
- 'Codex': { dir: '.codex/skills', global: path.join(os.homedir(), '.codex', 'skills') },
24
- 'OpenCode': { dir: '.opencode/skills', global: path.join(os.homedir(), '.opencode', 'skills') },
25
- }
26
-
27
- const args = process.argv.slice(2)
28
- const isGlobal = args.includes('--global') || args.includes('-g')
29
- const isPostinstall = args.includes('--postinstall')
30
- let installed = 0, skipped = 0
31
- const installedDirs = []
32
-
33
- for (const [agentName, cfg] of Object.entries(AGENTS)) {
34
- const targetBase = isGlobal ? cfg.global : path.join(process.cwd(), cfg.dir)
35
- const agentRootDir = path.dirname(cfg.global) // Check if the agent has ever been installed globally
36
-
37
- // In postinstall mode: silently skip agents that aren't set up globally
38
- if (isPostinstall || isGlobal) {
39
- if (!fs.existsSync(agentRootDir)) { skipped++; continue }
40
- }
41
-
42
- const dest = path.join(targetBase, SKILL_NAME)
43
- try {
44
- fs.mkdirSync(dest, { recursive: true })
45
- fs.cpSync(SKILL_SRC, dest, { recursive: true })
46
- console.log(`āœ… ${agentName}: installed to ${dest}`)
47
- installed++
48
- if (!isGlobal) installedDirs.push(cfg.dir + '/' + SKILL_NAME)
49
- } catch (err) {
50
- console.warn(`āš ļø ${agentName}: failed — ${err.message}`)
51
- }
52
- }
53
-
54
- // Add locally-installed skill dirs to .gitignore
55
- if (!isGlobal && installedDirs.length > 0) {
56
- const gitignorePath = path.join(process.cwd(), '.gitignore')
57
- let gitignoreContent = ''
58
- try { gitignoreContent = fs.readFileSync(gitignorePath, 'utf8') } catch {}
59
- const linesToAdd = installedDirs.filter(d => !gitignoreContent.includes(d))
60
- if (linesToAdd.length > 0) {
61
- const hasHeader = gitignoreContent.includes('# AI agent skills')
62
- const block = (gitignoreContent && !gitignoreContent.endsWith('\n') ? '\n' : '')
63
- + (hasHeader ? '' : '\n# AI agent skills (auto-generated by setup-skills)\n')
64
- + linesToAdd.join('\n') + '\n'
65
- fs.appendFileSync(gitignorePath, block)
66
- console.log(`šŸ“ Added ${linesToAdd.length} entries to .gitignore`)
67
- }
68
- }
69
-
70
- if (installed === 0 && isPostinstall) {
71
- // Silence is fine — no agents present, nothing to do
72
- } else if (installed === 0 && skipped === Object.keys(AGENTS).length) {
73
- console.log('No agent directories detected. Try --global or run without it for project-local install.')
74
- } else if (installed === 0) {
75
- console.log('Nothing installed. Run without --global to install project-locally.')
76
- } else {
77
- console.log(`\n✨ Done! Restart your AI agent to pick up the "${SKILL_NAME}" skill.`)
78
- }
@@ -1,115 +0,0 @@
1
- ---
2
- name: vunor
3
- description: "Vunor — Vue 3 / Nuxt 3 UI library and UnoCSS theme engine. Use this skill when working with: presetVunor, vunorShortcuts, defineShortcuts, mergeVunorShortcuts, VunorVueResolver, Vu-prefixed components (VuButton, VuInput, VuSelect, VuCombobox, VuCard, VuDialog, VuTabs, VuCheckbox, VuRadioGroup, VuSlider, VuDatePicker, VuMenu, VuAppLayout, VuIcon, VuPopover), vunor UnoCSS custom rules (scope-*, current-*, layer-*, surface-*, text-h1/text-body/text-label typography, text-mt-*/text-mb-* text margins, $xxs/$xs/$s/$m/$l/$xl/$xxl spacing tokens, card-* card spacing, fingertip-* touch targets, c8-filled/c8-flat/c8-outlined/c8-light clickable styles, i8-flat/i8-filled/i8-round input styles, i8-border-*/i8-bg-*/i8-outline-* input rules, icon-color/icon-size/icon-opacity-*, bg-current/text-current/icon-current/border-current current-color system), vunor Oklab perceptual color palette, vunor golden-ratio typography and spacing, vunor shortcut objects. Import paths: vunor, vunor/theme, vunor/utils, vunor/vite, vunor/nuxt."
4
- ---
5
-
6
- # vunor
7
-
8
- A UnoCSS theme engine that derives a complete design system from mathematical constants (golden ratio, Oklab color model) — plus 30+ accessible Vue 3 components built on Reka UI. All styling is UnoCSS-only with no CSS files.
9
-
10
- ## How to use this skill
11
-
12
- Read the domain file that matches the task. Do not load all files — only what you need.
13
-
14
- | Domain | File | Load when... |
15
- |--------|------|-------------|
16
- | Core concepts & setup | [core.md](core.md) | Installing vunor, setting up Vue+Vite or Nuxt, understanding the mental model |
17
- | Color palette | [palette.md](palette.md) | Configuring colors, using layers/surfaces/scopes, understanding the current-color system |
18
- | Typography & spacing | [typography.md](typography.md) | Using text utilities, spacing tokens, fingertip sizes, card spacing |
19
- | Shortcut objects | [shortcuts.md](shortcuts.md) | Customizing component styles, understanding c8/i8 systems, merging shortcuts |
20
- | Components overview | [components.md](components.md) | Using layout, action, feedback, or utility components (Card, Dialog, Button, Tabs, etc.) |
21
- | Form components | [forms.md](forms.md) | Using Input, Select, Combobox, Checkbox, RadioGroup, Slider, DatePicker |
22
- | UnoCSS custom rules | [rules.md](rules.md) | Understanding exact rule patterns, CSS custom properties, i8-*/scope-*/current-*/card-*/fingertip-*/icon-* rules |
23
-
24
- ## High-level guide
25
-
26
- ### Color scope — required foundation
27
-
28
- **`scope-{color}` must be set at the root level** (`<html>`, `<body>`, or your app wrapper). It defines the default palette for the entire page — layers, surfaces, buttons, inputs, and all components depend on it. Without a scope, no colors are available.
29
-
30
- ```html
31
- <html class="scope-primary"> <!-- sets the default palette for the whole app -->
32
- <body class="layer-0"> <!-- page background using that palette -->
33
- ```
34
-
35
- You can override the scope on any subtree for a different palette:
36
-
37
- ```html
38
- <body class="scope-primary layer-0">
39
- <main> <!-- inherits scope-primary -->
40
- <div class="scope-error"> <!-- this subtree uses error palette -->
41
- <button class="c8-filled">Delete</button>
42
- </div>
43
- </main>
44
- </body>
45
- ```
46
-
47
- See [palette.md](palette.md) for color configuration and details.
48
-
49
- ### Backgrounds: layers and surfaces
50
-
51
- Use `scope-{color}` to set the active palette, then apply backgrounds:
52
-
53
- - **`layer-0` through `layer-4`** — screen/page backgrounds. `layer-0` is the outermost (lightest in light mode, darkest in dark). Each layer steps progressively deeper. Layers auto-adapt to light/dark mode. Control the brightness difference between layers via `palette.layersDepth` in [palette.md](palette.md).
54
-
55
- - **`surface-50` through `surface-900`** — colored blocks, banners, callouts. These map to the main 10-step palette and apply a full bg + text + icon set. `surface-0`–`surface-4` map to the layer scale. Configure via `palette.surfaces` — see [palette.md](palette.md).
56
-
57
- ```html
58
- <div class="layer-0 scope-primary"> <!-- page background -->
59
- <div class="layer-1"> <!-- card/section -->
60
- <div class="surface-100">info banner</div> <!-- colored block -->
61
- <div class="surface-500">bold accent</div>
62
- </div>
63
- </div>
64
- ```
65
-
66
- ### Interactive elements: c8 and i8
67
-
68
- - **`c8-filled` / `c8-flat` / `c8-outlined` / `c8-light`** — clickable styles for buttons and interactive elements. Each includes hover, active, focus, and disabled states. Always pair with `scope-{color}`. See [shortcuts.md](shortcuts.md).
69
-
70
- - **`i8-flat` / `i8-filled` / `i8-round`** — input field styles with floating labels, underlines, and focus states. Used by `VuInput`, `VuSelect`, `VuCombobox`. See [shortcuts.md](shortcuts.md) and [forms.md](forms.md).
71
-
72
- ```html
73
- <button class="scope-primary c8-filled">Save</button>
74
- <button class="scope-error c8-flat">Cancel</button>
75
- <VuInput v-model="name" label="Name" design="filled" />
76
- ```
77
-
78
- ### Spacing and typography
79
-
80
- Golden-ratio spacing tokens work with all UnoCSS spacing utilities (`p-`, `m-`, `gap-`, etc.):
81
-
82
- | Token | ~Value | Usage |
83
- |-------|--------|-------|
84
- | `$xxs` | 0.24em | Tiny gaps |
85
- | `$xs` | 0.38em | Compact spacing |
86
- | `$s` | 0.62em | Small spacing |
87
- | `$m` | 1em | Standard spacing |
88
- | `$l` | 1.62em | Large spacing |
89
- | `$xl` | 2.62em | Section spacing |
90
- | `$xxl` | 4.24em | Page-level spacing |
91
-
92
- Typography utilities (`text-h1`..`text-caption`) set font size, weight, line height, and letter spacing in one class. Use `text-mt-*` / `text-mb-*` for optically-corrected margins between text blocks. See [typography.md](typography.md).
93
-
94
- ```html
95
- <h1 class="text-h1 text-mb-$m">Title</h1>
96
- <p class="text-body p-$s">Content with golden-ratio spacing</p>
97
- ```
98
-
99
- ## Quick reference
100
-
101
- ```ts
102
- // Setup
103
- import { presetVunor, vunorShortcuts } from 'vunor/theme'
104
- import { VunorVueResolver } from 'vunor/vite'
105
-
106
- // UnoCSS config
107
- presets: [presetVunor({ palette: { colors: { primary: '#6B4EFF' } } })]
108
- shortcuts: [vunorShortcuts()]
109
-
110
- // Components auto-import (Vite)
111
- resolvers: [VunorVueResolver] // maps <VuButton> → import from 'vunor/Button'
112
-
113
- // Nuxt — just add the module
114
- modules: ['vunor/nuxt']
115
- ```