@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,160 @@
1
+ ---
2
+ component: VJoyPanelSection
3
+ status: draft
4
+ language: en
5
+ dsds: JoyPanelSection.dsds.json
6
+ dsdsVersion: "0.15.2"
7
+ ---
8
+
9
+ # Panel section
10
+
11
+ Use **`VJoyPanelSection`** when you need a titled subsection inside a panel body — for example grouping related fields, separating informational blocks, or breaking long panel content into scannable chunks.
12
+
13
+ The component has no props: it exposes two named slots (`panel-section-title`, `panel-section-content`) with Joy typography on each block. Title and content wrappers render only when their slot is filled.
14
+
15
+ | | |
16
+ | --- | --- |
17
+ | **Code** | `VJoyPanelSection` from `@maltjoy/core-vue` |
18
+ | **Storybook** | [VJoyPanel docs](https://doc.malt.tech/joy-storybook/?path=/docs/components-layout-vjoypanel--docs) (`VJoyPanelSection` is a subcomponent) |
19
+ | **DSDS (machine)** | [`JoyPanelSection.dsds.json`](./JoyPanelSection.dsds.json) |
20
+ | **Live API** | `joy_get_component_info("VJoyPanelSection")` |
21
+
22
+ ---
23
+
24
+ ## When to use this component
25
+
26
+ Use a panel section when content inside `VJoyPanel`’s `panel-body` needs a **local heading plus body copy** without promoting that block to a full panel header. Typical jobs: labeled groups of form fields, short explanatory text above a control cluster, or multiple logical blocks inside one card.
27
+
28
+ Compose one or more `VJoyPanelSection` elements inside `panel-body`. Spacing between sections is handled by `VJoyPanel` styles — don’t add manual top margins on the section root.
29
+
30
+ ### When not to use this component
31
+
32
+ | Need | Use instead |
33
+ | --- | --- |
34
+ | Panel-level title, subtitle, or header actions | `VJoyPanel` slots (`panel-title`, `panel-subtitle`, `panel-title-action`) |
35
+ | Standalone card with header, body, and footer | `VJoyPanel` |
36
+ | Page-level layout (header, sidebar, main) | `VJoyTemplate` |
37
+ | Flex row/column spacing between siblings | `VJoyWrapper` |
38
+ | Form label + control + errors as one unit | `VJoyFormGroup` |
39
+ | Custom heading + body markup with ad-hoc font sizes | Still use `VJoyPanelSection` + Joy typography tokens |
40
+
41
+ ---
42
+
43
+ ## How it works
44
+
45
+ ### Anatomy
46
+
47
+ | Part | Required? | What it is |
48
+ | --- | --- | --- |
49
+ | Root (`div.joy-panel-section`) | Yes | Block container; always rendered |
50
+ | Title block (`.joy-panel-section__title`) | No | Renders only when `panel-section-title` slot has content |
51
+ | Content block (`.joy-panel-section__content`) | No | Renders only when `panel-section-content` slot has content |
52
+
53
+ ### Typography
54
+
55
+ | Slot | Token / style |
56
+ | --- | --- |
57
+ | `panel-section-title` | `primary-650` (section heading weight) |
58
+ | `panel-section-content` | `primary-400` (body text weight) |
59
+
60
+ Margins on title and content are reset to `0` inside the component. Vertical rhythm between multiple sections inside a panel comes from `VJoyPanel` (`margin-top` / `padding-top` on `.joy-panel-section` siblings).
61
+
62
+ ### Default values
63
+
64
+ - **No props** — composition is slot-only.
65
+ - Either slot may be omitted; empty slots do not render their wrapper `div`.
66
+
67
+ Slots: use Joy MCP or Storybook — this page focuses on **when** and **how**, not a full API dump.
68
+
69
+ ---
70
+
71
+ ## Best practices
72
+
73
+ Rules use RFC 2119 strength (**MUST** / **SHOULD** / **MUST NOT** / **SHOULD NOT**).
74
+
75
+ ### Composition
76
+
77
+ - **SHOULD** place `VJoyPanelSection` inside `VJoyPanel`’s `panel-body` — that is the intended parent context.
78
+ - **SHOULD** provide both title and content slots when the section needs a visible heading.
79
+ - **MAY** use only `panel-section-content` for untitled blocks (wrapper still applies body typography).
80
+ - **MUST NOT** use `VJoyPanelSection` as a replacement for the panel header — panel title/subtitle belong on `VJoyPanel`.
81
+ - **MUST NOT** add custom top margins on `.joy-panel-section` — parent panel spacing already accounts for section stacks.
82
+
83
+ ### Implementation
84
+
85
+ - **MUST NOT** invent props (`title`, `variant`, `size`, …) — the API is slot-only.
86
+ - **MUST NOT** override `.joy-panel-section__title` / `__content` font rules in product CSS; put semantic markup in slots (`h3`, `p`, `VJoyText`, …) and let Joy tokens apply.
87
+ - **SHOULD** keep section titles short (one line when possible) so they scan inside dense panels.
88
+
89
+ ### Do / don’t
90
+
91
+ | Do | Don’t |
92
+ | --- | --- |
93
+ | Nest sections in `panel-body` between form groups or lists | Duplicate `panel-title` in every subsection |
94
+ | Plain text or heading elements in slots | Inline `font-size` / `font-weight` on slot content |
95
+ | Multiple sections for distinct blocks in one panel | A separate `VJoyPanel` per small text block |
96
+
97
+ ---
98
+
99
+ ## Accessibility
100
+
101
+ `VJoyPanelSection` is a **non-interactive layout container** (`div`). It has no focusable parts and does not define ARIA roles.
102
+
103
+ | Behavior | Expectation |
104
+ | --- | --- |
105
+ | Semantics | Put heading semantics in `panel-section-title` (e.g. `h3`, `h4`) — the section root is not a heading |
106
+ | Reading order | Title block precedes content block in the DOM when both slots are used |
107
+ | Keyboard | No keyboard behavior on the section itself; interactive children keep their own focus order |
108
+ | Landmarks | Do not rely on the section as a landmark; use appropriate heading levels inside slots |
109
+
110
+ ---
111
+
112
+ ## Examples
113
+
114
+ ```vue
115
+ <script setup lang="ts">
116
+ import { VJoyPanel, VJoyPanelSection, VJoyCheckboxGroup } from '@maltjoy/core-vue'
117
+ import { ref } from 'vue'
118
+
119
+ const critical = ref<string[]>([])
120
+ const other = ref<string[]>([])
121
+ </script>
122
+
123
+ <template>
124
+ <VJoyPanel>
125
+ <template #panel-title>
126
+ <h2>Migration status</h2>
127
+ </template>
128
+
129
+ <template #panel-body>
130
+ <VJoyPanelSection>
131
+ <template #panel-section-title>Critical components</template>
132
+ <template #panel-section-content>Only for SSR rendering.</template>
133
+ </VJoyPanelSection>
134
+
135
+ <VJoyCheckboxGroup v-model:value="critical" :options="[]" />
136
+
137
+ <VJoyPanelSection>
138
+ <template #panel-section-title>Other components</template>
139
+ <template #panel-section-content>Not critical.</template>
140
+ </VJoyPanelSection>
141
+
142
+ <VJoyCheckboxGroup v-model:value="other" :options="[]" />
143
+ </template>
144
+ </VJoyPanel>
145
+ </template>
146
+ ```
147
+
148
+ In Nuxt (or apps with auto-import), omit the import if `VJoyPanelSection` is already global.
149
+
150
+ ---
151
+
152
+ ## Related
153
+
154
+ | Component | Use when |
155
+ | --- | --- |
156
+ | `VJoyPanel` | Card container with header, body, footer, and loading — parent of panel sections |
157
+ | `VJoyFormGroup` | Label + field + errors for a single form control |
158
+ | `VJoyWrapper` | Flex layout and gaps between siblings inside a section |
159
+ | `VJoyText` | Long copy inside `panel-section-content` when utility typography classes are needed |
160
+ | `VJoyTemplate` | Full page shell, not in-panel subsections |
@@ -0,0 +1,336 @@
1
+ ---
2
+ component: VJoyPasswordRequirement
3
+ status: draft
4
+ language: en
5
+ dsds: JoyPasswordRequirement.dsds.json
6
+ dsdsVersion: "0.15.2"
7
+ ---
8
+
9
+ # Password requirement
10
+
11
+ Use **`VJoyPasswordRequirement`** when you need to show the status of a single password-strength rule — for example “At least 8 characters” or “Contains an uppercase letter”.
12
+
13
+ Each row pairs a short label with a status icon (`neutral`, `success`, or `error`). Compose several rows under **`VJoyInputPassword`** via the `password-requirements` slot so users see live feedback while choosing a password.
14
+
15
+ | | |
16
+ | --- | --- |
17
+ | **Code** | `VJoyPasswordRequirement` from `@maltjoy/core-vue` |
18
+ | **Design** | [Figma — Joy Core Design System](https://www.figma.com/design/jfndp2QBJGS9yeuWbeGuvD/) |
19
+ | **Storybook** | [VJoyPasswordRequirement docs](https://doc.malt.tech/joy-storybook/?path=/docs/components-forms-vjoypasswordrequirement--docs) |
20
+ | **DSDS (machine)** | [`JoyPasswordRequirement.dsds.json`](./JoyPasswordRequirement.dsds.json) |
21
+ | **Live API** | `joy_get_component_info("VJoyPasswordRequirement")` |
22
+
23
+ ---
24
+
25
+ ## When to use this component
26
+
27
+ Use a password requirement row when signup or password-reset flows must communicate **multiple independent rules** and whether each rule is met.
28
+
29
+ Typical pattern: bind `VJoyInputPassword` with `v-model`, evaluate each rule in app logic, and render one `VJoyPasswordRequirement` per rule inside `#password-requirements`. The parent `VJoyWrapper` in `VJoyInputPassword` stacks rows with consistent spacing.
30
+
31
+ ### When not to use this component
32
+
33
+ | Need | Use instead |
34
+ | --- | --- |
35
+ | The password field itself (show/hide toggle, label, validation border) | `VJoyInputPassword` |
36
+ | A single global error after submit (“Password too weak”) | `VJoyFormError` below the field |
37
+ | A strength meter / score bar | A dedicated meter component or custom UI — not this row pattern |
38
+ | One-line helper text with no per-rule status | Plain `VJoyText` or `VJoyLabel` legend |
39
+ | Custom-styled checklist under a password field | Still use `VJoyPasswordRequirement` + Joy tokens — don’t reinvent row chrome |
40
+
41
+ ---
42
+
43
+ ## How it works
44
+
45
+ ### Anatomy
46
+
47
+ | Part | Required? | What it is |
48
+ | --- | --- | --- |
49
+ | Root container | Yes | `.joy-password-requirement` with status modifier class |
50
+ | Status icon | Yes | `VJoyIcon` — `circle` (neutral), `check-circle` (success), or `warning` (error) |
51
+ | Label | Yes | `.joy-password-requirement__label` — text from the `label` prop |
52
+ | Form error hook | No | `data-joy-form-error` on the root when `status="error"` |
53
+
54
+ The component is **presentational**: it does not validate passwords itself. Parent code computes `status` from the current value and focus state.
55
+
56
+ ### Default values
57
+
58
+ - `status` defaults to **`neutral`**
59
+ - `label` is **required**
60
+
61
+ Props, events, and slots: use Joy MCP or Storybook — this page focuses on **when** and **how**, not a full API dump.
62
+
63
+ ### Status semantics
64
+
65
+ Map `status` to user context, not only to “rule passed / failed”:
66
+
67
+ | `status` | Meaning (typical) |
68
+ | --- | --- |
69
+ | `neutral` | User is editing the password; this rule is **not yet** satisfied |
70
+ | `success` | This rule **is** satisfied for the current value |
71
+ | `error` | Field is **not focused** and this rule is still **not** satisfied (show after blur or submit) |
72
+
73
+ Avoid flipping a row to `error` while the field is still focused unless product rules explicitly require it.
74
+
75
+ ---
76
+
77
+ ## Variants
78
+
79
+ `status` is the only visual variant. Pick it from **validation context**, not from decorative preference.
80
+
81
+ ### `neutral`
82
+
83
+ Use while the user is typing and the rule has not been met yet.
84
+
85
+ Icon: `circle` in neutral color. Label uses `--joy-color-neutral-40`.
86
+
87
+ ### `success`
88
+
89
+ Use when the current password value satisfies this rule.
90
+
91
+ Icon: `check-circle` in success color. Label uses `--joy-color-success-90`.
92
+
93
+ ### `error`
94
+
95
+ Use when the rule is unmet and the password field is no longer focused (blur, tab away, or post-submit).
96
+
97
+ Icon: `warning` (`xsmall`) in error color. Label uses `--joy-color-error-50`. Root receives `data-joy-form-error` for Joy form error integration.
98
+
99
+ ### Not in the API: `valid` / `invalid`
100
+
101
+ Some samples use `status="valid"` or `status="invalid"`. The documented enum is **`success`**, **`error`**, and **`neutral`** only (`TVJoyPasswordRequirementStatus` in `JoyPasswordRequirement.types.ts`). Do not emit `valid` or `invalid`.
102
+
103
+ ---
104
+
105
+ ## States
106
+
107
+ | State | What the user sees |
108
+ | --- | --- |
109
+ | `neutral` | Hollow circle icon; muted label — rule pending while editing |
110
+ | `success` | Check icon; success-colored label — rule met |
111
+ | `error` | Warning icon; error-colored label — rule failed after focus left the field |
112
+ | Multiple rows | Independent status per rule; stack in `#password-requirements` |
113
+
114
+ There is no hover, focus, disabled, or loading API on this component.
115
+
116
+ ---
117
+
118
+ ## Best practices
119
+
120
+ Rules use RFC 2119 strength (**MUST** / **SHOULD** / **MUST NOT** / **SHOULD NOT**).
121
+
122
+ ### Composition
123
+
124
+ - **MUST** render requirement rows inside `VJoyInputPassword`’s `#password-requirements` slot (or an equivalent stacked list directly under the password field).
125
+ - **SHOULD** show **3–6** rules — enough guidance without overwhelming the form.
126
+ - **SHOULD** evaluate rules in parent logic and pass the computed `status` per row.
127
+ - **MUST NOT** use this component as the only validation feedback — still set `invalid` on `VJoyInputPassword` and show `VJoyFormError` when submission fails.
128
+
129
+ ### Implementation
130
+
131
+ - **MUST** use only `neutral`, `success`, and `error` for `status` (MCP / `JoyPasswordRequirement.types.ts`).
132
+ - **MUST** provide a non-empty `label` string per row.
133
+ - **MUST** style with Joy tokens — no custom `.joy-password-requirement` chrome overrides.
134
+ - **MUST NOT** invent props (`size`, `variant`, `icon`, …).
135
+ - **MUST NOT** embed validation logic inside the component — keep rules in the parent.
136
+
137
+ ### Interaction timing
138
+
139
+ - **SHOULD** use `neutral` while the password field is focused and a rule is unmet.
140
+ - **SHOULD** promote unmet rules to `error` on blur or submit, not on every keystroke.
141
+ - **SHOULD** set `success` as soon as a rule is satisfied, even while focused.
142
+
143
+ ### Do / don’t
144
+
145
+ | Do | Don’t |
146
+ | --- | --- |
147
+ | One row per rule with a clear `label` | One row that concatenates every rule |
148
+ | `#password-requirements` on `VJoyInputPassword` | Orphan rows with no password field |
149
+ | `success` / `error` / `neutral` only | `valid` / `invalid` status values |
150
+ | Parent-owned validation logic | Expect the component to validate passwords |
151
+ | `VJoyFormError` for submit-level failures | Only red requirement rows with no summary error |
152
+
153
+ ---
154
+
155
+ ## Content
156
+
157
+ Each row’s `label` is the only user-facing copy. Write rules so users can scan the list quickly.
158
+
159
+ ### Label formula
160
+
161
+ **Short requirement statement** — what the password must include:
162
+
163
+ - ✅ At least 8 characters
164
+ - ✅ Contains an uppercase letter
165
+ - ✅ Contains a number or symbol
166
+
167
+ Use sentence case. Start with “At least…”, “Contains…”, or “Must include…” for parallel structure across rows.
168
+
169
+ ### Writing rules
170
+
171
+ | Strength | Rule |
172
+ | --- | --- |
173
+ | **MUST** | State the rule positively — ✅ `Contains an uppercase letter` · ❌ `No uppercase missing` |
174
+ | **MUST** | Keep each label to one idea — split compound rules into separate rows |
175
+ | **MUST** | Use the same grammatical pattern for every row in the list |
176
+ | **MUST NOT** | Repeat the field label (“Password”) on every requirement row |
177
+ | **MUST NOT** | Use jargon without context — ❌ `Meets entropy threshold` |
178
+ | **SHOULD** | Put numeric thresholds in the label — ✅ `At least 12 characters` |
179
+ | **SHOULD** | Order rules from basic to advanced (length before complexity) |
180
+ | **SHOULD** (FR) | Follow French grammar for labels when the UI is localized |
181
+
182
+ ### Patterns
183
+
184
+ **Signup** — Show all rules as `neutral` on first focus; flip to `success` per rule as the user types; on blur, any remaining failures become `error`.
185
+
186
+ **Reset password** — Same list as signup for consistency; reuse labels across flows.
187
+
188
+ **Submit** — If the form is submitted with failures, set unmet rows to `error` and add a `VJoyFormError` such as `Your password does not meet all requirements`.
189
+
190
+ ---
191
+
192
+ ## Accessibility
193
+
194
+ Behaviors (what must happen), not slogans.
195
+
196
+ | Behavior | Expectation |
197
+ | --- | --- |
198
+ | Role | Presentational `div` — not a form control |
199
+ | Name | Rule text comes from the visible `label` span |
200
+ | Icons | Decorative status indicators; meaning is duplicated in label text |
201
+ | Error integration | `status="error"` sets `data-joy-form-error` on the row for Joy form patterns |
202
+ | Live updates | When statuses change as the user types, ensure the password field’s accessible name and any `VJoyFormError` still describe overall failure — don’t rely on color alone |
203
+ | Grouping | Multiple rows under one password field should read as a related checklist; keep DOM order matching visual order |
204
+
205
+ Target: **WCAG 2.2 AA** where the product requires it.
206
+
207
+ ---
208
+
209
+ ## Examples
210
+
211
+ ```vue
212
+ <script setup lang="ts">
213
+ import { computed, ref } from 'vue'
214
+ import {
215
+ VJoyInputPassword,
216
+ VJoyPasswordRequirement,
217
+ VJoyFormError,
218
+ type TVJoyPasswordRequirementStatus,
219
+ } from '@maltjoy/core-vue'
220
+
221
+ const password = ref('')
222
+ const focused = ref(false)
223
+ const submitted = ref(false)
224
+
225
+ const rules = [
226
+ { id: 'length', label: 'At least 8 characters', test: (v: string) => v.length >= 8 },
227
+ { id: 'upper', label: 'Contains an uppercase letter', test: (v: string) => /[A-Z]/.test(v) },
228
+ { id: 'symbol', label: 'Contains a number or symbol', test: (v: string) => /[\d\W]/.test(v) },
229
+ ]
230
+
231
+ function statusFor(test: (v: string) => boolean): TVJoyPasswordRequirementStatus {
232
+ if (test(password.value)) return 'success'
233
+ if (focused.value) return 'neutral'
234
+ if (submitted.value) return 'error'
235
+ return 'neutral'
236
+ }
237
+
238
+ const allValid = computed(() => rules.every((r) => r.test(password.value)))
239
+ </script>
240
+
241
+ <template>
242
+ <VJoyInputPassword
243
+ v-model="password"
244
+ name="new-password"
245
+ label="Password"
246
+ autocomplete="new-password"
247
+ :invalid="submitted && !allValid"
248
+ @focus="focused = true"
249
+ @blur="focused = false"
250
+ >
251
+ <template #password-requirements>
252
+ <VJoyPasswordRequirement
253
+ v-for="rule in rules"
254
+ :key="rule.id"
255
+ :label="rule.label"
256
+ :status="statusFor(rule.test)"
257
+ />
258
+ </template>
259
+ </VJoyInputPassword>
260
+
261
+ <VJoyFormError
262
+ v-if="submitted && !allValid"
263
+ message="Your password does not meet all requirements"
264
+ />
265
+ </template>
266
+ ```
267
+
268
+ In Nuxt (or apps with auto-import), omit the import if `VJoyPasswordRequirement` is already global.
269
+
270
+ ---
271
+
272
+ ## Related
273
+
274
+ | Component | Use when |
275
+ | --- | --- |
276
+ | `VJoyInputPassword` | Password entry with show/hide toggle and `#password-requirements` slot |
277
+ | `VJoyFormError` | Overall validation message on submit |
278
+ | `VJoyWrapper` | Layout inside `VJoyInputPassword` stacks requirement rows automatically |
279
+ | `VJoyInput` | Non-password single-line text — not for password + rules |
280
+ | `VJoyIcon` | Status glyphs are internal; don’t recompose rows with raw icons |
281
+
282
+ ---
283
+
284
+ ## For agents
285
+
286
+ Optional for readers; **required** for vibe-coding quality. Maps to `agentDocumentBlocks` in [`JoyPasswordRequirement.dsds.json`](./JoyPasswordRequirement.dsds.json).
287
+
288
+ ### Pick the right component
289
+
290
+ | If the intent is… | Emit… | Do not emit… |
291
+ | --- | --- | --- |
292
+ | Per-rule password feedback under a field | `VJoyPasswordRequirement` in `#password-requirements` | Custom `<ul>` with manual icon colors |
293
+ | Password input with toggle | `VJoyInputPassword` | `VJoyInput` + `type="password"` |
294
+ | Single submit error for the field | `VJoyFormError` | Only requirement rows |
295
+ | Rule passed / failed / pending | `status="success"` / `error` / `neutral` | `valid` / `invalid` |
296
+
297
+ ### Hard rules
298
+
299
+ 1. **MUST** call `joy_get_component_info("VJoyPasswordRequirement")` (or read `JoyPasswordRequirement.types.ts`) before generating props.
300
+ 2. **MUST** set `label` on every row.
301
+ 3. **MUST** use `status` values `neutral`, `success`, or `error` only.
302
+ 4. **MUST** place rows in `VJoyInputPassword`’s `#password-requirements` slot unless the layout explicitly mirrors that pattern.
303
+ 5. **MUST NOT** invent props (`size`, `variant`, `valid`, `invalid`, …).
304
+ 6. **MUST NOT** override `.joy-password-requirement` colors, gap, or font size in app CSS.
305
+ 7. **SHOULD** compute `status` in parent script — the component does not validate passwords.
306
+ 8. **SHOULD** pair requirement rows with `VJoyFormError` when the form is submitted invalid.
307
+
308
+ ### Checklist
309
+
310
+ - [ ] `VJoyInputPassword` + `#password-requirements` slot
311
+ - [ ] One `VJoyPasswordRequirement` per rule with `label`
312
+ - [ ] `status` is `neutral`, `success`, or `error` only
313
+ - [ ] No invented props / no custom requirement-row CSS
314
+ - [ ] Parent logic owns rule tests and focus/submit timing
315
+ - [ ] `VJoyFormError` (or equivalent) on submit when rules fail
316
+ - [ ] Labels are short, parallel, and positively phrased
317
+
318
+ ---
319
+
320
+ ## DSDS mapping
321
+
322
+ This Markdown mirrors [`JoyPasswordRequirement.dsds.json`](./JoyPasswordRequirement.dsds.json) (DSDS **0.15.2**).
323
+
324
+ | Section here | DSDS block |
325
+ | --- | --- |
326
+ | When to use / not | `use-cases` |
327
+ | Anatomy | `anatomy` |
328
+ | Status (`status`) | `variants` |
329
+ | States | `states` |
330
+ | Best practices / content rules | `guidelines` (+ `content`) |
331
+ | Accessibility | `accessibility` |
332
+ | Examples | `sections` |
333
+ | For agents | `agentDocumentBlocks` |
334
+ | Props detail | `api` in JSON + Joy MCP |
335
+ | Imports | `imports` in JSON |
336
+ | Token sizing / colors | `design-specifications` in JSON (`--joy-font-size-primary-300`, `--joy-color-neutral-40`, `--joy-color-success-90`, `--joy-color-error-50`) |
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "JoyPasswordRequirement",
3
3
  "displayName": "VJoyPasswordRequirement",
4
- "description": "A component to display a password requirement status.\nThis is meant to be displayed under a VJoyInput of type password.",
4
+ "description": "A component to display a password requirement status.\nThis is meant to be displayed under VJoyInputPassword.",
5
5
  "category": "Forms",
6
6
  "props": [
7
7
  {
@@ -1,5 +1,4 @@
1
1
  import {TJoyIconsNames} from '../JoyIcon/JoyIcon.types';
2
- import VJoyProductTourInner from './VJoyProductTourInner.vue';
3
2
 
4
3
  export const PRODUCT_TOUR_POSITIONS = ['left', 'right', 'top', 'bottom'] as const;
5
4
  export type TJoyProductTourPositions = (typeof PRODUCT_TOUR_POSITIONS)[number];