solid-tom-ui 1.0.10 → 1.0.14
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/README.md +246 -246
- package/dist/README.md +246 -246
- package/dist/components/avatar/avatar.js.map +1 -1
- package/dist/components/badge/badge.js.map +1 -1
- package/dist/components/breadcrumb/breadcrumb.js.map +1 -1
- package/dist/components/button/button.js.map +1 -1
- package/dist/components/carousel/carousel.js.map +1 -1
- package/dist/components/chat-bubble/chatBubble.js.map +1 -1
- package/dist/components/checkbox/checkbox.js.map +1 -1
- package/dist/components/collapse/collapse.js.map +1 -1
- package/dist/components/context-menu/context-menu.js.map +1 -1
- package/dist/components/context-menu/context-menu.store.js.map +1 -1
- package/dist/components/divider/divider.js.map +1 -1
- package/dist/components/dropdown/dropdown.js.map +1 -1
- package/dist/components/dropdown/dropdown.store.js.map +1 -1
- package/dist/components/float-button/float-button.js.map +1 -1
- package/dist/components/hover-3d-image/hover-3d-image.js.map +1 -1
- package/dist/components/image-preview/image-preview.js.map +1 -1
- package/dist/components/input/input.js.map +1 -1
- package/dist/components/input/input.utils.js.map +1 -1
- package/dist/components/input/variants/input-color.js.map +1 -1
- package/dist/components/input/variants/input-date.js.map +1 -1
- package/dist/components/input/variants/input-number.d.ts.map +1 -1
- package/dist/components/input/variants/input-number.js +1 -1
- package/dist/components/input/variants/input-number.js.map +1 -1
- package/dist/components/input/variants/input-otp.js.map +1 -1
- package/dist/components/input/variants/input-password.js.map +1 -1
- package/dist/components/input/variants/input-radio.js.map +1 -1
- package/dist/components/input/variants/input-range.js.map +1 -1
- package/dist/components/input/variants/input-text.d.ts.map +1 -1
- package/dist/components/input/variants/input-text.js +1 -1
- package/dist/components/input/variants/input-text.js.map +1 -1
- package/dist/components/input/variants/input-textarea.js.map +1 -1
- package/dist/components/loading/loading.js.map +1 -1
- package/dist/components/mansory/mansory.js.map +1 -1
- package/dist/components/menu/menu.js.map +1 -1
- package/dist/components/menu/menu.types.d.ts +2 -3
- package/dist/components/menu/menu.types.d.ts.map +1 -1
- package/dist/components/modal/modal.js.map +1 -1
- package/dist/components/modal/modalContext.js.map +1 -1
- package/dist/components/pagination/pagination.js.map +1 -1
- package/dist/components/progress-bar/progress-bar.js.map +1 -1
- package/dist/components/qr-code/qr-code.js.map +1 -1
- package/dist/components/select/select.js.map +1 -1
- package/dist/components/select-zone/select-zone.js.map +1 -1
- package/dist/components/skeleton/skeleton.js.map +1 -1
- package/dist/components/slider/slider.js.map +1 -1
- package/dist/components/splitter/splitter.js.map +1 -1
- package/dist/components/steps/steps.js.map +1 -1
- package/dist/components/swap/swap.js.map +1 -1
- package/dist/components/switch/switch.js.map +1 -1
- package/dist/components/tab/tab.js.map +1 -1
- package/dist/components/table/table.js.map +1 -1
- package/dist/components/timeline/timeline.js.map +1 -1
- package/dist/components/toast/icons/ErrorIcon.js.map +1 -1
- package/dist/components/toast/icons/IconCircle.js.map +1 -1
- package/dist/components/toast/icons/InfoIcon.js.map +1 -1
- package/dist/components/toast/icons/LoaderIcon.js.map +1 -1
- package/dist/components/toast/icons/SuccessIcon.js.map +1 -1
- package/dist/components/toast/icons/WarningIcon.js.map +1 -1
- package/dist/components/toast/toast.js.map +1 -1
- package/dist/components/toast/toast.store.js.map +1 -1
- package/dist/components/tooltip/tooltip.js.map +1 -1
- package/dist/components/tour/tour.js.map +1 -1
- package/dist/components/upload/upload.js.map +1 -1
- package/dist/components/z-index/z-index.context.js.map +1 -1
- package/dist/components/z-index/z-index.js.map +1 -1
- package/dist/components/z-index/z-index.store.js.map +1 -1
- package/dist/components/z-index/z-index.types.js.map +1 -1
- package/dist/package.json +1 -1
- package/dist/skill/avatar.skill.md.txt +255 -255
- package/dist/skill/badge.skill.md.txt +223 -223
- package/dist/skill/breadcrumb.skill.md.txt +177 -177
- package/dist/skill/button.skill.md.txt +198 -198
- package/dist/skill/carousel.skill.md.txt +406 -406
- package/dist/skill/chat-bubble.skill.md.txt +342 -342
- package/dist/skill/checkbox.skill.md.txt +326 -326
- package/dist/skill/code-preview.skill.md.txt +240 -240
- package/dist/skill/collapse.skill.md.txt +329 -329
- package/dist/skill/context-menu.skill.md.txt +233 -233
- package/dist/skill/diff.skill.md.txt +244 -244
- package/dist/skill/divider.skill.md.txt +151 -151
- package/dist/skill/doc.skill.md.txt +191 -191
- package/dist/skill/drawer.skill.md.txt +157 -157
- package/dist/skill/dropdown.skill.md.txt +198 -198
- package/dist/skill/float-button.skill.md.txt +315 -315
- package/dist/skill/hover-3d-image.skill.md.txt +120 -120
- package/dist/skill/iframe.skill.md.txt +114 -114
- package/dist/skill/image-preview.skill.md.txt +162 -162
- package/dist/skill/indicator.skill.md.txt +60 -60
- package/dist/skill/input.skill.md.txt +489 -489
- package/dist/skill/loading.skill.md.txt +127 -127
- package/dist/skill/menu.skill.md.txt +476 -476
- package/dist/skill/modal.skill.md.txt +359 -359
- package/dist/skill/pagination.skill.md.txt +405 -405
- package/dist/skill/progress-bar.skill.md.txt +207 -207
- package/dist/skill/qr-code.skill.md.txt +136 -136
- package/dist/skill/rating.skill.md.txt +167 -167
- package/dist/skill/select-zone.skill.md.txt +93 -93
- package/dist/skill/select.skill.md.txt +663 -663
- package/dist/skill/skeleton.skill.md.txt +192 -192
- package/dist/skill/slider.skill.md.txt +404 -404
- package/dist/skill/splitter.skill.md.txt +411 -411
- package/dist/skill/steps.skill.md.txt +264 -264
- package/dist/skill/swap.skill.md.txt +139 -139
- package/dist/skill/switch.skill.md.txt +191 -191
- package/dist/skill/tab.skill.md.txt +484 -484
- package/dist/skill/table.example.header.md.txt +666 -666
- package/dist/skill/table.skill.md.txt +1407 -1407
- package/dist/skill/text-rotate.skill.md.txt +186 -186
- package/dist/skill/timeline.skill.md.txt +247 -247
- package/dist/skill/toast.skill.md.txt +531 -531
- package/dist/skill/tooltip.skill.md.txt +222 -222
- package/dist/skill/tour.skill.md.txt +156 -156
- package/dist/skill/upload.skill.md.txt +358 -358
- package/dist/utils/cn.js.map +1 -1
- package/dist/utils/element-tracker.js.map +1 -1
- package/dist/utils/helper.js.map +1 -1
- package/dist/utils/hoc.js.map +1 -1
- package/package.json +132 -133
|
@@ -1,255 +1,255 @@
|
|
|
1
|
-
## COMPONENT IDENTITY
|
|
2
|
-
- **Import**: `import { Avatar } from 'solid-tom-ui';`
|
|
3
|
-
- **Exports**: `Avatar` (main), `Avatar.Group` (sub-component)
|
|
4
|
-
- **Framework**: SolidJS
|
|
5
|
-
- **Purpose**: Display user profile images, initials, or icon placeholders; supports groups
|
|
6
|
-
|
|
7
|
-
## TYPE SIGNATURES
|
|
8
|
-
|
|
9
|
-
### Avatar (single)
|
|
10
|
-
```typescript
|
|
11
|
-
import { Avatar } from 'solid-tom-ui';
|
|
12
|
-
|
|
13
|
-
type AvatarProps = {
|
|
14
|
-
width: string | number; // REQUIRED: size in px (number) or CSS units (string)
|
|
15
|
-
image?: string; // Image URL — if provided, renders <img>
|
|
16
|
-
placeholder?: SolidComponent; // Fallback JSX shown when no image (initials, icon, etc.)
|
|
17
|
-
mask?: 'heart' | 'squircle' | 'hexagon'; // Shape mask; omit for default circle
|
|
18
|
-
status?: 'online' | 'offline'; // Status indicator dot; omit for no indicator
|
|
19
|
-
class?: {
|
|
20
|
-
avatar?: string; // Extra classes on the avatar container div
|
|
21
|
-
};
|
|
22
|
-
};
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
### Avatar.Group
|
|
26
|
-
```typescript
|
|
27
|
-
type AvatarGroup = {
|
|
28
|
-
width: string | number; // REQUIRED: uniform size for all avatars in group
|
|
29
|
-
avatars: Omit<AvatarProps, 'width' | 'status'>[]; // REQUIRED: array of avatar configs
|
|
30
|
-
counter?: number; // Show "+N" badge at end of group
|
|
31
|
-
class?: string; // Extra classes on the group container
|
|
32
|
-
};
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
## KEY RULES
|
|
36
|
-
- `width` is **always required** on both `Avatar` and `Avatar.Group`
|
|
37
|
-
- `image` and `placeholder` are mutually exclusive in intent — if `image` is set and loads, `placeholder` is not shown
|
|
38
|
-
- `Avatar.Group` does **not** support per-avatar `status` — statuses are stripped in the group type
|
|
39
|
-
- In `Avatar.Group`, the `width` prop applies uniformly to all avatars; individual avatar items cannot override it
|
|
40
|
-
|
|
41
|
-
## WIDTH SPECIFICATION
|
|
42
|
-
```tsx
|
|
43
|
-
// Number → interpreted as pixels
|
|
44
|
-
<Avatar width={48} image={url} /> // 48px × 48px
|
|
45
|
-
|
|
46
|
-
// String → any valid CSS unit
|
|
47
|
-
<Avatar width="3rem" image={url} />
|
|
48
|
-
<Avatar width="5rem" image={url} />
|
|
49
|
-
<Avatar width="100px" image={url} />
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
## MASK (SHAPE) OPTIONS
|
|
53
|
-
| `mask` value | Shape |
|
|
54
|
-
|-------------|-------|
|
|
55
|
-
| `undefined` (omit) | Circle (default) |
|
|
56
|
-
| `"squircle"` | Rounded square |
|
|
57
|
-
| `"hexagon"` | Hexagonal |
|
|
58
|
-
| `"heart"` | Heart shape |
|
|
59
|
-
|
|
60
|
-
## STATUS INDICATOR
|
|
61
|
-
| `status` value | Indicator |
|
|
62
|
-
|---------------|-----------|
|
|
63
|
-
| `undefined` (omit) | None |
|
|
64
|
-
| `"online"` | Green dot |
|
|
65
|
-
| `"offline"` | Gray dot |
|
|
66
|
-
|
|
67
|
-
## USAGE PATTERNS
|
|
68
|
-
|
|
69
|
-
### Basic image avatar (circle, no status)
|
|
70
|
-
```tsx
|
|
71
|
-
<Avatar image="https://example.com/user.jpg" width={48} />
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
### Sized avatar
|
|
75
|
-
```tsx
|
|
76
|
-
// Common sizes: 32, 48, 64, 80, 96 (pixels)
|
|
77
|
-
<Avatar image={userPhotoUrl} width={32} /> // small (e.g., in list rows)
|
|
78
|
-
<Avatar image={userPhotoUrl} width={48} /> // medium (e.g., comment threads)
|
|
79
|
-
<Avatar image={userPhotoUrl} width={64} /> // large (e.g., profile cards)
|
|
80
|
-
<Avatar image={userPhotoUrl} width={96} /> // xl (e.g., profile page header)
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
### With online/offline status
|
|
84
|
-
```tsx
|
|
85
|
-
<Avatar image={userPhotoUrl} width={48} status="online" />
|
|
86
|
-
<Avatar image={userPhotoUrl} width={48} status="offline" />
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
### With mask (non-circle shape)
|
|
90
|
-
```tsx
|
|
91
|
-
<Avatar image={userPhotoUrl} width={64} mask="squircle" />
|
|
92
|
-
<Avatar image={userPhotoUrl} width={64} mask="hexagon" />
|
|
93
|
-
<Avatar image={userPhotoUrl} width={64} mask="heart" />
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
### Placeholder — initials (when no image)
|
|
97
|
-
```tsx
|
|
98
|
-
<Avatar
|
|
99
|
-
width={64}
|
|
100
|
-
placeholder={
|
|
101
|
-
<div class="bg-neutral text-neutral-content flex h-16 w-16 items-center justify-center rounded-full">
|
|
102
|
-
<span class="text-xl">AB</span>
|
|
103
|
-
</div>
|
|
104
|
-
}
|
|
105
|
-
/>
|
|
106
|
-
```
|
|
107
|
-
|
|
108
|
-
### Placeholder — icon (generic user silhouette)
|
|
109
|
-
```tsx
|
|
110
|
-
<Avatar
|
|
111
|
-
width={64}
|
|
112
|
-
placeholder={
|
|
113
|
-
<div class="bg-primary text-primary-content flex h-16 w-16 items-center justify-center rounded-full">
|
|
114
|
-
<DynamicIcon name="user" size={32} />
|
|
115
|
-
</div>
|
|
116
|
-
}
|
|
117
|
-
/>
|
|
118
|
-
```
|
|
119
|
-
|
|
120
|
-
### Placeholder with status
|
|
121
|
-
```tsx
|
|
122
|
-
<Avatar
|
|
123
|
-
width={64}
|
|
124
|
-
status="online"
|
|
125
|
-
placeholder={
|
|
126
|
-
<div class="bg-accent text-accent-content flex h-16 w-16 items-center justify-center rounded-full">
|
|
127
|
-
<span class="text-xl">JD</span>
|
|
128
|
-
</div>
|
|
129
|
-
}
|
|
130
|
-
/>
|
|
131
|
-
```
|
|
132
|
-
|
|
133
|
-
### Avatar.Group — basic group
|
|
134
|
-
```tsx
|
|
135
|
-
const users = [
|
|
136
|
-
{ image: 'https://example.com/user1.jpg' },
|
|
137
|
-
{ image: 'https://example.com/user2.jpg' },
|
|
138
|
-
{ image: 'https://example.com/user3.jpg' },
|
|
139
|
-
];
|
|
140
|
-
|
|
141
|
-
<Avatar.Group width={48} avatars={users} />
|
|
142
|
-
```
|
|
143
|
-
|
|
144
|
-
### Avatar.Group — with overflow counter
|
|
145
|
-
```tsx
|
|
146
|
-
// Shows avatars + "+12" badge at the end
|
|
147
|
-
<Avatar.Group
|
|
148
|
-
width={48}
|
|
149
|
-
avatars={[
|
|
150
|
-
{ image: url1 },
|
|
151
|
-
{ image: url2 },
|
|
152
|
-
{ image: url3 },
|
|
153
|
-
]}
|
|
154
|
-
counter={12}
|
|
155
|
-
/>
|
|
156
|
-
```
|
|
157
|
-
|
|
158
|
-
### Avatar.Group — with custom masks
|
|
159
|
-
```tsx
|
|
160
|
-
<Avatar.Group
|
|
161
|
-
width={48}
|
|
162
|
-
avatars={[
|
|
163
|
-
{ image: url1, mask: 'squircle' },
|
|
164
|
-
{ image: url2, mask: 'squircle' },
|
|
165
|
-
{ image: url3, mask: 'squircle' },
|
|
166
|
-
]}
|
|
167
|
-
counter={5}
|
|
168
|
-
/>
|
|
169
|
-
```
|
|
170
|
-
|
|
171
|
-
### Avatar.Group — with placeholder avatars
|
|
172
|
-
```tsx
|
|
173
|
-
<Avatar.Group
|
|
174
|
-
width={40}
|
|
175
|
-
avatars={[
|
|
176
|
-
{ image: url1 },
|
|
177
|
-
{
|
|
178
|
-
placeholder: (
|
|
179
|
-
<div class="bg-neutral text-neutral-content flex items-center justify-center rounded-full" style={{ width: '40px', height: '40px' }}>
|
|
180
|
-
<span class="text-sm">AB</span>
|
|
181
|
-
</div>
|
|
182
|
-
)
|
|
183
|
-
},
|
|
184
|
-
{ image: url3 },
|
|
185
|
-
]}
|
|
186
|
-
counter={8}
|
|
187
|
-
/>
|
|
188
|
-
```
|
|
189
|
-
|
|
190
|
-
## DECISION RULES
|
|
191
|
-
|
|
192
|
-
**Single Avatar vs Avatar.Group:**
|
|
193
|
-
- One user → `Avatar`
|
|
194
|
-
- Multiple users shown together (team, participants, collaborators) → `Avatar.Group`
|
|
195
|
-
|
|
196
|
-
**Image vs placeholder:**
|
|
197
|
-
- User has a profile photo → use `image`
|
|
198
|
-
- No profile photo → use `placeholder` with initials derived from user's name
|
|
199
|
-
- Unknown user → use `placeholder` with a generic user icon
|
|
200
|
-
|
|
201
|
-
**Width selection:**
|
|
202
|
-
- Navigation bar / list row → `32` or `40`
|
|
203
|
-
- Comment / chat UI → `48`
|
|
204
|
-
- Card / profile preview → `64`
|
|
205
|
-
- Full profile page header → `80` or `96`
|
|
206
|
-
- Group avatars → smaller size (e.g., `40` or `48`) since they overlap
|
|
207
|
-
|
|
208
|
-
**Mask selection:**
|
|
209
|
-
- Standard user avatar → no mask (circle)
|
|
210
|
-
- App/bot/system avatar → `squircle` or `hexagon`
|
|
211
|
-
- Decorative / brand avatar → `heart` or any mask
|
|
212
|
-
|
|
213
|
-
**Status dots:**
|
|
214
|
-
- Real-time presence system → use `status`
|
|
215
|
-
- Static display (profile page without live data) → omit `status`
|
|
216
|
-
|
|
217
|
-
**Counter in Avatar.Group:**
|
|
218
|
-
- Total participants count is known → set `counter` to (total - displayed) or total count
|
|
219
|
-
- If all participants are shown → omit `counter`
|
|
220
|
-
|
|
221
|
-
## PLACEHOLDER SIZING NOTE
|
|
222
|
-
When using `placeholder`, the inner element's dimensions must match the `width` prop manually:
|
|
223
|
-
```tsx
|
|
224
|
-
// width={64} → inner element must be 64px × 64px
|
|
225
|
-
<Avatar
|
|
226
|
-
width={64}
|
|
227
|
-
placeholder={
|
|
228
|
-
<div class="flex h-16 w-16 items-center justify-center rounded-full bg-primary text-primary-content">
|
|
229
|
-
{/* h-16 = 64px, w-16 = 64px */}
|
|
230
|
-
<span>AB</span>
|
|
231
|
-
</div>
|
|
232
|
-
}
|
|
233
|
-
/>
|
|
234
|
-
```
|
|
235
|
-
|
|
236
|
-
## ANTI-PATTERNS
|
|
237
|
-
```tsx
|
|
238
|
-
// ❌ Missing required width
|
|
239
|
-
<Avatar image={url} /> // TypeScript error
|
|
240
|
-
|
|
241
|
-
// ❌ Setting status on Avatar.Group items (not supported — stripped from type)
|
|
242
|
-
<Avatar.Group width={48} avatars={[{ image: url, status: 'online' }]} /> // TypeScript error
|
|
243
|
-
|
|
244
|
-
// ❌ Mismatched placeholder size vs width prop
|
|
245
|
-
<Avatar width={96} placeholder={<div class="h-8 w-8 rounded-full bg-gray-300" />} />
|
|
246
|
-
// ✅ Match placeholder dimensions to width
|
|
247
|
-
<Avatar width={96} placeholder={<div class="h-24 w-24 rounded-full bg-gray-300" />} />
|
|
248
|
-
```
|
|
249
|
-
---
|
|
250
|
-
|
|
251
|
-
## Component Conventions
|
|
252
|
-
|
|
253
|
-
> **CSS encoding**: internal CSS classes use short encoded names (e.g. `av01`, `av02`) per project convention.
|
|
254
|
-
|
|
255
|
-
> **Unique IDs**: if this component needs to generate HTML `id` attributes, always use `createUniqueId()` from `solid-js` — never `Math.random()` or `Date.now()`.
|
|
1
|
+
## COMPONENT IDENTITY
|
|
2
|
+
- **Import**: `import { Avatar } from 'solid-tom-ui';`
|
|
3
|
+
- **Exports**: `Avatar` (main), `Avatar.Group` (sub-component)
|
|
4
|
+
- **Framework**: SolidJS
|
|
5
|
+
- **Purpose**: Display user profile images, initials, or icon placeholders; supports groups
|
|
6
|
+
|
|
7
|
+
## TYPE SIGNATURES
|
|
8
|
+
|
|
9
|
+
### Avatar (single)
|
|
10
|
+
```typescript
|
|
11
|
+
import { Avatar } from 'solid-tom-ui';
|
|
12
|
+
|
|
13
|
+
type AvatarProps = {
|
|
14
|
+
width: string | number; // REQUIRED: size in px (number) or CSS units (string)
|
|
15
|
+
image?: string; // Image URL — if provided, renders <img>
|
|
16
|
+
placeholder?: SolidComponent; // Fallback JSX shown when no image (initials, icon, etc.)
|
|
17
|
+
mask?: 'heart' | 'squircle' | 'hexagon'; // Shape mask; omit for default circle
|
|
18
|
+
status?: 'online' | 'offline'; // Status indicator dot; omit for no indicator
|
|
19
|
+
class?: {
|
|
20
|
+
avatar?: string; // Extra classes on the avatar container div
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### Avatar.Group
|
|
26
|
+
```typescript
|
|
27
|
+
type AvatarGroup = {
|
|
28
|
+
width: string | number; // REQUIRED: uniform size for all avatars in group
|
|
29
|
+
avatars: Omit<AvatarProps, 'width' | 'status'>[]; // REQUIRED: array of avatar configs
|
|
30
|
+
counter?: number; // Show "+N" badge at end of group
|
|
31
|
+
class?: string; // Extra classes on the group container
|
|
32
|
+
};
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## KEY RULES
|
|
36
|
+
- `width` is **always required** on both `Avatar` and `Avatar.Group`
|
|
37
|
+
- `image` and `placeholder` are mutually exclusive in intent — if `image` is set and loads, `placeholder` is not shown
|
|
38
|
+
- `Avatar.Group` does **not** support per-avatar `status` — statuses are stripped in the group type
|
|
39
|
+
- In `Avatar.Group`, the `width` prop applies uniformly to all avatars; individual avatar items cannot override it
|
|
40
|
+
|
|
41
|
+
## WIDTH SPECIFICATION
|
|
42
|
+
```tsx
|
|
43
|
+
// Number → interpreted as pixels
|
|
44
|
+
<Avatar width={48} image={url} /> // 48px × 48px
|
|
45
|
+
|
|
46
|
+
// String → any valid CSS unit
|
|
47
|
+
<Avatar width="3rem" image={url} />
|
|
48
|
+
<Avatar width="5rem" image={url} />
|
|
49
|
+
<Avatar width="100px" image={url} />
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## MASK (SHAPE) OPTIONS
|
|
53
|
+
| `mask` value | Shape |
|
|
54
|
+
|-------------|-------|
|
|
55
|
+
| `undefined` (omit) | Circle (default) |
|
|
56
|
+
| `"squircle"` | Rounded square |
|
|
57
|
+
| `"hexagon"` | Hexagonal |
|
|
58
|
+
| `"heart"` | Heart shape |
|
|
59
|
+
|
|
60
|
+
## STATUS INDICATOR
|
|
61
|
+
| `status` value | Indicator |
|
|
62
|
+
|---------------|-----------|
|
|
63
|
+
| `undefined` (omit) | None |
|
|
64
|
+
| `"online"` | Green dot |
|
|
65
|
+
| `"offline"` | Gray dot |
|
|
66
|
+
|
|
67
|
+
## USAGE PATTERNS
|
|
68
|
+
|
|
69
|
+
### Basic image avatar (circle, no status)
|
|
70
|
+
```tsx
|
|
71
|
+
<Avatar image="https://example.com/user.jpg" width={48} />
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Sized avatar
|
|
75
|
+
```tsx
|
|
76
|
+
// Common sizes: 32, 48, 64, 80, 96 (pixels)
|
|
77
|
+
<Avatar image={userPhotoUrl} width={32} /> // small (e.g., in list rows)
|
|
78
|
+
<Avatar image={userPhotoUrl} width={48} /> // medium (e.g., comment threads)
|
|
79
|
+
<Avatar image={userPhotoUrl} width={64} /> // large (e.g., profile cards)
|
|
80
|
+
<Avatar image={userPhotoUrl} width={96} /> // xl (e.g., profile page header)
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### With online/offline status
|
|
84
|
+
```tsx
|
|
85
|
+
<Avatar image={userPhotoUrl} width={48} status="online" />
|
|
86
|
+
<Avatar image={userPhotoUrl} width={48} status="offline" />
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### With mask (non-circle shape)
|
|
90
|
+
```tsx
|
|
91
|
+
<Avatar image={userPhotoUrl} width={64} mask="squircle" />
|
|
92
|
+
<Avatar image={userPhotoUrl} width={64} mask="hexagon" />
|
|
93
|
+
<Avatar image={userPhotoUrl} width={64} mask="heart" />
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### Placeholder — initials (when no image)
|
|
97
|
+
```tsx
|
|
98
|
+
<Avatar
|
|
99
|
+
width={64}
|
|
100
|
+
placeholder={
|
|
101
|
+
<div class="bg-neutral text-neutral-content flex h-16 w-16 items-center justify-center rounded-full">
|
|
102
|
+
<span class="text-xl">AB</span>
|
|
103
|
+
</div>
|
|
104
|
+
}
|
|
105
|
+
/>
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Placeholder — icon (generic user silhouette)
|
|
109
|
+
```tsx
|
|
110
|
+
<Avatar
|
|
111
|
+
width={64}
|
|
112
|
+
placeholder={
|
|
113
|
+
<div class="bg-primary text-primary-content flex h-16 w-16 items-center justify-center rounded-full">
|
|
114
|
+
<DynamicIcon name="user" size={32} />
|
|
115
|
+
</div>
|
|
116
|
+
}
|
|
117
|
+
/>
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Placeholder with status
|
|
121
|
+
```tsx
|
|
122
|
+
<Avatar
|
|
123
|
+
width={64}
|
|
124
|
+
status="online"
|
|
125
|
+
placeholder={
|
|
126
|
+
<div class="bg-accent text-accent-content flex h-16 w-16 items-center justify-center rounded-full">
|
|
127
|
+
<span class="text-xl">JD</span>
|
|
128
|
+
</div>
|
|
129
|
+
}
|
|
130
|
+
/>
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### Avatar.Group — basic group
|
|
134
|
+
```tsx
|
|
135
|
+
const users = [
|
|
136
|
+
{ image: 'https://example.com/user1.jpg' },
|
|
137
|
+
{ image: 'https://example.com/user2.jpg' },
|
|
138
|
+
{ image: 'https://example.com/user3.jpg' },
|
|
139
|
+
];
|
|
140
|
+
|
|
141
|
+
<Avatar.Group width={48} avatars={users} />
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### Avatar.Group — with overflow counter
|
|
145
|
+
```tsx
|
|
146
|
+
// Shows avatars + "+12" badge at the end
|
|
147
|
+
<Avatar.Group
|
|
148
|
+
width={48}
|
|
149
|
+
avatars={[
|
|
150
|
+
{ image: url1 },
|
|
151
|
+
{ image: url2 },
|
|
152
|
+
{ image: url3 },
|
|
153
|
+
]}
|
|
154
|
+
counter={12}
|
|
155
|
+
/>
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### Avatar.Group — with custom masks
|
|
159
|
+
```tsx
|
|
160
|
+
<Avatar.Group
|
|
161
|
+
width={48}
|
|
162
|
+
avatars={[
|
|
163
|
+
{ image: url1, mask: 'squircle' },
|
|
164
|
+
{ image: url2, mask: 'squircle' },
|
|
165
|
+
{ image: url3, mask: 'squircle' },
|
|
166
|
+
]}
|
|
167
|
+
counter={5}
|
|
168
|
+
/>
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### Avatar.Group — with placeholder avatars
|
|
172
|
+
```tsx
|
|
173
|
+
<Avatar.Group
|
|
174
|
+
width={40}
|
|
175
|
+
avatars={[
|
|
176
|
+
{ image: url1 },
|
|
177
|
+
{
|
|
178
|
+
placeholder: (
|
|
179
|
+
<div class="bg-neutral text-neutral-content flex items-center justify-center rounded-full" style={{ width: '40px', height: '40px' }}>
|
|
180
|
+
<span class="text-sm">AB</span>
|
|
181
|
+
</div>
|
|
182
|
+
)
|
|
183
|
+
},
|
|
184
|
+
{ image: url3 },
|
|
185
|
+
]}
|
|
186
|
+
counter={8}
|
|
187
|
+
/>
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
## DECISION RULES
|
|
191
|
+
|
|
192
|
+
**Single Avatar vs Avatar.Group:**
|
|
193
|
+
- One user → `Avatar`
|
|
194
|
+
- Multiple users shown together (team, participants, collaborators) → `Avatar.Group`
|
|
195
|
+
|
|
196
|
+
**Image vs placeholder:**
|
|
197
|
+
- User has a profile photo → use `image`
|
|
198
|
+
- No profile photo → use `placeholder` with initials derived from user's name
|
|
199
|
+
- Unknown user → use `placeholder` with a generic user icon
|
|
200
|
+
|
|
201
|
+
**Width selection:**
|
|
202
|
+
- Navigation bar / list row → `32` or `40`
|
|
203
|
+
- Comment / chat UI → `48`
|
|
204
|
+
- Card / profile preview → `64`
|
|
205
|
+
- Full profile page header → `80` or `96`
|
|
206
|
+
- Group avatars → smaller size (e.g., `40` or `48`) since they overlap
|
|
207
|
+
|
|
208
|
+
**Mask selection:**
|
|
209
|
+
- Standard user avatar → no mask (circle)
|
|
210
|
+
- App/bot/system avatar → `squircle` or `hexagon`
|
|
211
|
+
- Decorative / brand avatar → `heart` or any mask
|
|
212
|
+
|
|
213
|
+
**Status dots:**
|
|
214
|
+
- Real-time presence system → use `status`
|
|
215
|
+
- Static display (profile page without live data) → omit `status`
|
|
216
|
+
|
|
217
|
+
**Counter in Avatar.Group:**
|
|
218
|
+
- Total participants count is known → set `counter` to (total - displayed) or total count
|
|
219
|
+
- If all participants are shown → omit `counter`
|
|
220
|
+
|
|
221
|
+
## PLACEHOLDER SIZING NOTE
|
|
222
|
+
When using `placeholder`, the inner element's dimensions must match the `width` prop manually:
|
|
223
|
+
```tsx
|
|
224
|
+
// width={64} → inner element must be 64px × 64px
|
|
225
|
+
<Avatar
|
|
226
|
+
width={64}
|
|
227
|
+
placeholder={
|
|
228
|
+
<div class="flex h-16 w-16 items-center justify-center rounded-full bg-primary text-primary-content">
|
|
229
|
+
{/* h-16 = 64px, w-16 = 64px */}
|
|
230
|
+
<span>AB</span>
|
|
231
|
+
</div>
|
|
232
|
+
}
|
|
233
|
+
/>
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
## ANTI-PATTERNS
|
|
237
|
+
```tsx
|
|
238
|
+
// ❌ Missing required width
|
|
239
|
+
<Avatar image={url} /> // TypeScript error
|
|
240
|
+
|
|
241
|
+
// ❌ Setting status on Avatar.Group items (not supported — stripped from type)
|
|
242
|
+
<Avatar.Group width={48} avatars={[{ image: url, status: 'online' }]} /> // TypeScript error
|
|
243
|
+
|
|
244
|
+
// ❌ Mismatched placeholder size vs width prop
|
|
245
|
+
<Avatar width={96} placeholder={<div class="h-8 w-8 rounded-full bg-gray-300" />} />
|
|
246
|
+
// ✅ Match placeholder dimensions to width
|
|
247
|
+
<Avatar width={96} placeholder={<div class="h-24 w-24 rounded-full bg-gray-300" />} />
|
|
248
|
+
```
|
|
249
|
+
---
|
|
250
|
+
|
|
251
|
+
## Component Conventions
|
|
252
|
+
|
|
253
|
+
> **CSS encoding**: internal CSS classes use short encoded names (e.g. `av01`, `av02`) per project convention.
|
|
254
|
+
|
|
255
|
+
> **Unique IDs**: if this component needs to generate HTML `id` attributes, always use `createUniqueId()` from `solid-js` — never `Math.random()` or `Date.now()`.
|