@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,331 @@
|
|
|
1
|
+
---
|
|
2
|
+
component: VJoyRadioGroup
|
|
3
|
+
status: draft
|
|
4
|
+
language: en
|
|
5
|
+
dsds: JoyRadioGroup.dsds.json
|
|
6
|
+
dsdsVersion: "0.15.2"
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Radio group
|
|
10
|
+
|
|
11
|
+
Use **`VJoyRadioGroup`** when the user must pick **exactly one** option from a short, visible set and the choices belong together as a single form field.
|
|
12
|
+
|
|
13
|
+
It wraps `VJoyRadio` siblings in a semantic `<fieldset role="radiogroup">`, supports a group legend, horizontal or vertical layout, shared validation (`invalid`), and native form association (`name`, `form`). Selection state lives on each child radio via a **shared** `v-model` — the group itself does not bind a model.
|
|
14
|
+
|
|
15
|
+
| | |
|
|
16
|
+
| --- | --- |
|
|
17
|
+
| **Code** | `VJoyRadioGroup` from `@maltjoy/core-vue` |
|
|
18
|
+
| **Design** | [Figma — Joy components](https://www.figma.com/design/jfndp2QBJGS9yeuWbeGuvD/) |
|
|
19
|
+
| **Storybook** | [VJoyRadioGroup docs](https://doc.malt.tech/joy-storybook/?path=/docs/components-forms-vjoyradiogroup--docs) |
|
|
20
|
+
| **DSDS (machine)** | [`JoyRadioGroup.dsds.json`](./JoyRadioGroup.dsds.json) |
|
|
21
|
+
| **Live API** | `joy_get_component_info("VJoyRadioGroup")` |
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## When to use this component
|
|
26
|
+
|
|
27
|
+
Use a radio group when only one answer is valid, every option should stay visible, and the set reads as one decision — for example billing frequency, delivery method, or profile type.
|
|
28
|
+
|
|
29
|
+
Groups work best with **2–7** options composed as `VJoyRadio` children. For richer option cards (sublabels, expandable fields), keep the group and set `theme="outline"` on each radio (vertical layout).
|
|
30
|
+
|
|
31
|
+
### When not to use this component
|
|
32
|
+
|
|
33
|
+
| Need | Use instead |
|
|
34
|
+
| --- | --- |
|
|
35
|
+
| A single radio without siblings | Don’t — radios are always grouped; use at least two `VJoyRadio` children |
|
|
36
|
+
| Multiple selections from a list | `VJoyCheckbox` inside `VJoyCheckboxGroup` |
|
|
37
|
+
| A single on/off preference | `VJoyToggle` (or a checkbox when the label is a statement) |
|
|
38
|
+
| Many options (roughly 8+) or searchable lists | `VJoySelect` |
|
|
39
|
+
| Label + spacing wrapper around unrelated fields | `VJoyFormGroup` — **not** for radios (ESLint disallows `VJoyRadio` inside `VJoyFormGroup`) |
|
|
40
|
+
| Option appearance, slots, or per-radio disabled state | `VJoyRadio` (inside this group) |
|
|
41
|
+
| Custom-styled native radio lists | Still use `VJoyRadioGroup` + `VJoyRadio` + 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
|
+
| Fieldset | Yes | Root `<fieldset class="joy-radio-group-fieldset">` with `role="radiogroup"` |
|
|
52
|
+
| Legend (`radio-group-legend` slot) | No (but **SHOULD** in forms) | Group label — typically `VJoyLabel` |
|
|
53
|
+
| Container | Yes | `.joy-radio-group-container` — flex layout for child radios |
|
|
54
|
+
| Default slot | Yes | One or more `VJoyRadio` components |
|
|
55
|
+
| `VJoyFormError` (sibling or inside group) | No | Explains validation failures when `invalid` is true |
|
|
56
|
+
|
|
57
|
+
### Default values
|
|
58
|
+
|
|
59
|
+
- `direction` defaults to **`horizontal`**
|
|
60
|
+
- `invalid` defaults to **`false`**
|
|
61
|
+
- `form` and `name` default to **`undefined`**
|
|
62
|
+
|
|
63
|
+
Props, events, and slots: use Joy MCP or Storybook — this page focuses on **when** and **how**, not a full API dump.
|
|
64
|
+
|
|
65
|
+
### Grouping and model
|
|
66
|
+
|
|
67
|
+
- **MUST** place every `VJoyRadio` in the group’s default slot.
|
|
68
|
+
- **MUST** bind the **same** `v-model` (`modelValue`) on each sibling radio.
|
|
69
|
+
- **MUST** give siblings the same `name` so the browser treats them as one group.
|
|
70
|
+
- **MUST** use a distinct `value` on each `VJoyRadio`.
|
|
71
|
+
- **MUST NOT** bind `v-model` on `VJoyRadioGroup` — it has no selection prop.
|
|
72
|
+
- Set `invalid` on the group to propagate error styling to children (they inherit via provide/inject unless a radio sets `invalid` explicitly).
|
|
73
|
+
- Optional `name` / `form` on the fieldset associate the group with native form submission.
|
|
74
|
+
|
|
75
|
+
### Not in the Vue API (Stencil / ZeroHeight drift)
|
|
76
|
+
|
|
77
|
+
The Stencil `joy-radio-group` exposes `label`, `labelSize`, `required`, `requiredMark`, `invalidText`, and `value` on the group. **`VJoyRadioGroup` does not.** Use the `radio-group-legend` slot + `VJoyLabel`, per-radio `required`, and `VJoyFormError` beside the group instead.
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## Variants
|
|
82
|
+
|
|
83
|
+
`direction` controls layout — not visual emphasis. Spacing comes from Joy tokens (`--joy-core-spacing-4` gap inside the container).
|
|
84
|
+
|
|
85
|
+
### `horizontal` (default)
|
|
86
|
+
|
|
87
|
+
Use for compact, inline option sets where labels are short and options fit on one or wrapped rows.
|
|
88
|
+
|
|
89
|
+
Avoid for `theme="outline"` radios (card layout) — Storybook documents outline only in vertical groups.
|
|
90
|
+
|
|
91
|
+
### `vertical`
|
|
92
|
+
|
|
93
|
+
Use when options stack (long labels, outline cards, sublabels, or expandable content).
|
|
94
|
+
|
|
95
|
+
Avoid when a tight horizontal toolbar-like row is enough and every option is a simple `default`-theme radio.
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## States
|
|
100
|
+
|
|
101
|
+
Group-level state complements per-radio states on `VJoyRadio` (checked, disabled, focus, etc.).
|
|
102
|
+
|
|
103
|
+
| State | What the user sees / can do |
|
|
104
|
+
| --- | --- |
|
|
105
|
+
| Default | Fieldset groups radios; one may be selected via shared `v-model` |
|
|
106
|
+
| Horizontal layout | Options in a row with token gap; container adds bottom margin |
|
|
107
|
+
| Vertical layout | Options stacked in a column |
|
|
108
|
+
| Invalid (`invalid` on group) | Error styling on child radios (inherited); pair with visible error text |
|
|
109
|
+
| Valid selection | Checked radio reflects `modelValue`; arrow keys move within the group |
|
|
110
|
+
| Mixed disabled | Individual radios set `disabled`; group stays interactive for enabled options |
|
|
111
|
+
|
|
112
|
+
When validation fails, set `invalid` on the **group** and show a `VJoyFormError` (or equivalent) explaining what to fix. Don’t rely on color alone.
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## Best practices
|
|
117
|
+
|
|
118
|
+
Rules use RFC 2119 strength (**MUST** / **SHOULD** / **MUST NOT** / **SHOULD NOT**).
|
|
119
|
+
|
|
120
|
+
### Selection and hierarchy
|
|
121
|
+
|
|
122
|
+
- **SHOULD** offer **2–7** options in a group; beyond that, prefer `VJoySelect`.
|
|
123
|
+
- **SHOULD** pre-select a sensible default when one option is clearly recommended.
|
|
124
|
+
- **SHOULD** keep option labels parallel across siblings (see `VJoyRadio` content guidance).
|
|
125
|
+
- **MUST NOT** wrap `VJoyRadio` in `VJoyFormGroup` — use `VJoyRadioGroup` (enforced by ESLint).
|
|
126
|
+
|
|
127
|
+
### Implementation
|
|
128
|
+
|
|
129
|
+
- **MUST** use only documented props and `direction` values from MCP or `JoyRadioGroup.types.ts` (`horizontal`, `vertical`).
|
|
130
|
+
- **MUST** share one `v-model` and one `name` across all radios in the group.
|
|
131
|
+
- **MUST** style with Joy tokens — no custom `.joy-radio-group` layout overrides.
|
|
132
|
+
- **MUST NOT** invent props (`label`, `size`, `variant`, `invalidText`, group `v-model`, …).
|
|
133
|
+
- **MUST NOT** hardcode gap or margin pixels — spacing is token-driven in `JoyRadioGroup.scss`.
|
|
134
|
+
|
|
135
|
+
### Interaction
|
|
136
|
+
|
|
137
|
+
- **MUST** set `invalid` on the group (not on every radio) for field-level validation errors.
|
|
138
|
+
- **SHOULD** use `direction="vertical"` when any child uses `theme="outline"`.
|
|
139
|
+
- **SHOULD** place `VJoyFormError` after the radio list (the group stylesheet reserves space for `.joy-form-error`).
|
|
140
|
+
|
|
141
|
+
### Do / don’t
|
|
142
|
+
|
|
143
|
+
| Do | Don’t |
|
|
144
|
+
| --- | --- |
|
|
145
|
+
| `VJoyRadioGroup` + shared `v-model` on each `VJoyRadio` | Lone radios or `VJoyFormGroup` around radios |
|
|
146
|
+
| Legend via `radio-group-legend` + `VJoyLabel` | Stencil-only `label` prop on the group |
|
|
147
|
+
| Group `invalid` + error message | Error color with no explanation |
|
|
148
|
+
| `vertical` for outline / rich options | `outline` radios in a horizontal row |
|
|
149
|
+
| Same `name` on every sibling | Different `name` values in one group |
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
## Content
|
|
154
|
+
|
|
155
|
+
The group legend frames the decision; individual option copy lives on each `VJoyRadio`.
|
|
156
|
+
|
|
157
|
+
### Legend formula
|
|
158
|
+
|
|
159
|
+
**Short question or category name** that applies to the whole set:
|
|
160
|
+
|
|
161
|
+
- ✅ Billing frequency
|
|
162
|
+
- ✅ How do you work?
|
|
163
|
+
- ✅ Delivery method
|
|
164
|
+
|
|
165
|
+
Use `VJoyLabel` in the `radio-group-legend` slot. Mark required groups on the label when the field is mandatory.
|
|
166
|
+
|
|
167
|
+
### Writing rules
|
|
168
|
+
|
|
169
|
+
| Strength | Rule |
|
|
170
|
+
| --- | --- |
|
|
171
|
+
| **MUST** | Legend describes the **set**, not a single option |
|
|
172
|
+
| **MUST** | Pair required groups with clear option labels on each `VJoyRadio` |
|
|
173
|
+
| **MUST NOT** | Repeat the legend text in every radio label |
|
|
174
|
+
| **SHOULD** | Use sentence case for the legend |
|
|
175
|
+
| **SHOULD** | Keep legends concise; move detail to radio sublabels or content slots |
|
|
176
|
+
| **SHOULD** | Match error copy to the legend (`Choose a delivery method` + `Select one option to continue`) |
|
|
177
|
+
|
|
178
|
+
### Patterns
|
|
179
|
+
|
|
180
|
+
**Settings block** — legend names the section; radios use parallel noun phrases (`Monthly`, `Yearly`).
|
|
181
|
+
|
|
182
|
+
**Plan / tier pickers** — `direction="vertical"`, `theme="outline"` on radios; legend stays short (`Select a plan`).
|
|
183
|
+
|
|
184
|
+
**Validation** — `invalid` on the group + `VJoyFormError` below the container.
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
188
|
+
## Accessibility
|
|
189
|
+
|
|
190
|
+
Behaviors (what must happen), not slogans.
|
|
191
|
+
|
|
192
|
+
| Behavior | Expectation |
|
|
193
|
+
| --- | --- |
|
|
194
|
+
| Role | Native `<fieldset role="radiogroup">` wrapping related radios |
|
|
195
|
+
| Name | Group accessible name from `radio-group-legend` (e.g. `VJoyLabel`); option names from each `VJoyRadio` label |
|
|
196
|
+
| Keyboard | **Arrow keys** move between radios in the group; **Space** selects the focused radio |
|
|
197
|
+
| Focus | Per-radio focus rings — don’t remove them in product CSS |
|
|
198
|
+
| Invalid | Group `invalid` propagates to children; pair with visible error text and `VJoyFormError` where appropriate |
|
|
199
|
+
| Form | `name` on fieldset and radios; `form` attribute when the group sits outside a `<form>` element |
|
|
200
|
+
|
|
201
|
+
Target: **WCAG 2.2 AA** where the product requires it.
|
|
202
|
+
|
|
203
|
+
---
|
|
204
|
+
|
|
205
|
+
## Examples
|
|
206
|
+
|
|
207
|
+
```vue
|
|
208
|
+
<script setup lang="ts">
|
|
209
|
+
import { ref } from 'vue'
|
|
210
|
+
import { VJoyRadio, VJoyRadioGroup, VJoyLabel, VJoyFormError } from '@maltjoy/core-vue'
|
|
211
|
+
|
|
212
|
+
const billing = ref('monthly')
|
|
213
|
+
const showError = ref(false)
|
|
214
|
+
|
|
215
|
+
function validate() {
|
|
216
|
+
showError.value = !billing.value
|
|
217
|
+
}
|
|
218
|
+
</script>
|
|
219
|
+
|
|
220
|
+
<template>
|
|
221
|
+
<!-- Horizontal — compact list -->
|
|
222
|
+
<VJoyRadioGroup>
|
|
223
|
+
<template #radio-group-legend>
|
|
224
|
+
<VJoyLabel>Billing frequency</VJoyLabel>
|
|
225
|
+
</template>
|
|
226
|
+
|
|
227
|
+
<VJoyRadio v-model="billing" name="billing" value="monthly">Monthly</VJoyRadio>
|
|
228
|
+
<VJoyRadio v-model="billing" name="billing" value="yearly">Yearly</VJoyRadio>
|
|
229
|
+
</VJoyRadioGroup>
|
|
230
|
+
|
|
231
|
+
<!-- Vertical + outline cards -->
|
|
232
|
+
<VJoyRadioGroup direction="vertical">
|
|
233
|
+
<template #radio-group-legend>
|
|
234
|
+
<VJoyLabel required-mark>Delivery method</VJoyLabel>
|
|
235
|
+
</template>
|
|
236
|
+
|
|
237
|
+
<VJoyRadio v-model="billing" theme="outline" name="delivery" value="standard">
|
|
238
|
+
Standard delivery
|
|
239
|
+
<template #radio-sublabel>3–5 business days</template>
|
|
240
|
+
</VJoyRadio>
|
|
241
|
+
<VJoyRadio v-model="billing" theme="outline" name="delivery" value="express">
|
|
242
|
+
Express delivery
|
|
243
|
+
</VJoyRadio>
|
|
244
|
+
</VJoyRadioGroup>
|
|
245
|
+
|
|
246
|
+
<!-- Validation -->
|
|
247
|
+
<VJoyRadioGroup :invalid="showError" direction="vertical">
|
|
248
|
+
<template #radio-group-legend>
|
|
249
|
+
<VJoyLabel required-mark>Delivery method</VJoyLabel>
|
|
250
|
+
</template>
|
|
251
|
+
|
|
252
|
+
<VJoyRadio v-model="billing" name="delivery-required" value="standard">Standard</VJoyRadio>
|
|
253
|
+
<VJoyRadio v-model="billing" name="delivery-required" value="express">Express</VJoyRadio>
|
|
254
|
+
|
|
255
|
+
<VJoyFormError v-if="showError">Select one option to continue</VJoyFormError>
|
|
256
|
+
</VJoyRadioGroup>
|
|
257
|
+
</template>
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
In Nuxt (or apps with auto-import), omit the import if components are already global.
|
|
261
|
+
|
|
262
|
+
---
|
|
263
|
+
|
|
264
|
+
## Related
|
|
265
|
+
|
|
266
|
+
| Component | Use when |
|
|
267
|
+
| --- | --- |
|
|
268
|
+
| `VJoyRadio` | Individual options, themes, slots, and per-option `disabled` |
|
|
269
|
+
| `VJoyLabel` | Accessible group legend in `radio-group-legend` |
|
|
270
|
+
| `VJoyFormError` | Explaining validation failures for the group |
|
|
271
|
+
| `VJoyCheckboxGroup` | Multiple selections |
|
|
272
|
+
| `VJoySelect` | Long or searchable single-choice lists |
|
|
273
|
+
| `VJoyFormGroup` | Label + control + error for other field types — not for radios |
|
|
274
|
+
| `VJoyTag` | Short metadata in a radio’s `radio-header-right` slot |
|
|
275
|
+
|
|
276
|
+
---
|
|
277
|
+
|
|
278
|
+
## For agents
|
|
279
|
+
|
|
280
|
+
Optional for readers; **required** for vibe-coding quality. Maps to `agentDocumentBlocks` in [`JoyRadioGroup.dsds.json`](./JoyRadioGroup.dsds.json).
|
|
281
|
+
|
|
282
|
+
### Pick the right component
|
|
283
|
+
|
|
284
|
+
| If the intent is… | Emit… | Do not emit… |
|
|
285
|
+
| --- | --- | --- |
|
|
286
|
+
| Exactly one of a few visible options | `VJoyRadio` inside `VJoyRadioGroup` | Standalone `VJoyRadio` or `VJoyFormGroup` wrapper |
|
|
287
|
+
| Multiple selections | `VJoyCheckboxGroup` | `VJoyRadioGroup` |
|
|
288
|
+
| Long dropdown list | `VJoySelect` | Many radios without a group |
|
|
289
|
+
| Rich card options | `VJoyRadioGroup` `direction="vertical"` + `VJoyRadio` `theme="outline"` | Horizontal outline row |
|
|
290
|
+
| Group validation error | `invalid` on `VJoyRadioGroup` + `VJoyFormError` | Stencil-only `invalidText` on the group |
|
|
291
|
+
|
|
292
|
+
### Hard rules
|
|
293
|
+
|
|
294
|
+
1. **MUST** call `joy_get_component_info("VJoyRadioGroup")` and `joy_get_component_types("VJoyRadioGroup")` (or read types) before generating props.
|
|
295
|
+
2. **MUST** wrap all `VJoyRadio` instances in `VJoyRadioGroup`.
|
|
296
|
+
3. **MUST** bind the same `v-model` and `name` to every sibling; each `value` must be unique.
|
|
297
|
+
4. **MUST NOT** bind `v-model` on `VJoyRadioGroup` — selection is on each `VJoyRadio`.
|
|
298
|
+
5. **MUST NOT** invent props (`label`, `invalidText`, `size`, group `modelValue`, …) or custom `.joy-radio-group` CSS.
|
|
299
|
+
6. **MUST NOT** place `VJoyRadio` inside `VJoyFormGroup`.
|
|
300
|
+
7. **SHOULD** use `direction="vertical"` when any child has `theme="outline"`.
|
|
301
|
+
8. **SHOULD** put the legend in `radio-group-legend` with `VJoyLabel`.
|
|
302
|
+
|
|
303
|
+
### Checklist
|
|
304
|
+
|
|
305
|
+
- [ ] `VJoyRadio` children inside `VJoyRadioGroup` (not `VJoyFormGroup`)
|
|
306
|
+
- [ ] Shared `v-model` + `name` on every radio; unique `value` per option
|
|
307
|
+
- [ ] `direction` is `horizontal` or `vertical` only (from types)
|
|
308
|
+
- [ ] No `v-model` on the group; no invented group props
|
|
309
|
+
- [ ] Legend via `radio-group-legend` + `VJoyLabel`
|
|
310
|
+
- [ ] Validation: `invalid` on group + visible `VJoyFormError`
|
|
311
|
+
- [ ] `vertical` when using `outline` theme radios
|
|
312
|
+
|
|
313
|
+
---
|
|
314
|
+
|
|
315
|
+
## DSDS mapping
|
|
316
|
+
|
|
317
|
+
This Markdown mirrors [`JoyRadioGroup.dsds.json`](./JoyRadioGroup.dsds.json) (DSDS **0.15.2**).
|
|
318
|
+
|
|
319
|
+
| Section here | DSDS block |
|
|
320
|
+
| --- | --- |
|
|
321
|
+
| When to use / not | `use-cases` |
|
|
322
|
+
| Anatomy | `anatomy` |
|
|
323
|
+
| Variants (`direction`) | `variants` |
|
|
324
|
+
| States | `states` |
|
|
325
|
+
| Best practices / content rules | `guidelines` (+ `content`) |
|
|
326
|
+
| Accessibility | `accessibility` |
|
|
327
|
+
| Examples | `sections` |
|
|
328
|
+
| For agents | `agentDocumentBlocks` |
|
|
329
|
+
| Props detail | `api` in JSON + Joy MCP |
|
|
330
|
+
| Imports | `imports` in JSON |
|
|
331
|
+
| Layout spacing | `design-specifications` |
|
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
---
|
|
2
|
+
component: VJoyRatingStars
|
|
3
|
+
status: draft
|
|
4
|
+
language: en
|
|
5
|
+
dsds: JoyRatingStars.dsds.json
|
|
6
|
+
dsdsVersion: "0.15.2"
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Rating stars
|
|
10
|
+
|
|
11
|
+
Use **`VJoyRatingStars`** when you need to **display** an aggregate rating from 0 to 5 — for example on a freelancer profile, mission feedback summary, or review list row.
|
|
12
|
+
|
|
13
|
+
It renders five star icons (full, half, or empty) from a numeric `ratingValue`, optional review count in parentheses, and a slot for translated supplementary text. It is **read-only** — users cannot change the rating through this component.
|
|
14
|
+
|
|
15
|
+
| | |
|
|
16
|
+
| --- | --- |
|
|
17
|
+
| **Code** | `VJoyRatingStars` from `@maltjoy/core-vue` |
|
|
18
|
+
| **Design** | [Figma — Joy Core Design System](https://www.figma.com/design/jfndp2QBJGS9yeuWbeGuvD/) |
|
|
19
|
+
| **Storybook** | [VJoyRatingStars docs](https://doc.malt.tech/joy-storybook/?path=/docs/components-view-vjoyratingstars--docs) |
|
|
20
|
+
| **DSDS (machine)** | [`JoyRatingStars.dsds.json`](./JoyRatingStars.dsds.json) |
|
|
21
|
+
| **Live API** | `joy_get_component_info("VJoyRatingStars")` |
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## When to use this component
|
|
26
|
+
|
|
27
|
+
Use rating stars when a **computed or fetched score** should be shown at a glance next to optional context (number of reviews, missions completed, etc.). Typical jobs: user cards, search result rows, review headers, and profile summaries.
|
|
28
|
+
|
|
29
|
+
Pair the stars with a translated `aria-label` in localized products — the built-in default is English-only.
|
|
30
|
+
|
|
31
|
+
### When not to use this component
|
|
32
|
+
|
|
33
|
+
| Need | Use instead |
|
|
34
|
+
| --- | --- |
|
|
35
|
+
| User must **submit** or **edit** a rating | A dedicated rating-input pattern (not `VJoyRatingStars`) |
|
|
36
|
+
| Show a percentage or step progress | `VJoyProgressBar` |
|
|
37
|
+
| Status, category, or tag label | `VJoyBadge` or `VJoyTag` |
|
|
38
|
+
| Plain numeric score without star metaphor | `VJoyText` |
|
|
39
|
+
| Custom star row with ad-hoc icons / CSS | Still use `VJoyRatingStars` + Joy tokens |
|
|
40
|
+
|
|
41
|
+
> **Deprecated:** on `VJoyUserCard`, do not use the `user-card-rating-stars` slot — put `VJoyRatingStars` in the **default** slot instead.
|
|
42
|
+
|
|
43
|
+
> **Legacy Stencil:** the old `@maltjoy/core` slot was `rating-stars-slot` and icons used `color="yellow"`. In Vue use **`rating-stars-content`**; star color is **`quaternary`** via `VJoyIcon` — do not recreate yellow styling.
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## How it works
|
|
48
|
+
|
|
49
|
+
### Anatomy
|
|
50
|
+
|
|
51
|
+
| Part | Required? | What it is |
|
|
52
|
+
| --- | --- | --- |
|
|
53
|
+
| Wrapper | Yes | Root `div` with `role="img"` and `aria-label` |
|
|
54
|
+
| Star list | Yes | `<ul>` of five `<li>` items, each with a `VJoyIcon` (`star-fill`, `star-half`, or `star`) |
|
|
55
|
+
| Trailing content | No | `rating-stars-content` slot; default shows `(reviewCount)` when `reviewCount > 0` |
|
|
56
|
+
| Typography | Yes | Wrapper uses `primary-200`; `<strong>` inside content uses bold weight |
|
|
57
|
+
|
|
58
|
+
### Default values
|
|
59
|
+
|
|
60
|
+
- `ratingValue` defaults to **`0`** (all empty stars)
|
|
61
|
+
- `reviewCount` defaults to **`0`** (no count text)
|
|
62
|
+
- `size` defaults to **`medium`**
|
|
63
|
+
|
|
64
|
+
Props and slots: use Joy MCP or Storybook — this page focuses on **when** and **how**, not a full API dump.
|
|
65
|
+
|
|
66
|
+
### Fractional ratings
|
|
67
|
+
|
|
68
|
+
`ratingValue` may include decimals. The component maps each of the five positions to **full**, **half**, or **empty** using fixed thresholds (e.g. `3.25` → three full + one half; `3.1` → three full only; `3.85` → four full). Values outside **0–5** are not clamped in code — **SHOULD** normalize server-side before passing the prop.
|
|
69
|
+
|
|
70
|
+
There is **no `variant` or `color` prop**. Star appearance is fixed (`quaternary` icons).
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## Sizes
|
|
75
|
+
|
|
76
|
+
Pick density to match surrounding typography — do not hardcode icon pixel sizes in product CSS.
|
|
77
|
+
|
|
78
|
+
| Size | Use when |
|
|
79
|
+
| --- | --- |
|
|
80
|
+
| `small` | Compact rows, dense lists, secondary metadata |
|
|
81
|
+
| `medium` | Default — profile cards, standard list items |
|
|
82
|
+
| `large` | Hero emphasis when the rating is a primary focal point |
|
|
83
|
+
|
|
84
|
+
Icon size is driven by `--rating-stars-size` inside the component (`11px` / `14px` / `17px`). **Don’t** override `.joy-icon` size on `.joy-rating-stars` in app stylesheets.
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## States
|
|
89
|
+
|
|
90
|
+
`VJoyRatingStars` is **presentational** — no hover, focus, disabled, or loading API. “States” here mean display configurations.
|
|
91
|
+
|
|
92
|
+
| Configuration | What the user sees |
|
|
93
|
+
| --- | --- |
|
|
94
|
+
| Zero rating (`ratingValue: 0`) | Five empty stars |
|
|
95
|
+
| Whole number (e.g. `3`) | Three full + two empty |
|
|
96
|
+
| Fractional (e.g. `4.25`) | Mix of full / half / empty per threshold rules |
|
|
97
|
+
| With `reviewCount` | Stars + `(12)` in default slot content |
|
|
98
|
+
| Custom slot content | Stars + slot output (e.g. `15 missions`) instead of default count |
|
|
99
|
+
| `size` variants | Same rating at `small`, `medium`, or `large` density |
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## Best practices
|
|
104
|
+
|
|
105
|
+
Rules use RFC 2119 strength (**MUST** / **SHOULD** / **MUST NOT** / **SHOULD NOT**).
|
|
106
|
+
|
|
107
|
+
### Display semantics
|
|
108
|
+
|
|
109
|
+
- **MUST** treat this as **read-only** — do not attach click handlers expecting the user to rate.
|
|
110
|
+
- **SHOULD** show `reviewCount` or slot copy when the count adds trust (reviews, missions, endorsements).
|
|
111
|
+
- **SHOULD** keep `ratingValue` on a **0–5** scale consistent with your backend; document if the API uses another scale and convert before render.
|
|
112
|
+
- **MUST NOT** use stars to represent non-rating metrics (completion %, skill level) without design approval.
|
|
113
|
+
|
|
114
|
+
### Implementation
|
|
115
|
+
|
|
116
|
+
- **MUST** use only documented props: `ratingValue`, `reviewCount`, `size`.
|
|
117
|
+
- **MUST** use Joy tokens — no custom star colors, gaps, or list styling on `.joy-rating-stars`.
|
|
118
|
+
- **MUST NOT** invent props (`variant`, `color`, `readonly`, `interactive`, …).
|
|
119
|
+
- **SHOULD** pass **`aria-label`** (attribute) with translated copy in localized apps.
|
|
120
|
+
- **SHOULD** use the **`rating-stars-content`** slot when copy needs i18n or markup (not only a raw number in parentheses).
|
|
121
|
+
|
|
122
|
+
### Composition
|
|
123
|
+
|
|
124
|
+
- **SHOULD** place inside `VJoyUserCard` default slot (not `user-card-rating-stars`).
|
|
125
|
+
- **SHOULD** align star `size` with adjacent text scale (`small` with compact cards, `medium` by default).
|
|
126
|
+
- **MUST NOT** nest interactive controls inside the `role="img"` wrapper without checking accessibility with design.
|
|
127
|
+
|
|
128
|
+
### Do / don’t
|
|
129
|
+
|
|
130
|
+
| Do | Don’t |
|
|
131
|
+
| --- | --- |
|
|
132
|
+
| `ratingValue={4.25}` from API | Hardcode five `VJoyIcon` stars in a loop |
|
|
133
|
+
| `aria-label="Note : 4,25 sur 5 (12 avis)"` (FR) | Rely on default English `aria-label` in FR UI |
|
|
134
|
+
| `#rating-stars-content` for `15 missions` | English-only string in app CSS `::after` |
|
|
135
|
+
| `reviewCount` for simple numeric count | Duplicate count in slot and prop |
|
|
136
|
+
| Normalize 0–5 before render | Pass `8.2` hoping the component clamps |
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
## Content
|
|
141
|
+
|
|
142
|
+
Trailing text sits in **`rating-stars-content`** or comes from **`reviewCount`** (rendered as `(n)`).
|
|
143
|
+
|
|
144
|
+
### Copy formula
|
|
145
|
+
|
|
146
|
+
**Parenthetical count** (default slot) — digits only, wrapped by the component:
|
|
147
|
+
|
|
148
|
+
- ✅ `(12)` — from `reviewCount={12}`
|
|
149
|
+
- ✅ `15 missions` — via slot when the unit must be translated
|
|
150
|
+
|
|
151
|
+
**Accessible name** (`aria-label`) — full sentence for screen readers:
|
|
152
|
+
|
|
153
|
+
- ✅ `Rating: 4.25 out of 5, 12 reviews`
|
|
154
|
+
- ✅ `Note : 4,25 sur 5, 12 avis` (localized)
|
|
155
|
+
|
|
156
|
+
### Writing rules
|
|
157
|
+
|
|
158
|
+
| Strength | Rule |
|
|
159
|
+
| --- | --- |
|
|
160
|
+
| **MUST** | Provide a translated `aria-label` when the UI locale is not English |
|
|
161
|
+
| **MUST** | Include review/mission count in `aria-label` when visible count text is shown |
|
|
162
|
+
| **MUST NOT** | Put the only mention of review count solely in visual text with no `aria-label` update |
|
|
163
|
+
| **SHOULD** | Use `reviewCount` for a bare number; use the slot for labeled counts (`12 reviews`, `15 missions`) |
|
|
164
|
+
| **SHOULD** | Match number formatting to locale (decimal separator, spacing) in `aria-label` and slot |
|
|
165
|
+
| **SHOULD** (FR) | Non-breaking spaces before `:` and inside parentheses where grammar requires |
|
|
166
|
+
|
|
167
|
+
### Patterns
|
|
168
|
+
|
|
169
|
+
**Profile / user card** — `medium` stars + `reviewCount` or slot under the name; full `aria-label` on the component.
|
|
170
|
+
|
|
171
|
+
**Search result row** — `small` stars; omit count if shown elsewhere on the row.
|
|
172
|
+
|
|
173
|
+
**Review detail header** — `large` optional; slot for rich copy (`Based on 12 verified reviews`).
|
|
174
|
+
|
|
175
|
+
---
|
|
176
|
+
|
|
177
|
+
## Accessibility
|
|
178
|
+
|
|
179
|
+
Behaviors (what must happen), not slogans.
|
|
180
|
+
|
|
181
|
+
| Behavior | Expectation |
|
|
182
|
+
| --- | --- |
|
|
183
|
+
| Role | Root uses `role="img"` — treated as one graphic, not five separate buttons |
|
|
184
|
+
| Name | `aria-label` from the `aria-label` attribute, or default `Rating: {ratingValue} out of 5` (English, not translated) |
|
|
185
|
+
| Stars | Each icon has `aria-hidden="true"` — decoration only; name comes from the wrapper |
|
|
186
|
+
| Keyboard | No focusable parts by default — correct for read-only display |
|
|
187
|
+
| Interaction | **MUST NOT** imply editability; if the row navigates, put the link on the parent card (`VJoyUserCard` + `link`), not on individual stars |
|
|
188
|
+
| Localization | **MUST** override default `aria-label` in non-English products |
|
|
189
|
+
|
|
190
|
+
Target: **WCAG 2.2 AA** where the product requires it.
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
## Examples
|
|
195
|
+
|
|
196
|
+
```vue
|
|
197
|
+
<script setup lang="ts">
|
|
198
|
+
import { VJoyRatingStars } from '@maltjoy/core-vue'
|
|
199
|
+
</script>
|
|
200
|
+
|
|
201
|
+
<template>
|
|
202
|
+
<!-- Default: fractional rating -->
|
|
203
|
+
<VJoyRatingStars :rating-value="4.25" />
|
|
204
|
+
|
|
205
|
+
<!-- With review count -->
|
|
206
|
+
<VJoyRatingStars
|
|
207
|
+
:rating-value="4.25"
|
|
208
|
+
:review-count="12"
|
|
209
|
+
aria-label="Rating: 4.25 out of 5, 12 reviews"
|
|
210
|
+
/>
|
|
211
|
+
|
|
212
|
+
<!-- Compact density -->
|
|
213
|
+
<VJoyRatingStars :rating-value="3" size="small" />
|
|
214
|
+
|
|
215
|
+
<!-- Translated supplementary text -->
|
|
216
|
+
<VJoyRatingStars :rating-value="5" aria-label="Note : 5 sur 5, 15 missions">
|
|
217
|
+
<template #rating-stars-content>
|
|
218
|
+
15 missions
|
|
219
|
+
</template>
|
|
220
|
+
</VJoyRatingStars>
|
|
221
|
+
|
|
222
|
+
<!-- Inside VJoyUserCard (default slot) -->
|
|
223
|
+
<VJoyUserCard full-name="Jane Doe" sub-title="Product designer">
|
|
224
|
+
<VJoyRatingStars :rating-value="4.8" :review-count="24" />
|
|
225
|
+
</VJoyUserCard>
|
|
226
|
+
</template>
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
In Nuxt (or apps with auto-import), omit the import if `VJoyRatingStars` is already global.
|
|
230
|
+
|
|
231
|
+
---
|
|
232
|
+
|
|
233
|
+
## Related
|
|
234
|
+
|
|
235
|
+
| Component | Use when |
|
|
236
|
+
| --- | --- |
|
|
237
|
+
| `VJoyUserCard` | Profile row with avatar, title, and optional rating in default slot |
|
|
238
|
+
| `VJoyIcon` | Star primitives used internally (`star`, `star-fill`, `star-half`) |
|
|
239
|
+
| `VJoyText` | Numeric or textual score without the star metaphor |
|
|
240
|
+
| `VJoyBadge` | Categorical labels, not aggregate ratings |
|
|
241
|
+
| `VJoyProgressBar` | Completion or progress, not review scores |
|
|
242
|
+
|
|
243
|
+
---
|
|
244
|
+
|
|
245
|
+
## For agents
|
|
246
|
+
|
|
247
|
+
Optional for readers; **required** for vibe-coding quality. Maps to `agentDocumentBlocks` in [`JoyRatingStars.dsds.json`](./JoyRatingStars.dsds.json).
|
|
248
|
+
|
|
249
|
+
### Pick the right component
|
|
250
|
+
|
|
251
|
+
| If the intent is… | Emit… | Do not emit… |
|
|
252
|
+
| --- | --- | --- |
|
|
253
|
+
| Show an existing 0–5 rating | `VJoyRatingStars` | Five manual `VJoyIcon` stars |
|
|
254
|
+
| User rates / edits a score | Dedicated input pattern (not in this API) | `VJoyRatingStars` with `@click` |
|
|
255
|
+
| Percent complete | `VJoyProgressBar` | Star row |
|
|
256
|
+
| Tag or status | `VJoyBadge` | `VJoyRatingStars` with fake `ratingValue` |
|
|
257
|
+
| Rating on user card | `VJoyRatingStars` in `VJoyUserCard` default slot | `#user-card-rating-stars` |
|
|
258
|
+
|
|
259
|
+
### Hard rules
|
|
260
|
+
|
|
261
|
+
1. **MUST** call `joy_get_component_info("VJoyRatingStars")` (or read `JoyRatingStars.types.ts`) before generating props.
|
|
262
|
+
2. **MUST** use only documented props: `ratingValue`, `reviewCount`, `size`.
|
|
263
|
+
3. **MUST** pass `aria-label` as a native attribute when the app locale is not English.
|
|
264
|
+
4. **MUST NOT** invent props (`variant`, `color`, `max`, `interactive`, `readonly`, …).
|
|
265
|
+
5. **MUST NOT** use slot name `rating-stars-slot` — Vue slot is **`rating-stars-content`**.
|
|
266
|
+
6. **MUST NOT** override `.joy-rating-stars` / `.joy-icon` colors or sizes in app CSS.
|
|
267
|
+
7. **MUST NOT** attach click handlers to change rating — component is display-only.
|
|
268
|
+
8. **SHOULD** default to `size="medium"` and `ratingValue` on 0–5 from the API.
|
|
269
|
+
9. **SHOULD** use `reviewCount` for `(n)` only; use `#rating-stars-content` for translated labels.
|
|
270
|
+
|
|
271
|
+
### Valid enums (from `JoyRatingStars.types.ts`)
|
|
272
|
+
|
|
273
|
+
| Prop | Values |
|
|
274
|
+
| --- | --- |
|
|
275
|
+
| `size` | `small`, `medium`, `large` |
|
|
276
|
+
| `ratingValue` | `number` (0–5 expected) |
|
|
277
|
+
| `reviewCount` | `number` (≥ 0) |
|
|
278
|
+
|
|
279
|
+
### Checklist
|
|
280
|
+
|
|
281
|
+
- [ ] Correct component (display-only rating, not input)
|
|
282
|
+
- [ ] Props / enums from MCP only
|
|
283
|
+
- [ ] No invented props / no custom star chrome CSS
|
|
284
|
+
- [ ] Translated `aria-label` when not English
|
|
285
|
+
- [ ] `rating-stars-content` (not legacy `rating-stars-slot`)
|
|
286
|
+
- [ ] `VJoyUserCard` uses default slot, not `user-card-rating-stars`
|
|
287
|
+
- [ ] `ratingValue` normalized to 0–5 before render
|
|
288
|
+
|
|
289
|
+
---
|
|
290
|
+
|
|
291
|
+
## DSDS mapping
|
|
292
|
+
|
|
293
|
+
This Markdown mirrors [`JoyRatingStars.dsds.json`](./JoyRatingStars.dsds.json) (DSDS **0.15.2**).
|
|
294
|
+
|
|
295
|
+
| Section here | DSDS block |
|
|
296
|
+
| --- | --- |
|
|
297
|
+
| When to use / not | `use-cases` |
|
|
298
|
+
| Anatomy / fractional logic | `anatomy` |
|
|
299
|
+
| Sizes | `variants` |
|
|
300
|
+
| Display configurations | `states` |
|
|
301
|
+
| Best practices / content rules | `guidelines` (+ `content`) |
|
|
302
|
+
| Accessibility | `accessibility` |
|
|
303
|
+
| Examples | `sections` |
|
|
304
|
+
| For agents | `agentDocumentBlocks` |
|
|
305
|
+
| Props detail | `api` in JSON + Joy MCP |
|
|
306
|
+
| Token sizing | `design-specifications` in JSON |
|