@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.
- package/LICENSE +21 -0
- package/README.md +30 -3
- package/dist/doc/VJoyAdminBanner/guideline.md +284 -0
- package/dist/doc/VJoyAvailability/guideline.md +352 -0
- package/dist/doc/VJoyAvatar/guideline.md +192 -0
- package/dist/doc/VJoyAvatarsList/guideline.md +328 -0
- package/dist/doc/VJoyBadge/guideline.md +169 -0
- package/dist/doc/VJoyBadgeLevel/guideline.md +166 -0
- package/dist/doc/VJoyBlockSkeleton/guideline.md +150 -0
- package/dist/doc/VJoyBottomSheet/guideline.md +345 -0
- package/dist/doc/VJoyBottomSheetTrigger/guideline.md +156 -0
- package/dist/doc/VJoyButton/guideline.md +371 -0
- package/dist/doc/VJoyButton/metadata.json +0 -16
- package/dist/doc/VJoyButtonCard/guideline.md +384 -0
- package/dist/doc/VJoyCheckbox/guideline.md +317 -0
- package/dist/doc/VJoyCheckboxCard/guideline.md +381 -0
- package/dist/doc/VJoyCheckboxGroup/guideline.md +363 -0
- package/dist/doc/VJoyCheckboxGroup/metadata.json +7 -7
- package/dist/doc/VJoyCollapse/guideline.md +362 -0
- package/dist/doc/VJoyCollapseItem/guideline.md +394 -0
- package/dist/doc/VJoyCompanyAvatar/guideline.md +162 -0
- package/dist/doc/VJoyDialog/guideline.md +425 -0
- package/dist/doc/VJoyDialogTrigger/guideline.md +186 -0
- package/dist/doc/VJoyDot/guideline.md +177 -0
- package/dist/doc/VJoyDrawer/guideline.md +392 -0
- package/dist/doc/VJoyDrawerTrigger/guideline.md +145 -0
- package/dist/doc/VJoyDropdown/guideline.md +393 -0
- package/dist/doc/VJoyDropdown/metadata.json +6 -6
- package/dist/doc/VJoyDropdownList/guideline.md +396 -0
- package/dist/doc/VJoyDropdownList/metadata.json +7 -7
- package/dist/doc/VJoyDropzone/guideline.md +390 -0
- package/dist/doc/VJoyDropzone/metadata.json +36 -1
- package/dist/doc/VJoyFilterBar/guideline.md +419 -0
- package/dist/doc/VJoyFilterBarButton/guideline.md +359 -0
- package/dist/doc/VJoyFloatingActionsBar/guideline.md +372 -0
- package/dist/doc/VJoyFormError/guideline.md +325 -0
- package/dist/doc/VJoyFormError/metadata.json +0 -14
- package/dist/doc/VJoyFormFieldSkeleton/guideline.md +159 -0
- package/dist/doc/VJoyFormGroup/guideline.md +285 -0
- package/dist/doc/VJoyFunnel/guideline.md +349 -0
- package/dist/doc/VJoyFunnelFooter/guideline.md +178 -0
- package/dist/doc/VJoyFunnelHeader/guideline.md +204 -0
- package/dist/doc/VJoyHighlight/guideline.md +169 -0
- package/dist/doc/VJoyIcon/JoyIcon.types.ts +1 -1
- package/dist/doc/VJoyIcon/guideline.md +168 -0
- package/dist/doc/VJoyIcon/metadata.json +0 -1
- package/dist/doc/VJoyIconButton/guideline.md +169 -0
- package/dist/doc/VJoyIconButton/metadata.json +1 -1
- package/dist/doc/VJoyIndicator/guideline.md +168 -0
- package/dist/doc/VJoyIndicators/guideline.md +183 -0
- package/dist/doc/VJoyInput/JoyInput.types.ts +1 -6
- package/dist/doc/VJoyInput/guideline.md +401 -0
- package/dist/doc/VJoyInput/metadata.json +5 -14
- package/dist/doc/VJoyInputDigit/guideline.md +381 -0
- package/dist/doc/VJoyInputNumber/guideline.md +414 -0
- package/dist/doc/VJoyInputNumber/metadata.json +22 -17
- package/dist/doc/VJoyInputPassword/guideline.md +379 -0
- package/dist/doc/VJoyInputPassword/metadata.json +0 -14
- package/dist/doc/VJoyLabel/guideline.md +200 -0
- package/dist/doc/VJoyLink/guideline.md +360 -0
- package/dist/doc/VJoyListItem/guideline.md +335 -0
- package/dist/doc/VJoyMenu/guideline.md +304 -0
- package/dist/doc/VJoyMenu/metadata.json +21 -21
- package/dist/doc/VJoyMenuItem/guideline.md +352 -0
- package/dist/doc/VJoyPagination/guideline.md +355 -0
- package/dist/doc/VJoyPanel/guideline.md +238 -0
- package/dist/doc/VJoyPanelSection/guideline.md +160 -0
- package/dist/doc/VJoyPasswordRequirement/guideline.md +336 -0
- package/dist/doc/VJoyPasswordRequirement/metadata.json +1 -1
- package/dist/doc/VJoyProductTour/JoyProductTour.types.ts +0 -1
- package/dist/doc/VJoyProductTour/guideline.md +455 -0
- package/dist/doc/VJoyProductTour/metadata.json +1 -1
- package/dist/doc/VJoyProductTourTrigger/guideline.md +167 -0
- package/dist/doc/VJoyProgressBar/guideline.md +348 -0
- package/dist/doc/VJoyRadio/guideline.md +346 -0
- package/dist/doc/VJoyRadioGroup/guideline.md +331 -0
- package/dist/doc/VJoyRatingStars/guideline.md +306 -0
- package/dist/doc/VJoyScreenLoader/guideline.md +172 -0
- package/dist/doc/VJoySelect/guideline.md +396 -0
- package/dist/doc/VJoySelectableItem/guideline.md +351 -0
- package/dist/doc/VJoySelectableItemGroup/guideline.md +370 -0
- package/dist/doc/VJoySeparator/guideline.md +161 -0
- package/dist/doc/VJoySnackbar/guideline.md +402 -0
- package/dist/doc/VJoySpinner/guideline.md +168 -0
- package/dist/doc/VJoyStep/guideline.md +182 -0
- package/dist/doc/VJoyStepper/guideline.md +390 -0
- package/dist/doc/VJoyTab/guideline.md +298 -0
- package/dist/doc/VJoyTabs/guideline.md +353 -0
- package/dist/doc/VJoyTag/guideline.md +226 -0
- package/dist/doc/VJoyTagsInput/guideline.md +387 -0
- package/dist/doc/VJoyTagsList/guideline.md +311 -0
- package/dist/doc/VJoyTagsList/metadata.json +27 -27
- package/dist/doc/VJoyTemplate/guideline.md +366 -0
- package/dist/doc/VJoyText/guideline.md +175 -0
- package/dist/doc/VJoyText/metadata.json +1 -1
- package/dist/doc/VJoyTextarea/guideline.md +378 -0
- package/dist/doc/VJoyTitleBrand/guideline.md +155 -0
- package/dist/doc/VJoyToggle/guideline.md +327 -0
- package/dist/doc/VJoyTooltip/guideline.md +322 -0
- package/dist/doc/VJoyUserCard/guideline.md +268 -0
- package/dist/doc/VJoyUserCard/metadata.json +3 -17
- package/dist/doc/VJoyWalkthrough/guideline.md +351 -0
- package/dist/doc/VJoyWalkthroughTrigger/guideline.md +171 -0
- package/dist/doc/VJoyWrapper/guideline.md +173 -0
- package/dist/doc/css-classes.json +1 -15
- package/dist/doc/design-tokens.json +1 -0
- package/dist/doc/index.json +20 -30
- package/dist/index.js +22 -2
- package/dist/index.js.map +1 -1
- package/dist/tools/get-component-guideline.d.ts +30 -0
- package/dist/tools/get-component-guideline.d.ts.map +1 -0
- package/dist/tools/get-component-guideline.js +51 -0
- package/dist/tools/get-component-guideline.js.map +1 -0
- package/dist/tools/get-documentation-page.d.ts +22 -0
- package/dist/tools/get-documentation-page.d.ts.map +1 -0
- package/dist/tools/get-documentation-page.js +21 -0
- package/dist/tools/get-documentation-page.js.map +1 -0
- package/dist/tools/list-documentation-pages.d.ts +22 -0
- package/dist/tools/list-documentation-pages.d.ts.map +1 -0
- package/dist/tools/list-documentation-pages.js +17 -0
- package/dist/tools/list-documentation-pages.js.map +1 -0
- package/dist/tools/search-documentation.d.ts +41 -0
- package/dist/tools/search-documentation.d.ts.map +1 -0
- package/dist/tools/search-documentation.js +25 -0
- package/dist/tools/search-documentation.js.map +1 -0
- package/dist/zeroheight-parser.d.ts +27 -0
- package/dist/zeroheight-parser.d.ts.map +1 -0
- package/dist/zeroheight-parser.js +77 -0
- package/dist/zeroheight-parser.js.map +1 -0
- package/package.json +10 -10
- 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,
|
|
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": "
|
|
315
|
-
"type": "
|
|
316
|
-
"isMethod":
|
|
305
|
+
"name": "focus",
|
|
306
|
+
"type": "() => void",
|
|
307
|
+
"isMethod": true
|
|
317
308
|
}
|
|
318
309
|
],
|
|
319
310
|
"hasVModel": true
|