@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,327 @@
|
|
|
1
|
+
---
|
|
2
|
+
component: VJoyToggle
|
|
3
|
+
status: draft
|
|
4
|
+
language: en
|
|
5
|
+
dsds: JoyToggle.dsds.json
|
|
6
|
+
dsdsVersion: "0.15.2"
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Toggle
|
|
10
|
+
|
|
11
|
+
Use **`VJoyToggle`** when the user needs to switch a single setting **on or off** with immediate effect — especially in settings rows, preferences, or compact forms.
|
|
12
|
+
|
|
13
|
+
It supports checked and disabled states, a label via prop or slot (left or right of the switch), native form attributes (`name`, `value`, `required`), and two visual variants: **`default`** (customer product) and **`admin`** (internal tooling).
|
|
14
|
+
|
|
15
|
+
| | |
|
|
16
|
+
| --- | --- |
|
|
17
|
+
| **Code** | `VJoyToggle` from `@maltjoy/core-vue` |
|
|
18
|
+
| **Design** | [Joy — Toggle](https://zeroheight.com/6bf479565/p/67497f) (page id `1423634`) |
|
|
19
|
+
| **Storybook** | [VJoyToggle docs](https://doc.malt.tech/joy-storybook/?path=/docs/components-forms-vjoytoggle--docs) |
|
|
20
|
+
| **DSDS (machine)** | [`JoyToggle.dsds.json`](./JoyToggle.dsds.json) |
|
|
21
|
+
| **Live API** | `joy_get_component_info("VJoyToggle")` |
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## When to use this component
|
|
26
|
+
|
|
27
|
+
Use a toggle when there are **exactly two mutually exclusive states** (on / off) that the user may change often and see take effect right away — for example enabling notifications, showing optional UI, or turning a feature on.
|
|
28
|
+
|
|
29
|
+
Toggles work well when space is tight and the two states are clearly related. Place the label beside the switch so the user knows what flips when they interact with the control.
|
|
30
|
+
|
|
31
|
+
### When not to use this component
|
|
32
|
+
|
|
33
|
+
| Need | Use instead |
|
|
34
|
+
| --- | --- |
|
|
35
|
+
| More than two options | `VJoyRadio` / `VJoyRadioGroup` or `VJoySelect` |
|
|
36
|
+
| Multiple independent selections | `VJoyCheckbox` / `VJoyCheckboxGroup` |
|
|
37
|
+
| Consent, agreement, or “I accept…” copy | `VJoyCheckbox` |
|
|
38
|
+
| Options that are not mutually exclusive | `VJoyCheckbox` |
|
|
39
|
+
| A change that only applies after Save / Submit | Checkbox or explicit submit — not an instant toggle |
|
|
40
|
+
| Customer-facing product UI with admin chrome | `variant="default"` — never `admin` |
|
|
41
|
+
| Custom-styled switch markup | Still use `VJoyToggle` + Joy tokens — don’t reinvent chrome |
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## How it works
|
|
46
|
+
|
|
47
|
+
### Anatomy
|
|
48
|
+
|
|
49
|
+
| Part | Required? | What it is |
|
|
50
|
+
| --- | --- | --- |
|
|
51
|
+
| Wrapper | Yes | Root container (`.joy-toggle__wrapper`) |
|
|
52
|
+
| Label | Yes | Clickable `<label>` wrapping the input and content row |
|
|
53
|
+
| Input | Yes | Visually hidden `<input type="checkbox">` with `data-joy-form-field` and `role="checkbox"` |
|
|
54
|
+
| Switch track | Yes | `.joy-toggle__symbol` — rounded track behind the bubble |
|
|
55
|
+
| Bubble | Yes | `.joy-toggle__symbol-bubble` — slides horizontally when checked |
|
|
56
|
+
| Variant icon | No | Smile SVG (`default`) or `VJoyIcon` `eye` (`admin`) inside the bubble |
|
|
57
|
+
| Label text | Yes* | Default slot or `label` prop in `.joy-toggle__content-label` (*one must provide an accessible name) |
|
|
58
|
+
| Focus ring | Yes | Outline on the track when the input is focused (`joy-toggle__focusing`) |
|
|
59
|
+
|
|
60
|
+
The component `provide`s `JoyFormElementContext` so it integrates with Joy form field patterns (e.g. labels, validation groups).
|
|
61
|
+
|
|
62
|
+
### Default values
|
|
63
|
+
|
|
64
|
+
- `modelValue` defaults to **`false`**
|
|
65
|
+
- `variant` defaults to **`default`**
|
|
66
|
+
- `labelPosition` defaults to **`right`**
|
|
67
|
+
- `disabled` defaults to **`false`**
|
|
68
|
+
- `invalid` defaults to **`false`** (declared on props; no dedicated invalid styling in component CSS yet — pair with `VJoyFormError` or group messaging)
|
|
69
|
+
- `required` defaults to **`false`**
|
|
70
|
+
- `value` defaults to **`"on"`** (submitted value when checked in native forms)
|
|
71
|
+
|
|
72
|
+
Props, events, and slots: use Joy MCP or Storybook — this page focuses on **when** and **how**, not a full API dump.
|
|
73
|
+
|
|
74
|
+
### Visual treatment
|
|
75
|
+
|
|
76
|
+
There is **no `size` prop**. Track and bubble dimensions come from component CSS variables (e.g. `--toggle-width`, `--toggle-height`) and Joy color tokens — **don’t hardcode switch width, height, or track colors** in product CSS.
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## Variants
|
|
81
|
+
|
|
82
|
+
Pick variant by **surface audience**, not by color preference.
|
|
83
|
+
|
|
84
|
+
### `default`
|
|
85
|
+
|
|
86
|
+
Use on **customer-facing** product UI. The bubble shows the Joy smile motif when checked.
|
|
87
|
+
|
|
88
|
+
Avoid `admin` styling on public or client surfaces.
|
|
89
|
+
|
|
90
|
+
### `admin`
|
|
91
|
+
|
|
92
|
+
Use **only** in internal / admin tooling. Checked state uses quaternary tokens; the bubble shows an **eye** icon instead of the smile.
|
|
93
|
+
|
|
94
|
+
Avoid `variant="admin"` outside admin contexts — it is documented separately in Storybook under Admin.
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## States
|
|
99
|
+
|
|
100
|
+
| State | What the user sees / can do |
|
|
101
|
+
| --- | --- |
|
|
102
|
+
| Off (`modelValue: false`) | Bubble on the left; neutral track; label in normal weight |
|
|
103
|
+
| On (`modelValue: true`) | Bubble slides right; track uses secondary (or quaternary for `admin`); smile or eye visible in bubble |
|
|
104
|
+
| Hover | Track and bubble border lighten (pointer devices); checked hover uses `--toggle-bg-color-hover-checked` |
|
|
105
|
+
| Focus | Visible focus outline on the track — don’t remove in product CSS |
|
|
106
|
+
| Disabled | No interaction; muted track, bubble, label, and icon — **explain why** nearby when possible |
|
|
107
|
+
| Disabled + on | Same as disabled with bubble in the “on” position |
|
|
108
|
+
|
|
109
|
+
Bind state with `v-model` (or `:model-value` + `@update:modelValue`). Changes emit immediately on `change` — there is no separate “Apply” step inside the component.
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## Best practices
|
|
114
|
+
|
|
115
|
+
Rules use RFC 2119 strength (**MUST** / **SHOULD** / **MUST NOT** / **SHOULD NOT**).
|
|
116
|
+
|
|
117
|
+
### Selection model
|
|
118
|
+
|
|
119
|
+
- **SHOULD** use a toggle only for **two** mutually exclusive, immediately applied states.
|
|
120
|
+
- **MUST NOT** use a toggle when the user can select multiple options — use checkboxes.
|
|
121
|
+
- **MUST NOT** use a toggle when more than two choices exist — use radio or select.
|
|
122
|
+
- **SHOULD** prefer `VJoyCheckbox` when the label is a consent statement (“I agree to…”) rather than a setting name.
|
|
123
|
+
|
|
124
|
+
### Implementation
|
|
125
|
+
|
|
126
|
+
- **MUST** bind state with `v-model` (or `:model-value` + `@update:modelValue`).
|
|
127
|
+
- **MUST** use only documented props from MCP or `VJoyToggle.vue` props.
|
|
128
|
+
- **MUST** use Joy tokens — no custom `.joy-toggle` track, bubble, or focus CSS.
|
|
129
|
+
- **MUST NOT** invent props (`size`, `color`, `checked` as v-model name, …).
|
|
130
|
+
- **MUST** use `variant="default"` on customer surfaces; reserve `admin` for internal tools.
|
|
131
|
+
- **SHOULD** set `name` and `value` when multiple toggles participate in the same native form submit.
|
|
132
|
+
- **SHOULD** surface validation errors with `VJoyFormError` or `VJoyFormGroup` — don’t rely on `invalid` alone until invalid styling is wired.
|
|
133
|
+
|
|
134
|
+
### Interaction
|
|
135
|
+
|
|
136
|
+
- **MUST** keep the label clickable (component wraps input in `<label>` — don’t break that association).
|
|
137
|
+
- **SHOULD** use `labelPosition="left"` when the switch must align with a column of controls on the right (e.g. settings tables).
|
|
138
|
+
- **SHOULD** disable rather than hide a setting the user cannot change, when the setting must remain visible.
|
|
139
|
+
|
|
140
|
+
### Do / don’t
|
|
141
|
+
|
|
142
|
+
| Do | Don’t |
|
|
143
|
+
| --- | --- |
|
|
144
|
+
| `v-model` for on/off state | Separate Save button for a single instant setting (unless product requires it) |
|
|
145
|
+
| Short setting names as labels | Full sentences that read like checkboxes (“I agree…”) |
|
|
146
|
+
| `default` on product UI | `admin` variant on customer flows |
|
|
147
|
+
| `VJoyCheckbox` for consent | Toggle for legal acceptance |
|
|
148
|
+
| Radio / select for 3+ options | Toggle as a multi-option picker |
|
|
149
|
+
|
|
150
|
+
---
|
|
151
|
+
|
|
152
|
+
## Content
|
|
153
|
+
|
|
154
|
+
Toggle labels name **what is enabled when the switch is on**. They are scannable, parallel in lists, and use the **infinitive** mood in English (per Joy conjugation guidelines).
|
|
155
|
+
|
|
156
|
+
### Label formula
|
|
157
|
+
|
|
158
|
+
**Infinitive verb + optional object** (English):
|
|
159
|
+
|
|
160
|
+
- ✅ Enable notifications
|
|
161
|
+
- ✅ Show completed projects
|
|
162
|
+
- ✅ Use dark mode
|
|
163
|
+
|
|
164
|
+
The label describes the **on** state. Off is implied.
|
|
165
|
+
|
|
166
|
+
### Writing rules
|
|
167
|
+
|
|
168
|
+
| Strength | Rule |
|
|
169
|
+
| --- | --- |
|
|
170
|
+
| **MUST** | Every toggle has a visible label (prop or default slot) — no unlabeled switches |
|
|
171
|
+
| **MUST** | Label states what is on when checked — ✅ `Enable email alerts` · ❌ `Email alerts are enabled` |
|
|
172
|
+
| **MUST** | Use infinitive mood (EN) — ✅ `Show profile` · ❌ `Showing profile` |
|
|
173
|
+
| **MUST NOT** | Use Yes / No as the only label — name the setting |
|
|
174
|
+
| **MUST NOT** | Use checkbox-style agreement copy — ✅ move to `VJoyCheckbox` |
|
|
175
|
+
| **SHOULD** | ≤ 40 characters; wrap rather than truncate |
|
|
176
|
+
| **SHOULD** | Sentence case; parallel grammar in stacked settings |
|
|
177
|
+
| **SHOULD** | Avoid “Turn on/off” padding when the infinitive alone is clear — ✅ `Enable notifications` |
|
|
178
|
+
| **SHOULD** (FR) | Follow product locale rules; infinitive is still preferred for toggle labels |
|
|
179
|
+
|
|
180
|
+
### Patterns
|
|
181
|
+
|
|
182
|
+
**Settings row** — One toggle per row; label on the right by default. Group related toggles under a `VJoyLabel` or section heading.
|
|
183
|
+
|
|
184
|
+
**Dialog / panel** — Use when the choice is binary and applies immediately (e.g. “Show archived items”). Prefer explicit labels over “On / Off” alone.
|
|
185
|
+
|
|
186
|
+
**Forms** — If the form is submitted as a whole, still bind `v-model`; set `name` / `value` so unchecked toggles behave as expected in native submit (checkbox semantics).
|
|
187
|
+
|
|
188
|
+
**Validation** — When a toggle must be on to proceed, show error copy next to the control (`VJoyFormError`) rather than only relying on border color.
|
|
189
|
+
|
|
190
|
+
---
|
|
191
|
+
|
|
192
|
+
## Accessibility
|
|
193
|
+
|
|
194
|
+
Behaviors (what must happen), not slogans.
|
|
195
|
+
|
|
196
|
+
| Behavior | Expectation |
|
|
197
|
+
| --- | --- |
|
|
198
|
+
| Role | Native checkbox (`<input type="checkbox">`) with `role="checkbox"` |
|
|
199
|
+
| Name | From default slot or `label` prop; associated via wrapping `<label>` |
|
|
200
|
+
| State | `aria-checked` reflects `modelValue` |
|
|
201
|
+
| Keyboard | **Space** toggles when focused; **Tab** moves focus |
|
|
202
|
+
| Focus | Visible focus ring on the track (`joy-toggle__focusing`); don’t remove in product CSS |
|
|
203
|
+
| Disabled | `disabled` on input; explain restriction in visible text when it matters |
|
|
204
|
+
| Motion | Bubble animates with `--joy-transition-duration-default`; respect `prefers-reduced-motion` at app level if you add wrappers |
|
|
205
|
+
|
|
206
|
+
Target: **WCAG 2.2 AA** where the product requires it.
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
## Examples
|
|
211
|
+
|
|
212
|
+
```vue
|
|
213
|
+
<script setup lang="ts">
|
|
214
|
+
import { ref } from 'vue'
|
|
215
|
+
import { VJoyToggle } from '@maltjoy/core-vue'
|
|
216
|
+
|
|
217
|
+
const notifications = ref(true)
|
|
218
|
+
const showArchived = ref(false)
|
|
219
|
+
</script>
|
|
220
|
+
|
|
221
|
+
<template>
|
|
222
|
+
<!-- Basic setting (label right) -->
|
|
223
|
+
<VJoyToggle v-model="notifications" label="Enable notifications" />
|
|
224
|
+
|
|
225
|
+
<!-- Label on the left (settings table alignment) -->
|
|
226
|
+
<VJoyToggle
|
|
227
|
+
v-model="showArchived"
|
|
228
|
+
label="Show archived projects"
|
|
229
|
+
label-position="left"
|
|
230
|
+
/>
|
|
231
|
+
|
|
232
|
+
<!-- Custom label slot -->
|
|
233
|
+
<VJoyToggle v-model="showArchived">
|
|
234
|
+
Show <strong>archived</strong> projects
|
|
235
|
+
</VJoyToggle>
|
|
236
|
+
|
|
237
|
+
<!-- Disabled -->
|
|
238
|
+
<VJoyToggle disabled :model-value="true" label="Managed by your organization" />
|
|
239
|
+
|
|
240
|
+
<!-- Native form field -->
|
|
241
|
+
<VJoyToggle
|
|
242
|
+
v-model="notifications"
|
|
243
|
+
name="email_alerts"
|
|
244
|
+
value="enabled"
|
|
245
|
+
label="Enable email alerts"
|
|
246
|
+
/>
|
|
247
|
+
|
|
248
|
+
<!-- Admin tooling only -->
|
|
249
|
+
<VJoyToggle variant="admin" v-model="showArchived" label="Admin view" />
|
|
250
|
+
</template>
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
In Nuxt (or apps with auto-import), omit the import if `VJoyToggle` is already global.
|
|
254
|
+
|
|
255
|
+
---
|
|
256
|
+
|
|
257
|
+
## Related
|
|
258
|
+
|
|
259
|
+
| Component | Use when |
|
|
260
|
+
| --- | --- |
|
|
261
|
+
| `VJoyCheckbox` | Consent, multi-select, or non-immediate binary confirmation |
|
|
262
|
+
| `VJoyCheckboxGroup` | Several independent checkboxes with shared legend |
|
|
263
|
+
| `VJoyRadio` / `VJoyRadioGroup` | Exactly one of three or more visible options |
|
|
264
|
+
| `VJoySelect` | Many options or searchable lists |
|
|
265
|
+
| `VJoyLabel` / `VJoyFormGroup` | Section headings, required marks, and form-level validation messaging |
|
|
266
|
+
| `VJoyFormError` | Explicit error text when validation fails |
|
|
267
|
+
|
|
268
|
+
---
|
|
269
|
+
|
|
270
|
+
## For agents
|
|
271
|
+
|
|
272
|
+
Optional for readers; **required** for vibe-coding quality. Maps to `agentDocumentBlocks` in [`JoyToggle.dsds.json`](./JoyToggle.dsds.json).
|
|
273
|
+
|
|
274
|
+
### Pick the right component
|
|
275
|
+
|
|
276
|
+
| If the intent is… | Emit… | Do not emit… |
|
|
277
|
+
| --- | --- | --- |
|
|
278
|
+
| Single on/off setting, immediate | `VJoyToggle` | `VJoyCheckbox` for a settings row |
|
|
279
|
+
| “I agree to terms” | `VJoyCheckbox` | `VJoyToggle` |
|
|
280
|
+
| Pick one of 3+ options | `VJoyRadio` / `VJoySelect` | `VJoyToggle` |
|
|
281
|
+
| Multi-select filters | `VJoyCheckbox` / `VJoyCheckboxGroup` | `VJoyToggle` |
|
|
282
|
+
| Customer product UI | `VJoyToggle` `variant="default"` | `variant="admin"` |
|
|
283
|
+
| Internal admin surface | `VJoyToggle` `variant="admin"` | `admin` on public pages |
|
|
284
|
+
|
|
285
|
+
### Hard rules
|
|
286
|
+
|
|
287
|
+
1. **MUST** read `VJoyToggle.vue` props (or MCP when available) before generating props — `joy_get_component_info("VJoyToggle")` may not be registered yet.
|
|
288
|
+
2. **MUST** use `v-model` / `:model-value` + `@update:modelValue` — not `v-model:checked`.
|
|
289
|
+
3. **MUST NOT** invent props — there is no `size`, `checked` v-model alias, or `color`.
|
|
290
|
+
4. **MUST NOT** override `.joy-toggle` track, bubble, or focus styles with custom CSS.
|
|
291
|
+
5. **MUST NOT** use `variant="admin"` outside admin / internal tooling.
|
|
292
|
+
6. **MUST** provide a visible label (prop or default slot) on every instance.
|
|
293
|
+
7. **SHOULD** use infinitive labels (EN): `Enable notifications`, not `Notifications enabled`.
|
|
294
|
+
8. **SHOULD** use `label-position="left"` only when layout requires label-before-switch alignment.
|
|
295
|
+
|
|
296
|
+
### Checklist
|
|
297
|
+
|
|
298
|
+
- [ ] Correct component (`VJoyToggle` or named alternative)
|
|
299
|
+
- [ ] Props from source / MCP only — no invented API
|
|
300
|
+
- [ ] `v-model` wired for boolean on/off state
|
|
301
|
+
- [ ] Visible label on every instance
|
|
302
|
+
- [ ] `variant="default"` on customer surfaces
|
|
303
|
+
- [ ] No custom `.joy-toggle` chrome CSS
|
|
304
|
+
- [ ] 3+ options → radio or select, not toggle
|
|
305
|
+
- [ ] Consent copy → checkbox, not toggle
|
|
306
|
+
- [ ] Disabled / validation explained in visible text when user-facing
|
|
307
|
+
- [ ] `name` / `value` set when needed for native form submit
|
|
308
|
+
|
|
309
|
+
---
|
|
310
|
+
|
|
311
|
+
## DSDS mapping
|
|
312
|
+
|
|
313
|
+
This Markdown mirrors [`JoyToggle.dsds.json`](./JoyToggle.dsds.json) (DSDS **0.15.2**).
|
|
314
|
+
|
|
315
|
+
| Section here | DSDS block |
|
|
316
|
+
| --- | --- |
|
|
317
|
+
| When to use / not | `use-cases` |
|
|
318
|
+
| Anatomy | `anatomy` |
|
|
319
|
+
| Variants | `variants` |
|
|
320
|
+
| States | `states` |
|
|
321
|
+
| Best practices / content rules | `guidelines` (+ `content`) |
|
|
322
|
+
| Accessibility | `accessibility` |
|
|
323
|
+
| Examples | `sections` |
|
|
324
|
+
| For agents | `agentDocumentBlocks` |
|
|
325
|
+
| Props detail | `api` in JSON + Joy MCP |
|
|
326
|
+
| Imports | `imports` in JSON |
|
|
327
|
+
| Token sizing | `design-specifications` in JSON (token names, not raw px dumps) |
|
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
---
|
|
2
|
+
component: VJoyTooltip
|
|
3
|
+
status: draft
|
|
4
|
+
language: en
|
|
5
|
+
dsds: JoyTooltip.dsds.json
|
|
6
|
+
dsdsVersion: "0.15.2"
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Tooltip
|
|
10
|
+
|
|
11
|
+
Use **`VJoyTooltip`** when you need brief, contextual help on hover or click — for example naming an icon-only control, explaining why something is disabled, or clarifying a field label.
|
|
12
|
+
|
|
13
|
+
The tooltip wraps a trigger (default slot), teleports its panel to `body`, positions itself with Floating UI (auto-flip when space is tight), and exposes `role="tooltip"` with `aria-describedby` on the trigger.
|
|
14
|
+
|
|
15
|
+
| | |
|
|
16
|
+
| --- | --- |
|
|
17
|
+
| **Code** | `VJoyTooltip` from `@maltjoy/core-vue` |
|
|
18
|
+
| **Design** | [ZeroHeight — Tooltip](https://zeroheight.com/6bf479565/p/137c09-tooltip) |
|
|
19
|
+
| **Storybook** | [VJoyTooltip docs](https://doc.malt.tech/joy-storybook/?path=/docs/components-overlays-vjoytooltip--docs) |
|
|
20
|
+
| **DSDS (machine)** | [`JoyTooltip.dsds.json`](./JoyTooltip.dsds.json) |
|
|
21
|
+
| **Live API** | `joy_get_component_info("VJoyTooltip")` |
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## When to use this component
|
|
26
|
+
|
|
27
|
+
Use a tooltip to reveal **short, supplementary** information tied to a single trigger — without pulling the user out of their current task. Typical jobs: label an icon button, explain a disabled control, or add optional detail to a form label (`VJoyLabel` uses this pattern).
|
|
28
|
+
|
|
29
|
+
Default interaction is **hover** (`event="mouseenter"`). Switch to **click** when hover is unreliable (touch-first surfaces) or when the tooltip must stay open while the user reads or interacts with its content.
|
|
30
|
+
|
|
31
|
+
### When not to use this component
|
|
32
|
+
|
|
33
|
+
| Need | Use instead |
|
|
34
|
+
| --- | --- |
|
|
35
|
+
| Information the user must read or act on | `VJoyDialog`, `VJoyDrawer`, or inline helper text |
|
|
36
|
+
| A list of actions or navigation | `VJoyMenu`, `VJoyDropdown` |
|
|
37
|
+
| Persistent page guidance or onboarding | Product tour / coachmark patterns (see Information helper guidelines) |
|
|
38
|
+
| Toast-style feedback after an action | `pushVJoySnackbar` |
|
|
39
|
+
| A custom floating panel with ad-hoc CSS | Still use `VJoyTooltip` + Joy tokens — don’t reinvent overlay chrome |
|
|
40
|
+
|
|
41
|
+
> **Deprecated:** `enableClickInContent` — behavior is already the default (`true`) and the prop will be removed. Omit it in new code unless you explicitly need the legacy `false` behavior.
|
|
42
|
+
|
|
43
|
+
> **Removed from API:** `variant` (`primary` / `secondary`) existed on the legacy Stencil tooltip. **`VJoyTooltip` has no `variant` prop.** Do not emit `variant="primary"` or `variant="secondary"`.
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## How it works
|
|
48
|
+
|
|
49
|
+
### Anatomy
|
|
50
|
+
|
|
51
|
+
| Part | Required? | What it is |
|
|
52
|
+
| --- | --- | --- |
|
|
53
|
+
| Click-outside wrapper | Yes | `OnClickOutside` root — dismisses click-triggered tooltips |
|
|
54
|
+
| Trigger wrapper | Yes | Wraps the default slot; holds pointer/keyboard listeners and `aria-describedby` |
|
|
55
|
+
| Trigger (default slot) | Yes | The control or element the user hovers/clicks (e.g. `VJoyIconButton`) |
|
|
56
|
+
| Tooltip panel | Yes* | Teleported to `body`; `role="tooltip"`; shown when visible |
|
|
57
|
+
| Arrow | Yes | Positioned by Floating UI middleware |
|
|
58
|
+
| Content inner | Yes* | `tooltip-content` slot or `text` prop output |
|
|
59
|
+
|
|
60
|
+
\*The panel is not rendered unless `text` or the `tooltip-content` slot is provided.
|
|
61
|
+
|
|
62
|
+
### Default values
|
|
63
|
+
|
|
64
|
+
- `placement` defaults to **`bottom`**
|
|
65
|
+
- `event` defaults to **`mouseenter`**
|
|
66
|
+
- `delay` defaults to **`100`** (ms, show/hide)
|
|
67
|
+
- `tooltipWidth` defaults to **`250`** (px `max-width` on the panel)
|
|
68
|
+
- `enableClickInContent` defaults to **`true`**
|
|
69
|
+
- `show` defaults to **`false`** (set `true` mainly in Storybook / visual tests)
|
|
70
|
+
|
|
71
|
+
Props, slots, and exposed members: use Joy MCP or Storybook — this page focuses on **when** and **how**, not a full API dump.
|
|
72
|
+
|
|
73
|
+
### Positioning and triggers
|
|
74
|
+
|
|
75
|
+
- **Placement** — any [Floating UI placement](https://floating-ui.com/docs/tutorial#placements) (`top`, `bottom`, `left`, `right`, and `*-start` / `*-end`). The component **flips** to `bottom`, `top`, `left`, or `right` when there isn’t enough room.
|
|
76
|
+
- **Hover (default)** — show on `mouseenter`, hide on `mouseleave`. Clicks alone do not open the tooltip.
|
|
77
|
+
- **Click** — set `event="click"`. Opens on trigger click; closes on outside click or **Tab** away from the trigger. With `enableClickInContent`, clicks inside the tooltip content do not dismiss it.
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## Variants
|
|
82
|
+
|
|
83
|
+
`VJoyTooltip` has **no visual variant prop**. Styling is fixed: neutral background (`--joy-color-neutral-10`), body text (`--joy-color-neutral-60`), `primary-300` typography, `--joy-core-radius-3`, and `--joy-core-elevation-3`.
|
|
84
|
+
|
|
85
|
+
### Not in the API: `primary` / `secondary` (legacy Stencil)
|
|
86
|
+
|
|
87
|
+
ZeroHeight and the legacy `@maltjoy/core` tooltip documented `variant="primary"` (information blue) and `variant="secondary"` (neutral). These values are **not** on `VJoyTooltip`. Do not generate them. If product needs an information-colored tooltip, confirm with design before adding a new API value.
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## Sizes
|
|
92
|
+
|
|
93
|
+
Single visual size — no `size` prop. Typography and padding come from Joy tokens inside the component (`primary-300`, `--joy-core-spacing-4`).
|
|
94
|
+
|
|
95
|
+
| Control | Use when |
|
|
96
|
+
| --- | --- |
|
|
97
|
+
| Default width | Short labels and icon explanations |
|
|
98
|
+
| `tooltipWidth` | Longer copy that should wrap within a narrower or wider column (value is `max-width` in px) |
|
|
99
|
+
|
|
100
|
+
**Don’t** hardcode font sizes or padding on `.joy-tooltip__content` in product CSS.
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## States
|
|
105
|
+
|
|
106
|
+
| State | What the user sees / can do |
|
|
107
|
+
| --- | --- |
|
|
108
|
+
| Hidden (default) | Only the trigger is visible |
|
|
109
|
+
| Delayed show | After `delay` ms, panel fades in (hover or click path) |
|
|
110
|
+
| Visible | Tooltip panel + arrow; describes the trigger for assistive tech |
|
|
111
|
+
| Hiding | Opacity animation when dismissed (`mouseleave`, outside click, or Tab) |
|
|
112
|
+
| Click + open | With `event="click"`, panel stays until outside click or Tab; content may be clickable when `enableClickInContent` is true |
|
|
113
|
+
| `show` (dev) | Forces visible on mount — for Storybook/tests, not production UX |
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
## Best practices
|
|
118
|
+
|
|
119
|
+
Rules use RFC 2119 strength (**MUST** / **SHOULD** / **MUST NOT** / **SHOULD NOT**).
|
|
120
|
+
|
|
121
|
+
### When to show a tooltip
|
|
122
|
+
|
|
123
|
+
- **SHOULD** add a tooltip on **icon-only** controls when the icon alone is not universally understood (see Button content guidelines).
|
|
124
|
+
- **SHOULD** explain **why** a nearby control is disabled (forms pattern: disabled submit + tooltip).
|
|
125
|
+
- **SHOULD** keep tooltips **supplementary** — the interface must remain usable if the tooltip never appears.
|
|
126
|
+
- **MUST NOT** put essential instructions, links, or decisions only inside a tooltip.
|
|
127
|
+
|
|
128
|
+
### Implementation
|
|
129
|
+
|
|
130
|
+
- **MUST** provide content via `text` **or** the `tooltip-content` slot — omitting both means no tooltip is rendered.
|
|
131
|
+
- **MUST** use only documented props and enums from MCP / component types.
|
|
132
|
+
- **MUST** use Joy tokens — no custom `.joy-tooltip__content` chrome (background, shadow, radius).
|
|
133
|
+
- **MUST NOT** invent props (`variant`, `size`, `color`, …).
|
|
134
|
+
- **SHOULD** prefer the **`tooltip-content` slot** over `text` when content includes markup (`<strong>`, `<small>`). Use `text` only for plain, trusted strings (XSS risk if fed user input).
|
|
135
|
+
- **SHOULD** set a stable **`id`** when multiple tooltips on one view need unambiguous `aria-describedby` targeting.
|
|
136
|
+
- **SHOULD** use `event="click"` on touch-heavy layouts or when users must interact with tooltip content.
|
|
137
|
+
|
|
138
|
+
### Interaction
|
|
139
|
+
|
|
140
|
+
- **MUST NOT** cover the trigger or adjacent primary actions with the tooltip panel.
|
|
141
|
+
- **SHOULD** use default hover on desktop pointer UIs; evaluate click for mobile/tablet.
|
|
142
|
+
- **SHOULD** keep `delay` at default unless UX research shows a different timing need.
|
|
143
|
+
|
|
144
|
+
### Do / don’t
|
|
145
|
+
|
|
146
|
+
| Do | Don’t |
|
|
147
|
+
| --- | --- |
|
|
148
|
+
| Wrap `VJoyIconButton` + short label in tooltip | Duplicate the button’s visible label in the tooltip |
|
|
149
|
+
| `tooltip-content` slot for formatted copy | `text` with HTML strings from the API |
|
|
150
|
+
| `event="click"` when content is tappable | Hover-only tooltips with links or buttons inside |
|
|
151
|
+
| `tooltipWidth` for readable line length | Fixed `width` overrides in app CSS |
|
|
152
|
+
| Dialog/drawer for required reading | Long paragraphs in a tooltip |
|
|
153
|
+
|
|
154
|
+
---
|
|
155
|
+
|
|
156
|
+
## Content
|
|
157
|
+
|
|
158
|
+
Tooltips carry **short, contextual** copy. They enhance the UI; they don’t replace labels, helper text, or dialog body content.
|
|
159
|
+
|
|
160
|
+
### Copy formula
|
|
161
|
+
|
|
162
|
+
**Noun phrase** or **short imperative** that names the control or states the constraint:
|
|
163
|
+
|
|
164
|
+
- ✅ Put to trash
|
|
165
|
+
- ✅ Notifications
|
|
166
|
+
- ✅ Complete all required fields to submit
|
|
167
|
+
- ✅ Annual billing only
|
|
168
|
+
|
|
169
|
+
Avoid full sentences unless explaining a disabled state.
|
|
170
|
+
|
|
171
|
+
### Writing rules
|
|
172
|
+
|
|
173
|
+
| Strength | Rule |
|
|
174
|
+
| --- | --- |
|
|
175
|
+
| **MUST** | One idea per tooltip — no paragraphs |
|
|
176
|
+
| **MUST** | Match the trigger’s language (icon `label`, button text, field name) |
|
|
177
|
+
| **MUST NOT** | Repeat visible text already on the trigger |
|
|
178
|
+
| **MUST NOT** | Put links, CTAs, or decisions only in a tooltip |
|
|
179
|
+
| **MUST NOT** | Use tooltips for error validation (use inline field errors) |
|
|
180
|
+
| **SHOULD** | ≤ ~60 characters; wrap naturally within `tooltipWidth` |
|
|
181
|
+
| **SHOULD** | Sentence case; no trailing period for labels |
|
|
182
|
+
| **SHOULD** | Name the **reason** when explaining disabled controls |
|
|
183
|
+
| **SHOULD** | Use `<strong>` sparingly for one emphasized word (slot content) |
|
|
184
|
+
| **SHOULD** (FR) | Non-breaking spaces before `;`, `?`, `!`, and `:` |
|
|
185
|
+
|
|
186
|
+
### Patterns
|
|
187
|
+
|
|
188
|
+
**Icon buttons** — Tooltip text should mirror or shorten the control’s accessible name (`label` on `VJoyIconButton`). If the icon is universal (e.g. trash → delete), tooltip still helps but label remains mandatory.
|
|
189
|
+
|
|
190
|
+
**Disabled submit** — Pair with the disabled control: e.g. “Complete all required fields to submit”. Same message as inline form guidance is acceptable.
|
|
191
|
+
|
|
192
|
+
**Form labels** — `VJoyLabel` exposes a `label-tooltip` slot pattern; keep copy factual (format, eligibility), not marketing.
|
|
193
|
+
|
|
194
|
+
**Information helper** — For the 16px `(?)` pattern, tooltips are **text on hover**; richer patterns (badge, dialog on click) use other components — don’t overload `VJoyTooltip`.
|
|
195
|
+
|
|
196
|
+
---
|
|
197
|
+
|
|
198
|
+
## Accessibility
|
|
199
|
+
|
|
200
|
+
Behaviors (what must happen), not slogans.
|
|
201
|
+
|
|
202
|
+
| Behavior | Expectation |
|
|
203
|
+
| --- | --- |
|
|
204
|
+
| Role | Tooltip panel uses `role="tooltip"` |
|
|
205
|
+
| Relationship | Trigger wrapper sets `aria-describedby` to the tooltip `id` when open |
|
|
206
|
+
| Name | Trigger must have its own accessible name (`label` on icon buttons, visible text, `aria-label`) — the tooltip **describes**, it doesn’t replace the name |
|
|
207
|
+
| Keyboard | **Tab** away from the trigger closes an open tooltip; tooltips are not a separate tab stop |
|
|
208
|
+
| Hover | Default `mouseenter` — ensure equivalent info is not hover-only on keyboard-only flows when content is essential (use visible text or click mode) |
|
|
209
|
+
| Click mode | `event="click"` improves discoverability on touch; still provide a clear trigger name |
|
|
210
|
+
| Motion | Show/hide uses `--joy-transition-duration-default`; respect `prefers-reduced-motion` at app level if you add global overrides |
|
|
211
|
+
| Content | Don’t rely on color alone inside tooltip copy; inherited tokens meet contrast for default neutral theme |
|
|
212
|
+
|
|
213
|
+
Target: **WCAG 2.2 AA** where the product requires it.
|
|
214
|
+
|
|
215
|
+
---
|
|
216
|
+
|
|
217
|
+
## Examples
|
|
218
|
+
|
|
219
|
+
```vue
|
|
220
|
+
<script setup lang="ts">
|
|
221
|
+
import { VJoyTooltip, VJoyIconButton, VJoyButton } from '@maltjoy/core-vue'
|
|
222
|
+
</script>
|
|
223
|
+
|
|
224
|
+
<template>
|
|
225
|
+
<!-- Icon button — default hover, plain text -->
|
|
226
|
+
<VJoyTooltip text="Put to trash">
|
|
227
|
+
<VJoyIconButton icon="trash" variant="ghost" label="Put to trash" />
|
|
228
|
+
</VJoyTooltip>
|
|
229
|
+
|
|
230
|
+
<!-- Rich content via slot -->
|
|
231
|
+
<VJoyTooltip placement="top">
|
|
232
|
+
<VJoyIconButton icon="bell" variant="ghost" label="Notifications" />
|
|
233
|
+
<template #tooltip-content>
|
|
234
|
+
You have <strong>3</strong> unread messages
|
|
235
|
+
</template>
|
|
236
|
+
</VJoyTooltip>
|
|
237
|
+
|
|
238
|
+
<!-- Click trigger (touch / interactive content) -->
|
|
239
|
+
<VJoyTooltip event="click" text="More details about this setting">
|
|
240
|
+
<VJoyIconButton icon="info" variant="ghost" label="Setting information" />
|
|
241
|
+
</VJoyTooltip>
|
|
242
|
+
|
|
243
|
+
<!-- Disabled control explanation -->
|
|
244
|
+
<VJoyTooltip text="Complete all required fields to submit">
|
|
245
|
+
<VJoyButton variant="main" label="Submit" disabled />
|
|
246
|
+
</VJoyTooltip>
|
|
247
|
+
</template>
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
In Nuxt (or apps with auto-import), omit the import if `VJoyTooltip` is already global.
|
|
251
|
+
|
|
252
|
+
---
|
|
253
|
+
|
|
254
|
+
## Related
|
|
255
|
+
|
|
256
|
+
| Component | Use when |
|
|
257
|
+
| --- | --- |
|
|
258
|
+
| `VJoyIconButton` | Icon-only trigger — pair with tooltip when meaning isn’t obvious |
|
|
259
|
+
| `VJoyLabel` | Field label + optional `label-tooltip` slot |
|
|
260
|
+
| `VJoyButton` | Disabled actions that need a “why” on hover |
|
|
261
|
+
| `VJoyDialog` | User must read content or confirm a decision |
|
|
262
|
+
| `VJoyDrawer` | Supplementary panel with header actions (may embed tooltips in chrome) |
|
|
263
|
+
| `VJoyMenu` / `VJoyDropdown` | Action or navigation lists |
|
|
264
|
+
| `pushVJoySnackbar` | Transient feedback after an action |
|
|
265
|
+
|
|
266
|
+
---
|
|
267
|
+
|
|
268
|
+
## For agents
|
|
269
|
+
|
|
270
|
+
Optional for readers; **required** for vibe-coding quality. Maps to `agentDocumentBlocks` in [`JoyTooltip.dsds.json`](./JoyTooltip.dsds.json).
|
|
271
|
+
|
|
272
|
+
### Pick the right component
|
|
273
|
+
|
|
274
|
+
| If the intent is… | Emit… | Do not emit… |
|
|
275
|
+
| --- | --- | --- |
|
|
276
|
+
| Short hint on hover/click for one trigger | `VJoyTooltip` | Custom `position: absolute` div + title attr |
|
|
277
|
+
| Icon-only control | `VJoyIconButton` inside `VJoyTooltip` | `VJoyButton` with only an icon |
|
|
278
|
+
| Required reading or confirm/cancel | `VJoyDialog` | Long tooltip copy |
|
|
279
|
+
| Menu of actions | `VJoyMenu` / `VJoyDropdown` | Tooltip with fake buttons |
|
|
280
|
+
| Post-action feedback | `pushVJoySnackbar` | Tooltip that stays after click |
|
|
281
|
+
| Legacy colored variant | Neutral `VJoyTooltip` only | `variant="primary"` / `variant="secondary"` |
|
|
282
|
+
|
|
283
|
+
### Hard rules
|
|
284
|
+
|
|
285
|
+
1. **MUST** call `joy_get_component_info("VJoyTooltip")` (or read `VJoyTooltip.vue` types) before generating props.
|
|
286
|
+
2. **MUST** wrap exactly one trigger in the default slot.
|
|
287
|
+
3. **MUST** supply `text` or `#tooltip-content` — never an empty tooltip.
|
|
288
|
+
4. **MUST NOT** invent props (`variant`, `size`, `open`, `theme`, …).
|
|
289
|
+
5. **MUST NOT** pass HTML through `text` from API/user data — use the slot or sanitize upstream.
|
|
290
|
+
6. **MUST NOT** override `.joy-tooltip__content` / `__arrow` colors, shadow, or radius in app CSS.
|
|
291
|
+
7. **SHOULD** set `event="click"` when the tooltip contains interactive elements or on mobile-first screens.
|
|
292
|
+
8. **SHOULD** reuse the icon button’s `label` text in the tooltip when clarifying the same action.
|
|
293
|
+
9. **SHOULD NOT** use `show` in production pages (Storybook/tests only).
|
|
294
|
+
|
|
295
|
+
### Checklist
|
|
296
|
+
|
|
297
|
+
- [ ] Correct component (or named alternative from table above)
|
|
298
|
+
- [ ] Props / enums from MCP only (`placement`, `event`, `delay`, `tooltipWidth`, `id`, `text`)
|
|
299
|
+
- [ ] Content via `text` (plain) or `#tooltip-content` (markup)
|
|
300
|
+
- [ ] No `variant` / no invented props / no custom tooltip chrome CSS
|
|
301
|
+
- [ ] Trigger has its own accessible name (`label`, visible text, or `aria-label`)
|
|
302
|
+
- [ ] Copy is short and non-essential; disabled/menu/dialog cases handled elsewhere if needed
|
|
303
|
+
- [ ] `event="click"` when content is interactive or hover is insufficient
|
|
304
|
+
|
|
305
|
+
---
|
|
306
|
+
|
|
307
|
+
## DSDS mapping
|
|
308
|
+
|
|
309
|
+
This Markdown mirrors [`JoyTooltip.dsds.json`](./JoyTooltip.dsds.json) (DSDS **0.15.2**).
|
|
310
|
+
|
|
311
|
+
| Section here | DSDS block |
|
|
312
|
+
| --- | --- |
|
|
313
|
+
| When to use / not | `use-cases` |
|
|
314
|
+
| Anatomy / placement | `anatomy` |
|
|
315
|
+
| Placements / triggers | `variants` (behavioral) |
|
|
316
|
+
| States | `states` |
|
|
317
|
+
| Best practices / content rules | `guidelines` (+ `content`) |
|
|
318
|
+
| Accessibility | `accessibility` |
|
|
319
|
+
| Examples | `sections` |
|
|
320
|
+
| For agents | `agentDocumentBlocks` |
|
|
321
|
+
| Props detail | `api` in JSON + Joy MCP |
|
|
322
|
+
| Token sizing | `design-specifications` in JSON |
|