@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,169 @@
1
+ ---
2
+ component: VJoyIconButton
3
+ status: draft
4
+ language: en
5
+ dsds: JoyIconButton.dsds.json
6
+ dsdsVersion: "0.15.2"
7
+ ---
8
+
9
+ # Icon button
10
+
11
+ Use **`VJoyIconButton`** when the user needs a compact, icon-only action — for example close a dialog, open a menu, delete a row, or toggle notifications.
12
+
13
+ It is built on `VJoyButton`: same variants, sizes, loading state, and native `<button>` / `<a>` behavior (`href`, `disabled`, `type`, … forwarded via `useAttrs`). The visible label is hidden visually but still exposed to assistive tech.
14
+
15
+ | | |
16
+ | --- | --- |
17
+ | **Code** | `VJoyIconButton` from `@maltjoy/core-vue` |
18
+ | **Design** | [ZeroHeight — Icon button](https://zeroheight.com/6bf479565/p/08acf7-icon-button) · [Figma — Buttons](https://www.figma.com/design/jfndp2QBJGS9yeuWbeGuvD/?node-id=12704-7106) |
19
+ | **Storybook** | [VJoyIconButton docs](https://doc.malt.tech/joy-storybook/?path=/docs/components-buttons-vjoyiconbutton--docs) |
20
+ | **DSDS (machine)** | [`JoyIconButton.dsds.json`](./JoyIconButton.dsds.json) |
21
+ | **Live API** | `joy_get_component_info("VJoyIconButton")` |
22
+
23
+ ---
24
+
25
+ ## When to use this component
26
+
27
+ Use an icon button when the action is clear from the icon alone in context — toolbar controls, row actions, dialog close, overflow menus, or compact headers.
28
+
29
+ Typical placements: dialog headers, data-table rows, `VJoyDropdown` triggers, and dense toolbars where a text label would not fit.
30
+
31
+ ### When not to use this component
32
+
33
+ | Need | Use instead |
34
+ | --- | --- |
35
+ | A labeled action with visible text | `VJoyButton` |
36
+ | A text link inside a sentence or paragraph | `VJoyLink` |
37
+ | Icon + visible label on the same control | `VJoyButton` with `icon` |
38
+ | Custom-styled `<button>` / `<a>` | Still use `VJoyIconButton` + Joy tokens — don’t reinvent chrome |
39
+
40
+ > **Deprecated:** do not use `circle` on `VJoyButton` for new work. Prefer `VJoyIconButton`.
41
+
42
+ ---
43
+
44
+ ## How it works
45
+
46
+ `VJoyIconButton` wraps `VJoyButton` with the `joy-icon-button` class. The icon is always shown; the label slot is rendered but hidden with CSS (`.joy-button--slot { display: none }`). Width is fixed per size using `--joy-form-field-height-*` tokens so the control stays square.
47
+
48
+ ### Anatomy
49
+
50
+ | Part | Required? | What it is |
51
+ | --- | --- | --- |
52
+ | Container | Yes | Root `<button>`, or `<a>` when `href` is set on the element (via attrs) |
53
+ | Icon | Yes | `VJoyIcon` from the required `icon` prop (`aria-hidden="true"`) |
54
+ | Label | Yes* | `label` prop or default slot — visually hidden, used for the accessible name |
55
+ | Spinner | No | `VJoySpinner` when `loading` is true |
56
+ | Ripple | Yes | `v-joy-ripple` from `VJoyButton` |
57
+ | Focus ring | Yes | Keyboard focus via `VJoyButton` styles — don’t remove it in product CSS |
58
+
59
+ \*Provide `label` or default-slot text on every instance.
60
+
61
+ ### Default values
62
+
63
+ - `icon` is **required**
64
+ - `variant` defaults to **`primary`**
65
+ - `size` defaults to **`medium`**
66
+ - `loading` defaults to **`false`**
67
+ - Native `type` defaults to **`button`** when the root is a `<button>`
68
+
69
+ `variant` and `size` share the same allowed values as `VJoyButton` (`TJoyButtonVariants`, `TJoyButtonSizes`). Props, events, and slots: use Joy MCP or Storybook — this page focuses on **when** and **how**, not a full API dump.
70
+
71
+ ---
72
+
73
+ ## Best practices
74
+
75
+ Rules use RFC 2119 strength (**MUST** / **SHOULD** / **MUST NOT** / **SHOULD NOT**).
76
+
77
+ ### Selection and hierarchy
78
+
79
+ - **MUST** provide an accessible name on every instance (`label` prop or default slot).
80
+ - **SHOULD** pair with `VJoyTooltip` when the icon meaning is not obvious from context alone.
81
+ - **SHOULD** follow the same variant hierarchy as `VJoyButton` — see [`JoyButton.DSDS.guideline.md`](../JoyButton/JoyButton.DSDS.guideline.md) for `main` / `primary` / `secondary` / `ghost` decisions.
82
+ - **SHOULD** match trigger size to surrounding controls (e.g. `xsmall` icon button beside a `xsmall` dropdown).
83
+
84
+ ### Implementation
85
+
86
+ - **MUST** use only documented `icon`, `variant`, and `size` values from MCP or component types.
87
+ - **MUST** use `VJoyIconButton` as shipped — no custom `.joy-icon-button` chrome in product CSS.
88
+ - **MUST NOT** use deprecated `circle` on `VJoyButton`.
89
+ - **MUST NOT** invent props (`color`, `white`, `circle`, …).
90
+ - **SHOULD** use `loading` during async work instead of only disabling without feedback.
91
+
92
+ ### Do / don’t
93
+
94
+ | Do | Don’t |
95
+ | --- | --- |
96
+ | `label="Close dialog"` on a close icon | Bare icon with no accessible name |
97
+ | `VJoyTooltip` when meaning needs clarification | Duplicate the full label in tooltip when it adds no value |
98
+ | `variant="ghost"` for tertiary toolbar actions | `main` for every icon on a dense toolbar |
99
+ | `VJoyIconButton` for icon-only | `VJoyButton` + `circle` |
100
+
101
+ ---
102
+
103
+ ## Accessibility
104
+
105
+ Behaviors (what must happen), not slogans.
106
+
107
+ | Behavior | Expectation |
108
+ | --- | --- |
109
+ | Role | Native `<button>` or `<a href>` — never a clickable `<div>` |
110
+ | Name | From `label` prop or default slot; `aria-labelledby` on the root points to the hidden label span |
111
+ | Icon | Decorative — `aria-hidden="true"` (Joy default) |
112
+ | Keyboard | **Enter** and **Space** activate a `<button>`; links follow native link keyboard behavior |
113
+ | Focus | Keep the focus ring visible — inherited from `VJoyButton` |
114
+ | Loading | Non-interactive (`disabled` when `loading`); keep the same `size` so layout doesn’t jump |
115
+ | Disabled | Don’t rely on color alone; explain why nearby (tooltip or helper text) |
116
+ | Type | Default `type="button"` on `<button>` roots to avoid accidental form submit |
117
+
118
+ Target: **WCAG 2.2 AA** where the product requires it.
119
+
120
+ ---
121
+
122
+ ## Examples
123
+
124
+ ```vue
125
+ <script setup lang="ts">
126
+ import { VJoyIconButton, VJoyTooltip } from '@maltjoy/core-vue'
127
+ </script>
128
+
129
+ <template>
130
+ <!-- Standard icon action -->
131
+ <VJoyIconButton icon="bell" label="Open notifications" variant="ghost" />
132
+
133
+ <!-- Dialog close (built-in pattern in VJoyDialog) -->
134
+ <VJoyIconButton icon="close" label="Close dialog" variant="ghost" size="small" />
135
+
136
+ <!-- Dropdown trigger -->
137
+ <VJoyIconButton icon="dots-vertical" label="More actions" variant="secondary" size="xsmall" />
138
+
139
+ <!-- Async -->
140
+ <VJoyIconButton icon="send" label="Send message" variant="main" :loading="true" />
141
+
142
+ <!-- As link -->
143
+ <VJoyIconButton icon="external-link" label="Open settings" variant="primary" href="/settings" />
144
+
145
+ <!-- Tooltip when meaning needs context -->
146
+ <VJoyTooltip text="Put to trash">
147
+ <VJoyIconButton icon="trash" label="Put to trash" variant="ghost" />
148
+ </VJoyTooltip>
149
+
150
+ <!-- Slot instead of label prop -->
151
+ <VJoyIconButton icon="pen" variant="secondary">
152
+ Edit profile
153
+ </VJoyIconButton>
154
+ </template>
155
+ ```
156
+
157
+ In Nuxt (or apps with auto-import), omit the import if `VJoyIconButton` is already global.
158
+
159
+ ---
160
+
161
+ ## Related
162
+
163
+ | Component | Use when |
164
+ | --- | --- |
165
+ | `VJoyButton` | Labeled actions with visible text |
166
+ | `VJoyTooltip` | Supplementary label or disabled explanation for icon-only controls |
167
+ | `VJoyDropdown` | Icon button as the `dropdown-button` trigger |
168
+ | `VJoyDialog` | Built-in close control uses `VJoyIconButton` |
169
+ | `VJoyIcon` | Icon primitive rendered inside the button |
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "JoyIconButton",
3
3
  "displayName": "VJoyIconButton",
4
- "description": "A dedicated icon-button component built on top of `VJoyButton`.\nUse this component instead of the deprecated `circle` prop from `VJoyButton`.",
4
+ "description": "A dedicated icon-button component built on top of `VJoyButton`.\nIcon-only button with an accessible label.",
5
5
  "category": "Buttons",
6
6
  "props": [
7
7
  {
@@ -0,0 +1,168 @@
1
+ ---
2
+ component: VJoyIndicator
3
+ status: draft
4
+ language: en
5
+ dsds: JoyIndicator.dsds.json
6
+ dsdsVersion: "0.15.2"
7
+ ---
8
+
9
+ # Indicator
10
+
11
+ Use **`VJoyIndicator`** as a single dot in a page or slide navigation strip — one position in a carousel, dialog step sequence, or similar multi-panel flow.
12
+
13
+ Indicators are text-less buttons by design. Always place them as children of **`VJoyIndicators`**, which owns selection state, `v-model`, and click handling. Do not use `VJoyIndicator` on its own.
14
+
15
+ | | |
16
+ | --- | --- |
17
+ | **Code** | `VJoyIndicator` from `@maltjoy/core-vue` |
18
+ | **Design** | [ZeroHeight — Page indicator](https://zeroheight.com/6bf479565/) (page id `2427818`) |
19
+ | **Storybook** | [VJoyIndicators docs](https://doc.malt.tech/joy-storybook/?path=/docs/components-buttons-vjoyindicators--docs) (includes `VJoyIndicator` children) |
20
+ | **DSDS (machine)** | [`JoyIndicator.dsds.json`](./JoyIndicator.dsds.json) |
21
+ | **Live API** | `joy_get_component_info("VJoyIndicator")` |
22
+
23
+ ---
24
+
25
+ ## When to use this component
26
+
27
+ Use an indicator when the user needs to see **where they are** in a short, ordered set of panels (typically 2–10 items) and optionally jump to another panel by clicking a dot.
28
+
29
+ Common placements: carousel pagination, multi-step `VJoyDialog` flows (`dialog-indicators` slot), or any view where `VJoyIndicators` already wraps the strip.
30
+
31
+ Each child **must** declare a unique `value` (string or number) that matches the parent `v-model`.
32
+
33
+ ### When not to use this component
34
+
35
+ | Need | Use instead |
36
+ | --- | --- |
37
+ | Managing the dot strip, selection, and `v-model` | `VJoyIndicators` — always wrap indicators |
38
+ | Linear process steps with labels (onboarding, checkout) | `VJoyStepper` + `VJoyStep` |
39
+ | Tabbed content with named sections | `VJoyTabs` + `VJoyTab` |
40
+ | Status or notification dots (not navigation) | `VJoyDot`, `VJoyBadge` |
41
+ | Custom-styled pagination dots | Still use `VJoyIndicator` inside `VJoyIndicators` — don’t reinvent with ad-hoc CSS |
42
+
43
+ ---
44
+
45
+ ## How it works
46
+
47
+ ### Anatomy
48
+
49
+ | Part | Required? | What it is |
50
+ | --- | --- | --- |
51
+ | List item (`<li>`) | Yes | Root `.joy-indicator` wrapper in the parent `<ul>` |
52
+ | Indicator button | Yes | Text-less `<button type="button">` — `.joy-indicator--button` |
53
+ | `value` | Yes | Identity of this dot; drives parent `v-model` matching |
54
+ | `selected` | Yes* | Highlight state — set automatically by `VJoyIndicators`; don’t bind manually |
55
+ | `variant` | No | `default` or `light` — usually inherited from parent `VJoyIndicators` |
56
+ | `ariaLabel` | No | Accessible name when `value` alone is not descriptive enough |
57
+
58
+ \*Required for correct visuals, but owned by the parent.
59
+
60
+ ### Default values
61
+
62
+ - `variant` defaults to **`default`**
63
+ - `selected` defaults to **`false`** (parent sets the active dot)
64
+ - `value` is **required** — no default
65
+ - `ariaLabel` is optional — when omitted, `aria-label` falls back to `value.toString()`
66
+
67
+ Props and parent events: use Joy MCP or Storybook — this page focuses on **when** and **how**, not a full API dump.
68
+
69
+ ### Parent composition
70
+
71
+ - **MUST** nest every `VJoyIndicator` inside `VJoyIndicators` (default slot).
72
+ - **MUST** bind `v-model` on `VJoyIndicators` to the currently selected `value`.
73
+ - **SHOULD** set `variant` on `VJoyIndicators` so all children share `default` or `light` styling.
74
+ - **MUST NOT** set `selected` yourself — the parent computes it from `modelValue`.
75
+
76
+ ---
77
+
78
+ ## Best practices
79
+
80
+ Rules use RFC 2119 strength (**MUST** / **SHOULD** / **MUST NOT** / **SHOULD NOT**).
81
+
82
+ ### Composition
83
+
84
+ - **MUST** use one `VJoyIndicator` per navigable panel; keep counts modest (roughly 2–10 dots).
85
+ - **MUST** give each sibling a **unique** `value` within the same `VJoyIndicators` group.
86
+ - **MUST NOT** render `VJoyIndicator` outside `VJoyIndicators`.
87
+ - **MUST NOT** invent props (`size`, `color`, `disabled`, …) — they are not on the API.
88
+
89
+ ### Visual variant
90
+
91
+ - **SHOULD** use `variant="default"` on neutral/light backgrounds (standard carousel, dialog chrome).
92
+ - **SHOULD** use `variant="light"` when the strip sits on a dark or tinted surface (parent passes variant to children).
93
+ - **MUST NOT** override `.joy-indicator` colors, width, height, or radius in product CSS — use Joy tokens via the component.
94
+
95
+ ### Do / don’t
96
+
97
+ | Do | Don’t |
98
+ | --- | --- |
99
+ | `v-model` on `VJoyIndicators` + one child per slide/step | Standalone `VJoyIndicator` with manual `selected` |
100
+ | Meaningful `ariaLabel` when `value` is opaque (`"step-2"`) | Rely on raw numeric `value` as the only accessible name |
101
+ | `variant` on parent for the whole strip | Mix `default` and `light` siblings in one group |
102
+ | `VJoyStepper` when steps need labels | Indicator dots for a labeled wizard |
103
+
104
+ ---
105
+
106
+ ## Accessibility
107
+
108
+ Behaviors (what must happen), not slogans.
109
+
110
+ | Behavior | Expectation |
111
+ | --- | --- |
112
+ | Control type | Each dot is a `<button type="button">` — not a decorative `<span>` |
113
+ | Name | `aria-label` is set from `ariaLabel` or `value.toString()` — prefer explicit `ariaLabel` when `value` is not human-readable |
114
+ | Selection | Selected dot uses `.joy-indicator--button-selected` background; don’t rely on color alone if product adds extra context |
115
+ | Focus | `:focus-visible` shows a 2px focus ring via `box-shadow` on a pseudo-element — don’t remove it in product CSS |
116
+ | Keyboard | Focus moves to each button in tab order; activation is handled by the parent click listener on each child |
117
+ | Group context | Pair with visible panel content so users who cannot see the dots still know their position (e.g. dialog title, slide heading) |
118
+
119
+ Target: **WCAG 2.2 AA** where the product requires it.
120
+
121
+ ---
122
+
123
+ ## Examples
124
+
125
+ ```vue
126
+ <script setup lang="ts">
127
+ import { ref } from 'vue'
128
+ import { VJoyIndicators, VJoyIndicator } from '@maltjoy/core-vue'
129
+
130
+ const activeSlide = ref('slide-1')
131
+ </script>
132
+
133
+ <template>
134
+ <!-- Carousel-style pagination -->
135
+ <VJoyIndicators v-model="activeSlide">
136
+ <VJoyIndicator value="slide-1" aria-label="Slide 1 of 3" />
137
+ <VJoyIndicator value="slide-2" aria-label="Slide 2 of 3" />
138
+ <VJoyIndicator value="slide-3" aria-label="Slide 3 of 3" />
139
+ </VJoyIndicators>
140
+
141
+ <!-- v-for when values are dynamic -->
142
+ <VJoyIndicators v-model="activeSlide" variant="light">
143
+ <VJoyIndicator
144
+ v-for="(slide, index) in ['slide-1', 'slide-2', 'slide-3']"
145
+ :key="slide"
146
+ :value="slide"
147
+ :aria-label="`Slide ${index + 1} of 3`"
148
+ />
149
+ </VJoyIndicators>
150
+ </template>
151
+ ```
152
+
153
+ **Multi-step dialog** — inject `VJoyIndicators` into `VJoyDialog`’s `dialog-indicators` slot; see [VJoyDialog DSDS guideline](../JoyDialog/JoyDialog.DSDS.guideline.md).
154
+
155
+ In Nuxt (or apps with auto-import), omit the import if components are already global.
156
+
157
+ ---
158
+
159
+ ## Related
160
+
161
+ | Component | Use when |
162
+ | --- | --- |
163
+ | `VJoyIndicators` | Parent strip — **required** wrapper for every indicator |
164
+ | `VJoyDialog` | Multi-step modal with `dialog-indicators` slot |
165
+ | `VJoyStepper` / `VJoyStep` | Labeled multi-step progress (not dot-only navigation) |
166
+ | `VJoyTabs` / `VJoyTab` | Named tab panels instead of anonymous slides |
167
+ | `VJoyDot` | Status or count dots — not slide navigation |
168
+ | `VJoyPagination` | Numeric page navigation for large datasets |
@@ -0,0 +1,183 @@
1
+ ---
2
+ component: VJoyIndicators
3
+ status: draft
4
+ language: en
5
+ dsds: JoyIndicators.dsds.json
6
+ dsdsVersion: "0.15.2"
7
+ ---
8
+
9
+ # Indicators
10
+
11
+ Use **`VJoyIndicators`** when the user needs to see their position in a short, ordered set of panels and optionally jump to another panel — carousels, image galleries, or multi-step `VJoyDialog` flows.
12
+
13
+ The component wraps one or more **`VJoyIndicator`** children in a horizontal strip, manages selection with `v-model`, and passes `variant` styling to every dot. It does not render panels or slides — only the navigation dots.
14
+
15
+ | | |
16
+ | --- | --- |
17
+ | **Code** | `VJoyIndicators` from `@maltjoy/core-vue` |
18
+ | **Design** | [ZeroHeight — Page indicator](https://zeroheight.com/6bf479565/) (page id `2427818`) |
19
+ | **Storybook** | [VJoyIndicators docs](https://doc.malt.tech/joy-storybook/?path=/docs/components-buttons-vjoyindicators--docs) |
20
+ | **DSDS (machine)** | [`JoyIndicators.dsds.json`](./JoyIndicators.dsds.json) |
21
+ | **Live API** | `joy_get_component_info("VJoyIndicators")` |
22
+
23
+ ---
24
+
25
+ ## When to use this component
26
+
27
+ Use an indicators strip when **2–10** anonymous panels need dot-style pagination — the user sees which item is active and can click another dot to jump there.
28
+
29
+ Typical placements: carousel footers, hero sliders, or the `dialog-indicators` slot on `VJoyDialog` for a short multi-dialog sequence. Bind `v-model` to the `value` of the active `VJoyIndicator`.
30
+
31
+ ### When not to use this component
32
+
33
+ | Need | Use instead |
34
+ | --- | --- |
35
+ | A single dot (no strip / no shared selection) | You still need `VJoyIndicators` — use `VJoyIndicator` only as its child |
36
+ | Linear process steps with labels (onboarding, checkout) | `VJoyStepper` + `VJoyStep` |
37
+ | Tabbed content with named sections | `VJoyTabs` + `VJoyTab` |
38
+ | Numeric page navigation for large datasets | `VJoyPagination` |
39
+ | Status or notification dots (not navigation) | `VJoyDot`, `VJoyBadge` |
40
+ | Custom-styled pagination dots | Still use `VJoyIndicators` + `VJoyIndicator` — don’t reinvent with ad-hoc CSS |
41
+
42
+ > **Legacy Stencil:** the old `joy-indicators` web component used a numeric `selected` index and `joy-indicators-change`. **`VJoyIndicators` uses `v-model` matched to each child’s `value`** (string or number) — don’t port the index-based API.
43
+
44
+ ---
45
+
46
+ ## How it works
47
+
48
+ ### Anatomy
49
+
50
+ | Part | Required? | What it is |
51
+ | --- | --- | --- |
52
+ | List container (`<ul>`) | Yes | Root `.joy-indicators` — horizontal flex row |
53
+ | `default` slot | Yes | One or more `VJoyIndicator` children |
54
+ | `modelValue` | No* | Selected child `value` — bind with `v-model` |
55
+ | `variant` | No | `default` or `light` — forwarded to every child |
56
+
57
+ \*Strongly recommended whenever clicking a dot should update visible content.
58
+
59
+ ### Default values
60
+
61
+ - `variant` is optional — when set on the parent, it is passed to each `VJoyIndicator` (child `variant` defaults to **`default`** when omitted)
62
+ - `modelValue` has no default — parent or `v-model` should initialize to one child `value` when a dot should start selected
63
+
64
+ Props, events, slots, and exposed members: use Joy MCP or Storybook — this page focuses on **when** and **how**, not a full API dump.
65
+
66
+ ### Selection and children
67
+
68
+ - **MUST** place only `VJoyIndicator` components in the default slot (static list or `v-for`).
69
+ - **MUST** give each child a **unique** `value` — the parent compares `modelValue` to `value` to set `selected`.
70
+ - **MUST** bind `v-model` when dots drive panel visibility; clicking a dot emits `update:modelValue` with that child’s `value`.
71
+ - **MUST NOT** set `selected` on children — the parent computes it.
72
+ - **SHOULD** keep the strip short (roughly 2–10 dots); very long strips are hard to scan and activate.
73
+
74
+ The parent also detects `v-for` output (a single fragment whose children are indicators) so dynamic lists work without extra markup.
75
+
76
+ ### Visual variant
77
+
78
+ | `variant` | Use when |
79
+ | --- | --- |
80
+ | `default` | Neutral/light backgrounds — standard carousel or dialog chrome |
81
+ | `light` | Strip sits on a dark or tinted surface (lighter unselected dots, white selected dot) |
82
+
83
+ Set `variant` on **`VJoyIndicators`** so the whole strip stays consistent — don’t mix variants across siblings.
84
+
85
+ ---
86
+
87
+ ## Best practices
88
+
89
+ Rules use RFC 2119 strength (**MUST** / **SHOULD** / **MUST NOT** / **SHOULD NOT**).
90
+
91
+ ### Composition
92
+
93
+ - **MUST** render one `VJoyIndicator` per navigable panel (slide, dialog step, carousel item).
94
+ - **MUST** sync `v-model` with the panel the user sees — changing the model from code updates the highlighted dot.
95
+ - **SHOULD** pair the strip with visible panel content (slide image, dialog title) so position is clear without relying on dots alone.
96
+ - **MUST NOT** use `VJoyIndicators` without `VJoyIndicator` children — the slot is not for arbitrary markup.
97
+
98
+ ### Implementation
99
+
100
+ - **MUST** use only documented props (`variant`, `modelValue` / `v-model`) and Joy tokens — no custom dot chrome CSS.
101
+ - **MUST NOT** invent props (`size`, `color`, `disabled`, `count`, …).
102
+ - **SHOULD** set meaningful `aria-label` on each `VJoyIndicator` when `value` is opaque (see [JoyIndicator DSDS guideline](../JoyIndicator/JoyIndicator.DSDS.guideline.md)).
103
+ - **SHOULD** use `variant="light"` on dark hero/carousel overlays; `default` elsewhere.
104
+
105
+ ### Do / don’t
106
+
107
+ | Do | Don’t |
108
+ | --- | --- |
109
+ | `v-model` + one child per slide/step | Index-based selection or manual `selected` on children |
110
+ | `variant` on the parent for the whole strip | Per-child variant overrides in the same group |
111
+ | `dialog-indicators` slot for multi-step dialogs | Orphan dots with no linked panel content |
112
+ | `VJoyStepper` when steps need labels | Dot strip for a labeled wizard |
113
+
114
+ ---
115
+
116
+ ## Accessibility
117
+
118
+ Behaviors (what must happen), not slogans.
119
+
120
+ | Behavior | Expectation |
121
+ | --- | --- |
122
+ | Structure | Strip is a `<ul>` of indicator list items — each child renders a `<button type="button">` |
123
+ | Selection | Active dot is styled via `.joy-indicator--button-selected`; pair with visible panel content for context |
124
+ | Names | Each dot gets `aria-label` from the child’s `ariaLabel` or `value` — prefer explicit labels when `value` is not human-readable |
125
+ | Focus | Each dot is focusable; `:focus-visible` ring on the button — don’t remove it in product CSS |
126
+ | Keyboard | Tab between dots; click (or Enter/Space on the focused button) updates `v-model` and the associated panel |
127
+ | Group context | Dots supplement the main content — don’t make position information hover-only or dots-only |
128
+
129
+ Target: **WCAG 2.2 AA** where the product requires it.
130
+
131
+ ---
132
+
133
+ ## Examples
134
+
135
+ ```vue
136
+ <script setup lang="ts">
137
+ import { ref } from 'vue'
138
+ import { VJoyIndicators, VJoyIndicator } from '@maltjoy/core-vue'
139
+
140
+ const activeSlide = ref('slide-1')
141
+ const slides = ['slide-1', 'slide-2', 'slide-3'] as const
142
+ </script>
143
+
144
+ <template>
145
+ <!-- Static children -->
146
+ <VJoyIndicators v-model="activeSlide">
147
+ <VJoyIndicator value="slide-1" aria-label="Slide 1 of 3" />
148
+ <VJoyIndicator value="slide-2" aria-label="Slide 2 of 3" />
149
+ <VJoyIndicator value="slide-3" aria-label="Slide 3 of 3" />
150
+ </VJoyIndicators>
151
+
152
+ <!-- Dynamic list (v-for) -->
153
+ <VJoyIndicators v-model="activeSlide" variant="light">
154
+ <VJoyIndicator
155
+ v-for="(slide, index) in slides"
156
+ :key="slide"
157
+ :value="slide"
158
+ :aria-label="`Slide ${index + 1} of ${slides.length}`"
159
+ />
160
+ </VJoyIndicators>
161
+
162
+ <!-- Show the panel that matches v-model -->
163
+ <img v-if="activeSlide === 'slide-1'" src="/hero-1.jpg" alt="…" />
164
+ <!-- … -->
165
+ </template>
166
+ ```
167
+
168
+ **Multi-step dialog** — pass `VJoyIndicators` into `VJoyDialog`’s `dialog-indicators` slot; keep `v-model` in sync with which dialog is open. See [VJoyDialog DSDS guideline](../JoyDialog/JoyDialog.DSDS.guideline.md).
169
+
170
+ In Nuxt (or apps with auto-import), omit the import if components are already global.
171
+
172
+ ---
173
+
174
+ ## Related
175
+
176
+ | Component | Use when |
177
+ | --- | --- |
178
+ | `VJoyIndicator` | **Required** child — one dot per panel |
179
+ | `VJoyDialog` | Multi-step modal with `dialog-indicators` slot |
180
+ | `VJoyStepper` / `VJoyStep` | Labeled multi-step progress (not dot-only navigation) |
181
+ | `VJoyTabs` / `VJoyTab` | Named tab panels instead of anonymous slides |
182
+ | `VJoyDot` | Status or count dots — not slide navigation |
183
+ | `VJoyPagination` | Numeric page navigation for large datasets |
@@ -26,13 +26,8 @@ export interface VJoyInputProps {
26
26
  /** Add a JoyIcon / joy-icon with given name on left-side. */
27
27
  icon?: TJoyIconsNames;
28
28
  size?: TJoyInputSizes;
29
- /**
30
- * @deprecated Password mode is deprecated on VJoyInput.
31
- * Use VJoyInputPassword for password fields and toggle behavior.
32
- */
29
+ /** HTML input type. Use VJoyInputPassword for password fields. */
33
30
  type?: string;
34
- /** Adds a legend like symbol on the right of the component. Made for number based values */
35
- unit?: string;
36
31
  /** Activates the readonly mode for the input */
37
32
  readonly?: boolean;
38
33
  /** When using the clearable property, you have to specific an aria-label for accessibility. */