@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,394 @@
|
|
|
1
|
+
---
|
|
2
|
+
component: VJoyCollapseItem
|
|
3
|
+
status: draft
|
|
4
|
+
language: en
|
|
5
|
+
dsds: JoyCollapseItem.dsds.json
|
|
6
|
+
dsdsVersion: "0.15.2"
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Collapse item
|
|
10
|
+
|
|
11
|
+
Use **`VJoyCollapseItem`** when a section of content should stay hidden until the user expands it — FAQs, optional settings, or dense detail that would clutter the page when always visible.
|
|
12
|
+
|
|
13
|
+
Each item has a clickable header (with optional icon, subheader, and preview), a chevron marker, and a collapsible body. Use it alone for a single disclosure, or nest several inside **`VJoyCollapse`** for grouped lists and accordion behavior.
|
|
14
|
+
|
|
15
|
+
| | |
|
|
16
|
+
| --- | --- |
|
|
17
|
+
| **Code** | `VJoyCollapseItem` from `@maltjoy/core-vue` |
|
|
18
|
+
| **Design** | [Figma — Joy Core Design System](https://www.figma.com/design/jfndp2QBJGS9yeuWbeGuvD/) |
|
|
19
|
+
| **Storybook** | [VJoyCollapseItem docs](https://doc.malt.tech/joy-storybook/?path=/docs/components-buttons-vjoycollapseitem--docs) · [VJoyCollapse docs](https://doc.malt.tech/joy-storybook/?path=/docs/components-buttons-vjoycollapse--docs) (grouped examples) |
|
|
20
|
+
| **DSDS (machine)** | [`JoyCollapseItem.dsds.json`](./JoyCollapseItem.dsds.json) |
|
|
21
|
+
| **Live API** | `joy_get_component_info("VJoyCollapseItem")` |
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## When to use this component
|
|
26
|
+
|
|
27
|
+
Use a collapse item when users benefit from **progressive disclosure** on the same screen — they scan short headers first and open only what they need.
|
|
28
|
+
|
|
29
|
+
Typical jobs: FAQ answers, advanced settings tucked under a summary, filter or form sections that are optional, or outline cards that preview key values before expansion.
|
|
30
|
+
|
|
31
|
+
### When not to use this component
|
|
32
|
+
|
|
33
|
+
| Need | Use instead |
|
|
34
|
+
| --- | --- |
|
|
35
|
+
| Several items with shared open/close logic or accordion (one open at a time) | `VJoyCollapse` wrapping `VJoyCollapseItem` children |
|
|
36
|
+
| Switching between peer panels on one surface | `VJoyTabs` + `VJoyTab` |
|
|
37
|
+
| Blocking modal decision or form | `VJoyDialog` |
|
|
38
|
+
| Linear multi-step flow with progress | `VJoyStepper` |
|
|
39
|
+
| Primary site or app navigation | `VJoyMenu`, sidebar, or header nav |
|
|
40
|
+
| Inline “show more” for long text only | Truncation / “Read more” pattern on `VJoyText` — not a full panel |
|
|
41
|
+
| Custom expand/collapse markup with ad-hoc CSS | Still use `VJoyCollapseItem` + Joy tokens — don’t reinvent chrome |
|
|
42
|
+
|
|
43
|
+
> **Experimental:** `mode="outline"` renders a bordered card treatment. It may become the default later; confirm with design before rolling it out broadly.
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## How it works
|
|
48
|
+
|
|
49
|
+
Clicking the **summary** row (header area) toggles open state. When open, the **detail** region renders the default slot. The chevron rotates to indicate state.
|
|
50
|
+
|
|
51
|
+
### Anatomy
|
|
52
|
+
|
|
53
|
+
| Part | Required? | What it is |
|
|
54
|
+
| --- | --- | --- |
|
|
55
|
+
| Summary row | Yes | Clickable header (`role="button"`) — toggles open/closed |
|
|
56
|
+
| Header label | Yes | Text from the `header` prop |
|
|
57
|
+
| Summary icon | No | Leading `VJoyIcon` when `summaryIcon` is set |
|
|
58
|
+
| Subheader | No | Secondary line under the header (`subheader` prop) |
|
|
59
|
+
| Header right (`collapse-header-right` slot) | No | Short metadata between title and chevron (e.g. `VJoyTag`) — keep non-interactive |
|
|
60
|
+
| Chevron marker | Yes | Trailing `chevron-down` icon; rotates 180° when open |
|
|
61
|
+
| Preview (`collapse-preview` slot) | No | Short snippet visible while collapsed (often tags or a one-line summary) |
|
|
62
|
+
| Detail region | Yes (when open) | Default slot content (`role="region"`, labelled by summary `id`) |
|
|
63
|
+
| Focus / hover chrome | No* | Outline `mode` adds border highlight and elevation on hover/focus |
|
|
64
|
+
|
|
65
|
+
### Default values
|
|
66
|
+
|
|
67
|
+
- `open` defaults to **`false`**
|
|
68
|
+
- `mode` defaults to **`default`**
|
|
69
|
+
- `header` is **required**
|
|
70
|
+
- `subheader`, `summaryIcon`, and `id` are optional
|
|
71
|
+
|
|
72
|
+
Props, events, and slots: use Joy MCP (`joy_list_components`, `joy_get_component_info`, `joy_get_component_types`) or Storybook — this page focuses on **when** and **how**, not a full API dump.
|
|
73
|
+
|
|
74
|
+
### Open state
|
|
75
|
+
|
|
76
|
+
Two patterns:
|
|
77
|
+
|
|
78
|
+
1. **Per item** — set `:open="true"` on each `VJoyCollapseItem` you want expanded initially.
|
|
79
|
+
2. **Grouped** — wrap items in `VJoyCollapse` and bind `v-model` to an array of open item ids. **Set a stable `id` on each item** when using `v-model` (falls back to `header` text if `id` is omitted).
|
|
80
|
+
|
|
81
|
+
`VJoyCollapse` also supports `accordion` (only one item open at a time) and passes `mode` to all children.
|
|
82
|
+
|
|
83
|
+
### Composition
|
|
84
|
+
|
|
85
|
+
```vue
|
|
86
|
+
<VJoyCollapse v-model="openIds">
|
|
87
|
+
<VJoyCollapseItem id="billing" header="Billing details">…</VJoyCollapseItem>
|
|
88
|
+
<VJoyCollapseItem id="shipping" header="Shipping address">…</VJoyCollapseItem>
|
|
89
|
+
</VJoyCollapse>
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Listen for `@collapse-item:open` and `@collapse-item:close` on each item when you need side effects outside `v-model`.
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## Variants
|
|
97
|
+
|
|
98
|
+
`mode` controls the visual treatment — not semantic emphasis.
|
|
99
|
+
|
|
100
|
+
### `default`
|
|
101
|
+
|
|
102
|
+
Use for stacked lists inside `VJoyCollapse`: items get a bottom divider from the parent wrapper. Compact, text-forward headers.
|
|
103
|
+
|
|
104
|
+
Avoid when each item should read as an independent card with border and padding.
|
|
105
|
+
|
|
106
|
+
### `outline`
|
|
107
|
+
|
|
108
|
+
Use when each item is a **bordered card** — common in settings or selectable sections with icons, subheaders, and preview content.
|
|
109
|
+
|
|
110
|
+
Hover and keyboard focus lift the border to secondary color and add elevation. Open items keep the active border.
|
|
111
|
+
|
|
112
|
+
Avoid mixing `default` and `outline` items in the same `VJoyCollapse` group; set `mode` once on `VJoyCollapse` (or consistently per item).
|
|
113
|
+
|
|
114
|
+
### Not in the Vue API: Stencil slot names
|
|
115
|
+
|
|
116
|
+
The legacy `joy-collapse-item` web component uses slots `collapse-summary`, `collapse-marker`, and `collapse-detail`. **`VJoyCollapseItem` uses the `header` prop, built-in chevron, and the default slot** — do not port Stencil slot names into Vue templates.
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## Sizes
|
|
121
|
+
|
|
122
|
+
`VJoyCollapseItem` exposes **no `size` prop**. Typography scales via CSS custom properties on the root:
|
|
123
|
+
|
|
124
|
+
| Token / variable | Role |
|
|
125
|
+
| --- | --- |
|
|
126
|
+
| `--collapse-item-font-size` | Base font size for summary and detail |
|
|
127
|
+
| `--collapse-item-summary-font-size` | Summary row only (overrides base) |
|
|
128
|
+
| `--collapse-item-detail-font-size` | Detail body only (overrides base) |
|
|
129
|
+
|
|
130
|
+
Defaults map to Joy primary font tokens (`--joy-font-size-primary-400` summary context, `--joy-font-size-primary-300` detail). **Don’t hardcode pixel font sizes** in apps — override these variables if design requires a local tweak.
|
|
131
|
+
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
## States
|
|
135
|
+
|
|
136
|
+
| State | What the user sees / can do |
|
|
137
|
+
| --- | --- |
|
|
138
|
+
| Collapsed (default) | Header, optional subheader/preview visible; detail hidden; chevron points down |
|
|
139
|
+
| Expanded (`open`) | Detail region visible; chevron rotated 180°; `collapse-item:open` emitted |
|
|
140
|
+
| Collapsed again | Detail unmounted from DOM; `collapse-item:close` emitted |
|
|
141
|
+
| Hover (`outline` mode) | Border and chevron use secondary color; light elevation |
|
|
142
|
+
| Focus (`outline` mode) | Same highlight as hover while summary has focus (`joy-collapse-item--focusing`) |
|
|
143
|
+
| With preview slot | Preview content stays visible in the summary row while collapsed |
|
|
144
|
+
|
|
145
|
+
Internal open state syncs from the `open` prop via a watcher — parent `v-model` on `VJoyCollapse` or explicit `:open` both work.
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
## Best practices
|
|
150
|
+
|
|
151
|
+
Rules use RFC 2119 strength (**MUST** / **SHOULD** / **MUST NOT** / **SHOULD NOT**).
|
|
152
|
+
|
|
153
|
+
### Structure and hierarchy
|
|
154
|
+
|
|
155
|
+
- **SHOULD** use **`VJoyCollapse`** when there are **two or more** related items, accordion behavior, or shared `v-model`.
|
|
156
|
+
- **SHOULD** give each item a **stable `id`** when `VJoyCollapse` manages open state.
|
|
157
|
+
- **SHOULD** keep **3–8** collapse items per group; beyond that, rethink IA (tabs, separate page, search).
|
|
158
|
+
- **SHOULD NOT** nest another collapse item inside a detail body unless the inner content is truly independent.
|
|
159
|
+
- **MUST NOT** put primary page CTAs only inside collapsed content — surface the main action outside.
|
|
160
|
+
|
|
161
|
+
### Implementation
|
|
162
|
+
|
|
163
|
+
- **MUST** use only documented props and `mode` values from `JoyCollapseItem.types.ts` (`default`, `outline`).
|
|
164
|
+
- **MUST** style with Joy tokens / CSS variables — no custom `.joy-collapse-item` chrome overrides.
|
|
165
|
+
- **MUST NOT** invent props (`variant`, `size`, `disabled`, …).
|
|
166
|
+
- **MUST NOT** replace the summary with a custom clickable `<div>` — use `header`, slots, and `summaryIcon`.
|
|
167
|
+
- **SHOULD** set `mode` on `VJoyCollapse` when all siblings share the same treatment.
|
|
168
|
+
- **SHOULD** use `collapse-preview` for at-a-glance values (tags, status) — not full detail content.
|
|
169
|
+
|
|
170
|
+
### Interaction
|
|
171
|
+
|
|
172
|
+
- **SHOULD** initialize `open` or `v-model` so the most helpful section is expanded on first visit (when product rules allow).
|
|
173
|
+
- **SHOULD** keep `collapse-header-right` content **display-only** (badges, tags) — not buttons or links that compete with the summary toggle.
|
|
174
|
+
- **MUST NOT** rely on collapse to hide required form fields without a clear way to discover them (validation + error messaging).
|
|
175
|
+
|
|
176
|
+
### Do / don’t
|
|
177
|
+
|
|
178
|
+
| Do | Don’t |
|
|
179
|
+
| --- | --- |
|
|
180
|
+
| `VJoyCollapse` + `id` + `v-model` for groups | Duplicate toggle logic on custom wrappers |
|
|
181
|
+
| Short, scannable `header` text | Full paragraphs in the header |
|
|
182
|
+
| `summaryIcon` when it aids recognition | Decorative icons on every row |
|
|
183
|
+
| `collapse-preview` for one-line summaries | Entire forms in the preview slot |
|
|
184
|
+
| `mode="outline"` for card-style sections | Mixing modes in one list |
|
|
185
|
+
| Joy typography CSS variables | Hardcoded `14px` / `16px` in app CSS |
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
## Content
|
|
190
|
+
|
|
191
|
+
Headers are navigation labels; detail bodies hold the substance.
|
|
192
|
+
|
|
193
|
+
### Header formula
|
|
194
|
+
|
|
195
|
+
**Short noun phrase or topic name** naming the section:
|
|
196
|
+
|
|
197
|
+
- ✅ Billing information
|
|
198
|
+
- ✅ Advanced options
|
|
199
|
+
- ✅ What is Malt Protect?
|
|
200
|
+
|
|
201
|
+
Use **parallel structure** across siblings in the same `VJoyCollapse` (all questions, all settings categories, etc.).
|
|
202
|
+
|
|
203
|
+
### Subheader and preview
|
|
204
|
+
|
|
205
|
+
- **`subheader`** — one supporting line (eligibility, last updated, short context). Sentence case.
|
|
206
|
+
- **`collapse-preview`** — compact collapsed-state hint (chip list, status, single metric). Not a substitute for the full body.
|
|
207
|
+
|
|
208
|
+
### Writing rules
|
|
209
|
+
|
|
210
|
+
| Strength | Rule |
|
|
211
|
+
| --- | --- |
|
|
212
|
+
| **MUST** | Header names the **topic**, not the action — ✅ `Payment method` · ❌ `Click to see payment method` |
|
|
213
|
+
| **MUST** | Keep headers ≤ ~50 characters; move detail to subheader or body |
|
|
214
|
+
| **MUST** | Use sentence case for headers and subheaders |
|
|
215
|
+
| **MUST NOT** | Use “Show” / “Hide” / “Click here” as the header — the chevron already signals expand/collapse |
|
|
216
|
+
| **MUST NOT** | Duplicate the page title as every item header |
|
|
217
|
+
| **SHOULD** | Phrase FAQ headers as the user’s question |
|
|
218
|
+
| **SHOULD** | Match header wording to links or buttons that scroll to the section |
|
|
219
|
+
| **SHOULD** (FR) | Use articles and punctuation as grammar requires — same length discipline applies |
|
|
220
|
+
|
|
221
|
+
### Patterns
|
|
222
|
+
|
|
223
|
+
**FAQs** — Question as `header`, answer in the default slot. Keep answers concise; link out for long docs.
|
|
224
|
+
|
|
225
|
+
**Settings** — `outline` + `summaryIcon` + optional `collapse-preview` (e.g. current value). Subheader for “Last saved …” metadata.
|
|
226
|
+
|
|
227
|
+
**Forms inside detail** — Validate on submit, not on collapse. If a section has errors, consider leaving it open or expanding it when validation fails.
|
|
228
|
+
|
|
229
|
+
---
|
|
230
|
+
|
|
231
|
+
## Accessibility
|
|
232
|
+
|
|
233
|
+
Behaviors (what must happen), not slogans.
|
|
234
|
+
|
|
235
|
+
| Behavior | Expectation |
|
|
236
|
+
| --- | --- |
|
|
237
|
+
| Summary control | `role="button"` with `tabindex="0"` on the summary row |
|
|
238
|
+
| Toggle | **Click** and **Enter** activate toggle (summary `@keydown.enter`) |
|
|
239
|
+
| Expanded content | `role="region"` with `aria-labelledby` pointing to the summary label element |
|
|
240
|
+
| Label id | **Set `id`** on the item when multiple collapse items share a page — required for correct `aria-labelledby` on the region |
|
|
241
|
+
| Name | Accessible name comes from visible `header` text (and subheader is supplementary visual text, not the primary name) |
|
|
242
|
+
| Focus | Outline mode shows visible focus via border/elevation — don’t remove it in product CSS |
|
|
243
|
+
| Icons | `summaryIcon` and chevron are decorative (`aria-hidden` on summary icon) |
|
|
244
|
+
| Header-right slot | Must not trap focus or replace the summary’s accessible name |
|
|
245
|
+
|
|
246
|
+
Target: **WCAG 2.2 AA** where the product requires it.
|
|
247
|
+
|
|
248
|
+
> **Gap to be aware of:** the summary does not currently expose `aria-expanded`. Don’t remove native semantics if you wrap the item; prefer upstream fixes over per-app patches.
|
|
249
|
+
|
|
250
|
+
---
|
|
251
|
+
|
|
252
|
+
## Examples
|
|
253
|
+
|
|
254
|
+
```vue
|
|
255
|
+
<script setup lang="ts">
|
|
256
|
+
import { ref } from 'vue'
|
|
257
|
+
import { VJoyCollapse, VJoyCollapseItem, VJoyTag } from '@maltjoy/core-vue'
|
|
258
|
+
|
|
259
|
+
const openIds = ref(['billing'])
|
|
260
|
+
</script>
|
|
261
|
+
|
|
262
|
+
<template>
|
|
263
|
+
<!-- Standalone item -->
|
|
264
|
+
<VJoyCollapseItem header="Release notes" :open="true">
|
|
265
|
+
<p>Version 2.4 includes performance improvements.</p>
|
|
266
|
+
</VJoyCollapseItem>
|
|
267
|
+
|
|
268
|
+
<!-- Grouped with v-model -->
|
|
269
|
+
<VJoyCollapse v-model="openIds">
|
|
270
|
+
<VJoyCollapseItem id="billing" header="Billing" subheader="Invoices and tax info">
|
|
271
|
+
<p>Update your billing address here.</p>
|
|
272
|
+
</VJoyCollapseItem>
|
|
273
|
+
<VJoyCollapseItem id="notifications" header="Notifications">
|
|
274
|
+
<p>Choose which emails you receive.</p>
|
|
275
|
+
</VJoyCollapseItem>
|
|
276
|
+
</VJoyCollapse>
|
|
277
|
+
|
|
278
|
+
<!-- Outline card with icon, tag, and preview -->
|
|
279
|
+
<VJoyCollapse mode="outline" v-model="openIds">
|
|
280
|
+
<VJoyCollapseItem
|
|
281
|
+
id="profile"
|
|
282
|
+
header="Profile"
|
|
283
|
+
subheader="Visible to clients"
|
|
284
|
+
summary-icon="user"
|
|
285
|
+
>
|
|
286
|
+
<template #collapse-header-right>
|
|
287
|
+
<VJoyTag label="Complete" size="small" />
|
|
288
|
+
</template>
|
|
289
|
+
<template #collapse-preview>
|
|
290
|
+
<span class="joy-mt-4">Paris · French · Available</span>
|
|
291
|
+
</template>
|
|
292
|
+
<p>Full profile editor content.</p>
|
|
293
|
+
</VJoyCollapseItem>
|
|
294
|
+
</VJoyCollapse>
|
|
295
|
+
|
|
296
|
+
<!-- Accordion: one open at a time -->
|
|
297
|
+
<VJoyCollapse v-model="openIds" accordion>
|
|
298
|
+
<VJoyCollapseItem id="step-1" header="Step 1">…</VJoyCollapseItem>
|
|
299
|
+
<VJoyCollapseItem id="step-2" header="Step 2">…</VJoyCollapseItem>
|
|
300
|
+
</VJoyCollapse>
|
|
301
|
+
</template>
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
In Nuxt (or apps with auto-import), omit imports if `VJoyCollapseItem` and `VJoyCollapse` are already global.
|
|
305
|
+
|
|
306
|
+
---
|
|
307
|
+
|
|
308
|
+
## Related
|
|
309
|
+
|
|
310
|
+
| Component | Use when |
|
|
311
|
+
| --- | --- |
|
|
312
|
+
| `VJoyCollapse` | Multiple items, `v-model`, or accordion mode |
|
|
313
|
+
| `VJoyIcon` | `summaryIcon` values (Joy icon names) |
|
|
314
|
+
| `VJoyTag` / `VJoyTagsList` | Status or preview chips in header-right or preview slot |
|
|
315
|
+
| `VJoyTabs` | Peer sections that should stay visible as tabs, not stacked disclosure |
|
|
316
|
+
| `VJoyPanel` | Static card layout without expand/collapse interaction |
|
|
317
|
+
|
|
318
|
+
---
|
|
319
|
+
|
|
320
|
+
## For agents
|
|
321
|
+
|
|
322
|
+
Optional for readers; **required** for vibe-coding quality. Maps to `agentDocumentBlocks` in [`JoyCollapseItem.dsds.json`](./JoyCollapseItem.dsds.json).
|
|
323
|
+
|
|
324
|
+
### Pick the right component
|
|
325
|
+
|
|
326
|
+
| If the intent is… | Emit… | Do not emit… |
|
|
327
|
+
| --- | --- | --- |
|
|
328
|
+
| One expandable section | `VJoyCollapseItem` | Custom `<details>` with Joy-like CSS |
|
|
329
|
+
| Multiple expandable sections | `VJoyCollapse` + `VJoyCollapseItem` children | Several unrelated `VJoyCollapseItem` without a parent |
|
|
330
|
+
| Only one open at a time | `VJoyCollapse` + `accordion` + `v-model` | Manual open-state logic per item |
|
|
331
|
+
| Card-style bordered rows | `mode="outline"` on collapse (parent or item) | Custom bordered divs + click handlers |
|
|
332
|
+
| Tabbed peer content | `VJoyTabs` + `VJoyTab` | Collapse items for primary navigation |
|
|
333
|
+
| Modal interrupt | `VJoyDialog` | Collapse for blocking confirmations |
|
|
334
|
+
|
|
335
|
+
### Hard rules
|
|
336
|
+
|
|
337
|
+
1. **MUST** read `JoyCollapseItem.types.ts` and/or `joy_list_components` before generating props (detailed MCP info may lag for this component).
|
|
338
|
+
2. **MUST** use only documented props: `header`, `subheader`, `open`, `summaryIcon`, `id`, `mode`.
|
|
339
|
+
3. **MUST** use `header` prop for the title — not Stencil slot names (`collapse-summary`).
|
|
340
|
+
4. **MUST** put expandable body content in the **default slot** — not `collapse-detail`.
|
|
341
|
+
5. **MUST** set `id` on each item when using `VJoyCollapse` `v-model`.
|
|
342
|
+
6. **MUST NOT** invent props (`variant`, `size`, `disabled`, `accordion` on the item).
|
|
343
|
+
7. **MUST NOT** override `.joy-collapse-item` border, padding, radius, or chevron rotation in app CSS.
|
|
344
|
+
8. **SHOULD** listen for `collapse-item:open` / `collapse-item:close` (kebab-case in templates) — not Stencil `joy-collapse-item-*` event names.
|
|
345
|
+
9. **SHOULD** use `summary-icon` (kebab-case) in templates for the `summaryIcon` prop.
|
|
346
|
+
|
|
347
|
+
### Valid enums (from `JoyCollapseItem.types.ts`)
|
|
348
|
+
|
|
349
|
+
| Prop | Values |
|
|
350
|
+
| --- | --- |
|
|
351
|
+
| `mode` | `default`, `outline` |
|
|
352
|
+
| `open` | `boolean` (default `false`) |
|
|
353
|
+
| `summaryIcon` | Any `TJoyIconsNames` value (see `VJoyIcon` / Joy icon docs) |
|
|
354
|
+
|
|
355
|
+
### Slots
|
|
356
|
+
|
|
357
|
+
| Slot | Purpose |
|
|
358
|
+
| --- | --- |
|
|
359
|
+
| `default` | Detail content when open |
|
|
360
|
+
| `collapse-header-right` | Non-interactive metadata before chevron |
|
|
361
|
+
| `collapse-preview` | Collapsed-state preview line |
|
|
362
|
+
|
|
363
|
+
`defineSlots` also lists `collapse-subheader`, but the template uses the **`subheader` prop** — prefer the prop unless the API gains a real subheader slot.
|
|
364
|
+
|
|
365
|
+
### Checklist
|
|
366
|
+
|
|
367
|
+
- [ ] Correct component (`VJoyCollapseItem` alone vs. with `VJoyCollapse`)
|
|
368
|
+
- [ ] `header` set; `id` set when parent uses `v-model`
|
|
369
|
+
- [ ] Props / enums from types only — no invented API
|
|
370
|
+
- [ ] Default slot for body; no Stencil slot names
|
|
371
|
+
- [ ] `mode` consistent across siblings
|
|
372
|
+
- [ ] Header copy is a topic label, not “Show/Hide”
|
|
373
|
+
- [ ] `collapse-header-right` is display-only
|
|
374
|
+
- [ ] No custom `.joy-collapse-item` chrome CSS
|
|
375
|
+
|
|
376
|
+
---
|
|
377
|
+
|
|
378
|
+
## DSDS mapping
|
|
379
|
+
|
|
380
|
+
This Markdown mirrors [`JoyCollapseItem.dsds.json`](./JoyCollapseItem.dsds.json) (DSDS **0.15.2**).
|
|
381
|
+
|
|
382
|
+
| Section here | DSDS block |
|
|
383
|
+
| --- | --- |
|
|
384
|
+
| When to use / not | `use-cases` |
|
|
385
|
+
| Anatomy | `anatomy` |
|
|
386
|
+
| Variants (`mode`) | `variants` |
|
|
387
|
+
| Sizes (CSS variables) | `design-specifications` |
|
|
388
|
+
| States | `states` |
|
|
389
|
+
| Best practices / content rules | `guidelines` (+ `content`) |
|
|
390
|
+
| Accessibility | `accessibility` |
|
|
391
|
+
| Examples | `sections` |
|
|
392
|
+
| For agents | `agentDocumentBlocks` |
|
|
393
|
+
| Props detail | `api` in JSON + Joy MCP |
|
|
394
|
+
| Imports | `imports` in JSON |
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
---
|
|
2
|
+
component: VJoyCompanyAvatar
|
|
3
|
+
status: deprecated
|
|
4
|
+
language: en
|
|
5
|
+
dsds: JoyCompanyAvatar.dsds.json
|
|
6
|
+
dsdsVersion: "0.15.2"
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Company avatar
|
|
10
|
+
|
|
11
|
+
Use **`VJoyCompanyAvatar`** to show a company logo in a square, bordered frame — or a generic company placeholder when no logo URL is available.
|
|
12
|
+
|
|
13
|
+
> **Deprecated:** do not use on new work. Prefer **`VJoyAvatar`** with `placeholder="company-placeholder"` and `showLetters={false}` for the same job. See [ZeroHeight — Avatar](https://zeroheight.com/6bf479565/p/52ceb2-avatar) and the V5 release note (`VJoyCompanyAvatar` merged into `VJoyAvatar`).
|
|
14
|
+
|
|
15
|
+
| | |
|
|
16
|
+
| --- | --- |
|
|
17
|
+
| **Code** | `VJoyCompanyAvatar` from `@maltjoy/core-vue` |
|
|
18
|
+
| **Design** | [ZeroHeight — Avatar](https://zeroheight.com/6bf479565/p/52ceb2-avatar) |
|
|
19
|
+
| **Storybook** | [VJoyCompanyAvatar docs](https://doc.malt.tech/joy-storybook/?path=/docs/components-view-vjoycompanyavatar--docs) |
|
|
20
|
+
| **DSDS (machine)** | [`JoyCompanyAvatar.dsds.json`](./JoyCompanyAvatar.dsds.json) |
|
|
21
|
+
| **Live API** | `joy_list_components` (View category) — `joy_get_component_info` may not resolve this legacy name |
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## When to use this component
|
|
26
|
+
|
|
27
|
+
**Only in existing code** that already renders `VJoyCompanyAvatar`. Typical job: display a client or employer logo next to a name, in a list row, or on a user card.
|
|
28
|
+
|
|
29
|
+
When `imgSrc` is set, the component shows the image (`object-fit: contain`). Without `imgSrc`, it falls back to the `company-placeholder` icon.
|
|
30
|
+
|
|
31
|
+
### When not to use this component
|
|
32
|
+
|
|
33
|
+
| Need | Use instead |
|
|
34
|
+
| --- | --- |
|
|
35
|
+
| Any new company logo / brand mark | `VJoyAvatar` with `photoUrl`, `fullName` (company name), `placeholder="company-placeholder"`, `showLetters={false}` |
|
|
36
|
+
| A person’s profile photo or initials | `VJoyAvatar` (default `user-photo` placeholder) |
|
|
37
|
+
| Several logos in a row | `VJoyAvatarsList` + `VJoyAvatar` |
|
|
38
|
+
| Custom square image with ad-hoc border CSS | Still use `VJoyAvatar` + Joy tokens — don’t reinvent chrome |
|
|
39
|
+
|
|
40
|
+
> **Deprecated:** the whole component. The legacy Stencil `color` prop (`red`, `teal`, `turquoise`, `yellow`) is **not** on `VJoyCompanyAvatar` — do not emit it.
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## How it works
|
|
45
|
+
|
|
46
|
+
Presentational only: no slots, events, or `v-model`. The root is a `div.joy-company-avatar` with a size modifier.
|
|
47
|
+
|
|
48
|
+
### Anatomy
|
|
49
|
+
|
|
50
|
+
| Part | Required? | What it is |
|
|
51
|
+
| --- | --- | --- |
|
|
52
|
+
| Root container | Yes | `div` with `joy-company-avatar` and `joy-company-avatar--{size}` |
|
|
53
|
+
| Logo image | No | `<img>` when `imgSrc` is set; `alt` = `imgAlt` or `companyName`; `title` = `companyName` |
|
|
54
|
+
| Placeholder icon | Yes* | `VJoyIcon` `company-placeholder` when `imgSrc` is absent |
|
|
55
|
+
| Border / background | Yes | Neutral border and background from Joy tokens — don’t override in product CSS |
|
|
56
|
+
|
|
57
|
+
\*Shown whenever there is no `imgSrc`.
|
|
58
|
+
|
|
59
|
+
### Default values
|
|
60
|
+
|
|
61
|
+
- `size` defaults to **`large`** (`large` \| `medium` \| `small`)
|
|
62
|
+
- `loading` defaults to **`lazy`** (only applied when `imgSrc` is set)
|
|
63
|
+
- `imgSrc`, `imgAlt`, and `companyName` are **optional** — with none set, you get the anonymous placeholder icon
|
|
64
|
+
|
|
65
|
+
**Size → frame** (token-driven inside the component; don’t hardcode px in apps):
|
|
66
|
+
|
|
67
|
+
| `size` | Frame |
|
|
68
|
+
| --- | --- |
|
|
69
|
+
| `large` | 46px, `--joy-core-radius-3` |
|
|
70
|
+
| `medium` | 30px, `--joy-core-radius-2` |
|
|
71
|
+
| `small` | 20px, `--joy-core-radius-1` |
|
|
72
|
+
|
|
73
|
+
Props: use Storybook or read `VJoyCompanyAvatar.vue` — this page focuses on **when** and **how**, not a full API dump.
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## Best practices
|
|
78
|
+
|
|
79
|
+
Rules use RFC 2119 strength (**MUST** / **SHOULD** / **MUST NOT** / **SHOULD NOT**).
|
|
80
|
+
|
|
81
|
+
### Deprecation and migration
|
|
82
|
+
|
|
83
|
+
- **MUST NOT** add new usages of `VJoyCompanyAvatar`.
|
|
84
|
+
- **SHOULD** migrate to `VJoyAvatar` when touching surrounding code.
|
|
85
|
+
- **SHOULD** map `imgSrc` → `photoUrl`, `companyName` / `imgAlt` → `fullName` (avatar uses `fullName` for image `alt` and `title`).
|
|
86
|
+
|
|
87
|
+
### Implementation
|
|
88
|
+
|
|
89
|
+
- **MUST** set `companyName` (and `imgAlt` when the logo needs a specific description) whenever `imgSrc` is present — screen readers and hover tooltips depend on it.
|
|
90
|
+
- **MUST** use only documented props: `imgSrc`, `imgAlt`, `companyName`, `size`, `loading`.
|
|
91
|
+
- **MUST** use Joy tokens — no custom `.joy-company-avatar` border, radius, or background overrides.
|
|
92
|
+
- **MUST NOT** invent props (`color`, `variant`, `href`, …).
|
|
93
|
+
- **SHOULD** pick `size` to match adjacent avatars or list density (`large` for profile-scale, `small` in compact tables).
|
|
94
|
+
|
|
95
|
+
### Do / don’t
|
|
96
|
+
|
|
97
|
+
| Do | Don’t |
|
|
98
|
+
| --- | --- |
|
|
99
|
+
| `companyName` + `imgAlt` with a real logo URL | Logo `img` with empty `alt` |
|
|
100
|
+
| `VJoyAvatar` for new company logos | New `VJoyCompanyAvatar` instances |
|
|
101
|
+
| Token-driven sizes via the `size` prop | Fixed `width` / `height` in app CSS |
|
|
102
|
+
| `loading="lazy"` for below-the-fold logos | Eager-load every logo in a long list |
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## Accessibility
|
|
107
|
+
|
|
108
|
+
Behaviors (what must happen), not slogans.
|
|
109
|
+
|
|
110
|
+
| Behavior | Expectation |
|
|
111
|
+
| --- | --- |
|
|
112
|
+
| Image present | `alt` comes from `imgAlt` or falls back to `companyName` — provide at least one meaningful string |
|
|
113
|
+
| Image absent | Placeholder is decorative; parent context must name the company in visible text nearby |
|
|
114
|
+
| Title | `companyName` is exposed as the image `title` for pointer hover — supplementary only |
|
|
115
|
+
| Focus | Component is not focusable; wrap in a link/button in the parent if the logo is interactive |
|
|
116
|
+
| Motion | No built-in animation; respect `prefers-reduced-motion` at app level if you add transitions around it |
|
|
117
|
+
|
|
118
|
+
Target: **WCAG 2.2 AA** where the product requires it.
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## Examples
|
|
123
|
+
|
|
124
|
+
```vue
|
|
125
|
+
<script setup lang="ts">
|
|
126
|
+
import { VJoyCompanyAvatar } from '@maltjoy/core-vue'
|
|
127
|
+
</script>
|
|
128
|
+
|
|
129
|
+
<template>
|
|
130
|
+
<!-- Legacy — prefer VJoyAvatar for new code -->
|
|
131
|
+
<VJoyCompanyAvatar
|
|
132
|
+
company-name="Malt"
|
|
133
|
+
img-alt="Malt logo"
|
|
134
|
+
img-src="https://dam.malt.com/cms-front/maltLogo.png"
|
|
135
|
+
/>
|
|
136
|
+
|
|
137
|
+
<VJoyCompanyAvatar size="small" />
|
|
138
|
+
|
|
139
|
+
<!-- Replacement pattern (new work) -->
|
|
140
|
+
<!--
|
|
141
|
+
<VJoyAvatar
|
|
142
|
+
full-name="Malt"
|
|
143
|
+
photo-url="https://dam.malt.com/cms-front/maltLogo.png"
|
|
144
|
+
placeholder="company-placeholder"
|
|
145
|
+
:show-letters="false"
|
|
146
|
+
/>
|
|
147
|
+
-->
|
|
148
|
+
</template>
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
In Nuxt (or apps with auto-import), omit the import if the component is already global.
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
## Related
|
|
156
|
+
|
|
157
|
+
| Component | Use when |
|
|
158
|
+
| --- | --- |
|
|
159
|
+
| `VJoyAvatar` | **Preferred** — company logos, people, placeholders, initials |
|
|
160
|
+
| `VJoyAvatarsList` | Multiple avatars or logos in one row |
|
|
161
|
+
| `VJoyUserCard` | Profile card that may show a company context |
|
|
162
|
+
| `VJoyListItem` | Row layout with a leading logo slot |
|