@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,311 @@
|
|
|
1
|
+
---
|
|
2
|
+
component: VJoyTagsList
|
|
3
|
+
status: draft
|
|
4
|
+
language: en
|
|
5
|
+
dsds: JoyTagsList.dsds.json
|
|
6
|
+
dsdsVersion: "0.15.2"
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Tags list
|
|
10
|
+
|
|
11
|
+
Use **`VJoyTagsList`** when you need a horizontal, wrapping row of **`VJoyTag`** chips driven from data — for example skills on a profile, applied filters, selected categories, or removable tokens.
|
|
12
|
+
|
|
13
|
+
It applies shared layout (`flex`, wrap, gap), optional alignment, list-level `variant` / `removable` / `selectable` defaults, and `v-model` for multi-select toggling. Per-tag options in the `tags` array can override those defaults.
|
|
14
|
+
|
|
15
|
+
| | |
|
|
16
|
+
| --- | --- |
|
|
17
|
+
| **Code** | `VJoyTagsList` from `@maltjoy/core-vue` |
|
|
18
|
+
| **Design** | [Figma — Joy Core Design System](https://www.figma.com/design/jfndp2QBJGS9yeuWbeGuvD/) |
|
|
19
|
+
| **Storybook** | [VJoyTagsList docs](https://doc.malt.tech/joy-storybook/?path=/docs/components-view-vjoytagslist--docs) |
|
|
20
|
+
| **DSDS (machine)** | [`JoyTagsList.dsds.json`](./JoyTagsList.dsds.json) |
|
|
21
|
+
| **Live API** | `joy_get_component_info("VJoyTagsList")` |
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## When to use this component
|
|
26
|
+
|
|
27
|
+
Use a tags list when several labels should appear together as chips with consistent spacing and alignment — especially when the set comes from an array and you want list-level styling or selection/removal behavior without hand-rolling a flex wrapper.
|
|
28
|
+
|
|
29
|
+
Typical jobs: show assigned skills or technologies, display active filters, let users toggle filter chips on/off, or present removable tokens after a search or tags-input flow.
|
|
30
|
+
|
|
31
|
+
### When not to use this component
|
|
32
|
+
|
|
33
|
+
| Need | Use instead |
|
|
34
|
+
| --- | --- |
|
|
35
|
+
| A single standalone chip | `VJoyTag` |
|
|
36
|
+
| Full control over layout, drag-and-drop, or one-off tag markup | `VJoyTag` (or several) inside `VJoyWrapper` — the metadata explicitly allows dropping `VJoyTagsList` for flexibility |
|
|
37
|
+
| Typing and adding new tags in a form field | `VJoyTagsInput` |
|
|
38
|
+
| Choosing exactly one option from a list | `VJoyRadio` / `VJoyRadioGroup` |
|
|
39
|
+
| Multi-select inside a dropdown | `VJoySelect` (multi) or `VJoyCheckboxGroup` |
|
|
40
|
+
| Custom flex row / ad-hoc chip CSS | Still use `VJoyTagsList` or `VJoyTag` + Joy tokens |
|
|
41
|
+
|
|
42
|
+
> **Note:** `selectable` and `removable` are **not compatible** on the same list. Pick one interaction model per instance.
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## How it works
|
|
47
|
+
|
|
48
|
+
`VJoyTagsList` renders one `VJoyTag` per entry in `tags`, forwarding each tag’s props and merging list-level defaults. Selection state is driven by `v-model` (`modelValue` as an array of tag `value`s). Removal emits `removeTag` with the removed tag’s `value` — the parent must update `tags`.
|
|
49
|
+
|
|
50
|
+
### Anatomy
|
|
51
|
+
|
|
52
|
+
| Part | Required? | What it is |
|
|
53
|
+
| --- | --- | --- |
|
|
54
|
+
| Root container | Yes | `.joy-tags-list` flex wrapper with alignment modifier |
|
|
55
|
+
| `VJoyTag` (per item) | Yes | One chip per `tags` entry; label from `tag.label` unless `tag` slot overrides |
|
|
56
|
+
| `tag` slot | No | Custom content per tag; forwarded tag props as slot props |
|
|
57
|
+
| Gap | Yes | `--joy-core-spacing-4` between tags — don’t hardcode margins in apps |
|
|
58
|
+
|
|
59
|
+
### Default values
|
|
60
|
+
|
|
61
|
+
- `align` defaults to **`left`**
|
|
62
|
+
- `variant` defaults to **`primary`** (applied to every tag unless a tag sets its own `variant`)
|
|
63
|
+
- `removable` defaults to **`false`**
|
|
64
|
+
- `selectable` defaults to **`false`**
|
|
65
|
+
- `tags` defaults to **`[]`**
|
|
66
|
+
- `modelValue` has **no default** — bind `v-model` when using selectable tags
|
|
67
|
+
|
|
68
|
+
Props, events, and slots: use Joy MCP or Storybook — this page focuses on **when** and **how**, not a full API dump.
|
|
69
|
+
|
|
70
|
+
### Selection and removal
|
|
71
|
+
|
|
72
|
+
- **Selectable** — set `selectable` (or per-tag `selectable`) **and** bind `v-model`. Each tag **must** have a unique `value`. Toggling a tag updates `modelValue` with that `value` added or removed.
|
|
73
|
+
- **Removable** — set `removable` (or per-tag `removable`) and listen for `@removeTag`. Update the `tags` array in the parent; the list does not remove items by itself.
|
|
74
|
+
- **Per-tag overrides** — any `IJoyTag` field on a `tags` entry overrides the list default (`variant`, `selectable`, `removable`, `size`, `draggable`, etc.).
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## Variants
|
|
79
|
+
|
|
80
|
+
List-level `variant` sets the default chip style for all tags. Override individual entries with `tags[i].variant` when one chip needs different emphasis (e.g. one `important` tag in a `secondary` list).
|
|
81
|
+
|
|
82
|
+
Choose variant by **meaning**, not decoration.
|
|
83
|
+
|
|
84
|
+
| Variant | Use when |
|
|
85
|
+
| --- | --- |
|
|
86
|
+
| `primary` | Default product chips; supports **selectable** styling |
|
|
87
|
+
| `secondary` | Lower emphasis; supports **selectable** styling |
|
|
88
|
+
| `important` | Critical or high-attention labels |
|
|
89
|
+
| `inactive` | Deprecated, archived, or unavailable items |
|
|
90
|
+
| `pending` | Awaiting action or in-progress state |
|
|
91
|
+
| `pricing` | Price or billing-related labels |
|
|
92
|
+
| `special` | Promotional or highlighted offers |
|
|
93
|
+
| `empty` | Placeholder or “no value” styling |
|
|
94
|
+
| `ai-primary` / `ai-secondary` | Tags that are explicitly part of an AI feature |
|
|
95
|
+
|
|
96
|
+
### Selectable styling constraint
|
|
97
|
+
|
|
98
|
+
On `VJoyTag`, **selectable interaction only applies to `primary` and `secondary`**. Other variants render as chips but won’t toggle selection on click even if `selectable` is true.
|
|
99
|
+
|
|
100
|
+
### Not in the API: list-level `size`
|
|
101
|
+
|
|
102
|
+
There is no `size` prop on `VJoyTagsList`. Set `size` on each tag object (`small`, `medium`, `large`, `xsmall`, `xxlarge`) when density must differ within the list.
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## Sizes
|
|
107
|
+
|
|
108
|
+
`VJoyTagsList` has **no size API**. Density comes from per-tag `size` on `VJoyTag` entries (default **`medium`** on each tag).
|
|
109
|
+
|
|
110
|
+
| Tag `size` | Use when |
|
|
111
|
+
| --- | --- |
|
|
112
|
+
| `medium` | Default product chips |
|
|
113
|
+
| `small` / `xsmall` | Dense toolbars, tables, or filter rows |
|
|
114
|
+
| `large` / `xxlarge` | Marketing or hero-scale emphasis (rare for lists) |
|
|
115
|
+
|
|
116
|
+
Layout gap is fixed via `--joy-core-spacing-4` on the list — **don’t** hardcode pixel gaps between tags in product CSS.
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## States
|
|
121
|
+
|
|
122
|
+
| State | What the user sees / can do |
|
|
123
|
+
| --- | --- |
|
|
124
|
+
| Default (read-only) | Chips in a wrapping row; no remove icon; not toggleable |
|
|
125
|
+
| Selected (`v-model` + `selectable`) | Matching tags show selected styling (`joy-tag__selected`) |
|
|
126
|
+
| Removable | Cross icon on each removable tag; click emits `removeTag` |
|
|
127
|
+
| Hover / focus | Per `VJoyTag` — selectable tags use `role="button"` and `tabindex="0"` |
|
|
128
|
+
| Disabled (per tag) | Set `disabled: true` on a tag entry; click and selection are blocked |
|
|
129
|
+
| Custom `tag` slot | Full control of chip content; **you** must reimplement remove/select/drag if needed |
|
|
130
|
+
|
|
131
|
+
When `removable` is true at list level, selected styling is suppressed (`tagIsSelected` returns false).
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## Best practices
|
|
136
|
+
|
|
137
|
+
Rules use RFC 2119 strength (**MUST** / **SHOULD** / **MUST NOT** / **SHOULD NOT**).
|
|
138
|
+
|
|
139
|
+
### Data and interaction
|
|
140
|
+
|
|
141
|
+
- **MUST** give every tag a unique **`value`** when using `selectable` or `removable`.
|
|
142
|
+
- **MUST** bind **`v-model`** when tags should toggle selection; `selectable` alone does nothing without `modelValue`.
|
|
143
|
+
- **MUST** handle **`@removeTag`** and update the `tags` source — the list only emits the event.
|
|
144
|
+
- **MUST NOT** combine **`selectable`** and **`removable`** on the same list.
|
|
145
|
+
- **SHOULD** keep tag sets **scannable** (roughly under ~10 visible chips before considering truncation, “show more”, or a summary).
|
|
146
|
+
- **SHOULD** use **`secondary`** for filter chips and **`primary`** for assigned metadata unless design specifies otherwise.
|
|
147
|
+
|
|
148
|
+
### Implementation
|
|
149
|
+
|
|
150
|
+
- **MUST** use only documented props and enums from MCP or `JoyTagsList.types.ts` / `JoyTag.types.ts`.
|
|
151
|
+
- **MUST** use Joy tokens — no custom `.joy-tags-list` or `.joy-tag` chrome overrides.
|
|
152
|
+
- **MUST NOT** invent list-level props (`size`, `gap`, `color`, …).
|
|
153
|
+
- **SHOULD** prefer list-level `variant` / `removable` / `selectable` and override per tag only when needed.
|
|
154
|
+
- **SHOULD** use raw **`VJoyTag` + `VJoyWrapper`** when you need drag-and-drop reordering or non-standard layout — `draggable` on a tag only shows a drag icon; it does not implement sorting.
|
|
155
|
+
|
|
156
|
+
### Custom slot
|
|
157
|
+
|
|
158
|
+
- **MUST** reimplement remove, select, and drag behavior yourself when using the **`tag` slot — default `VJoyTag` behaviors for `draggable` / `removable` are bypassed.
|
|
159
|
+
- **SHOULD** avoid the `tag` slot unless the default label + icon layout is insufficient.
|
|
160
|
+
|
|
161
|
+
### Do / don’t
|
|
162
|
+
|
|
163
|
+
| Do | Don’t |
|
|
164
|
+
| --- | --- |
|
|
165
|
+
| `v-model` + `selectable` + unique `value`s | `selectable` without `v-model` |
|
|
166
|
+
| `@removeTag` → filter `tags` in parent | Expect the list to mutate `tags` automatically |
|
|
167
|
+
| List `variant="secondary"` for filters | Mix `selectable` and `removable` on one list |
|
|
168
|
+
| Per-tag `variant` for one outlier chip | Different list components for the same chip row |
|
|
169
|
+
| `VJoyTagsInput` for adding tags | `VJoyTagsList` as a free-text input |
|
|
170
|
+
|
|
171
|
+
---
|
|
172
|
+
|
|
173
|
+
## Accessibility
|
|
174
|
+
|
|
175
|
+
Behaviors (what must happen), not slogans.
|
|
176
|
+
|
|
177
|
+
| Behavior | Expectation |
|
|
178
|
+
| --- | --- |
|
|
179
|
+
| Structure | Plain `div` list; semantics come from each `VJoyTag` |
|
|
180
|
+
| Selectable tags | `role="button"`, `tabindex="0"` on `VJoyTag`; toggle via click (keyboard activation follows tag implementation) |
|
|
181
|
+
| Removable tags | Remove control is a `VJoyIcon` with `role="button"`; `@keydown.enter` removes |
|
|
182
|
+
| Name | Each chip’s accessible name should come from visible `label` text (or meaningful slot content) |
|
|
183
|
+
| Selection state | Don’t rely on color alone — selected chips use `joy-tag__selected` styling; ensure contrast meets product requirements |
|
|
184
|
+
| Disabled tags | Set `disabled: true` on the tag entry; don’t only dim with CSS |
|
|
185
|
+
|
|
186
|
+
Target: **WCAG 2.2 AA** where the product requires it.
|
|
187
|
+
|
|
188
|
+
---
|
|
189
|
+
|
|
190
|
+
## Examples
|
|
191
|
+
|
|
192
|
+
```vue
|
|
193
|
+
<script setup lang="ts">
|
|
194
|
+
import { ref } from 'vue'
|
|
195
|
+
import { VJoyTagsList } from '@maltjoy/core-vue'
|
|
196
|
+
import type { TJoyTagsList, TJoyTagsListModel } from '@maltjoy/core-vue'
|
|
197
|
+
|
|
198
|
+
const skills = ref<TJoyTagsList>([
|
|
199
|
+
{ value: 'vue', label: 'Vue.js' },
|
|
200
|
+
{ value: 'ts', label: 'TypeScript' },
|
|
201
|
+
{ value: 'design', label: 'Design systems' },
|
|
202
|
+
])
|
|
203
|
+
|
|
204
|
+
const selectedFilters = ref<TJoyTagsListModel>(['vue'])
|
|
205
|
+
|
|
206
|
+
const filters = ref<TJoyTagsList>([
|
|
207
|
+
{ value: 'vue', label: 'Vue.js' },
|
|
208
|
+
{ value: 'ts', label: 'TypeScript' },
|
|
209
|
+
{ value: 'design', label: 'Design systems' },
|
|
210
|
+
])
|
|
211
|
+
|
|
212
|
+
function onRemoveTag(tagValue: string | number | undefined) {
|
|
213
|
+
filters.value = filters.value.filter((t) => t.value !== tagValue)
|
|
214
|
+
}
|
|
215
|
+
</script>
|
|
216
|
+
|
|
217
|
+
<template>
|
|
218
|
+
<!-- Read-only metadata -->
|
|
219
|
+
<VJoyTagsList variant="secondary" :tags="skills" />
|
|
220
|
+
|
|
221
|
+
<!-- Toggleable filter chips -->
|
|
222
|
+
<VJoyTagsList
|
|
223
|
+
v-model="selectedFilters"
|
|
224
|
+
variant="secondary"
|
|
225
|
+
selectable
|
|
226
|
+
:tags="skills"
|
|
227
|
+
/>
|
|
228
|
+
|
|
229
|
+
<!-- Removable tokens (parent updates tags) -->
|
|
230
|
+
<VJoyTagsList
|
|
231
|
+
variant="secondary"
|
|
232
|
+
removable
|
|
233
|
+
:tags="filters"
|
|
234
|
+
@remove-tag="onRemoveTag"
|
|
235
|
+
/>
|
|
236
|
+
|
|
237
|
+
<!-- Centered row -->
|
|
238
|
+
<VJoyTagsList align="center" variant="primary" :tags="skills" />
|
|
239
|
+
</template>
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
In Nuxt (or apps with auto-import), omit the import if `VJoyTagsList` is already global.
|
|
243
|
+
|
|
244
|
+
---
|
|
245
|
+
|
|
246
|
+
## Related
|
|
247
|
+
|
|
248
|
+
| Component | Use when |
|
|
249
|
+
| --- | --- |
|
|
250
|
+
| `VJoyTag` | A single chip, or manual lists with custom layout |
|
|
251
|
+
| `VJoyTagsInput` | Users type and add tags in a form field |
|
|
252
|
+
| `VJoyWrapper` | Spacing wrapper when composing tags manually |
|
|
253
|
+
| `VJoySelectableItemGroup` | Selectable list rows rather than chips |
|
|
254
|
+
| `VJoyCheckbox` / `VJoyCheckboxGroup` | Multi-select with checkbox affordance |
|
|
255
|
+
|
|
256
|
+
---
|
|
257
|
+
|
|
258
|
+
## For agents
|
|
259
|
+
|
|
260
|
+
Maps to `agentDocumentBlocks` in [`JoyTagsList.dsds.json`](./JoyTagsList.dsds.json). Humans can skip this section.
|
|
261
|
+
|
|
262
|
+
### Pick the right component
|
|
263
|
+
|
|
264
|
+
| If the intent is… | Emit… | Do not emit… |
|
|
265
|
+
| --- | --- | --- |
|
|
266
|
+
| Display chips from an array | `VJoyTagsList` | Manual `div` + custom chip CSS |
|
|
267
|
+
| One chip | `VJoyTag` | `VJoyTagsList` with one item |
|
|
268
|
+
| User adds tags by typing | `VJoyTagsInput` | `VJoyTagsList` with a text field |
|
|
269
|
+
| Toggle filters on/off | `VJoyTagsList` + `v-model` + `selectable` | `removable` on the same list |
|
|
270
|
+
| Remove chips | `VJoyTagsList` + `removable` + `@removeTag` | `selectable` on the same list |
|
|
271
|
+
| Full layout / DnD control | `VJoyTag` in `VJoyWrapper` | `VJoyTagsList` + heavy `tag` slot hacks |
|
|
272
|
+
|
|
273
|
+
### Hard rules
|
|
274
|
+
|
|
275
|
+
1. **MUST** call `joy_get_component_info("VJoyTagsList")` (or read types) before generating props.
|
|
276
|
+
2. **MUST** include unique `value` on each tag when `selectable` or `removable` is used.
|
|
277
|
+
3. **MUST** bind `v-model` for selectable lists.
|
|
278
|
+
4. **MUST** handle `@removeTag` and update `tags` in the parent for removable lists.
|
|
279
|
+
5. **MUST NOT** set `selectable` and `removable` together on one list.
|
|
280
|
+
6. **MUST NOT** invent props (`size`, `gap`, `color`, …) on `VJoyTagsList`.
|
|
281
|
+
7. **MUST NOT** override `.joy-tags-list` or `.joy-tag` layout/colors in product CSS.
|
|
282
|
+
8. **SHOULD** use `primary` or `secondary` variants when chips are selectable.
|
|
283
|
+
|
|
284
|
+
### Checklist
|
|
285
|
+
|
|
286
|
+
- [ ] Correct component (`VJoyTagsList` or named alternative)
|
|
287
|
+
- [ ] Props / enums from MCP only
|
|
288
|
+
- [ ] `tags` entries have `label`; `value` when selectable or removable
|
|
289
|
+
- [ ] `v-model` present when `selectable` is true
|
|
290
|
+
- [ ] Not mixing `selectable` and `removable`
|
|
291
|
+
- [ ] `@removeTag` wired when `removable` is true
|
|
292
|
+
- [ ] No custom chip/list chrome CSS
|
|
293
|
+
- [ ] `tag` slot only when custom content is required (and behaviors reimplemented if needed)
|
|
294
|
+
|
|
295
|
+
---
|
|
296
|
+
|
|
297
|
+
## DSDS mapping
|
|
298
|
+
|
|
299
|
+
This Markdown mirrors [`JoyTagsList.dsds.json`](./JoyTagsList.dsds.json) (DSDS **0.15.2**).
|
|
300
|
+
|
|
301
|
+
| Section here | DSDS block |
|
|
302
|
+
| --- | --- |
|
|
303
|
+
| When to use / not | `use-cases` |
|
|
304
|
+
| Anatomy | `anatomy` |
|
|
305
|
+
| Variants / sizes | `variants` |
|
|
306
|
+
| States | `states` |
|
|
307
|
+
| Best practices | `guidelines` |
|
|
308
|
+
| Accessibility | `accessibility` |
|
|
309
|
+
| Examples | `sections` |
|
|
310
|
+
| For agents | `agentDocumentBlocks` |
|
|
311
|
+
| Props detail | `api` in JSON + Joy MCP |
|
|
@@ -80,7 +80,7 @@
|
|
|
80
80
|
"type": "string | undefined",
|
|
81
81
|
"declarations": [
|
|
82
82
|
{
|
|
83
|
-
"file": "/
|
|
83
|
+
"file": "/Users/pierrereynaud/Documents/Work/design-system/packages/core-vue/src/components/JoyTag/VJoyTag.vue",
|
|
84
84
|
"range": [
|
|
85
85
|
796,
|
|
86
86
|
811
|
|
@@ -105,7 +105,7 @@
|
|
|
105
105
|
"type": "TJoyTagSizes | undefined",
|
|
106
106
|
"declarations": [
|
|
107
107
|
{
|
|
108
|
-
"file": "/
|
|
108
|
+
"file": "/Users/pierrereynaud/Documents/Work/design-system/packages/core-vue/src/components/JoyTag/VJoyTag.vue",
|
|
109
109
|
"range": [
|
|
110
110
|
820,
|
|
111
111
|
840
|
|
@@ -134,7 +134,7 @@
|
|
|
134
134
|
"type": "TJoyTagVariants | undefined",
|
|
135
135
|
"declarations": [
|
|
136
136
|
{
|
|
137
|
-
"file": "/
|
|
137
|
+
"file": "/Users/pierrereynaud/Documents/Work/design-system/packages/core-vue/src/components/JoyTag/VJoyTag.vue",
|
|
138
138
|
"range": [
|
|
139
139
|
849,
|
|
140
140
|
875
|
|
@@ -168,7 +168,7 @@
|
|
|
168
168
|
"type": "boolean | undefined",
|
|
169
169
|
"declarations": [
|
|
170
170
|
{
|
|
171
|
-
"file": "/
|
|
171
|
+
"file": "/Users/pierrereynaud/Documents/Work/design-system/packages/core-vue/src/components/JoyTag/VJoyTag.vue",
|
|
172
172
|
"range": [
|
|
173
173
|
1003,
|
|
174
174
|
1023
|
|
@@ -194,7 +194,7 @@
|
|
|
194
194
|
"type": "boolean | undefined",
|
|
195
195
|
"declarations": [
|
|
196
196
|
{
|
|
197
|
-
"file": "/
|
|
197
|
+
"file": "/Users/pierrereynaud/Documents/Work/design-system/packages/core-vue/src/components/JoyTag/VJoyTag.vue",
|
|
198
198
|
"range": [
|
|
199
199
|
1082,
|
|
200
200
|
1102
|
|
@@ -212,7 +212,7 @@
|
|
|
212
212
|
"type": "boolean | undefined",
|
|
213
213
|
"declarations": [
|
|
214
214
|
{
|
|
215
|
-
"file": "/
|
|
215
|
+
"file": "/Users/pierrereynaud/Documents/Work/design-system/packages/core-vue/src/components/JoyTag/VJoyTag.vue",
|
|
216
216
|
"range": [
|
|
217
217
|
1111,
|
|
218
218
|
1130
|
|
@@ -230,7 +230,7 @@
|
|
|
230
230
|
"type": "boolean | undefined",
|
|
231
231
|
"declarations": [
|
|
232
232
|
{
|
|
233
|
-
"file": "/
|
|
233
|
+
"file": "/Users/pierrereynaud/Documents/Work/design-system/packages/core-vue/src/components/JoyTag/VJoyTag.vue",
|
|
234
234
|
"range": [
|
|
235
235
|
1224,
|
|
236
236
|
1245
|
|
@@ -248,7 +248,7 @@
|
|
|
248
248
|
"type": "boolean | undefined",
|
|
249
249
|
"declarations": [
|
|
250
250
|
{
|
|
251
|
-
"file": "/
|
|
251
|
+
"file": "/Users/pierrereynaud/Documents/Work/design-system/packages/core-vue/src/components/JoyTag/VJoyTag.vue",
|
|
252
252
|
"range": [
|
|
253
253
|
1312,
|
|
254
254
|
1327
|
|
@@ -266,7 +266,7 @@
|
|
|
266
266
|
"type": "string | number | undefined",
|
|
267
267
|
"declarations": [
|
|
268
268
|
{
|
|
269
|
-
"file": "/
|
|
269
|
+
"file": "/Users/pierrereynaud/Documents/Work/design-system/packages/core-vue/src/components/JoyTag/VJoyTag.vue",
|
|
270
270
|
"range": [
|
|
271
271
|
1420,
|
|
272
272
|
1444
|
|
@@ -292,7 +292,7 @@
|
|
|
292
292
|
"type": "boolean | undefined",
|
|
293
293
|
"declarations": [
|
|
294
294
|
{
|
|
295
|
-
"file": "/
|
|
295
|
+
"file": "/Users/pierrereynaud/Documents/Work/design-system/packages/core-vue/src/components/JoyTag/VJoyTag.vue",
|
|
296
296
|
"range": [
|
|
297
297
|
1497,
|
|
298
298
|
1521
|
|
@@ -310,7 +310,7 @@
|
|
|
310
310
|
"type": "boolean | undefined",
|
|
311
311
|
"declarations": [
|
|
312
312
|
{
|
|
313
|
-
"file": "/
|
|
313
|
+
"file": "/Users/pierrereynaud/Documents/Work/design-system/packages/core-vue/src/components/JoyTag/VJoyTag.vue",
|
|
314
314
|
"range": [
|
|
315
315
|
1530,
|
|
316
316
|
1549
|
|
@@ -328,7 +328,7 @@
|
|
|
328
328
|
"type": "string | undefined",
|
|
329
329
|
"declarations": [
|
|
330
330
|
{
|
|
331
|
-
"file": "/
|
|
331
|
+
"file": "/Users/pierrereynaud/Documents/Work/design-system/packages/core-vue/src/components/JoyTag/VJoyTag.vue",
|
|
332
332
|
"range": [
|
|
333
333
|
1558,
|
|
334
334
|
1570
|
|
@@ -367,7 +367,7 @@
|
|
|
367
367
|
"type": "string | number | undefined",
|
|
368
368
|
"declarations": [
|
|
369
369
|
{
|
|
370
|
-
"file": "/
|
|
370
|
+
"file": "/Users/pierrereynaud/Documents/Work/design-system/packages/core-vue/src/components/JoyTag/JoyTag.types.ts",
|
|
371
371
|
"range": [
|
|
372
372
|
503,
|
|
373
373
|
532
|
|
@@ -434,7 +434,7 @@
|
|
|
434
434
|
"type": "boolean",
|
|
435
435
|
"declarations": [
|
|
436
436
|
{
|
|
437
|
-
"file": "/
|
|
437
|
+
"file": "/Users/pierrereynaud/Documents/Work/design-system/packages/core-vue/src/components/JoyTag/JoyTag.types.ts",
|
|
438
438
|
"range": [
|
|
439
439
|
409,
|
|
440
440
|
427
|
|
@@ -459,7 +459,7 @@
|
|
|
459
459
|
"type": "string | number | undefined",
|
|
460
460
|
"declarations": [
|
|
461
461
|
{
|
|
462
|
-
"file": "/
|
|
462
|
+
"file": "/Users/pierrereynaud/Documents/Work/design-system/packages/core-vue/src/components/JoyTag/JoyTag.types.ts",
|
|
463
463
|
"range": [
|
|
464
464
|
432,
|
|
465
465
|
461
|
|
@@ -484,7 +484,7 @@
|
|
|
484
484
|
"type": "PropertyKey | undefined",
|
|
485
485
|
"declarations": [
|
|
486
486
|
{
|
|
487
|
-
"file": "/
|
|
487
|
+
"file": "/Users/pierrereynaud/Documents/Work/design-system/node_modules/.pnpm/@vue+runtime-core@3.5.25/node_modules/@vue/runtime-core/dist/runtime-core.d.ts",
|
|
488
488
|
"range": [
|
|
489
489
|
65064,
|
|
490
490
|
65082
|
|
@@ -511,7 +511,7 @@
|
|
|
511
511
|
"type": "VNodeRef | undefined",
|
|
512
512
|
"declarations": [
|
|
513
513
|
{
|
|
514
|
-
"file": "/
|
|
514
|
+
"file": "/Users/pierrereynaud/Documents/Work/design-system/node_modules/.pnpm/@vue+runtime-core@3.5.25/node_modules/@vue/runtime-core/dist/runtime-core.d.ts",
|
|
515
515
|
"range": [
|
|
516
516
|
65087,
|
|
517
517
|
65102
|
|
@@ -542,7 +542,7 @@
|
|
|
542
542
|
"type": "boolean | undefined",
|
|
543
543
|
"declarations": [
|
|
544
544
|
{
|
|
545
|
-
"file": "/
|
|
545
|
+
"file": "/Users/pierrereynaud/Documents/Work/design-system/node_modules/.pnpm/@vue+runtime-core@3.5.25/node_modules/@vue/runtime-core/dist/runtime-core.d.ts",
|
|
546
546
|
"range": [
|
|
547
547
|
65107,
|
|
548
548
|
65125
|
|
@@ -560,7 +560,7 @@
|
|
|
560
560
|
"type": "string | undefined",
|
|
561
561
|
"declarations": [
|
|
562
562
|
{
|
|
563
|
-
"file": "/
|
|
563
|
+
"file": "/Users/pierrereynaud/Documents/Work/design-system/node_modules/.pnpm/@vue+runtime-core@3.5.25/node_modules/@vue/runtime-core/dist/runtime-core.d.ts",
|
|
564
564
|
"range": [
|
|
565
565
|
65130,
|
|
566
566
|
65147
|
|
@@ -578,7 +578,7 @@
|
|
|
578
578
|
"type": "VNodeMountHook | VNodeMountHook[] | undefined",
|
|
579
579
|
"declarations": [
|
|
580
580
|
{
|
|
581
|
-
"file": "/
|
|
581
|
+
"file": "/Users/pierrereynaud/Documents/Work/design-system/node_modules/.pnpm/@vue+runtime-core@3.5.25/node_modules/@vue/runtime-core/dist/runtime-core.d.ts",
|
|
582
582
|
"range": [
|
|
583
583
|
65152,
|
|
584
584
|
65207
|
|
@@ -630,7 +630,7 @@
|
|
|
630
630
|
"type": "VNodeMountHook | VNodeMountHook[] | undefined",
|
|
631
631
|
"declarations": [
|
|
632
632
|
{
|
|
633
|
-
"file": "/
|
|
633
|
+
"file": "/Users/pierrereynaud/Documents/Work/design-system/node_modules/.pnpm/@vue+runtime-core@3.5.25/node_modules/@vue/runtime-core/dist/runtime-core.d.ts",
|
|
634
634
|
"range": [
|
|
635
635
|
65212,
|
|
636
636
|
65263
|
|
@@ -648,7 +648,7 @@
|
|
|
648
648
|
"type": "VNodeUpdateHook | VNodeUpdateHook[] | undefined",
|
|
649
649
|
"declarations": [
|
|
650
650
|
{
|
|
651
|
-
"file": "/
|
|
651
|
+
"file": "/Users/pierrereynaud/Documents/Work/design-system/node_modules/.pnpm/@vue+runtime-core@3.5.25/node_modules/@vue/runtime-core/dist/runtime-core.d.ts",
|
|
652
652
|
"range": [
|
|
653
653
|
65268,
|
|
654
654
|
65326
|
|
@@ -688,7 +688,7 @@
|
|
|
688
688
|
"type": "VNodeUpdateHook | VNodeUpdateHook[] | undefined",
|
|
689
689
|
"declarations": [
|
|
690
690
|
{
|
|
691
|
-
"file": "/
|
|
691
|
+
"file": "/Users/pierrereynaud/Documents/Work/design-system/node_modules/.pnpm/@vue+runtime-core@3.5.25/node_modules/@vue/runtime-core/dist/runtime-core.d.ts",
|
|
692
692
|
"range": [
|
|
693
693
|
65331,
|
|
694
694
|
65384
|
|
@@ -706,7 +706,7 @@
|
|
|
706
706
|
"type": "VNodeMountHook | VNodeMountHook[] | undefined",
|
|
707
707
|
"declarations": [
|
|
708
708
|
{
|
|
709
|
-
"file": "/
|
|
709
|
+
"file": "/Users/pierrereynaud/Documents/Work/design-system/node_modules/.pnpm/@vue+runtime-core@3.5.25/node_modules/@vue/runtime-core/dist/runtime-core.d.ts",
|
|
710
710
|
"range": [
|
|
711
711
|
65389,
|
|
712
712
|
65446
|
|
@@ -724,7 +724,7 @@
|
|
|
724
724
|
"type": "VNodeMountHook | VNodeMountHook[] | undefined",
|
|
725
725
|
"declarations": [
|
|
726
726
|
{
|
|
727
|
-
"file": "/
|
|
727
|
+
"file": "/Users/pierrereynaud/Documents/Work/design-system/node_modules/.pnpm/@vue+runtime-core@3.5.25/node_modules/@vue/runtime-core/dist/runtime-core.d.ts",
|
|
728
728
|
"range": [
|
|
729
729
|
65451,
|
|
730
730
|
65504
|
|
@@ -742,7 +742,7 @@
|
|
|
742
742
|
"type": "unknown",
|
|
743
743
|
"declarations": [
|
|
744
744
|
{
|
|
745
|
-
"file": "/
|
|
745
|
+
"file": "/Users/pierrereynaud/Documents/Work/design-system/node_modules/.pnpm/@vue+runtime-core@3.5.25/node_modules/@vue/runtime-core/dist/runtime-core.d.ts",
|
|
746
746
|
"range": [
|
|
747
747
|
72189,
|
|
748
748
|
72205
|
|
@@ -760,7 +760,7 @@
|
|
|
760
760
|
"type": "unknown",
|
|
761
761
|
"declarations": [
|
|
762
762
|
{
|
|
763
|
-
"file": "/
|
|
763
|
+
"file": "/Users/pierrereynaud/Documents/Work/design-system/node_modules/.pnpm/@vue+runtime-core@3.5.25/node_modules/@vue/runtime-core/dist/runtime-core.d.ts",
|
|
764
764
|
"range": [
|
|
765
765
|
72210,
|
|
766
766
|
72226
|