canonrs-server 0.1.0

CanonRS server-side rendering support
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
---
component: Avatar
layer: UI
status: Stable
since: v1.0
last_review: 2025-01-18
ownership: canonrs
keywords:
  - design system
  - dioxus
  - ssr
  - avatar
  - profile
  - user identity
  - media
path_primitive: /opt/docker/monorepo/packages-rust/rs-design/src/primitives/avatar.rs
path_ui: /opt/docker/monorepo/packages-rust/rs-design/src/ui/avatar/
---

# Avatar

## 1. Conceptual Introduction

The Avatar is a **UI component** that displays user or entity identity through profile images or fallback initials. It serves as the canonical enterprise solution for user profiles, comment systems, identity chips, team rosters, and any interface requiring visual representation of people or entities.

The Avatar exists in the **UI layer** because it provides:
- Size variants (xs, sm, md, lg, xl) for different contexts
- Ergonomic composition of image and fallback states
- Semantic identity representation
- Composition of primitives without business logic

**What it is NOT:**
- Not a primitive (it composes primitives)
- Not a button (use AvatarButton if clickable)
- Not a badge (use Badge for status indicators)
- Not a layout component (it's a single identity representation)

---

## 2. Architectural Responsibility (Contract)

### Responsibility

The Avatar UI component:
- **Composes** `AvatarPrimitive`, `AvatarImage`, and `AvatarFallback`
- **Declares** size via `data-size` attribute (xs, sm, md, lg, xl)
- **Exposes** ergonomic API with `size` prop (default: `md`)
- **Emits** SSR-safe HTML with data-attributes for styling
- **Guarantees** circular container with image or fallback display

### Non-Responsibility

The Avatar UI component explicitly does NOT:
- ❌ Execute browser APIs (image loading, error handling beyond CSS)
- ❌ Manage online/offline status (use separate StatusIndicator)
- ❌ Apply CSS classes or inline styles
- ❌ Register event listeners (no click behavior)
- ❌ Perform side effects or mutations

**Side effects are PROHIBITED.**  
Avatar is purely presentational—image loading is native browser behavior.

---

## 3. Position in CanonRS Ecosystem

The Avatar participates in the canonical CanonRS flow:
```text
Page/Block (usage)
  ↓
UI Component (Avatar) — size variants, composition
  ↓
Primitives (AvatarPrimitive, AvatarImage, AvatarFallback) — HTML + data-attributes
  ↓
SSR Render — static HTML emitted
  ↓
CSS — styling via [data-avatar-*] selectors
  ↓
Browser — renders avatar (image load handled natively)
```

**SSR Context:**
- Avatar renders complete HTML structure on server
- Image `src` present in initial HTML (browser handles loading)
- Fallback visible until image loads (native `<img>` behavior)

**Hydration:**
- Avatar requires no hydration (no interactive behavior)
- CSS applies styling via data-attributes
- Image loading is native browser behavior

---

## 4. Tokens Applied

The Avatar UI component does **not directly apply tokens**—it delegates to CSS.  
The CSS layer (`style/ui/avatar.css`) consumes the following token families:

### Data & Media Family (F)
Avatar belongs to **Family F — Data & Media** (identity representation).

### Layout Tokens
- `--space-md` (implicit: size tokens derive from spacing scale)

### Typography Tokens
- `--font-family-sans` (fallback text)
- `--font-size-xs` (xs, sm sizes)
- `--font-size-sm` (md size)
- `--font-size-md` (lg, xl sizes)
- `--font-weight-medium` (fallback text weight)
- `--line-height-tight` (fallback text line height)

### Color Tokens
- `--color-bg-muted` (background, fallback background)
- `--color-fg-muted` (fallback text)
- `--color-border-muted` (border)
- `--color-bg-surface` (outlined variant background)
- `--color-border-default` (outlined variant border)

### Border & Radius Tokens
- `--border-width-hairline` (border)
- `--radius-lg` (circular: 50% effective, but token consistency)

### State Tokens
- `--state-disabled-opacity` (disabled state)

### Avatar Family Tokens (Defined in CSS)
- `--avatar-size` (size per variant: 1.5rem to 4rem)
- `--avatar-fallback-font-size` (scales with size)

**Token Resolution:**  
UI component emits `data-size` → CSS applies size tokens → Browser renders.

---

## 5. Technical Structure (How It Works)

### SSR Render Phase

The Avatar component renders to static HTML:
```html
<span data-avatar="" data-size="md">
  <img data-avatar-image="" src="/avatar.jpg" alt="John Doe" />
  <span data-avatar-fallback="">JD</span>
</span>
```

**Key contracts:**
- `data-avatar` marks root container (circular, overflow hidden)
- `data-size="xs|sm|md|lg|xl"` determines dimensions
- `data-avatar-image` marks profile image
- `data-avatar-fallback` marks fallback initials (shown if image fails to load)

### CSS Styling Phase

CSS selectors target data-attributes:
```css
[data-avatar] {
  width: var(--avatar-size, 2.5rem);
  height: var(--avatar-size, 2.5rem);
  border-radius: var(--radius-lg); /* Effectively circular */
  overflow: hidden;
}

[data-avatar][data-size="md"] {
  --avatar-size: 2.5rem;
  --avatar-fallback-font-size: var(--font-size-sm);
}

[data-avatar-image] {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

[data-avatar-fallback] {
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--avatar-fallback-font-size);
  color: var(--color-fg-muted);
}
```

**Image Loading Behavior:**
- Browser natively handles image loading
- If image loads successfully: image visible, fallback hidden
- If image fails: image hidden, fallback visible (native `<img>` error behavior + CSS)

**No classes. No inline styles. Only data-attributes.**

---

## 6. Execution Flow
```text
1. SSR Render (Server)
      Avatar component executes
      Emits span with data-avatar, data-size
      Includes img (with src) and fallback span

2. HTML Delivery (Network)
      Browser receives HTML
      Fallback visible initially

3. CSS Application (Client)
      Browser applies avatar.css
      Circular container with size applied

4. Image Load (Native Browser)
      Browser requests image from src
      If successful: image visible, fallback hidden
      If failed: fallback remains visible

5. Final Render
      User sees avatar image OR fallback initials
      No JavaScript required
```

**Critical:** Avatar is fully functional without JavaScript.  
Image loading and fallback are native browser behaviors.

---

## 7. Canonical Use Cases

### User Profile Avatar (Medium Size)
```rust
use dioxus::prelude::*;
use rs_design::ui::avatar::*;

fn UserAvatar() -> Element {
    rsx! {
        Avatar {
            size: AvatarSize::Md,
            
            AvatarImage {
                src: "/users/johndoe.jpg".to_string(),
                alt: "John Doe".to_string(),
            }
            AvatarFallback { "JD" }
        }
    }
}
```

### Small Avatar in Comment Thread
```rust
Avatar {
    size: AvatarSize::Sm,
    
    AvatarImage {
        src: "/users/jane.jpg".to_string(),
        alt: "Jane Smith".to_string(),
    }
    AvatarFallback { "JS" }
}
```

### Large Avatar in Profile Header
```rust
Avatar {
    size: AvatarSize::Lg,
    
    AvatarImage {
        src: "/users/profile.jpg".to_string(),
        alt: "User Profile".to_string(),
    }
    AvatarFallback { "UP" }
}
```

### Avatar Without Image (Fallback Only)
```rust
Avatar {
    size: AvatarSize::Md,
    
    AvatarFallback { "AB" }
}
```

### Extra Small Avatar in Roster
```rust
Avatar {
    size: AvatarSize::Xs,
    
    AvatarImage {
        src: "/team/member.jpg".to_string(),
        alt: "Team Member".to_string(),
    }
    AvatarFallback { "TM" }
}
```

---

## 8. Anti-Patterns (PROHIBITED)

### ❌ Anti-Pattern 1: Using Avatar as a Button
```rust
// WRONG — Avatar has no click behavior
Avatar {
    size: AvatarSize::Md,
    onclick: |_| { /* ... */ }, // FORBIDDEN
    
    AvatarImage { /* ... */ }
}
```

**Why it breaks:**
- Avatar is presentational only
- No interactive behavior built-in
- Not focusable or clickable

**Correct approach:**  
Wrap Avatar in a `<button>` or create `AvatarButton` component.

---

### ❌ Anti-Pattern 2: Inline Styles for Size
```rust
// WRONG — inline style instead of size prop
rsx! {
    span {
        style: "width: 3rem; height: 3rem", // FORBIDDEN
        img { src: "/avatar.jpg" }
    }
}
```

**Why it breaks:**
- Bypasses component API
- Not SSR-trackable
- Breaks token system

**Correct approach:**  
Use Avatar component with `size` prop.

---

### ❌ Anti-Pattern 3: Using Avatar for Logos or Icons
```rust
// WRONG — Avatar is for user/entity identity, not logos
Avatar {
    size: AvatarSize::Md,
    
    AvatarImage {
        src: "/logo.svg".to_string(),
        alt: "Company Logo".to_string(),
    }
}
```

**Why it breaks:**
- Avatar implies user/entity identity
- Logos are not user avatars
- Semantic mismatch

**Correct approach:**  
Use `<img>` directly or create `Logo` component.

---

### ❌ Anti-Pattern 4: Nesting Status Indicators Inside Avatar
```rust
// WRONG — status indicator should be sibling, not child
Avatar {
    AvatarImage { /* ... */ }
    AvatarFallback { "JD" }
    
    div { class: "status-dot", /* ... */ } // FORBIDDEN nesting
}
```

**Why it breaks:**
- Avatar has `overflow: hidden` (hides positioned elements)
- Status should be absolutely positioned relative to parent container
- Architectural confusion

**Correct approach:**  
Wrap Avatar + StatusIndicator in a positioned container:
```rust
div { style: "position: relative",
    Avatar { /* ... */ }
    StatusIndicator { /* positioned absolutely */ }
}
```

---

## 9. SSR, Hydration, and Runtime

### SSR Impact

**Server-Side:**
- Avatar renders complete HTML structure
- Image `src` present in initial HTML
- Fallback text rendered
- No JavaScript required for display

**Benefits:**
- SEO-friendly (alt text visible to crawlers)
- Instant display (no layout shift)
- Zero JavaScript bundle cost
- Works with JavaScript disabled

**Constraints:**
- Cannot use browser APIs during SSR
- Must emit pure HTML

---

### Hydration Process

Avatar **does not require hydration** because it has no interactive behavior.

1. **HTML Delivery:** Browser receives static HTML
2. **CSS Application:** Browser applies `avatar.css` styles
3. **Image Load:** Browser natively loads image from `src`
4. **Final Render:** Avatar displays image or fallback

No JavaScript execution needed.

---

### Runtime Global Constraints

**No Runtime Constraints:**
- Avatar has no runtime behavior
- No event listeners
- No state mutations
- Image loading is native browser behavior

**AutoReload/Hot Reload:**
- Avatar preserves across reloads (static HTML)
- No state to lose

---

## 10. Conformance Checklist

- [x] SSR-safe (no browser APIs)
- [x] No imperative JS (pure presentational)
- [x] Uses tokens (indirectly via CSS)
- [x] All tokens documented in section 4
- [x] Anti-patterns documented with explanations
- [x] Canon Rules cited in section 11
- [x] Execution flow documented
- [x] Use cases provided
- [x] Hydration contract explicit (none required)
- [x] Runtime constraints documented (none)
- [x] Belongs to Family F (Data & Media)

---

## 11. Canon Rules Applied

### Canon Rules Applied

- **Canon Rule #107 — Primitives Are SSR-Safe Structural Components**  
  Avatar composes SSR-safe primitives that emit only HTML and data-attributes, never browser-dependent logic.

- **Canon Rule #108 — UI Components Provide Ergonomic Composition**  
  Avatar exists in the UI layer to provide size variants (`xs`, `sm`, `md`, `lg`, `xl`) and reduce boilerplate in application code.

- **Canon Rule #109 — State Lives in DOM, Not Memory**  
  Avatar has no state—size is declared via `data-size` attribute. Image load state is managed by native browser behavior.

- **Canon Rule #110 — CSS Targets Data-Attributes, Never Classes**  
  Avatar styling uses `[data-avatar-*]` selectors exclusively, ensuring token-based theming and avoiding utility class pollution.

- **Canon Rule #112 — Presentational Components Require No Hydration**  
  Avatar is fully functional without JavaScript, relying on SSR, CSS, and native image loading. No hydration step needed.

- **Canon Rule #113 — Avatar Belongs to Family F (Data & Media)**  
  Avatar represents user/entity identity through media (images) and data (fallback initials), never layout or navigation.

---

**End of Documentation**