@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,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"` |
|