@maltjoy/mcp-server 0.4.0 → 0.6.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (131) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +30 -3
  3. package/dist/doc/VJoyAdminBanner/guideline.md +284 -0
  4. package/dist/doc/VJoyAvailability/guideline.md +352 -0
  5. package/dist/doc/VJoyAvatar/guideline.md +192 -0
  6. package/dist/doc/VJoyAvatarsList/guideline.md +328 -0
  7. package/dist/doc/VJoyBadge/guideline.md +169 -0
  8. package/dist/doc/VJoyBadgeLevel/guideline.md +166 -0
  9. package/dist/doc/VJoyBlockSkeleton/guideline.md +150 -0
  10. package/dist/doc/VJoyBottomSheet/guideline.md +345 -0
  11. package/dist/doc/VJoyBottomSheetTrigger/guideline.md +156 -0
  12. package/dist/doc/VJoyButton/guideline.md +371 -0
  13. package/dist/doc/VJoyButton/metadata.json +0 -16
  14. package/dist/doc/VJoyButtonCard/guideline.md +384 -0
  15. package/dist/doc/VJoyCheckbox/guideline.md +317 -0
  16. package/dist/doc/VJoyCheckboxCard/guideline.md +381 -0
  17. package/dist/doc/VJoyCheckboxGroup/guideline.md +363 -0
  18. package/dist/doc/VJoyCheckboxGroup/metadata.json +7 -7
  19. package/dist/doc/VJoyCollapse/guideline.md +362 -0
  20. package/dist/doc/VJoyCollapseItem/guideline.md +394 -0
  21. package/dist/doc/VJoyCompanyAvatar/guideline.md +162 -0
  22. package/dist/doc/VJoyDialog/guideline.md +425 -0
  23. package/dist/doc/VJoyDialogTrigger/guideline.md +186 -0
  24. package/dist/doc/VJoyDot/guideline.md +177 -0
  25. package/dist/doc/VJoyDrawer/guideline.md +392 -0
  26. package/dist/doc/VJoyDrawerTrigger/guideline.md +145 -0
  27. package/dist/doc/VJoyDropdown/guideline.md +393 -0
  28. package/dist/doc/VJoyDropdown/metadata.json +6 -6
  29. package/dist/doc/VJoyDropdownList/guideline.md +396 -0
  30. package/dist/doc/VJoyDropdownList/metadata.json +7 -7
  31. package/dist/doc/VJoyDropzone/guideline.md +390 -0
  32. package/dist/doc/VJoyDropzone/metadata.json +36 -1
  33. package/dist/doc/VJoyFilterBar/guideline.md +419 -0
  34. package/dist/doc/VJoyFilterBarButton/guideline.md +359 -0
  35. package/dist/doc/VJoyFloatingActionsBar/guideline.md +372 -0
  36. package/dist/doc/VJoyFormError/guideline.md +325 -0
  37. package/dist/doc/VJoyFormError/metadata.json +0 -14
  38. package/dist/doc/VJoyFormFieldSkeleton/guideline.md +159 -0
  39. package/dist/doc/VJoyFormGroup/guideline.md +285 -0
  40. package/dist/doc/VJoyFunnel/guideline.md +349 -0
  41. package/dist/doc/VJoyFunnelFooter/guideline.md +178 -0
  42. package/dist/doc/VJoyFunnelHeader/guideline.md +204 -0
  43. package/dist/doc/VJoyHighlight/guideline.md +169 -0
  44. package/dist/doc/VJoyIcon/JoyIcon.types.ts +1 -1
  45. package/dist/doc/VJoyIcon/guideline.md +168 -0
  46. package/dist/doc/VJoyIcon/metadata.json +0 -1
  47. package/dist/doc/VJoyIconButton/guideline.md +169 -0
  48. package/dist/doc/VJoyIconButton/metadata.json +1 -1
  49. package/dist/doc/VJoyIndicator/guideline.md +168 -0
  50. package/dist/doc/VJoyIndicators/guideline.md +183 -0
  51. package/dist/doc/VJoyInput/JoyInput.types.ts +1 -6
  52. package/dist/doc/VJoyInput/guideline.md +401 -0
  53. package/dist/doc/VJoyInput/metadata.json +5 -14
  54. package/dist/doc/VJoyInputDigit/guideline.md +381 -0
  55. package/dist/doc/VJoyInputNumber/guideline.md +414 -0
  56. package/dist/doc/VJoyInputNumber/metadata.json +22 -17
  57. package/dist/doc/VJoyInputPassword/guideline.md +379 -0
  58. package/dist/doc/VJoyInputPassword/metadata.json +0 -14
  59. package/dist/doc/VJoyLabel/guideline.md +200 -0
  60. package/dist/doc/VJoyLink/guideline.md +360 -0
  61. package/dist/doc/VJoyListItem/guideline.md +335 -0
  62. package/dist/doc/VJoyMenu/guideline.md +304 -0
  63. package/dist/doc/VJoyMenu/metadata.json +21 -21
  64. package/dist/doc/VJoyMenuItem/guideline.md +352 -0
  65. package/dist/doc/VJoyPagination/guideline.md +355 -0
  66. package/dist/doc/VJoyPanel/guideline.md +238 -0
  67. package/dist/doc/VJoyPanelSection/guideline.md +160 -0
  68. package/dist/doc/VJoyPasswordRequirement/guideline.md +336 -0
  69. package/dist/doc/VJoyPasswordRequirement/metadata.json +1 -1
  70. package/dist/doc/VJoyProductTour/JoyProductTour.types.ts +0 -1
  71. package/dist/doc/VJoyProductTour/guideline.md +455 -0
  72. package/dist/doc/VJoyProductTour/metadata.json +1 -1
  73. package/dist/doc/VJoyProductTourTrigger/guideline.md +167 -0
  74. package/dist/doc/VJoyProgressBar/guideline.md +348 -0
  75. package/dist/doc/VJoyRadio/guideline.md +346 -0
  76. package/dist/doc/VJoyRadioGroup/guideline.md +331 -0
  77. package/dist/doc/VJoyRatingStars/guideline.md +306 -0
  78. package/dist/doc/VJoyScreenLoader/guideline.md +172 -0
  79. package/dist/doc/VJoySelect/guideline.md +396 -0
  80. package/dist/doc/VJoySelectableItem/guideline.md +351 -0
  81. package/dist/doc/VJoySelectableItemGroup/guideline.md +370 -0
  82. package/dist/doc/VJoySeparator/guideline.md +161 -0
  83. package/dist/doc/VJoySnackbar/guideline.md +402 -0
  84. package/dist/doc/VJoySpinner/guideline.md +168 -0
  85. package/dist/doc/VJoyStep/guideline.md +182 -0
  86. package/dist/doc/VJoyStepper/guideline.md +390 -0
  87. package/dist/doc/VJoyTab/guideline.md +298 -0
  88. package/dist/doc/VJoyTabs/guideline.md +353 -0
  89. package/dist/doc/VJoyTag/guideline.md +226 -0
  90. package/dist/doc/VJoyTagsInput/guideline.md +387 -0
  91. package/dist/doc/VJoyTagsList/guideline.md +311 -0
  92. package/dist/doc/VJoyTagsList/metadata.json +27 -27
  93. package/dist/doc/VJoyTemplate/guideline.md +366 -0
  94. package/dist/doc/VJoyText/guideline.md +175 -0
  95. package/dist/doc/VJoyText/metadata.json +1 -1
  96. package/dist/doc/VJoyTextarea/guideline.md +378 -0
  97. package/dist/doc/VJoyTitleBrand/guideline.md +155 -0
  98. package/dist/doc/VJoyToggle/guideline.md +327 -0
  99. package/dist/doc/VJoyTooltip/guideline.md +322 -0
  100. package/dist/doc/VJoyUserCard/guideline.md +268 -0
  101. package/dist/doc/VJoyUserCard/metadata.json +3 -17
  102. package/dist/doc/VJoyWalkthrough/guideline.md +351 -0
  103. package/dist/doc/VJoyWalkthroughTrigger/guideline.md +171 -0
  104. package/dist/doc/VJoyWrapper/guideline.md +173 -0
  105. package/dist/doc/css-classes.json +1 -15
  106. package/dist/doc/design-tokens.json +1 -0
  107. package/dist/doc/index.json +20 -30
  108. package/dist/index.js +22 -2
  109. package/dist/index.js.map +1 -1
  110. package/dist/tools/get-component-guideline.d.ts +30 -0
  111. package/dist/tools/get-component-guideline.d.ts.map +1 -0
  112. package/dist/tools/get-component-guideline.js +51 -0
  113. package/dist/tools/get-component-guideline.js.map +1 -0
  114. package/dist/tools/get-documentation-page.d.ts +22 -0
  115. package/dist/tools/get-documentation-page.d.ts.map +1 -0
  116. package/dist/tools/get-documentation-page.js +21 -0
  117. package/dist/tools/get-documentation-page.js.map +1 -0
  118. package/dist/tools/list-documentation-pages.d.ts +22 -0
  119. package/dist/tools/list-documentation-pages.d.ts.map +1 -0
  120. package/dist/tools/list-documentation-pages.js +17 -0
  121. package/dist/tools/list-documentation-pages.js.map +1 -0
  122. package/dist/tools/search-documentation.d.ts +41 -0
  123. package/dist/tools/search-documentation.d.ts.map +1 -0
  124. package/dist/tools/search-documentation.js +25 -0
  125. package/dist/tools/search-documentation.js.map +1 -0
  126. package/dist/zeroheight-parser.d.ts +27 -0
  127. package/dist/zeroheight-parser.d.ts.map +1 -0
  128. package/dist/zeroheight-parser.js +77 -0
  129. package/dist/zeroheight-parser.js.map +1 -0
  130. package/package.json +10 -10
  131. package/dist/doc/VJoyMultiCheckbox/metadata.json +0 -332
@@ -0,0 +1,371 @@
1
+ ---
2
+ component: VJoyButton
3
+ status: draft
4
+ language: en
5
+ dsds: JoyButton.dsds.json
6
+ dsdsVersion: "0.15.2"
7
+ ---
8
+
9
+ # Button
10
+
11
+ Use **`VJoyButton`** when the user needs to take an action — save, confirm, continue, or cancel.
12
+
13
+ It supports variants and sizes, optional icons, a loading state, full-width layout, and can look like a button while navigating somewhere when you set a native `href` (the root becomes an `<a>`). Native `<button>` / `<a>` attributes (for example `disabled`, `type`, `target`, `rel`) are passed through via `useAttrs` — they are not declared as component props.
14
+
15
+ | | |
16
+ | --- | --- |
17
+ | **Code** | `VJoyButton` from `@maltjoy/core-vue` |
18
+ | **Design** | [Figma — Buttons](https://www.figma.com/design/jfndp2QBJGS9yeuWbeGuvD/?node-id=12704-7106) |
19
+ | **Storybook** | [VJoyButton docs](https://doc.malt.tech/joy-storybook/?path=/docs/components-buttons-vjoybutton--docs) |
20
+ | **DSDS (machine)** | [`JoyButton.dsds.json`](./JoyButton.dsds.json) |
21
+ | **Live API** | `joy_get_component_info("VJoyButton")` |
22
+
23
+ ---
24
+
25
+ ## When to use this component
26
+
27
+ Use a button to help someone carry out an action in the current view — for example submitting a form, confirming a dialog, or starting the next step. `VJoyButton` is the default choice for labeled actions with clear emphasis (main, primary, secondary, ghost) and optional leading or trailing icons.
28
+
29
+ ### When not to use this component
30
+
31
+ | Need | Use instead |
32
+ | --- | --- |
33
+ | Icon only (no visible text) | [`VJoyIconButton`](https://doc.malt.tech/joy-storybook/?path=/docs/components-buttons-vjoyiconbutton--docs) |
34
+ | A text link inside a sentence or paragraph | `VJoyLink` |
35
+ | A custom-styled `<button>` / `<a>` | Still use `VJoyButton` + Joy tokens — don’t reinvent chrome |
36
+
37
+ > **Deprecated:** do not use `circle` on `VJoyButton` for new work. The prop may still appear in older MCP snapshots; it is not part of the current `VJoyButton` API. Prefer `VJoyIconButton`.
38
+
39
+ ---
40
+
41
+ ## How it works
42
+
43
+ ### Anatomy
44
+
45
+ | Part | Required? | What it is |
46
+ | --- | --- | --- |
47
+ | Container | Yes | Root `<button>`, or `<a>` when `href` is set on the element |
48
+ | Label | Yes | Text from the default slot or the `label` prop (rendered in `.joy-button--slot`) |
49
+ | Icon | No | Leading or trailing `VJoyIcon` when `icon` is set (`iconPosition`: `left` or `right`) |
50
+ | Spinner | No | `VJoySpinner` shown when `loading` is true; replaces visible label color |
51
+ | Ripple | Yes | `v-joy-ripple` on the root — tactile feedback on press |
52
+ | Focus ring | Yes | Keyboard focus via border + inset box-shadow — don’t remove it in product CSS |
53
+
54
+ ### Default values
55
+
56
+ - `variant` defaults to **`primary`**
57
+ - `size` defaults to **`medium`**
58
+ - `iconPosition` defaults to **`left`**
59
+ - `loading` defaults to **`false`**
60
+ - `full` defaults to **`false`**
61
+ - Native `type` defaults to **`button`** when the root is a `<button>`
62
+
63
+ Props, events, and slots: use Joy MCP (`joy_get_component_info`, `joy_get_component_types`) or Storybook — this page focuses on **when** and **how**, not a full API dump.
64
+
65
+ ---
66
+
67
+ ## Variants
68
+
69
+ Pick emphasis from what the action means on the surface — not from which swatch “looks nicer.”
70
+
71
+ Allowed values (from `TJoyButtonVariants`): `main`, `primary`, `secondary`, `ghost`, `admin`, `main-ai`, `primary-ai`, `secondary-ai`, `ghost-ai`. There is no `admin-ai`.
72
+
73
+ ### Main
74
+
75
+ Use for the **single principal CTA** on a page, dialog finalize, or side-panel finalize.
76
+
77
+ Avoid a second `main` on the **same** surface. The app header, a modal, and a side panel may each have their own `main`.
78
+
79
+ ### Primary
80
+
81
+ Use for important actions that are **not** the page’s principal CTA. This is the component default.
82
+
83
+ Avoid competing with an existing `main` for the same decision.
84
+
85
+ ### Secondary
86
+
87
+ Use for companions to `main` or `primary` — Cancel, Decline, Back.
88
+
89
+ Avoid using secondary alone when users still need a clear primary action.
90
+
91
+ ### Ghost
92
+
93
+ Lowest emphasis; no filled background. Use for tertiary or toolbar-like actions.
94
+
95
+ Avoid for high-stakes confirmations.
96
+
97
+ ### Admin
98
+
99
+ Internal / admin tooling only. Do not use on customer-facing product UI.
100
+
101
+ ### AI variants (`main-ai`, `primary-ai`, `secondary-ai`, `ghost-ai`)
102
+
103
+ Use only when the action is explicitly part of an AI feature. Don’t invent custom “AI” colors on a non-AI variant.
104
+
105
+ ### Not in the API: White
106
+
107
+ ZeroHeight shows a **White** variant. It is **not** in `TJoyButtonVariants`. Do not emit `variant="white"`. Prefer `secondary` or `ghost`, or confirm with design before adding a new API value.
108
+
109
+ ---
110
+
111
+ ## Sizes
112
+
113
+ Choose size for **density**, not decoration. Heights come from `--joy-form-field-height-*` inside the component — **don’t hardcode pixel heights** in apps.
114
+
115
+ | Size | Use when |
116
+ | --- | --- |
117
+ | `large` | Hero / marketing-scale CTAs. Only size with a built-in min-width (`calc(var(--joy-core-spacing-base) * 40)`). |
118
+ | `medium` | Default product actions |
119
+ | `small` | Dense toolbars |
120
+ | `xsmall` | Compact UI |
121
+ | `xxsmall` | Inline / very tight layouts |
122
+
123
+ > ZeroHeight’s “120px min-width” rule is **not** implemented. Don’t use `120px`.
124
+
125
+ ---
126
+
127
+ ## States
128
+
129
+ | State | What the user sees / can do |
130
+ | --- | --- |
131
+ | Default | Enabled and interactive |
132
+ | Hover | Pointer highlight (pointer devices) |
133
+ | Focus | Visible focus ring (keyboard / AT) — `border` + inset `box-shadow` |
134
+ | Active | Pressed; ripple feedback |
135
+ | Disabled | Not interactive (`disabled` attribute) — **always explain why** nearby (tooltip or helper) |
136
+ | Loading | Spinner (white on filled variants; teal on `ghost` / `secondary`); root is non-interactive (`disabled` when `loading`); label text becomes transparent — keep the same `size` so layout doesn’t jump |
137
+ | Full width | `full` prop sets `width: 100%` on the root |
138
+
139
+ Prefer `loading` during async work instead of only swapping the label or silently disabling.
140
+
141
+ ---
142
+
143
+ ## Best practices
144
+
145
+ Rules use RFC 2119 strength (same idea as DSDS `guidelines.level`).
146
+
147
+ ### Hierarchy
148
+
149
+ - **SHOULD** use one `main` CTA per surface (page / dialog / panel counted separately).
150
+ - **SHOULD** pair `secondary` or `ghost` with a stronger CTA when both appear.
151
+ - **SHOULD** put the fuller label on the stronger CTA in a pair (`Approve request` + `Decline`).
152
+
153
+ ### Implementation
154
+
155
+ - **MUST** use only `variant` / `size` / `iconPosition` values from MCP or `JoyButton.types.ts`.
156
+ - **MUST** style with Joy tokens / utilities — no custom `.joy-button` chrome.
157
+ - **MUST NOT** invent props (`color`, `white`, `height`, …).
158
+ - **MUST NOT** use deprecated `circle` — use `VJoyIconButton`.
159
+ - **MUST NOT** hardcode heights or `min-width: 120px`.
160
+ - **SHOULD** pass native attributes (`disabled`, `href`, `type`, `target`, `rel`) as HTML attributes, not as invented props.
161
+ - **SHOULD** use the default slot for rich label content; use `label` for simple string labels.
162
+
163
+ ### Interaction
164
+
165
+ - **MUST** set `loading` for async work.
166
+ - **MUST** explain disabled buttons when the user can see them.
167
+ - **SHOULD** set `href` when the control navigates with button chrome (root becomes `<a>`).
168
+ - **SHOULD** use `full` only when the button should span its container (for example mobile primary actions).
169
+
170
+ ### Do / don’t
171
+
172
+ | Do | Don’t |
173
+ | --- | --- |
174
+ | Use `size` + tokens | Hardcode `24` / `32` / `40` / `48` / `64`px |
175
+ | One `main` per surface | Several competing `main` CTAs |
176
+ | `VJoyIconButton` for icon-only | `VJoyButton` + `circle` |
177
+ | Explain why it’s disabled | A disabled button with no reason |
178
+ | Label = the outcome | Vague labels (`Click`, `Submit`, `Maybe later`) |
179
+ | `loading` during submit | Only changing label text |
180
+
181
+ ---
182
+
183
+ ## Content
184
+
185
+ Buttons drive action. Labels must be clear, predictable, and aligned with what happens next.
186
+
187
+ ### Label formula
188
+
189
+ **Infinitive verb + noun** (English):
190
+
191
+ - ✅ Upload document
192
+ - ✅ Send message
193
+ - ✅ Delete project
194
+
195
+ **Exceptions:** `Close`, `Cancel`, and `Done` may stand alone (especially on secondary).
196
+
197
+ Use the default slot or `label` prop — both render the same visible text. Prefer the slot when the label needs markup; prefer `label` for simple strings in Storybook / generated UIs.
198
+
199
+ ### Writing rules
200
+
201
+ | Strength | Rule |
202
+ | --- | --- |
203
+ | **MUST** | ≤ 25 characters; never truncate with ellipsis — wrap if needed |
204
+ | **MUST** | Active voice — ✅ `Send message` · ❌ `Message will be sent` |
205
+ | **MUST NOT** | Vague verbs alone — ❌ `Click`, ❌ `Submit` |
206
+ | **MUST NOT** | Yes / No pairs — ✅ `Enable notifications` / `Keep disabled` |
207
+ | **MUST NOT** | User or object names — ✅ `Send quote` · ❌ `Send quote to Jane Doe` |
208
+ | **SHOULD** | ≤ 3 words |
209
+ | **SHOULD** | Counts in parentheses — ✅ `Delete files (6)` |
210
+ | **SHOULD** | Echo title / header wording when it helps |
211
+ | **SHOULD** | Name the destination — ✅ `Continue to payment` · ❌ `Next` (except linear funnels) |
212
+ | **SHOULD** | Secondary still names an action — ✅ `View details`, `Skip step` |
213
+ | **SHOULD NOT** (EN) | Padding articles / pronouns — ❌ `Send my quote` |
214
+ | **SHOULD** (FR) | Articles / pronouns when grammar needs them — _mon profil_, _le projet_ |
215
+ | **SHOULD** | Neutral tone; joyful copy only for tours / promo dialogs |
216
+
217
+ ### Patterns
218
+
219
+ **Funnels** — Use `Next` / `Previous` only in linear flows. Otherwise name the destination (`Continue to payment`, `Review and confirm`). Keep the same verb + object when the action repeats.
220
+
221
+ **Dialogs** — Secondary must not guilt the user:
222
+
223
+ - ✅ Not now · Skip step · Continue without AI
224
+ - ❌ No thanks · I hate saving money
225
+
226
+ Destructive confirms name the object: ✅ `Delete project brief`, `Cancel subscription`.
227
+
228
+ **Icons** — Prefer text. Use an icon with label when it reinforces meaning (`icon` + `iconPosition`). Use icon alone only if the meaning is unambiguous (e.g. trash = delete); otherwise add a tooltip. No visible text → `VJoyIconButton`.
229
+
230
+ **Loading** — Keep a short, present-tense label (`Saving`, `Sending`) while `loading` is true; the spinner provides the progress cue.
231
+
232
+ ---
233
+
234
+ ## Accessibility
235
+
236
+ Behaviors (what must happen), not slogans.
237
+
238
+ | Behavior | Expectation |
239
+ | --- | --- |
240
+ | Role | Native `<button>` or `<a href>` — never a clickable `<div>` |
241
+ | Name | From default slot or `label`; `aria-labelledby` points to the label span when slot or `label` is present |
242
+ | Keyboard | **Enter** and **Space** activate a `<button>`; links follow native link keyboard behavior |
243
+ | Focus | Keep the focus ring visible — component uses `border` + inset `box-shadow` on `:focus` |
244
+ | Loading | Non-interactive (`disabled` when `loading`); prefer the `loading` prop over manual disable |
245
+ | Disabled | Don’t rely on color alone; provide text explaining why |
246
+ | Icons | Decorative icons are `aria-hidden="true"` (Joy default) |
247
+ | Type | Default `type="button"` on `<button>` roots to avoid accidental form submit |
248
+
249
+ Target: **WCAG 2.2 AA** where the product requires it.
250
+
251
+ ---
252
+
253
+ ## Examples
254
+
255
+ ```vue
256
+ <script setup lang="ts">
257
+ import { VJoyButton } from '@maltjoy/core-vue'
258
+ </script>
259
+
260
+ <template>
261
+ <!-- Principal CTA -->
262
+ <VJoyButton variant="main" size="medium" label="Send quote" />
263
+
264
+ <!-- Companions -->
265
+ <VJoyButton variant="secondary" size="medium" label="Cancel" />
266
+ <VJoyButton variant="ghost" size="medium" label="View details" />
267
+
268
+ <!-- Async -->
269
+ <VJoyButton variant="main" :loading="true" label="Saving" />
270
+
271
+ <!-- As link -->
272
+ <VJoyButton variant="primary" href="/settings" label="Open settings" />
273
+
274
+ <!-- With icon -->
275
+ <VJoyButton variant="primary" icon="add" icon-position="left" label="Create project" />
276
+
277
+ <!-- Full width (e.g. mobile) -->
278
+ <VJoyButton variant="primary" full label="Continue" />
279
+
280
+ <!-- Slot instead of label -->
281
+ <VJoyButton variant="secondary">
282
+ Delete files (6)
283
+ </VJoyButton>
284
+ </template>
285
+ ```
286
+
287
+ In Nuxt (or apps with auto-import), omit the import if `VJoyButton` is already global.
288
+
289
+ ---
290
+
291
+ ## Related
292
+
293
+ | Component | Use when |
294
+ | --- | --- |
295
+ | `VJoyIconButton` | Icon-only actions |
296
+ | `VJoyLink` | Inline text navigation |
297
+ | `VJoySpinner` | Standalone loading indicator (button embeds its own when `loading`) |
298
+ | `VJoyIcon` | Icon primitive used inside the button |
299
+ | `VJoyTooltip` | Explain disabled reasons or icon meaning |
300
+
301
+ ---
302
+
303
+ ## For agents
304
+
305
+ Optional for readers; **required** for vibe-coding quality. Maps to `agentDocumentBlocks` in [`JoyButton.dsds.json`](./JoyButton.dsds.json).
306
+
307
+ ### Pick the right component
308
+
309
+ | If the intent is… | Emit… | Do not emit… |
310
+ | --- | --- | --- |
311
+ | Icon only | `VJoyIconButton` | `VJoyButton` + `circle` |
312
+ | Navigate in body copy | `VJoyLink` | Ghost button in a paragraph |
313
+ | In-page action | `VJoyButton` | Custom CSS button |
314
+ | Navigate with button chrome | `VJoyButton` + `href` attribute | `<button>` + `@click` router push for external-style links |
315
+ | AI feature | `*-ai` variant (`main-ai`, `primary-ai`, `secondary-ai`, `ghost-ai`) | Non-ai + invented AI styling |
316
+ | Admin-only UI | `variant="admin"` | `admin` on customer surfaces |
317
+ | Full-width mobile CTA | `VJoyButton` + `full` | Custom `width: 100%` on `.joy-button` |
318
+
319
+ ### Hard rules
320
+
321
+ 1. **MUST** call `joy_get_component_info("VJoyButton")` and/or `joy_get_component_types("VJoyButton")` (or read `JoyButton.types.ts`) before generating props.
322
+ 2. **MUST** use only documented props: `variant`, `size`, `loading`, `full`, `icon`, `iconPosition`, `label`, `id`.
323
+ 3. **MUST** pass native HTML attributes (`disabled`, `href`, `type`, `target`, `rel`, …) as attributes on `VJoyButton`, not as invented props.
324
+ 4. **MUST** pass `href` when the control navigates with button chrome.
325
+ 5. **MUST** set `loading` for async submit.
326
+ 6. **MUST NOT** use `variant="white"`, `variant="admin-ai"`, hardcoded heights, or `min-width: 120px`.
327
+ 7. **MUST NOT** override `.joy-button` background, padding, radius, or height.
328
+ 8. **MUST NOT** use `circle` — it is not in the current component API.
329
+ 9. **SHOULD** default to `variant="primary"` and `size="medium"`; use `main` only for the surface’s principal CTA.
330
+ 10. **SHOULD** use `icon-position="left"` (default) or `icon-position="right"` — kebab-case in templates matches Vue prop `iconPosition`.
331
+
332
+ ### Valid enums (from `JoyButton.types.ts`)
333
+
334
+ | Prop | Values |
335
+ | --- | --- |
336
+ | `variant` | `main`, `primary`, `secondary`, `ghost`, `admin`, `main-ai`, `primary-ai`, `secondary-ai`, `ghost-ai` |
337
+ | `size` | `xxsmall`, `xsmall`, `small`, `medium`, `large` |
338
+ | `iconPosition` | `left`, `right` |
339
+ | `icon` | Any `TJoyIconsNames` value (see Joy Icon docs / MCP) |
340
+
341
+ ### Checklist
342
+
343
+ - [ ] Correct component (`VJoyButton` or named alternative)
344
+ - [ ] Props / enums from MCP or types only
345
+ - [ ] No invented props / no custom button chrome CSS
346
+ - [ ] Native attrs (`disabled`, `href`, …) passed as HTML attributes
347
+ - [ ] Label ≤ 25 characters; verb + noun (EN) unless exception
348
+ - [ ] Icon-only → `VJoyIconButton`
349
+ - [ ] Disabled / loading explained if user-visible
350
+ - [ ] At most one `main` per surface (documented exceptions OK)
351
+ - [ ] `loading` set for async actions; same `size` retained
352
+
353
+ ---
354
+
355
+ ## DSDS mapping
356
+
357
+ This Markdown mirrors [`JoyButton.dsds.json`](./JoyButton.dsds.json) (DSDS **0.15.2**).
358
+
359
+ | Section here | DSDS block |
360
+ | --- | --- |
361
+ | When to use / not | `use-cases` |
362
+ | Anatomy | `anatomy` |
363
+ | Variants / sizes | `variants` |
364
+ | States | `states` |
365
+ | Best practices / content rules | `guidelines` (+ `content`) |
366
+ | Accessibility | `accessibility` |
367
+ | Examples | `sections` |
368
+ | For agents | `agentDocumentBlocks` |
369
+ | Props detail | `api` in JSON + Joy MCP |
370
+ | Imports | `imports` in JSON |
371
+ | Token sizing | `design-specifications` in JSON (token names, not raw px dumps) |
@@ -29,17 +29,6 @@
29
29
  "true"
30
30
  ]
31
31
  },
32
- {
33
- "name": "circle",
34
- "type": "boolean | undefined",
35
- "required": false,
36
- "default": "false",
37
- "description": "If you only need a button with an icon. To keep your component accessible, you can give a text as slot, it will be used as title and aria-label.\nThis property takes effect only if icon property is set",
38
- "possibleValues": [
39
- "false",
40
- "true"
41
- ]
42
- },
43
32
  {
44
33
  "name": "variant",
45
34
  "type": "TJoyButtonVariants | undefined",
@@ -124,11 +113,6 @@
124
113
  "type": "boolean",
125
114
  "isMethod": false
126
115
  },
127
- {
128
- "name": "circle",
129
- "type": "boolean",
130
- "isMethod": false
131
- },
132
116
  {
133
117
  "name": "variant",
134
118
  "type": "TJoyButtonVariants",