@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,401 @@
1
+ ---
2
+ component: VJoyInput
3
+ status: draft
4
+ language: en
5
+ dsds: JoyInput.dsds.json
6
+ dsdsVersion: "0.15.2"
7
+ ---
8
+
9
+ # Input
10
+
11
+ Use **`VJoyInput`** when the user needs to enter a single line of text — names, emails, search queries, short identifiers, or other free-form values in a form.
12
+
13
+ It supports labels, optional leading icons, a clear action, validation styling, and binds to `v-model`. Native attributes such as `placeholder`, `autocomplete`, and `aria-*` pass through to the underlying `<input>`.
14
+
15
+ | | |
16
+ | --- | --- |
17
+ | **Code** | `VJoyInput` from `@maltjoy/core-vue` |
18
+ | **Design** | [Figma — Joy Core Design System](https://www.figma.com/design/jfndp2QBJGS9yeuWbeGuvD/) |
19
+ | **Storybook** | [VJoyInput docs](https://doc.malt.tech/joy-storybook/?path=/docs/components-forms-vjoyinput--docs) |
20
+ | **DSDS (machine)** | [`JoyInput.dsds.json`](./JoyInput.dsds.json) |
21
+ | **Live API** | `joy_get_component_info("VJoyInput")` |
22
+
23
+ ---
24
+
25
+ ## When to use this component
26
+
27
+ Use an input when someone must type or paste a value that is not constrained to a fixed list — for example an email address, company name, reference code, or search term.
28
+
29
+ Pair it with a visible label, validation feedback when needed, and (inside forms) `VJoyWrapper` for consistent spacing.
30
+
31
+ ### When not to use this component
32
+
33
+ | Need | Use instead |
34
+ | --- | --- |
35
+ | Password with show/hide toggle | `VJoyInputPassword` |
36
+ | Numeric value with a unit suffix (€, %, days…) | `VJoyInputNumber` |
37
+ | Multi-line text (description, comment, bio) | `VJoyTextarea` |
38
+ | One-time / verification code (OTP) | `VJoyInputDigit` |
39
+ | Choosing from a known set of options | `VJoySelect`, `VJoyRadio`, or `VJoySelectableItemGroup` |
40
+ | Multiple tags or tokenized values | `VJoyTagsInput` |
41
+ | Read-only display of existing data | `VJoyText` or plain text — not a disabled input masquerading as content |
42
+ | Custom-styled `<input>` / ad-hoc field chrome | Still use `VJoyInput` + Joy tokens |
43
+
44
+ > **Deprecated:** do not use the default slot for labels on new work — prefer the `label` prop or a separate `VJoyLabel`. Do not use `type="password"` on `VJoyInput` — use `VJoyInputPassword`.
45
+
46
+ ---
47
+
48
+ ## How it works
49
+
50
+ ### Anatomy
51
+
52
+ | Part | Required? | What it is |
53
+ | --- | --- | --- |
54
+ | Root container | Yes | Size wrapper (`joy-input--{size}`) |
55
+ | Label | No | `VJoyLabel` from the `label` prop (or deprecated default slot) |
56
+ | Field wrapper | Yes | Positions icon, input, clear control, and `right-action` slot |
57
+ | Leading icon | No | Decorative `VJoyIcon` on the left (`icon` prop) |
58
+ | Native `<input>` | Yes | The actual form control; receives `$attrs` (placeholder, autocomplete, etc.) |
59
+ | Clear control | No | `VJoyIconButton` when `clearable` and the field has a non-empty string value |
60
+ | Right action | No | `right-action` slot for custom trailing UI (e.g. password toggle in `VJoyInputPassword`) |
61
+ | Focus ring | Yes | Applied on focus via Joy form-field tokens — do not remove in product CSS |
62
+
63
+ ### Default values
64
+
65
+ - `size` defaults to **`medium`**
66
+ - `type` defaults to **`text`**
67
+ - `labelSize` defaults to **`medium`**
68
+ - `modelModifiers` defaults to **`{ lazy: false }`** (updates on `input`)
69
+ - `clearAriaLabel` defaults to **`"Clear input"`** — override when `clearable` is true
70
+ - `disabled`, `invalid`, `required`, `readonly`, `clearable`, `requiredMark`, and `autofocus` default to **`false`**
71
+
72
+ Props, events, and slots: use Joy MCP or Storybook — this page focuses on **when** and **how**, not a full API dump.
73
+
74
+ ---
75
+
76
+ ## Variants
77
+
78
+ `VJoyInput` has no visual “variant” prop (no primary/secondary). Visual meaning comes from **state** (`invalid`, `disabled`, `readonly`) and **density** (`size`).
79
+
80
+ ### Default (valid)
81
+
82
+ Use for standard editable fields. Border uses neutral tokens; focus uses `--joy-color-state-focus`.
83
+
84
+ ### Invalid
85
+
86
+ Set `invalid` when server-side or client-side validation failed. Pair with `VJoyFormError` (or equivalent) so the error is announced — the red border alone is not enough.
87
+
88
+ Avoid toggling `invalid` while the user is still typing unless the value is clearly wrong (e.g. empty required field on blur).
89
+
90
+ ### Readonly
91
+
92
+ Use when the value must remain visible but not editable (e.g. prefilled reference). Prefer readonly over disabled when the user should still read and copy the value.
93
+
94
+ ### Disabled
95
+
96
+ Use when the field cannot be edited and the reason is external (permissions, workflow step). **Always explain why** nearby.
97
+
98
+ ### Not in the API: `unit`
99
+
100
+ Joy MCP may list a `unit` prop on `VJoyInput`. It is **not** on `VJoyInputProps` in `JoyInput.types.ts`. Use **`VJoyInputNumber`** for values with a trailing unit label.
101
+
102
+ ### Not in the API: floating label
103
+
104
+ Some legacy design docs describe a floating label pattern. `VJoyInput` uses a **top label** (`label` / `VJoyLabel`) — do not simulate floating labels with custom CSS.
105
+
106
+ ---
107
+
108
+ ## Sizes
109
+
110
+ Choose size for **density** within the form. Heights and radii come from `--joy-form-field-height-*` and `--joy-form-field-radius-*` — **do not hardcode pixel heights** in apps.
111
+
112
+ | Size | Use when |
113
+ | --- | --- |
114
+ | `small` | Dense toolbars, filter bars, inline filters (often with a search icon) |
115
+ | `medium` | Default product forms |
116
+ | `large` | Marketing-scale or hero forms where fields need more prominence |
117
+
118
+ Match label size to field size when possible (`labelSize` aligns with `VJoyLabel` sizes).
119
+
120
+ ---
121
+
122
+ ## States
123
+
124
+ | State | What the user sees / can do |
125
+ | --- | --- |
126
+ | Default | Empty or filled; editable; neutral border |
127
+ | Hover | Border shifts to `--joy-color-state-hover` (pointer devices) |
128
+ | Focus | Focus border `--joy-color-state-focus`; wrapper gets `joy-input--focusing` |
129
+ | Valid (implicit) | `joy-input--valid` when not `invalid` and not disabled |
130
+ | Invalid | Error border and text color; icon follows error color |
131
+ | Disabled | Not interactive; muted background and border; explain why nearby |
132
+ | Readonly | Value visible; no edit; default cursor; no focus styling for readonly |
133
+ | Clearable | Clear icon appears when `clearable` and string `modelValue` is non-empty; clears via `update:modelValue` with `''` |
134
+
135
+ `type="number"` fields block mouse-wheel from changing the value while focused.
136
+
137
+ ---
138
+
139
+ ## Best practices
140
+
141
+ Rules use RFC 2119 strength (**MUST** / **SHOULD** / **MUST NOT** / **SHOULD NOT**).
142
+
143
+ ### Labels and forms
144
+
145
+ - **MUST** provide a visible label for every input (via `label`, `VJoyLabel`, or an associated `<label for="…">`).
146
+ - **MUST** set `name` (and `id` when multiple fields share a form) so labels, autofill, and tests bind correctly. `id` falls back to `name`.
147
+ - **SHOULD** use `requiredMark` together with `required` when the asterisk pattern is used in the product.
148
+ - **SHOULD** use `optionalLabel` on non-required fields when the form mixes required and optional inputs.
149
+ - **SHOULD** wrap related fields in `VJoyWrapper` for spacing; margin adjusts automatically when inside a wrapper.
150
+
151
+ ### Implementation
152
+
153
+ - **MUST** use only documented prop / enum values from MCP or `JoyInput.types.ts`.
154
+ - **MUST** bind value with `v-model` (`modelValue` / `update:modelValue`).
155
+ - **MUST** style with Joy tokens — no custom `.joy-input` chrome (border, height, radius, padding).
156
+ - **MUST NOT** invent props (`unit`, `variant`, `errorMessage`, …).
157
+ - **MUST NOT** use `type="password"` — use `VJoyInputPassword`.
158
+ - **MUST** override `clearAriaLabel` when the default `"Clear input"` is too generic (e.g. `"Clear search"`).
159
+ - **SHOULD** use `v-model.lazy` (via `modelModifiers: { lazy: true }`) when updates on every keystroke are expensive.
160
+
161
+ ### Validation and errors
162
+
163
+ - **MUST** set `invalid` when showing a validation error for this field.
164
+ - **MUST** show the error message in `VJoyFormError` (or equivalent) below the field — not only red border.
165
+ - **MUST NOT** rely on placeholder color alone to convey errors.
166
+
167
+ ### Icons and actions
168
+
169
+ - **SHOULD** use `icon` only when it reinforces meaning (search, calendar, user) — decorative-only icons add noise.
170
+ - **SHOULD** use `clearable` for search or filter fields where resetting is common.
171
+ - **MUST NOT** put the only accessible name of the field on an icon — the label carries the name.
172
+
173
+ ### Do / don’t
174
+
175
+ | Do | Don’t |
176
+ | --- | --- |
177
+ | `label` + `name` on every field | Placeholder as the only label |
178
+ | `VJoyFormError` with `invalid` | Red border with no message |
179
+ | `VJoyInputPassword` for passwords | `type="password"` on `VJoyInput` |
180
+ | `VJoyInputNumber` for amounts with units | Invented `unit` prop on `VJoyInput` |
181
+ | `clearAriaLabel` tailored to context | Generic clear button with no accessible name |
182
+ | Joy form-field size tokens | Hardcoded `32` / `40` / `48`px heights |
183
+
184
+ ---
185
+
186
+ ## Content
187
+
188
+ Inputs expose label, placeholder, and optional helper copy. All must help users enter the **right** value the **first** time.
189
+
190
+ ### Label formula
191
+
192
+ **Noun or short noun phrase** describing the data (not the action):
193
+
194
+ - ✅ Email address
195
+ - ✅ Company name
196
+ - ✅ Project reference
197
+
198
+ Use sentence case. Questions are acceptable for uncommon fields (✅ `What is your VAT number?`) but prefer nouns when the field is standard.
199
+
200
+ ### Placeholder formula
201
+
202
+ **Example or format hint** — not a repeat of the label:
203
+
204
+ - ✅ `name@company.com` (under label “Email address”)
205
+ - ✅ `AB-12345` (under label “Reference code”)
206
+
207
+ - ❌ `Email address` as placeholder when the label already says “Email address”
208
+
209
+ ### Optional / required markers
210
+
211
+ | Pattern | When |
212
+ | --- | --- |
213
+ | `required` + `requiredMark` | Required field in a form that uses asterisks |
214
+ | `optionalLabel` (e.g. “optional”) | Field is not required among mostly required fields |
215
+
216
+ Do not mark every optional field “optional” when the form is entirely optional.
217
+
218
+ ### Writing rules
219
+
220
+ | Strength | Rule |
221
+ | --- | --- |
222
+ | **MUST** | Every field has a visible label — never placeholder-only |
223
+ | **MUST** | Error messages state what went wrong and how to fix it — ✅ `Enter a valid email address` · ❌ `Invalid` |
224
+ | **MUST** | `clearAriaLabel` describes what is cleared — ✅ `Clear search` · ❌ `Click here` |
225
+ | **MUST NOT** | Use labels that only make sense after failure — ❌ `Correct email` |
226
+ | **MUST NOT** | Embed instructions inside the label that belong in helper text |
227
+ | **SHOULD** | Keep labels ≤ 3–5 words when possible |
228
+ | **SHOULD** | Use placeholders for format examples, not requirements |
229
+ | **SHOULD** | Match autocomplete attributes to the data (`email`, `name`, `organization`) via native attrs |
230
+ | **SHOULD** | Use consistent terminology with adjacent fields and page headings |
231
+ | **SHOULD** (FR) | Follow French grammar for labels and optional markers when the UI is localized |
232
+
233
+ ### Patterns
234
+
235
+ **Forms** — One idea per field. Split “First name” and “Last name” instead of a single “Full name” when both are needed downstream.
236
+
237
+ **Search / filters** — Short placeholder with action implied: `Search projects…`. Pair with `icon="search"` and `clearable` when results update live.
238
+
239
+ **Readonly / disabled** — Label stays descriptive; explain unavailability in helper text or tooltip, not by changing the label to “Disabled email”.
240
+
241
+ **Errors** — Show on blur or submit for most fields; avoid shouting errors on first keystroke unless the format is unambiguous (e.g. OTP length).
242
+
243
+ ---
244
+
245
+ ## Accessibility
246
+
247
+ Behaviors (what must happen), not slogans.
248
+
249
+ | Behavior | Expectation |
250
+ | --- | --- |
251
+ | Role | Native `<input>` with appropriate `type` |
252
+ | Name | From associated `VJoyLabel` / `<label for>`; `label` prop wires `for` to `id \|\| name` |
253
+ | Value | Controlled via `v-model`; clear action emits empty string |
254
+ | Keyboard | Standard text editing; Tab moves focus; clear button is a real button (`VJoyIconButton`) |
255
+ | Focus | Visible focus ring on the input — do not remove `outline` / focus tokens |
256
+ | Invalid | `invalid` styles the field; pair with `VJoyFormError` (`role="alert"`) for the message |
257
+ | Disabled | Native `disabled`; do not rely on color alone — provide text explanation |
258
+ | Readonly | Native `readonly`; value still readable and copyable |
259
+ | Icons | Leading icon is decorative; clear button has `clearAriaLabel` |
260
+ | Autocomplete | Pass `autocomplete` via attrs when the data type is known |
261
+
262
+ Target: **WCAG 2.2 AA** where the product requires it.
263
+
264
+ ---
265
+
266
+ ## Examples
267
+
268
+ ```vue
269
+ <script setup lang="ts">
270
+ import { ref } from 'vue'
271
+ import { VJoyInput, VJoyLabel, VJoyFormError, VJoyWrapper } from '@maltjoy/core-vue'
272
+
273
+ const email = ref('')
274
+ const search = ref('')
275
+ const showError = ref(false)
276
+ </script>
277
+
278
+ <template>
279
+ <!-- Standard form field -->
280
+ <VJoyWrapper direction="column" row-gap="4">
281
+ <VJoyInput
282
+ v-model="email"
283
+ name="email"
284
+ label="Email address"
285
+ placeholder="name@company.com"
286
+ autocomplete="email"
287
+ required
288
+ required-mark
289
+ :invalid="showError"
290
+ />
291
+ <VJoyFormError v-if="showError" message="Enter a valid email address" />
292
+ </VJoyWrapper>
293
+
294
+ <!-- Search with icon + clear -->
295
+ <VJoyInput
296
+ v-model="search"
297
+ name="project-search"
298
+ size="small"
299
+ icon="search"
300
+ clearable
301
+ clear-aria-label="Clear search"
302
+ placeholder="Search projects…"
303
+ />
304
+
305
+ <!-- Custom label composition -->
306
+ <VJoyLabel for="company-legal-name" required>
307
+ Legal company name
308
+ <template #label-legend>As shown on official documents</template>
309
+ </VJoyLabel>
310
+ <VJoyInput
311
+ id="company-legal-name"
312
+ v-model="email"
313
+ name="company-legal-name"
314
+ placeholder="Acme SAS"
315
+ />
316
+ </template>
317
+ ```
318
+
319
+ In Nuxt (or apps with auto-import), omit the import if `VJoyInput` is already global.
320
+
321
+ ---
322
+
323
+ ## Related
324
+
325
+ | Component | Use when |
326
+ | --- | --- |
327
+ | `VJoyLabel` | Rich labels (legend, tooltip) separate from the field |
328
+ | `VJoyFormError` | Inline validation message below the field |
329
+ | `VJoyWrapper` | Form layout and spacing between fields |
330
+ | `VJoyInputPassword` | Password entry with visibility toggle |
331
+ | `VJoyInputNumber` | Numeric values with optional unit suffix |
332
+ | `VJoyTextarea` | Multi-line text |
333
+ | `VJoyInputDigit` | Fixed-length codes (OTP, PIN) |
334
+ | `VJoySelect` | Single choice from a list |
335
+ | `VJoyIcon` / `VJoyIconButton` | Icons inside `right-action` when building composed fields |
336
+
337
+ ---
338
+
339
+ ## For agents
340
+
341
+ Optional for readers; **required** for vibe-coding quality. Maps to `agentDocumentBlocks` in [`JoyInput.dsds.json`](./JoyInput.dsds.json).
342
+
343
+ ### Pick the right component
344
+
345
+ | If the intent is… | Emit… | Do not emit… |
346
+ | --- | --- | --- |
347
+ | Single-line free text | `VJoyInput` | Raw `<input class="…">` |
348
+ | Password | `VJoyInputPassword` | `VJoyInput` + `type="password"` |
349
+ | Number with unit (€, %, days) | `VJoyInputNumber` | `VJoyInput` + `unit` |
350
+ | Multi-line text | `VJoyTextarea` | Tall `VJoyInput` |
351
+ | OTP / verification code | `VJoyInputDigit` | Multiple single-char `VJoyInput`s |
352
+ | Pick one of N known options | `VJoySelect` / radios | `VJoyInput` with datalist hack |
353
+ | Search/filter bar | `VJoyInput` + `icon="search"` + optional `clearable` | Custom search div |
354
+ | Display-only value | `VJoyText` | `disabled` input without reason |
355
+
356
+ ### Hard rules
357
+
358
+ 1. **MUST** call `joy_get_component_info("VJoyInput")` or read `JoyInput.types.ts` before generating props.
359
+ 2. **MUST** bind `v-model` for editable values.
360
+ 3. **MUST** set `name` (and `id` when needed for label association).
361
+ 4. **MUST** pass native attrs (`placeholder`, `autocomplete`, `maxlength`, `aria-*`) on the component — they flow to `<input>`.
362
+ 5. **MUST** set `invalid` when showing validation errors and render `VJoyFormError` with a message.
363
+ 6. **MUST** set a specific `clearAriaLabel` when `clearable` is true.
364
+ 7. **MUST NOT** emit `unit` on `VJoyInput` — use `VJoyInputNumber`.
365
+ 8. **MUST NOT** emit `type="password"` — use `VJoyInputPassword`.
366
+ 9. **MUST NOT** use the default slot for new labels — use `label` or `VJoyLabel`.
367
+ 10. **MUST NOT** override `.joy-input` height, border, radius, or padding.
368
+ 11. **SHOULD** use `size="small"` in dense toolbars; default `medium` elsewhere.
369
+ 12. **SHOULD** use `VJoyWrapper` in multi-field forms.
370
+
371
+ ### Checklist
372
+
373
+ - [ ] Correct component (or named alternative from table above)
374
+ - [ ] Props / enums from MCP or types only
375
+ - [ ] `v-model` + `name` present
376
+ - [ ] Visible label (not placeholder-only)
377
+ - [ ] `invalid` + `VJoyFormError` when validation fails
378
+ - [ ] `clearAriaLabel` set when `clearable`
379
+ - [ ] No invented props / no custom input chrome CSS
380
+ - [ ] Password → `VJoyInputPassword`; number + unit → `VJoyInputNumber`
381
+ - [ ] Disabled / readonly explained if user-visible
382
+
383
+ ---
384
+
385
+ ## DSDS mapping
386
+
387
+ This Markdown mirrors [`JoyInput.dsds.json`](./JoyInput.dsds.json) (DSDS **0.15.2**).
388
+
389
+ | Section here | DSDS block |
390
+ | --- | --- |
391
+ | When to use / not | `use-cases` |
392
+ | Anatomy | `anatomy` |
393
+ | Sizes | `variants` |
394
+ | States | `states` |
395
+ | Best practices / content rules | `guidelines` (+ `content`) |
396
+ | Accessibility | `accessibility` |
397
+ | Examples | `sections` |
398
+ | For agents | `agentDocumentBlocks` |
399
+ | Props detail | `api` in JSON + Joy MCP |
400
+ | Imports | `imports` in JSON |
401
+ | Token sizing | `design-specifications` in JSON (`--joy-form-field-height-*`, `--joy-form-field-radius-*`) |
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "JoyInput",
3
3
  "displayName": "VJoyInput",
4
- "description": "A comprehensive form input component with extensive customization and validation features.\nSupports multiple input types, icon support, clearable functionality, unit displays, and comprehensive validation states.\nFeatures auto-focus capabilities, accessibility compliance, and seamless integration with form validation systems.",
4
+ "description": "A comprehensive form input component with extensive customization and validation features.\nSupports multiple input types, icon support, clearable functionality, and comprehensive validation states.\nFeatures auto-focus capabilities, accessibility compliance, and seamless integration with form validation systems.",
5
5
  "category": "Forms",
6
6
  "props": [
7
7
  {
@@ -163,18 +163,9 @@
163
163
  "type": "string | undefined",
164
164
  "required": false,
165
165
  "default": "\"text\"",
166
- "description": "",
166
+ "description": "HTML input type. Use VJoyInputPassword for password fields.",
167
167
  "possibleValues": null
168
168
  },
169
- {
170
- "name": "unit",
171
- "type": "string | undefined",
172
- "required": false,
173
- "description": "Adds a legend like symbol on the right of the component. Made for number based values",
174
- "possibleValues": [
175
- "string"
176
- ]
177
- },
178
169
  {
179
170
  "name": "readonly",
180
171
  "type": "boolean | undefined",
@@ -311,9 +302,9 @@
311
302
  "isMethod": true
312
303
  },
313
304
  {
314
- "name": "unit",
315
- "type": "string | undefined",
316
- "isMethod": false
305
+ "name": "focus",
306
+ "type": "() => void",
307
+ "isMethod": true
317
308
  }
318
309
  ],
319
310
  "hasVModel": true