@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.
Files changed (131) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +30 -3
  3. package/dist/doc/VJoyAdminBanner/guideline.md +284 -0
  4. package/dist/doc/VJoyAvailability/guideline.md +352 -0
  5. package/dist/doc/VJoyAvatar/guideline.md +192 -0
  6. package/dist/doc/VJoyAvatarsList/guideline.md +328 -0
  7. package/dist/doc/VJoyBadge/guideline.md +169 -0
  8. package/dist/doc/VJoyBadgeLevel/guideline.md +166 -0
  9. package/dist/doc/VJoyBlockSkeleton/guideline.md +150 -0
  10. package/dist/doc/VJoyBottomSheet/guideline.md +345 -0
  11. package/dist/doc/VJoyBottomSheetTrigger/guideline.md +156 -0
  12. package/dist/doc/VJoyButton/guideline.md +371 -0
  13. package/dist/doc/VJoyButton/metadata.json +0 -16
  14. package/dist/doc/VJoyButtonCard/guideline.md +384 -0
  15. package/dist/doc/VJoyCheckbox/guideline.md +317 -0
  16. package/dist/doc/VJoyCheckboxCard/guideline.md +381 -0
  17. package/dist/doc/VJoyCheckboxGroup/guideline.md +363 -0
  18. package/dist/doc/VJoyCheckboxGroup/metadata.json +7 -7
  19. package/dist/doc/VJoyCollapse/guideline.md +362 -0
  20. package/dist/doc/VJoyCollapseItem/guideline.md +394 -0
  21. package/dist/doc/VJoyCompanyAvatar/guideline.md +162 -0
  22. package/dist/doc/VJoyDialog/guideline.md +425 -0
  23. package/dist/doc/VJoyDialogTrigger/guideline.md +186 -0
  24. package/dist/doc/VJoyDot/guideline.md +177 -0
  25. package/dist/doc/VJoyDrawer/guideline.md +392 -0
  26. package/dist/doc/VJoyDrawerTrigger/guideline.md +145 -0
  27. package/dist/doc/VJoyDropdown/guideline.md +393 -0
  28. package/dist/doc/VJoyDropdown/metadata.json +6 -6
  29. package/dist/doc/VJoyDropdownList/guideline.md +396 -0
  30. package/dist/doc/VJoyDropdownList/metadata.json +7 -7
  31. package/dist/doc/VJoyDropzone/guideline.md +390 -0
  32. package/dist/doc/VJoyDropzone/metadata.json +36 -1
  33. package/dist/doc/VJoyFilterBar/guideline.md +419 -0
  34. package/dist/doc/VJoyFilterBarButton/guideline.md +359 -0
  35. package/dist/doc/VJoyFloatingActionsBar/guideline.md +372 -0
  36. package/dist/doc/VJoyFormError/guideline.md +325 -0
  37. package/dist/doc/VJoyFormError/metadata.json +0 -14
  38. package/dist/doc/VJoyFormFieldSkeleton/guideline.md +159 -0
  39. package/dist/doc/VJoyFormGroup/guideline.md +285 -0
  40. package/dist/doc/VJoyFunnel/guideline.md +349 -0
  41. package/dist/doc/VJoyFunnelFooter/guideline.md +178 -0
  42. package/dist/doc/VJoyFunnelHeader/guideline.md +204 -0
  43. package/dist/doc/VJoyHighlight/guideline.md +169 -0
  44. package/dist/doc/VJoyIcon/JoyIcon.types.ts +1 -1
  45. package/dist/doc/VJoyIcon/guideline.md +168 -0
  46. package/dist/doc/VJoyIcon/metadata.json +0 -1
  47. package/dist/doc/VJoyIconButton/guideline.md +169 -0
  48. package/dist/doc/VJoyIconButton/metadata.json +1 -1
  49. package/dist/doc/VJoyIndicator/guideline.md +168 -0
  50. package/dist/doc/VJoyIndicators/guideline.md +183 -0
  51. package/dist/doc/VJoyInput/JoyInput.types.ts +1 -6
  52. package/dist/doc/VJoyInput/guideline.md +401 -0
  53. package/dist/doc/VJoyInput/metadata.json +5 -14
  54. package/dist/doc/VJoyInputDigit/guideline.md +381 -0
  55. package/dist/doc/VJoyInputNumber/guideline.md +414 -0
  56. package/dist/doc/VJoyInputNumber/metadata.json +22 -17
  57. package/dist/doc/VJoyInputPassword/guideline.md +379 -0
  58. package/dist/doc/VJoyInputPassword/metadata.json +0 -14
  59. package/dist/doc/VJoyLabel/guideline.md +200 -0
  60. package/dist/doc/VJoyLink/guideline.md +360 -0
  61. package/dist/doc/VJoyListItem/guideline.md +335 -0
  62. package/dist/doc/VJoyMenu/guideline.md +304 -0
  63. package/dist/doc/VJoyMenu/metadata.json +21 -21
  64. package/dist/doc/VJoyMenuItem/guideline.md +352 -0
  65. package/dist/doc/VJoyPagination/guideline.md +355 -0
  66. package/dist/doc/VJoyPanel/guideline.md +238 -0
  67. package/dist/doc/VJoyPanelSection/guideline.md +160 -0
  68. package/dist/doc/VJoyPasswordRequirement/guideline.md +336 -0
  69. package/dist/doc/VJoyPasswordRequirement/metadata.json +1 -1
  70. package/dist/doc/VJoyProductTour/JoyProductTour.types.ts +0 -1
  71. package/dist/doc/VJoyProductTour/guideline.md +455 -0
  72. package/dist/doc/VJoyProductTour/metadata.json +1 -1
  73. package/dist/doc/VJoyProductTourTrigger/guideline.md +167 -0
  74. package/dist/doc/VJoyProgressBar/guideline.md +348 -0
  75. package/dist/doc/VJoyRadio/guideline.md +346 -0
  76. package/dist/doc/VJoyRadioGroup/guideline.md +331 -0
  77. package/dist/doc/VJoyRatingStars/guideline.md +306 -0
  78. package/dist/doc/VJoyScreenLoader/guideline.md +172 -0
  79. package/dist/doc/VJoySelect/guideline.md +396 -0
  80. package/dist/doc/VJoySelectableItem/guideline.md +351 -0
  81. package/dist/doc/VJoySelectableItemGroup/guideline.md +370 -0
  82. package/dist/doc/VJoySeparator/guideline.md +161 -0
  83. package/dist/doc/VJoySnackbar/guideline.md +402 -0
  84. package/dist/doc/VJoySpinner/guideline.md +168 -0
  85. package/dist/doc/VJoyStep/guideline.md +182 -0
  86. package/dist/doc/VJoyStepper/guideline.md +390 -0
  87. package/dist/doc/VJoyTab/guideline.md +298 -0
  88. package/dist/doc/VJoyTabs/guideline.md +353 -0
  89. package/dist/doc/VJoyTag/guideline.md +226 -0
  90. package/dist/doc/VJoyTagsInput/guideline.md +387 -0
  91. package/dist/doc/VJoyTagsList/guideline.md +311 -0
  92. package/dist/doc/VJoyTagsList/metadata.json +27 -27
  93. package/dist/doc/VJoyTemplate/guideline.md +366 -0
  94. package/dist/doc/VJoyText/guideline.md +175 -0
  95. package/dist/doc/VJoyText/metadata.json +1 -1
  96. package/dist/doc/VJoyTextarea/guideline.md +378 -0
  97. package/dist/doc/VJoyTitleBrand/guideline.md +155 -0
  98. package/dist/doc/VJoyToggle/guideline.md +327 -0
  99. package/dist/doc/VJoyTooltip/guideline.md +322 -0
  100. package/dist/doc/VJoyUserCard/guideline.md +268 -0
  101. package/dist/doc/VJoyUserCard/metadata.json +3 -17
  102. package/dist/doc/VJoyWalkthrough/guideline.md +351 -0
  103. package/dist/doc/VJoyWalkthroughTrigger/guideline.md +171 -0
  104. package/dist/doc/VJoyWrapper/guideline.md +173 -0
  105. package/dist/doc/css-classes.json +1 -15
  106. package/dist/doc/design-tokens.json +1 -0
  107. package/dist/doc/index.json +20 -30
  108. package/dist/index.js +22 -2
  109. package/dist/index.js.map +1 -1
  110. package/dist/tools/get-component-guideline.d.ts +30 -0
  111. package/dist/tools/get-component-guideline.d.ts.map +1 -0
  112. package/dist/tools/get-component-guideline.js +51 -0
  113. package/dist/tools/get-component-guideline.js.map +1 -0
  114. package/dist/tools/get-documentation-page.d.ts +22 -0
  115. package/dist/tools/get-documentation-page.d.ts.map +1 -0
  116. package/dist/tools/get-documentation-page.js +21 -0
  117. package/dist/tools/get-documentation-page.js.map +1 -0
  118. package/dist/tools/list-documentation-pages.d.ts +22 -0
  119. package/dist/tools/list-documentation-pages.d.ts.map +1 -0
  120. package/dist/tools/list-documentation-pages.js +17 -0
  121. package/dist/tools/list-documentation-pages.js.map +1 -0
  122. package/dist/tools/search-documentation.d.ts +41 -0
  123. package/dist/tools/search-documentation.d.ts.map +1 -0
  124. package/dist/tools/search-documentation.js +25 -0
  125. package/dist/tools/search-documentation.js.map +1 -0
  126. package/dist/zeroheight-parser.d.ts +27 -0
  127. package/dist/zeroheight-parser.d.ts.map +1 -0
  128. package/dist/zeroheight-parser.js +77 -0
  129. package/dist/zeroheight-parser.js.map +1 -0
  130. package/package.json +10 -10
  131. package/dist/doc/VJoyMultiCheckbox/metadata.json +0 -332
@@ -0,0 +1,352 @@
1
+ ---
2
+ component: VJoyAvailability
3
+ status: draft
4
+ language: en
5
+ dsds: JoyAvailability.dsds.json
6
+ dsdsVersion: "0.15.2"
7
+ ---
8
+
9
+ # Availability
10
+
11
+ Use **`VJoyAvailability`** when you need to show a freelancer’s (or user’s) availability at a glance — as a colored status dot, with an optional short label.
12
+
13
+ It maps backend availability states to Joy semantic colors, supports a hollow “partial” dot, and truncates long labels with ellipsis while exposing the full text via the native `title` tooltip.
14
+
15
+ | | |
16
+ | --- | --- |
17
+ | **Code** | `VJoyAvailability` from `@maltjoy/core-vue` |
18
+ | **Design** | [ZeroHeight — Availability](https://zeroheight.com/6bf479565/p/1423580-availability) |
19
+ | **Storybook** | [VJoyAvailability docs](https://doc.malt.tech/joy-storybook/?path=/docs/components-view-vjoyavailability--docs) |
20
+ | **DSDS (machine)** | [`JoyAvailability.dsds.json`](./JoyAvailability.dsds.json) |
21
+ | **Live API** | `joy_get_component_info("VJoyAvailability")` |
22
+
23
+ ---
24
+
25
+ ## When to use this component
26
+
27
+ Use availability when someone needs to read **current work availability** on profile surfaces — search results, freelancer cards, headers, or compact list rows.
28
+
29
+ Choose **dot + label** on profile and search contexts where the status should be explicit. Choose **dot only** in dense layouts (for example a freelancer pool beside an avatar) where space is tight and the dot color carries the meaning.
30
+
31
+ ### When not to use this component
32
+
33
+ | Need | Use instead |
34
+ | --- | --- |
35
+ | Generic status / category label (not availability) | `VJoyBadge` |
36
+ | Simple notification or count dot | `VJoyDot` |
37
+ | Rich alert or callout with title and body | `VJoyHighlight` |
38
+ | Editable availability settings (form control) | Product-specific settings UI — not this read-only indicator |
39
+ | Custom colored dot + ad-hoc label markup | Still use `VJoyAvailability` + Joy tokens — don’t reinvent chrome |
40
+
41
+ ---
42
+
43
+ ## How it works
44
+
45
+ ### Anatomy
46
+
47
+ | Part | Required? | What it is |
48
+ | --- | --- | --- |
49
+ | Root container | Yes | `<div class="joy-availability">` — always rendered in `VJoyAvailability` |
50
+ | Status dot | Yes | `<span class="joy-availability__dot">` with a `status` class and optional `joy-availability--partial` |
51
+ | Label | No | Plain text from the `label` prop; omitted for dot-only display |
52
+ | Label chrome | No* | `joy-availability-has-label` adds pill background and padding when `label` is set |
53
+ | Native tooltip | No* | `title` on the root mirrors `label` when provided (full text on hover) |
54
+
55
+ \*Present only when `label` is set.
56
+
57
+ ### Default values
58
+
59
+ - `status` defaults to **`AVAILABLE`**
60
+ - `isPartial` defaults to **`false`**
61
+ - `label` defaults to **`undefined`** (dot-only)
62
+
63
+ Props: use Joy MCP (`joy_get_component_info`, `joy_get_component_types`) or Storybook — this page focuses on **when** and **how**, not a full API dump. There are **no events** and **no slots**.
64
+
65
+ ### Display modes
66
+
67
+ | Mode | When | What renders |
68
+ | --- | --- | --- |
69
+ | **Default (dot + label)** | Search, freelancer profiles, anywhere the status must be readable without relying on color alone | Colored dot + truncated label in a pill |
70
+ | **Dot only** | Dense lists, avatar overlays (freelancer pool) | Dot without label text — pair with `VJoyAvatar` (bottom-right placement per design) |
71
+
72
+ ---
73
+
74
+ ## Variants
75
+
76
+ `status` is the only visual variant. Pick it from **backend availability data**, not from preferred colors.
77
+
78
+ Allowed values (from `TJoyAvailabilityStatus`): `AVAILABLE`, `AVAILABLE_AND_VERIFIED`, `NOT_AVAILABLE_WITH_DATE`, `AVAILABLE_SOON`, `NOT_AVAILABLE`.
79
+
80
+ ### `AVAILABLE`
81
+
82
+ Use when the user is available but the “verified availability” state does not apply (neutral / secondary tone).
83
+
84
+ Avoid when the product surface expects the verified-available green state.
85
+
86
+ ### `AVAILABLE_AND_VERIFIED`
87
+
88
+ Use when availability is confirmed / verified (success green dot).
89
+
90
+ Avoid substituting `AVAILABLE` when the data model exposes verified availability.
91
+
92
+ ### `AVAILABLE_SOON`
93
+
94
+ Use when the user will become available soon (warning tone).
95
+
96
+ Avoid for indefinite unavailability — use `NOT_AVAILABLE` or `NOT_AVAILABLE_WITH_DATE`.
97
+
98
+ ### `NOT_AVAILABLE`
99
+
100
+ Use for fully unavailable users (filled error-colored dot).
101
+
102
+ Avoid when a return date is known and should appear in the label — prefer `NOT_AVAILABLE_WITH_DATE` + descriptive `label`.
103
+
104
+ ### `NOT_AVAILABLE_WITH_DATE`
105
+
106
+ Use when unavailable **and** a date (or date phrase) belongs in the label (hollow error-bordered dot).
107
+
108
+ Pair with a label such as `Not available until 30 July` — the component truncates overflow but keeps the full string in `title`.
109
+
110
+ ### Partial availability (`isPartial`)
111
+
112
+ Set `isPartial` to **`true`** for partially available users. The dot renders **hollow** (transparent fill) while keeping the `status` border color.
113
+
114
+ Use with `AVAILABLE_AND_VERIFIED` (or another positive status) when “partly available” is distinct from fully available.
115
+
116
+ ### Not in the API: `INVISIBLE`
117
+
118
+ Legacy Stencil styles reference an `INVISIBLE` status class. It is **not** in `TJoyAvailabilityStatus`. Do not emit `status="INVISIBLE"`. Map hidden availability in product logic instead of inventing a status value.
119
+
120
+ ---
121
+
122
+ ## Sizes
123
+
124
+ Single visual scale — **no `size` prop**.
125
+
126
+ | Aspect | Guidance |
127
+ | --- | --- |
128
+ | Dot | `--availability-dot-size` (15px default) — don’t hardcode dot diameter in apps |
129
+ | Label typography | `primary-200` via Joy font utilities |
130
+ | Pill height | `--joy-core-spacing-7` on the labeled container |
131
+ | Long labels | `text-overflow: ellipsis` + `white-space: nowrap`; full text in `title` |
132
+
133
+ **Don’t** override `.joy-availability` padding, radius, or dot dimensions in product CSS unless theming through the documented CSS custom properties.
134
+
135
+ ---
136
+
137
+ ## States
138
+
139
+ Presentational component — no hover, focus, or disabled interaction states. Meaning comes from **`status`** and **`isPartial`**.
140
+
141
+ | Status / flag | What the user sees |
142
+ | --- | --- |
143
+ | `AVAILABLE` | Filled secondary-toned dot |
144
+ | `AVAILABLE_AND_VERIFIED` | Filled success-toned dot |
145
+ | `AVAILABLE_SOON` | Filled warning-toned dot |
146
+ | `NOT_AVAILABLE` | Filled error-toned dot |
147
+ | `NOT_AVAILABLE_WITH_DATE` | Hollow dot with error border (transparent fill) |
148
+ | `isPartial: true` | Hollow dot (transparent fill) for any `status` |
149
+ | With `label` | Pill background (`--availability-background`), truncated text, `title` tooltip |
150
+ | Without `label` | Dot only inside the root container |
151
+
152
+ ---
153
+
154
+ ## Best practices
155
+
156
+ Rules use RFC 2119 strength (**MUST** / **SHOULD** / **MUST NOT** / **SHOULD NOT**).
157
+
158
+ ### Selection and placement
159
+
160
+ - **SHOULD** use **dot + label** on search and profile surfaces (ZeroHeight default).
161
+ - **SHOULD** use **dot only** on freelancer pool rows, positioned with `VJoyAvatar` per design (bottom-right of the avatar).
162
+ - **MUST NOT** rely on dot color alone when the label fits the layout — add `label` for clarity.
163
+ - **SHOULD** keep labels short; move long date phrases into `label` knowing truncation is expected in narrow columns.
164
+
165
+ ### Implementation
166
+
167
+ - **MUST** use only `status` values from MCP or `JoyAvailability.types.ts`.
168
+ - **MUST** map `status` from API / domain models — don’t pick colors manually.
169
+ - **MUST** style with Joy tokens or documented CSS variables (`--availability-*`) — no custom availability chrome.
170
+ - **MUST NOT** invent props (`variant`, `size`, `color`, …).
171
+ - **MUST NOT** emit `status="INVISIBLE"` or other undocumented status strings.
172
+ - **SHOULD** set `isPartial` only when product rules define partial availability.
173
+
174
+ ### Do / don’t
175
+
176
+ | Do | Don’t |
177
+ | --- | --- |
178
+ | `status` from backend data | Hardcoded green/red dots in custom markup |
179
+ | Short, scannable labels | Paragraph-length status text |
180
+ | Dot-only beside avatars in pools | Dot-only on profile headers without context |
181
+ | `NOT_AVAILABLE_WITH_DATE` + date label | `NOT_AVAILABLE` when a date should be shown |
182
+ | Theme via `--availability-*` variables | Override `.joy-availability__dot` border colors ad hoc |
183
+
184
+ ---
185
+
186
+ ## Content
187
+
188
+ Labels describe **availability status** in plain language. They are required for accessible, unambiguous reading wherever space allows.
189
+
190
+ ### Label formula
191
+
192
+ **Status phrase**, optionally with a **time boundary**:
193
+
194
+ - ✅ Available
195
+ - ✅ Available soon
196
+ - ✅ Not available
197
+ - ✅ Not available until 30 July
198
+
199
+ Keep copy aligned with the `status` value — don’t show a green verified dot with “Unavailable” text.
200
+
201
+ ### Writing rules
202
+
203
+ | Strength | Rule |
204
+ | --- | --- |
205
+ | **MUST** | Label meaning must match `status` (color + words tell the same story) |
206
+ | **MUST** | Use sentence case |
207
+ | **MUST** | Prefer concise phrases; long strings truncate with ellipsis in tight layouts |
208
+ | **MUST NOT** | Duplicate the user’s name in the label — context already identifies who |
209
+ | **MUST NOT** | Use availability labels as CTAs (“Change availability”) — this is read-only status |
210
+ | **SHOULD** | ≤ ~40 characters when possible; dates may be longer (tooltip preserves full text) |
211
+ | **SHOULD** | Localize date phrases (`30 July` / `30 juillet`) via i18n in the app layer |
212
+ | **SHOULD** | For dot-only mode, ensure surrounding UI (avatar, row title, tooltip) supplies context |
213
+
214
+ ### Patterns
215
+
216
+ **Profile / search** — Dot + label: `label="Available"` with `status="AVAILABLE_AND_VERIFIED"` when verified.
217
+
218
+ **Freelancer pool** — Dot only on the avatar corner; no `label` prop.
219
+
220
+ **Temporary unavailability** — `status="NOT_AVAILABLE_WITH_DATE"` and label `Not available until {date}`.
221
+
222
+ ---
223
+
224
+ ## Accessibility
225
+
226
+ Read-only status display — not interactive. Color reinforces meaning but must not be the only cue when a label is shown.
227
+
228
+ | Behavior | Expectation |
229
+ | --- | --- |
230
+ | Role | Plain text in a `<div>` — not a button or live region |
231
+ | Name | Visible `label` text provides the accessible name when present |
232
+ | Dot-only | No accessible name on the component itself — provide context in adjacent text or an enclosing link/card label |
233
+ | Color | Pair dot color with `label` wherever layout allows |
234
+ | Tooltip | Native `title` exposes full label when truncated — don’t rely on `title` as the primary accessible name |
235
+ | Motion | No animation — no reduced-motion concerns |
236
+
237
+ Target: **WCAG 2.2 AA** where the product requires it. For dot-only avatar overlays, ensure the avatar or parent row has an accessible name that includes availability when it matters.
238
+
239
+ ---
240
+
241
+ ## Examples
242
+
243
+ ```vue
244
+ <script setup lang="ts">
245
+ import { VJoyAvailability } from '@maltjoy/core-vue'
246
+ </script>
247
+
248
+ <template>
249
+ <!-- Profile / search: dot + label -->
250
+ <VJoyAvailability
251
+ status="AVAILABLE_AND_VERIFIED"
252
+ label="Available"
253
+ />
254
+
255
+ <!-- Partially available -->
256
+ <VJoyAvailability
257
+ status="AVAILABLE_AND_VERIFIED"
258
+ :is-partial="true"
259
+ label="Partially available"
260
+ />
261
+
262
+ <!-- Unavailable with return date -->
263
+ <VJoyAvailability
264
+ status="NOT_AVAILABLE_WITH_DATE"
265
+ label="Not available until 30 July"
266
+ />
267
+
268
+ <!-- Dense pool row: dot only (often beside VJoyAvatar) -->
269
+ <VJoyAvailability status="AVAILABLE_SOON" />
270
+
271
+ <!-- Soon / not available -->
272
+ <VJoyAvailability status="NOT_AVAILABLE" label="Not available" />
273
+ </template>
274
+ ```
275
+
276
+ In Nuxt (or apps with auto-import), omit the import if `VJoyAvailability` is already global.
277
+
278
+ ---
279
+
280
+ ## Related
281
+
282
+ | Component | Use when |
283
+ | --- | --- |
284
+ | `VJoyAvatar` | User photo / initials — availability dot overlays the avatar in pool views |
285
+ | `VJoyBadge` | Generic tags, categories, or non-availability status |
286
+ | `VJoyDot` | Notification counts or simple semantic dots unrelated to availability |
287
+ | `VJoyUserCard` | Structured profile cards that may compose avatar + metadata |
288
+ | `VJoyTooltip` | Extra explanation when dot-only mode needs supplementary detail |
289
+
290
+ ---
291
+
292
+ ## For agents
293
+
294
+ Optional for readers; **required** for vibe-coding quality. Maps to `agentDocumentBlocks` in [`JoyAvailability.dsds.json`](./JoyAvailability.dsds.json).
295
+
296
+ ### Pick the right component
297
+
298
+ | If the intent is… | Emit… | Do not emit… |
299
+ | --- | --- | --- |
300
+ | Freelancer / user availability | `VJoyAvailability` | `VJoyBadge` or `VJoyDot` with custom colors |
301
+ | Generic status tag | `VJoyBadge` | `VJoyAvailability` |
302
+ | Notification count on an icon | `VJoyDot` | `VJoyAvailability` |
303
+ | Avatar with pool overlay dot | `VJoyAvatar` + `VJoyAvailability` (no label) | Custom positioned `<span>` |
304
+ | Editable schedule | Form / settings UI | Read-only `VJoyAvailability` |
305
+
306
+ ### Hard rules
307
+
308
+ 1. **MUST** call `joy_get_component_info("VJoyAvailability")` and/or `joy_get_component_types("VJoyAvailability")` (or read `JoyAvailability.types.ts`) before generating props.
309
+ 2. **MUST** use only documented props: `label`, `status`, `isPartial`.
310
+ 3. **MUST** use only `TJoyAvailabilityStatus` enum values — no invented statuses (`INVISIBLE`, `offline`, …).
311
+ 4. **MUST NOT** invent props (`variant`, `size`, `color`, `href`, …).
312
+ 5. **MUST NOT** override `.joy-availability` / `.joy-availability__dot` colors in product CSS — use `status` + tokens.
313
+ 6. **SHOULD** default to `status="AVAILABLE"` when data is missing; prefer explicit mapping from API fields.
314
+ 7. **SHOULD** omit `label` for dot-only avatar overlays; include `label` on profile and search surfaces.
315
+
316
+ ### Valid enums (from `JoyAvailability.types.ts`)
317
+
318
+ | Prop | Values |
319
+ | --- | --- |
320
+ | `status` | `AVAILABLE`, `AVAILABLE_AND_VERIFIED`, `NOT_AVAILABLE_WITH_DATE`, `AVAILABLE_SOON`, `NOT_AVAILABLE` |
321
+ | `isPartial` | `true`, `false` (default `false`) |
322
+ | `label` | `string` or omit |
323
+
324
+ ### Checklist
325
+
326
+ - [ ] Correct component (`VJoyAvailability` or named alternative)
327
+ - [ ] `status` from `TJoyAvailabilityStatus` only
328
+ - [ ] `label` text consistent with `status`
329
+ - [ ] `isPartial` only for defined partial-availability cases
330
+ - [ ] Dot-only only in dense / avatar-overlay contexts
331
+ - [ ] No invented props / no custom availability chrome CSS
332
+ - [ ] Long labels understood to truncate; `title` is a bonus, not primary a11y
333
+
334
+ ---
335
+
336
+ ## DSDS mapping
337
+
338
+ This Markdown mirrors [`JoyAvailability.dsds.json`](./JoyAvailability.dsds.json) (DSDS **0.15.2**).
339
+
340
+ | Section here | DSDS block |
341
+ | --- | --- |
342
+ | When to use / not | `use-cases` |
343
+ | Anatomy | `anatomy` |
344
+ | Variants (`status` / `isPartial`) | `variants` |
345
+ | Sizes | `design-specifications` |
346
+ | States | `states` |
347
+ | Best practices / content rules | `guidelines` (+ `content`) |
348
+ | Accessibility | `accessibility` |
349
+ | Examples | `sections` |
350
+ | For agents | `agentDocumentBlocks` |
351
+ | Props detail | `api` in JSON + Joy MCP |
352
+ | Imports | `imports` in JSON |
@@ -0,0 +1,192 @@
1
+ ---
2
+ component: VJoyAvatar
3
+ status: draft
4
+ language: en
5
+ dsds: JoyAvatar.dsds.json
6
+ dsdsVersion: "0.15.2"
7
+ ---
8
+
9
+ # Avatar
10
+
11
+ Use **`VJoyAvatar`** when you need to show a person (or overflow count) at a glance — profile photo, initials, anonymous placeholder, or a “+N more” chip in a list.
12
+
13
+ It supports six sizes, optional click styling via `link` (you handle navigation in `@click`), a Malt Strategy badge, and a default slot for custom image markup when `photoUrl` is not enough.
14
+
15
+ | | |
16
+ | --- | --- |
17
+ | **Code** | `VJoyAvatar` from `@maltjoy/core-vue` |
18
+ | **Design** | [ZeroHeight — Avatar](https://zeroheight.com/6bf479565/p/52ceb2-avatar) |
19
+ | **Storybook** | [VJoyAvatar docs](https://doc.malt.tech/joy-storybook/?path=/docs/components-view-vjoyavatar--docs) |
20
+ | **DSDS (machine)** | [`JoyAvatar.dsds.json`](./JoyAvatar.dsds.json) |
21
+ | **Live API** | `joy_get_component_info("VJoyAvatar")` |
22
+
23
+ ---
24
+
25
+ ## When to use this component
26
+
27
+ Use an avatar to identify a user in compact UI — profile headers, comment threads, member lists, cards, or toolbars. Provide `photoUrl` (or an `<img>` in the default slot) when a photo exists; otherwise pass `fullName` so initials render on a colored background.
28
+
29
+ For stacked or overlapping avatars, compose multiple `VJoyAvatar` instances inside **`VJoyAvatarsList`** (optionally with `compress`). Use `totalNumber` on the last avatar to show how many people are not shown (for example `+18`).
30
+
31
+ ### When not to use this component
32
+
33
+ | Need | Use instead |
34
+ | --- | --- |
35
+ | A group container with list spacing / compression | `VJoyAvatarsList` wrapping `VJoyAvatar` children |
36
+ | Company logo only (legacy) | `VJoyAvatar` with `placeholder="company-placeholder"` — **`VJoyCompanyAvatar` is deprecated** |
37
+ | Full user identity block (name, role, metadata) | `VJoyUserCard` |
38
+ | A decorative illustration or generic icon | `VJoyIcon` / `VJoyIllustration` — not an avatar |
39
+ | Real navigation via URL (`href`) | `link` + `@click` with your router, or wrap with `VJoyLink` — `link` only applies button styling |
40
+ | Custom circular image markup / ad-hoc CSS | Still use `VJoyAvatar` + Joy tokens — don’t reinvent chrome |
41
+
42
+ > **Deprecated:** `VJoyCompanyAvatar` — merged into `VJoyAvatar` (see release notes). Do not add new usages of the old component.
43
+
44
+ > **Not in the Vue API:** legacy Stencil `joy-avatar` props `href`, `color`, `compress`, and `is-first-from-list`. Compression comes from `VJoyAvatarsList` via provide/inject; there is no `color` or `href` prop on `VJoyAvatar`.
45
+
46
+ ---
47
+
48
+ ## How it works
49
+
50
+ ### Anatomy
51
+
52
+ | Part | Required? | What it is |
53
+ | --- | --- | --- |
54
+ | Wrapper | Yes | `.joy-avatar__wrapper` — sets dimensions from `size` |
55
+ | Avatar surface | Yes | Root `.joy-avatar` — photo, initials, icon, or `+N` text |
56
+ | Photo | No | `<img>` from `photoUrl` or default slot (slot preferred for perf / Nuxt image wrappers) |
57
+ | Initials | No | Up to two letters from `fullName` (first letter of first two name segments) |
58
+ | Placeholder icon | No | `VJoyIcon` when anonymous (`placeholder`, default `user-photo`) |
59
+ | Strategy badge | No | `.joy-avatar__strategy` SVG when `profile="strategy"` |
60
+ | Focus ring | Yes* | Box shadow on focus when the surface is focusable (`link`) |
61
+
62
+ ### Display modes (by props, not a `variant` prop)
63
+
64
+ | Mode | When it appears |
65
+ | --- | --- |
66
+ | **Photo** | `photoUrl` set, or default slot contains an `<img>` |
67
+ | **Initials** | `fullName` set, no photo, `showLetters` not `false` |
68
+ | **Anonymous** | No `fullName`, `photoUrl`, `totalNumber`, or `isEmpty` — shows placeholder icon |
69
+ | **Empty** | `isEmpty` — neutral bordered circle, no icon or text |
70
+ | **Overflow count** | `totalNumber` — shows `+{n}` (mutually exclusive with `fullName` and `photoUrl`) |
71
+ | **Strategy** | `profile="strategy"` — adds the Strategy badge overlay |
72
+
73
+ ### Default values
74
+
75
+ - `size` defaults to **`medium`**
76
+ - `profile` defaults to **`default`**
77
+ - `loading` defaults to **`lazy`** (on the built-in `<img>` when `photoUrl` is used)
78
+ - `isEmpty` defaults to **`false`**
79
+ - `placeholder` defaults to **`user-photo`**
80
+ - `showLetters` defaults to **`true`**
81
+ - `link` defaults to **`false`**
82
+
83
+ Props, events, and slots: use Joy MCP or Storybook — this page focuses on **when** and **how**, not a full API dump.
84
+
85
+ ---
86
+
87
+ ## Best practices
88
+
89
+ Rules use RFC 2119 strength (**MUST** / **SHOULD** / **MUST NOT** / **SHOULD NOT**).
90
+
91
+ ### Data and display
92
+
93
+ - **MUST NOT** combine `totalNumber` with `fullName` or `photoUrl` — pick either a person avatar or an overflow chip (enforced by ESLint).
94
+ - **SHOULD** pass `fullName` whenever a photo is shown so `alt` / `title` stay meaningful.
95
+ - **SHOULD** use the default slot (custom `<img>` or image component) instead of `photoUrl` when you need framework-specific image optimization.
96
+ - **SHOULD** set `showLetters` to `false` only when you want the placeholder icon despite having a name (rare).
97
+
98
+ ### Lists and navigation
99
+
100
+ - **SHOULD** wrap multiple avatars in `VJoyAvatarsList`; use `compress` on the list for overlapping stacks — do not set compression on individual avatars.
101
+ - **MUST** handle routing yourself when `link` is true — the root becomes a `<button type="button">`; there is no built-in `href`.
102
+ - **SHOULD** reserve `profile="strategy"` for Malt Strategy consultants only.
103
+
104
+ ### Implementation
105
+
106
+ - **MUST** use only documented prop / enum values (MCP / types). Sizes: `xsmall`, `small`, `medium`, `large`, `xlarge`, `xxlarge`.
107
+ - **MUST** use Joy tokens — no custom avatar chrome CSS (dimensions come from `--avatar-size` and related tokens).
108
+ - **MUST NOT** invent props (`color`, `href`, `compress` from legacy Stencil are not on `VJoyAvatar`).
109
+
110
+ ### Do / don’t
111
+
112
+ | Do | Don’t |
113
+ | --- | --- |
114
+ | Photo + `fullName` for accessible images | `totalNumber` alongside `fullName` or `photoUrl` |
115
+ | `VJoyAvatarsList` for groups | Manual negative margins to overlap avatars |
116
+ | `@click` + router when `link` | Expect `link` to navigate by itself |
117
+ | `placeholder="company-placeholder"` for org logos | New `VJoyCompanyAvatar` instances |
118
+
119
+ ---
120
+
121
+ ## Accessibility
122
+
123
+ Behaviors (what must happen), not slogans.
124
+
125
+ | Behavior | Expectation |
126
+ | --- | --- |
127
+ | Image name | When `photoUrl` (or slot img) is used, `alt` and `title` come from `fullName` — provide it when possible |
128
+ | Non-photo identity | Initials or `+N` text are visible content; anonymous state relies on the placeholder icon (decorative in context — ensure nearby text names the person) |
129
+ | Clickable avatar | With `link`, root is a `<button>`; keyboard users get focus ring (`--joy-form-field-focus-shadow`) — wire `@click` for the action |
130
+ | Hover | `link` reduces opacity on hover — supplementary cue only; don’t rely on hover alone for critical info |
131
+
132
+ Target: **WCAG 2.2 AA** where the product requires it.
133
+
134
+ ---
135
+
136
+ ## Examples
137
+
138
+ ```vue
139
+ <script setup lang="ts">
140
+ import { VJoyAvatar, VJoyAvatarsList } from '@maltjoy/core-vue'
141
+ import { useRouter } from 'vue-router'
142
+
143
+ const router = useRouter()
144
+
145
+ function goToProfile() {
146
+ router.push('/profile/ada')
147
+ }
148
+ </script>
149
+
150
+ <template>
151
+ <!-- Photo + accessible name -->
152
+ <VJoyAvatar
153
+ full-name="Ada Lovelace"
154
+ photo-url="https://example.com/ada.webp"
155
+ size="medium"
156
+ />
157
+
158
+ <!-- Initials fallback -->
159
+ <VJoyAvatar full-name="Jean-Sébastien Bach" size="small" />
160
+
161
+ <!-- Clickable (style only — handle navigation) -->
162
+ <VJoyAvatar
163
+ link
164
+ full-name="Ellie Sattler"
165
+ photo-url="https://example.com/ellie.webp"
166
+ @click="goToProfile"
167
+ />
168
+
169
+ <!-- Avatar list with overflow -->
170
+ <VJoyAvatarsList compress>
171
+ <VJoyAvatar photo-url="https://example.com/a.webp" full-name="User A" size="small" />
172
+ <VJoyAvatar photo-url="https://example.com/b.webp" full-name="User B" size="small" />
173
+ <VJoyAvatar :total-number="18" size="small" />
174
+ </VJoyAvatarsList>
175
+
176
+ <!-- Malt Strategy consultant -->
177
+ <VJoyAvatar full-name="Strategy Consultant" profile="strategy" size="large" />
178
+ </template>
179
+ ```
180
+
181
+ In Nuxt (or apps with auto-import), omit the import if `VJoyAvatar` is already global.
182
+
183
+ ---
184
+
185
+ ## Related
186
+
187
+ | Component | Use when |
188
+ | --- | --- |
189
+ | `VJoyAvatarsList` | Layout and optional compression for multiple avatars |
190
+ | `VJoyUserCard` | Avatar plus name, subtitle, and actions in a card |
191
+ | `VJoyIcon` | Standalone icons without a circular avatar treatment |
192
+ | `VJoyCompanyAvatar` | **Deprecated** — use `VJoyAvatar` with `placeholder="company-placeholder"` |