@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,381 @@
|
|
|
1
|
+
---
|
|
2
|
+
component: VJoyCheckboxCard
|
|
3
|
+
status: draft
|
|
4
|
+
language: en
|
|
5
|
+
dsds: JoyCheckboxCard.dsds.json
|
|
6
|
+
dsdsVersion: "0.15.2"
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Checkbox card
|
|
10
|
+
|
|
11
|
+
Use **`VJoyCheckboxCard`** when the user can select **zero, one, or more** independent options and each option needs a **card layout** — a primary label, optional sublabel, and room for supporting content.
|
|
12
|
+
|
|
13
|
+
The whole card is clickable (except nested interactive controls). It wraps `VJoyCheckbox` with bordered card chrome, optional `header-right` metadata, and a `checkbox-card-content` body slot. Bind state with `v-model:checked`.
|
|
14
|
+
|
|
15
|
+
| | |
|
|
16
|
+
| --- | --- |
|
|
17
|
+
| **Code** | `VJoyCheckboxCard` from `@maltjoy/core-vue` |
|
|
18
|
+
| **Design** | [Figma — Joy components](https://www.figma.com/design/jfndp2QBJGS9yeuWbeGuvD/) |
|
|
19
|
+
| **Storybook** | [VJoyCheckboxCard docs](https://doc.malt.tech/joy-storybook/?path=/docs/components-forms-vjoycheckboxcard--docs) |
|
|
20
|
+
| **DSDS (machine)** | [`JoyCheckboxCard.dsds.json`](./JoyCheckboxCard.dsds.json) |
|
|
21
|
+
| **Live API** | `joy_get_component_info("VJoyCheckboxCard")` |
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## When to use this component
|
|
26
|
+
|
|
27
|
+
Use a checkbox card when options are **not mutually exclusive** and each choice benefits from a scannable title, short supporting line, and optional body copy — for example feature add-ons, permission bundles, export formats with descriptions, or filter tiles in a grid.
|
|
28
|
+
|
|
29
|
+
Compose several cards inside `VJoyCheckboxGroup` when you manage a shared array of selected `value`s, or bind each card independently when selections are unrelated.
|
|
30
|
+
|
|
31
|
+
### When not to use this component
|
|
32
|
+
|
|
33
|
+
| Need | Use instead |
|
|
34
|
+
| --- | --- |
|
|
35
|
+
| Compact label-only multi-select | `VJoyCheckbox` inside `VJoyCheckboxGroup` |
|
|
36
|
+
| Exactly one option from a short list | `VJoyRadio` (`theme="outline"`) inside `VJoyRadioGroup` |
|
|
37
|
+
| A single on/off setting (settings row) | `VJoyToggle` |
|
|
38
|
+
| List row with custom chrome wrapping a control | `VJoySelectableItem` (often with checkbox slot) |
|
|
39
|
+
| Custom-styled card + checkbox markup | Still use `VJoyCheckboxCard` + Joy tokens — don’t reinvent chrome |
|
|
40
|
+
|
|
41
|
+
> **Indeterminate:** use for “select all” / partial selection in parent rows. Do not bind `indeterminate` together with `v-model:checked` on the same instance — see [MDN indeterminate checkboxes](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/checkbox#indeterminate_state_checkboxes).
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## How it works
|
|
46
|
+
|
|
47
|
+
### Anatomy
|
|
48
|
+
|
|
49
|
+
| Part | Required? | What it is |
|
|
50
|
+
| --- | --- | --- |
|
|
51
|
+
| Card container | Yes | Root `.joy-checkbox-card` — receives hover, focus, checked, invalid, and disabled styling |
|
|
52
|
+
| Checkbox input | Yes | Native `<input type="checkbox">` inside embedded `VJoyCheckbox` (`data-joy-form-field`) |
|
|
53
|
+
| Label | Yes | Primary title via the `label` prop (`.joy-checkbox-card__label`) |
|
|
54
|
+
| Sublabel | No | Secondary line via `subLabel` (`.joy-checkbox-card__sublabel`) |
|
|
55
|
+
| `header-right` | No | Right-aligned slot beside the label row (e.g. a tag or short meta) |
|
|
56
|
+
| `checkbox-card-content` | No | Body content below the header (`.joy-checkbox-card__content`) |
|
|
57
|
+
| Focus ring | Yes | Card border uses focus token when the checkbox is focused — don’t remove it in product CSS |
|
|
58
|
+
|
|
59
|
+
The card delegates checkbox semantics to `VJoyCheckbox`. Clicks on the card surface toggle selection unless they target the native label/input or a nested interactive element (`a`, `button`, `textarea`, `select`, `option`, `[role="button"]`, or `[data-no-card-toggle]`).
|
|
60
|
+
|
|
61
|
+
### Default values
|
|
62
|
+
|
|
63
|
+
- `checked` defaults to **`false`**
|
|
64
|
+
- `subLabel` defaults to **`""`** (hidden when empty)
|
|
65
|
+
- `indeterminate` defaults to **`false`**
|
|
66
|
+
- `invalid` defaults to **`false`**
|
|
67
|
+
- `disabled` defaults to **`false`**
|
|
68
|
+
- `required` defaults to **`false`**
|
|
69
|
+
- `value` defaults to **`"on"`** (used when building multi-value form submissions)
|
|
70
|
+
- `fitContent` defaults to **`false`** (card stretches to container width)
|
|
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
|
+
### Layout
|
|
75
|
+
|
|
76
|
+
- **Full width (default):** card fills its parent — typical in vertical stacks and form fields.
|
|
77
|
+
- **`fitContent`:** card width shrinks to content — use in horizontal groups or inline pickers when labels are short.
|
|
78
|
+
|
|
79
|
+
There is **no `variant` or `size` prop**. Border, radius, spacing, and typography come from Joy tokens inside the component — **don’t hardcode card dimensions or border colors** in product CSS.
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## Variants
|
|
84
|
+
|
|
85
|
+
`VJoyCheckboxCard` has **no visual emphasis variants** (no primary/secondary). Appearance is controlled by **state** (`checked`, `indeterminate`, `invalid`, `disabled`, focus, hover) and the optional **`fitContent`** layout flag.
|
|
86
|
+
|
|
87
|
+
Choose `VJoyRadio` with `theme="outline"` when only one option may be selected, not this component.
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## Sizes
|
|
92
|
+
|
|
93
|
+
`VJoyCheckboxCard` exposes **no size API**. The embedded checkbox uses the standard Joy checkbox size; card padding and borders use Joy spacing and form tokens (`--joy-core-spacing-4`, `--joy-form-border-width`, `--joy-core-radius-4`).
|
|
94
|
+
|
|
95
|
+
| Aspect | Guidance |
|
|
96
|
+
| --- | --- |
|
|
97
|
+
| Card width | Default full width; `fitContent` for compact tiles |
|
|
98
|
+
| Checkbox control | Inherited from `VJoyCheckbox` — don’t override `.joy-checkbox` size in apps |
|
|
99
|
+
| Density | Prefer fewer cards per row or shorter copy — not invented `size` props |
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## States
|
|
104
|
+
|
|
105
|
+
| State | What the user sees / can do |
|
|
106
|
+
| --- | --- |
|
|
107
|
+
| Default (unchecked) | Neutral border; empty checkbox; full card clickable |
|
|
108
|
+
| Checked | Secondary accent border; filled checkbox; label in **bold** |
|
|
109
|
+
| Indeterminate | Secondary accent border; dash in checkbox; label in **bold** |
|
|
110
|
+
| Hover | Border uses hover token (pointer devices, when not disabled) |
|
|
111
|
+
| Focus | Border uses focus token while the checkbox input is focused |
|
|
112
|
+
| Disabled | Muted border and text; no toggle — **explain why** nearby when possible |
|
|
113
|
+
| Invalid | Error border on the **unchecked** card only; cleared while checked |
|
|
114
|
+
|
|
115
|
+
**Invalid vs checked:** a checked card **cannot** appear invalid — `checked` wins. Unchecking restores `invalid` if the prop is still true.
|
|
116
|
+
|
|
117
|
+
**Indeterminate lifecycle:** any user change clears indeterminate (component sets internal indeterminate to `false` on toggle).
|
|
118
|
+
|
|
119
|
+
**Nested actions:** buttons, links, and other controls inside `checkbox-card-content` keep their own click behavior; the card does not toggle when those are clicked.
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## Best practices
|
|
124
|
+
|
|
125
|
+
Rules use RFC 2119 strength (**MUST** / **SHOULD** / **MUST NOT** / **SHOULD NOT**).
|
|
126
|
+
|
|
127
|
+
### Selection model
|
|
128
|
+
|
|
129
|
+
- **SHOULD** use checkbox cards when options are independent and any combination is valid.
|
|
130
|
+
- **MUST NOT** use checkbox cards when only one option may be selected — use `VJoyRadio` with `theme="outline"`.
|
|
131
|
+
- **SHOULD** place related cards in `VJoyCheckboxGroup` and wire `v-model:value` on the group (or manage `checked` / `value` explicitly in the default slot).
|
|
132
|
+
- **SHOULD** use `indeterminate` only on parent “select all” controls, not on every leaf card.
|
|
133
|
+
|
|
134
|
+
### Implementation
|
|
135
|
+
|
|
136
|
+
- **MUST** bind state with `v-model:checked` (or `:checked` + `@update:checked`).
|
|
137
|
+
- **MUST** use only documented props from MCP or `JoyCheckboxCard.types.ts`.
|
|
138
|
+
- **MUST** use Joy tokens — no custom `.joy-checkbox-card` chrome CSS.
|
|
139
|
+
- **MUST NOT** invent props (`variant`, `size`, `color`, …).
|
|
140
|
+
- **MUST NOT** combine `indeterminate` with `v-model:checked` on the same instance.
|
|
141
|
+
- **MUST** set distinct `id` / `name` / `value` when submitting multiple cards in one form.
|
|
142
|
+
- **SHOULD** set `invalid` from form validation only while the card is unchecked.
|
|
143
|
+
- **SHOULD** add `data-no-card-toggle` on custom interactive elements in the body when they must not toggle the card.
|
|
144
|
+
|
|
145
|
+
### Interaction
|
|
146
|
+
|
|
147
|
+
- **MUST** keep the entire card surface toggling selection except for documented interactive exclusions.
|
|
148
|
+
- **SHOULD** put error or helper copy in `checkbox-card-content` or adjacent form messaging — not only border color.
|
|
149
|
+
- **SHOULD** use `fitContent` in horizontal `VJoyCheckboxGroup` layouts only when labels and body copy stay short.
|
|
150
|
+
- **SHOULD** disable rather than hide options the user cannot choose, when the choice must remain visible.
|
|
151
|
+
|
|
152
|
+
### Do / don’t
|
|
153
|
+
|
|
154
|
+
| Do | Don’t |
|
|
155
|
+
| --- | --- |
|
|
156
|
+
| `v-model:checked` for boolean state | Manual `input.checked` without updating model |
|
|
157
|
+
| `VJoyCheckboxGroup` for related multi-select | Unrelated cards with no group legend when context needs one |
|
|
158
|
+
| `header-right` for tags / short meta | Primary actions in `header-right` that compete with card toggle |
|
|
159
|
+
| `data-no-card-toggle` on nested buttons/links | Expect card click to fire when user clicks a button in the body |
|
|
160
|
+
| `VJoyRadio` outline for exclusive choice | Checkbox cards for “pick one” |
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
## Content
|
|
165
|
+
|
|
166
|
+
Card copy should make each option scannable: a clear **title** (`label`), an optional **one-line hook** (`subLabel`), and longer detail in `checkbox-card-content`.
|
|
167
|
+
|
|
168
|
+
### Label formula
|
|
169
|
+
|
|
170
|
+
**Noun phrase or short statement** naming what is selected when checked:
|
|
171
|
+
|
|
172
|
+
- ✅ Email digests
|
|
173
|
+
- ✅ Advanced analytics
|
|
174
|
+
- ✅ Export as PDF
|
|
175
|
+
|
|
176
|
+
Keep labels **parallel** across siblings (same grammar and similar length):
|
|
177
|
+
|
|
178
|
+
- ✅ PDF · DOCX · XLSX
|
|
179
|
+
- ❌ Export as PDF · Word document · spreadsheet (xlsx)
|
|
180
|
+
|
|
181
|
+
### Sublabel and body copy
|
|
182
|
+
|
|
183
|
+
- **`subLabel`** — one supporting line (price, cadence, eligibility, timing).
|
|
184
|
+
- **`checkbox-card-content`** — feature bullets, legal snippets, illustrations, or validation messages.
|
|
185
|
+
- **`header-right`** — short non-interactive metadata (`VJoyTag`, price badge).
|
|
186
|
+
|
|
187
|
+
### Writing rules
|
|
188
|
+
|
|
189
|
+
| Strength | Rule |
|
|
190
|
+
| --- | --- |
|
|
191
|
+
| **MUST** | Every card has a visible `label` — no unlabeled checkbox cards |
|
|
192
|
+
| **MUST** | Label describes the option, not the click action — ✅ `Weekly digest` · ❌ `Click to enable weekly digest` |
|
|
193
|
+
| **MUST NOT** | Duplicate the group legend in every card label when `VJoyCheckboxGroup` already provides one |
|
|
194
|
+
| **MUST NOT** | Use Yes / No as the only labels in a multi-card set — name each outcome |
|
|
195
|
+
| **SHOULD** | ≤ 60 characters for `label`; wrap rather than truncate |
|
|
196
|
+
| **SHOULD** | Keep `subLabel` to one line; move paragraphs to `checkbox-card-content` |
|
|
197
|
+
| **SHOULD** | Put legal links or long explanations in `checkbox-card-content`, not in the primary label |
|
|
198
|
+
| **SHOULD** | “Select all” parent: `Select all` or `Select all {noun}` — not `All` alone |
|
|
199
|
+
|
|
200
|
+
### Patterns
|
|
201
|
+
|
|
202
|
+
**Feature add-ons** — `label` names the feature, `subLabel` states cost or scope, `checkbox-card-content` lists what’s included.
|
|
203
|
+
|
|
204
|
+
**Filter tiles** — short parallel labels; optional `fitContent` in a horizontal group; avoid long body copy in horizontal layouts.
|
|
205
|
+
|
|
206
|
+
**Validation** — pair `invalid` with explicit error text in `checkbox-card-content` or form-level error (e.g. “Select at least one export format”). Don’t rely on red border alone.
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
## Accessibility
|
|
211
|
+
|
|
212
|
+
Behaviors (what must happen), not slogans.
|
|
213
|
+
|
|
214
|
+
| Behavior | Expectation |
|
|
215
|
+
| --- | --- |
|
|
216
|
+
| Role | Native `checkbox` via embedded `<input type="checkbox">` |
|
|
217
|
+
| Name | From `label` prop (rendered in the checkbox label association) |
|
|
218
|
+
| Keyboard | **Space** toggles when the checkbox is focused; **Tab** moves focus to the input |
|
|
219
|
+
| Focus | Visible focus on the card border (`joy-checkbox-card--focusing`); don’t remove in product CSS |
|
|
220
|
+
| Large target | Card click toggles selection for pointer users; nested controls remain independently operable |
|
|
221
|
+
| Grouping | Related cards: `VJoyCheckboxGroup` uses `<fieldset>` + legend |
|
|
222
|
+
| Disabled | `disabled` on input; explain restriction in visible text when it matters |
|
|
223
|
+
| Invalid | Don’t rely on color alone — provide text for the error |
|
|
224
|
+
| Indeterminate | Exposed to AT via native `indeterminate` on the input |
|
|
225
|
+
|
|
226
|
+
Target: **WCAG 2.2 AA** where the product requires it.
|
|
227
|
+
|
|
228
|
+
---
|
|
229
|
+
|
|
230
|
+
## Examples
|
|
231
|
+
|
|
232
|
+
```vue
|
|
233
|
+
<script setup lang="ts">
|
|
234
|
+
import { ref } from 'vue'
|
|
235
|
+
import { VJoyCheckboxCard, VJoyCheckboxGroup, VJoyTag } from '@maltjoy/core-vue'
|
|
236
|
+
|
|
237
|
+
const analytics = ref(false)
|
|
238
|
+
const selected = ref(['pdf'])
|
|
239
|
+
</script>
|
|
240
|
+
|
|
241
|
+
<template>
|
|
242
|
+
<!-- Standalone card -->
|
|
243
|
+
<VJoyCheckboxCard
|
|
244
|
+
v-model:checked="analytics"
|
|
245
|
+
label="Advanced analytics"
|
|
246
|
+
sub-label="Includes funnel and cohort reports"
|
|
247
|
+
>
|
|
248
|
+
<template #checkbox-card-content>
|
|
249
|
+
Available on Pro plans. Data refreshes every 24 hours.
|
|
250
|
+
</template>
|
|
251
|
+
</VJoyCheckboxCard>
|
|
252
|
+
|
|
253
|
+
<!-- With header metadata -->
|
|
254
|
+
<VJoyCheckboxCard
|
|
255
|
+
v-model:checked="analytics"
|
|
256
|
+
label="Priority support"
|
|
257
|
+
sub-label="24/7 chat"
|
|
258
|
+
>
|
|
259
|
+
<template #header-right>
|
|
260
|
+
<VJoyTag variant="important" size="xsmall">New</VJoyTag>
|
|
261
|
+
</template>
|
|
262
|
+
</VJoyCheckboxCard>
|
|
263
|
+
|
|
264
|
+
<!-- Inside a group (wire slot helpers from VJoyCheckboxGroup) -->
|
|
265
|
+
<VJoyCheckboxGroup v-model:value="selected" label="Export formats" direction="vertical">
|
|
266
|
+
<template #default="{ isChecked, updateModel }">
|
|
267
|
+
<VJoyCheckboxCard
|
|
268
|
+
value="pdf"
|
|
269
|
+
label="PDF"
|
|
270
|
+
sub-label="Best for sharing"
|
|
271
|
+
:checked="isChecked('pdf')"
|
|
272
|
+
@update:checked="updateModel('pdf', $event)"
|
|
273
|
+
/>
|
|
274
|
+
<VJoyCheckboxCard
|
|
275
|
+
value="csv"
|
|
276
|
+
label="CSV"
|
|
277
|
+
sub-label="Best for spreadsheets"
|
|
278
|
+
:checked="isChecked('csv')"
|
|
279
|
+
@update:checked="updateModel('csv', $event)"
|
|
280
|
+
/>
|
|
281
|
+
</template>
|
|
282
|
+
</VJoyCheckboxGroup>
|
|
283
|
+
|
|
284
|
+
<!-- Compact horizontal tiles -->
|
|
285
|
+
<VJoyCheckboxGroup direction="horizontal">
|
|
286
|
+
<VJoyCheckboxCard fit-content label="PDF" :checked="true" />
|
|
287
|
+
<VJoyCheckboxCard fit-content label="DOCX" :checked="false" />
|
|
288
|
+
</VJoyCheckboxGroup>
|
|
289
|
+
|
|
290
|
+
<!-- Invalid until selected -->
|
|
291
|
+
<VJoyCheckboxCard
|
|
292
|
+
v-model:checked="analytics"
|
|
293
|
+
:invalid="!analytics"
|
|
294
|
+
label="I agree to the data processing terms"
|
|
295
|
+
/>
|
|
296
|
+
|
|
297
|
+
<!-- Body action that must not toggle the card -->
|
|
298
|
+
<VJoyCheckboxCard v-model:checked="analytics" label="Custom integration">
|
|
299
|
+
<template #checkbox-card-content>
|
|
300
|
+
<button type="button" data-no-card-toggle>Configure webhook</button>
|
|
301
|
+
</template>
|
|
302
|
+
</VJoyCheckboxCard>
|
|
303
|
+
</template>
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
In Nuxt (or apps with auto-import), omit the import if `VJoyCheckboxCard` is already global.
|
|
307
|
+
|
|
308
|
+
When using `VJoyCheckboxGroup`’s default slot, bind each card with `isChecked(value)` and `updateModel(value, $event)` from the slot props — the group does not auto-bind `checked` for slot children.
|
|
309
|
+
|
|
310
|
+
---
|
|
311
|
+
|
|
312
|
+
## Related
|
|
313
|
+
|
|
314
|
+
| Component | Use when |
|
|
315
|
+
| --- | --- |
|
|
316
|
+
| `VJoyCheckbox` | Label-only multi-select without card chrome |
|
|
317
|
+
| `VJoyCheckboxGroup` | Shared legend, layout, and array `v-model:value` |
|
|
318
|
+
| `VJoyRadio` / `VJoyRadioGroup` | Exactly one choice (`theme="outline"` for card-like radios) |
|
|
319
|
+
| `VJoyToggle` | Single on/off preference row |
|
|
320
|
+
| `VJoyTag` | Short metadata in `header-right` |
|
|
321
|
+
| `VJoyLabel` / `VJoyFormGroup` | Field legends, required marks, and form-level validation messaging |
|
|
322
|
+
|
|
323
|
+
---
|
|
324
|
+
|
|
325
|
+
## For agents
|
|
326
|
+
|
|
327
|
+
Optional for readers; **required** for vibe-coding quality. Maps to `agentDocumentBlocks` in [`JoyCheckboxCard.dsds.json`](./JoyCheckboxCard.dsds.json).
|
|
328
|
+
|
|
329
|
+
### Pick the right component
|
|
330
|
+
|
|
331
|
+
| If the intent is… | Emit… | Do not emit… |
|
|
332
|
+
| --- | --- | --- |
|
|
333
|
+
| Multi-select with title + description cards | `VJoyCheckboxCard` | Custom bordered div + raw checkbox |
|
|
334
|
+
| Compact multi-select list | `VJoyCheckbox` | `VJoyCheckboxCard` without sublabel/body need |
|
|
335
|
+
| Pick exactly one rich option | `VJoyRadio` `theme="outline"` | `VJoyCheckboxCard` |
|
|
336
|
+
| Managed array of selected values | `VJoyCheckboxGroup` + cards or checkboxes | Orphan cards with no group when options are related |
|
|
337
|
+
| Select all / partial parent | `VJoyCheckboxCard` or `VJoyCheckbox` with `indeterminate` | `indeterminate` + `v-model:checked` on same node |
|
|
338
|
+
|
|
339
|
+
### Hard rules
|
|
340
|
+
|
|
341
|
+
1. **MUST** call `joy_get_component_info("VJoyCheckboxCard")` or read `JoyCheckboxCard.types.ts` before generating props.
|
|
342
|
+
2. **MUST** use `v-model:checked` (or `:checked` + `@update:checked`) for boolean state.
|
|
343
|
+
3. **MUST** set `label` on every instance — there is no default slot for the title.
|
|
344
|
+
4. **MUST NOT** invent props — there is no `variant`, `size`, or `color`.
|
|
345
|
+
5. **MUST NOT** set `indeterminate` on the same instance as `v-model:checked`.
|
|
346
|
+
6. **MUST NOT** override `.joy-checkbox-card` border, padding, radius, or background with custom CSS.
|
|
347
|
+
7. **MUST** treat `invalid` as visible only when unchecked; checking clears invalid styling.
|
|
348
|
+
8. **SHOULD** use `checkbox-card-content` for helper text, links, and errors — not overloaded `label` / `subLabel`.
|
|
349
|
+
9. **SHOULD** add `data-no-card-toggle` on interactive elements in the body that must not toggle the card.
|
|
350
|
+
|
|
351
|
+
### Checklist
|
|
352
|
+
|
|
353
|
+
- [ ] Correct component (`VJoyCheckboxCard` or named alternative)
|
|
354
|
+
- [ ] Props from MCP / types only — no invented API
|
|
355
|
+
- [ ] `label` set; `v-model:checked` wired; indeterminate parent not v-modelled
|
|
356
|
+
- [ ] Exclusive choice → `VJoyRadio`, not checkbox card
|
|
357
|
+
- [ ] Related options → `VJoyCheckboxGroup` with legend when needed
|
|
358
|
+
- [ ] No custom `.joy-checkbox-card` chrome CSS
|
|
359
|
+
- [ ] Nested buttons/links use `data-no-card-toggle` when they must not toggle
|
|
360
|
+
- [ ] Invalid / disabled states have explanatory text when user-visible
|
|
361
|
+
- [ ] `id` / `name` / `value` set appropriately for forms
|
|
362
|
+
|
|
363
|
+
---
|
|
364
|
+
|
|
365
|
+
## DSDS mapping
|
|
366
|
+
|
|
367
|
+
This Markdown mirrors [`JoyCheckboxCard.dsds.json`](./JoyCheckboxCard.dsds.json) (DSDS **0.15.2**).
|
|
368
|
+
|
|
369
|
+
| Section here | DSDS block |
|
|
370
|
+
| --- | --- |
|
|
371
|
+
| When to use / not | `use-cases` |
|
|
372
|
+
| Anatomy | `anatomy` |
|
|
373
|
+
| Variants / layout (`fitContent`) | `variants` |
|
|
374
|
+
| Sizes (no size API) | `design-specifications` |
|
|
375
|
+
| States | `states` |
|
|
376
|
+
| Best practices / content rules | `guidelines` (+ `content`) |
|
|
377
|
+
| Accessibility | `accessibility` |
|
|
378
|
+
| Examples | `sections` |
|
|
379
|
+
| For agents | `agentDocumentBlocks` |
|
|
380
|
+
| Props detail | `api` in JSON + Joy MCP |
|
|
381
|
+
| Imports | `imports` in JSON |
|