@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,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`.\
|
|
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. */
|