@adamosuiteservices/ui 1.7.12 → 1.8.13

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 (307) hide show
  1. package/dist/accordion-rounded.cjs +24 -2
  2. package/dist/accordion-rounded.js +46 -8
  3. package/dist/accordion.cjs +20 -1
  4. package/dist/accordion.js +29 -5
  5. package/dist/alert.cjs +26 -1
  6. package/dist/alert.js +33 -8
  7. package/dist/avatar.cjs +7 -1
  8. package/dist/avatar.js +8 -2
  9. package/dist/badge.cjs +83 -1
  10. package/dist/badge.js +106 -24
  11. package/dist/breadcrumb.cjs +8 -1
  12. package/dist/breadcrumb.js +11 -4
  13. package/dist/button-B7ZP4LZN.js +127 -0
  14. package/dist/button-D-qFRXiM.cjs +70 -0
  15. package/dist/button-group.cjs +25 -1
  16. package/dist/button-group.js +33 -9
  17. package/dist/button.cjs +1 -1
  18. package/dist/button.js +1 -1
  19. package/dist/calendar.cjs +74 -1
  20. package/dist/calendar.js +114 -35
  21. package/dist/card.cjs +35 -1
  22. package/dist/card.js +45 -11
  23. package/dist/{checkbox-YWAnswaW.cjs → checkbox-CdnZ8VFJ.cjs} +21 -1
  24. package/dist/{checkbox-Dr487kAg.js → checkbox-DhBcmKze.js} +34 -4
  25. package/dist/checkbox.cjs +1 -1
  26. package/dist/checkbox.js +1 -1
  27. package/dist/combobox.cjs +36 -2
  28. package/dist/combobox.js +302 -253
  29. package/dist/components/icons/account-balance-icon.d.ts +3 -0
  30. package/dist/components/icons/account-icon.d.ts +3 -0
  31. package/dist/components/icons/add-circle-icon.d.ts +3 -0
  32. package/dist/components/icons/alarm-icon.d.ts +3 -0
  33. package/dist/components/icons/archive-icon.d.ts +3 -0
  34. package/dist/components/icons/arrow-back-icon.d.ts +3 -0
  35. package/dist/components/icons/arrow-circle-up-icon.d.ts +3 -0
  36. package/dist/components/icons/arrow-forward-icon.d.ts +3 -0
  37. package/dist/components/icons/arrow-outward-icon.d.ts +3 -0
  38. package/dist/components/icons/article-icon.d.ts +3 -0
  39. package/dist/components/icons/attach-file-icon.d.ts +3 -0
  40. package/dist/components/icons/autorenew-icon.d.ts +3 -0
  41. package/dist/components/icons/bookmark-icon.d.ts +3 -0
  42. package/dist/components/icons/calculate-icon.d.ts +3 -0
  43. package/dist/components/icons/calendar-today-icon.d.ts +3 -0
  44. package/dist/components/icons/call-split-icon.d.ts +3 -0
  45. package/dist/components/icons/cancel-filled-icon.d.ts +3 -0
  46. package/dist/components/icons/cancel-icon.d.ts +3 -0
  47. package/dist/components/icons/check-circle-icon.d.ts +3 -0
  48. package/dist/components/icons/check-icon.d.ts +3 -0
  49. package/dist/components/icons/chevron-back-icon.d.ts +3 -0
  50. package/dist/components/icons/chevron-down-icon.d.ts +3 -0
  51. package/dist/components/icons/chevron-forward-icon.d.ts +3 -0
  52. package/dist/components/icons/chevron-up-icon.d.ts +3 -0
  53. package/dist/components/icons/clarify-icon.d.ts +3 -0
  54. package/dist/components/icons/clock-icon.d.ts +3 -0
  55. package/dist/components/icons/close-icon.d.ts +3 -0
  56. package/dist/components/icons/confirmation-number-icon.d.ts +3 -0
  57. package/dist/components/icons/contacts-icon.d.ts +3 -0
  58. package/dist/components/icons/contract-delete-icon.d.ts +3 -0
  59. package/dist/components/icons/copy-icon.d.ts +3 -0
  60. package/dist/components/icons/do-not-touch-icon.d.ts +3 -0
  61. package/dist/components/icons/download-icon.d.ts +3 -0
  62. package/dist/components/icons/dragger-icon.d.ts +3 -0
  63. package/dist/components/icons/edit-icon.d.ts +3 -0
  64. package/dist/components/icons/edit-square-icon.d.ts +3 -0
  65. package/dist/components/icons/exclamation-icon.d.ts +3 -0
  66. package/dist/components/icons/expand-circle-right-icon.d.ts +3 -0
  67. package/dist/components/icons/feature-search-icon.d.ts +3 -0
  68. package/dist/components/icons/filter-icon.d.ts +3 -0
  69. package/dist/components/icons/folder-icon.d.ts +3 -0
  70. package/dist/components/icons/folder-open-icon.d.ts +3 -0
  71. package/dist/components/icons/format-list-bulleted-icon.d.ts +3 -0
  72. package/dist/components/icons/hamburger-menu-icon.d.ts +3 -0
  73. package/dist/components/icons/help-icon.d.ts +3 -0
  74. package/dist/components/icons/hide-pass-icon.d.ts +3 -0
  75. package/dist/components/icons/home-icon.d.ts +3 -0
  76. package/dist/components/icons/id-card-icon.d.ts +3 -0
  77. package/dist/components/icons/index.d.ts +88 -0
  78. package/dist/components/icons/info-icon.d.ts +3 -0
  79. package/dist/components/icons/kid-star-icon.d.ts +3 -0
  80. package/dist/components/icons/language-icon.d.ts +3 -0
  81. package/dist/components/icons/last-page-icon.d.ts +3 -0
  82. package/dist/components/icons/layers-icon.d.ts +3 -0
  83. package/dist/components/icons/location-icon.d.ts +3 -0
  84. package/dist/components/icons/mail-icon.d.ts +3 -0
  85. package/dist/components/icons/manage-search-icon.d.ts +3 -0
  86. package/dist/components/icons/menu-icon.d.ts +3 -0
  87. package/dist/components/icons/message-icon.d.ts +3 -0
  88. package/dist/components/icons/metrics-icon.d.ts +3 -0
  89. package/dist/components/icons/mic-icon.d.ts +3 -0
  90. package/dist/components/icons/minus-icon.d.ts +3 -0
  91. package/dist/components/icons/mode-comment-icon.d.ts +3 -0
  92. package/dist/components/icons/money-icon.d.ts +3 -0
  93. package/dist/components/icons/monitoring-icon.d.ts +3 -0
  94. package/dist/components/icons/more-icon.d.ts +3 -0
  95. package/dist/components/icons/notifications-icon.d.ts +3 -0
  96. package/dist/components/icons/open-in-new-icon.d.ts +3 -0
  97. package/dist/components/icons/palette-icon.d.ts +3 -0
  98. package/dist/components/icons/password-icon.d.ts +3 -0
  99. package/dist/components/icons/pending-icon.d.ts +3 -0
  100. package/dist/components/icons/person-add-icon.d.ts +3 -0
  101. package/dist/components/icons/person-search-icon.d.ts +3 -0
  102. package/dist/components/icons/photo-icon.d.ts +3 -0
  103. package/dist/components/icons/plus-icon.d.ts +3 -0
  104. package/dist/components/icons/policy-icon.d.ts +3 -0
  105. package/dist/components/icons/publish-icon.d.ts +3 -0
  106. package/dist/components/icons/ready-icon.d.ts +3 -0
  107. package/dist/components/icons/receipt-icon.d.ts +3 -0
  108. package/dist/components/icons/receive-icon.d.ts +3 -0
  109. package/dist/components/icons/refresh-icon.d.ts +3 -0
  110. package/dist/components/icons/search-icon.d.ts +3 -0
  111. package/dist/components/icons/see-icon.d.ts +3 -0
  112. package/dist/components/icons/send-icon.d.ts +3 -0
  113. package/dist/components/icons/settings-icon.d.ts +3 -0
  114. package/dist/components/icons/shield-icon.d.ts +3 -0
  115. package/dist/components/icons/swap-horiz-icon.d.ts +3 -0
  116. package/dist/components/icons/tag-icon.d.ts +3 -0
  117. package/dist/components/icons/trash-icon.d.ts +3 -0
  118. package/dist/components/layout/toaster/toaster.d.ts +1 -1
  119. package/dist/components/layout/toaster/toaster.stories.d.ts +1 -1
  120. package/dist/components/ui/accordion/accordion.d.ts +1 -1
  121. package/dist/components/ui/accordion/accordion.stories.d.ts +1 -1
  122. package/dist/components/ui/accordion-rounded/accordion-rounded.d.ts +1 -1
  123. package/dist/components/ui/accordion-rounded/accordion-rounded.stories.d.ts +1 -1
  124. package/dist/components/ui/alert/alert.stories.d.ts +1 -1
  125. package/dist/components/ui/avatar/avatar.d.ts +1 -1
  126. package/dist/components/ui/avatar/avatar.stories.d.ts +1 -1
  127. package/dist/components/ui/badge/badge.stories.d.ts +1 -1
  128. package/dist/components/ui/breadcrumb/breadcrumb.stories.d.ts +1 -1
  129. package/dist/components/ui/button/button.stories.d.ts +1 -1
  130. package/dist/components/ui/button-group/button-group.d.ts +1 -1
  131. package/dist/components/ui/button-group/button-group.stories.d.ts +1 -1
  132. package/dist/components/ui/calendar/calendar.d.ts +1 -1
  133. package/dist/components/ui/calendar/calendar.stories.d.ts +1 -1
  134. package/dist/components/ui/card/card.stories.d.ts +1 -1
  135. package/dist/components/ui/checkbox/checkbox.d.ts +1 -1
  136. package/dist/components/ui/checkbox/checkbox.stories.d.ts +1 -1
  137. package/dist/components/ui/collapsible/collapsible.stories.d.ts +1 -1
  138. package/dist/components/ui/combobox/combobox.stories.d.ts +1 -1
  139. package/dist/components/ui/command/command.d.ts +1 -1
  140. package/dist/components/ui/context-menu/context-menu.d.ts +1 -1
  141. package/dist/components/ui/context-menu/context-menu.stories.d.ts +1 -1
  142. package/dist/components/ui/dialog/dialog.d.ts +1 -1
  143. package/dist/components/ui/dialog/dialog.stories.d.ts +1 -1
  144. package/dist/components/ui/dropdown-menu/dropdown-menu.d.ts +1 -1
  145. package/dist/components/ui/dropdown-menu/dropdown-menu.stories.d.ts +1 -1
  146. package/dist/components/ui/field/field.d.ts +1 -1
  147. package/dist/components/ui/field/field.stories.d.ts +1 -1
  148. package/dist/components/ui/hover-card/hover-card.d.ts +1 -1
  149. package/dist/components/ui/hover-card/hover-card.stories.d.ts +1 -1
  150. package/dist/components/ui/input/input.stories.d.ts +1 -1
  151. package/dist/components/ui/input-group/Input-group.stories.d.ts +1 -1
  152. package/dist/components/ui/input-group/input-group.d.ts +1 -1
  153. package/dist/components/ui/kbd/kbd.stories.d.ts +1 -1
  154. package/dist/components/ui/label/label.d.ts +1 -1
  155. package/dist/components/ui/label/label.stories.d.ts +1 -1
  156. package/dist/components/ui/pagination/pagination.stories.d.ts +1 -1
  157. package/dist/components/ui/popover/popover.d.ts +1 -1
  158. package/dist/components/ui/popover/popover.stories.d.ts +1 -1
  159. package/dist/components/ui/progress/progress.d.ts +1 -1
  160. package/dist/components/ui/progress/progress.stories.d.ts +1 -1
  161. package/dist/components/ui/radio-group/radio-group.d.ts +1 -1
  162. package/dist/components/ui/radio-group/radio-group.stories.d.ts +1 -1
  163. package/dist/components/ui/scroll-area/scroll-area.d.ts +1 -1
  164. package/dist/components/ui/scroll-area/scroll-area.stories.d.ts +1 -1
  165. package/dist/components/ui/select/select.d.ts +1 -1
  166. package/dist/components/ui/select/select.stories.d.ts +1 -1
  167. package/dist/components/ui/separator/separator.d.ts +1 -1
  168. package/dist/components/ui/separator/separator.stories.d.ts +1 -1
  169. package/dist/components/ui/sheet/sheet.d.ts +1 -1
  170. package/dist/components/ui/sheet/sheet.stories.d.ts +1 -1
  171. package/dist/components/ui/skeleton/skeleton.stories.d.ts +1 -1
  172. package/dist/components/ui/slider/slider.d.ts +1 -1
  173. package/dist/components/ui/slider/slider.stories.d.ts +1 -1
  174. package/dist/components/ui/spinner/spinner.stories.d.ts +1 -1
  175. package/dist/components/ui/switch/switch.d.ts +1 -1
  176. package/dist/components/ui/switch/switch.stories.d.ts +1 -1
  177. package/dist/components/ui/tabs/tabs.d.ts +1 -1
  178. package/dist/components/ui/tabs/tabs.stories.d.ts +1 -1
  179. package/dist/components/ui/tabs-underline/tabs-underline.d.ts +1 -1
  180. package/dist/components/ui/tabs-underline/tabs-underline.stories.d.ts +1 -1
  181. package/dist/components/ui/textarea/textarea.stories.d.ts +1 -1
  182. package/dist/components/ui/toggle/toggle.d.ts +1 -1
  183. package/dist/components/ui/toggle/toggle.stories.d.ts +1 -1
  184. package/dist/components/ui/tooltip/tooltip.d.ts +1 -1
  185. package/dist/components/ui/tooltip/tooltip.stories.d.ts +1 -1
  186. package/dist/context-menu.cjs +79 -1
  187. package/dist/context-menu.js +101 -11
  188. package/dist/custom-layered-styles.css +1 -1
  189. package/dist/dialog.cjs +30 -1
  190. package/dist/dialog.js +35 -6
  191. package/dist/dropdown-menu.cjs +79 -1
  192. package/dist/dropdown-menu.js +101 -11
  193. package/dist/field.cjs +66 -1
  194. package/dist/field.js +91 -26
  195. package/dist/hover-card.cjs +15 -1
  196. package/dist/hover-card.js +15 -1
  197. package/dist/icons.cjs +1 -0
  198. package/dist/icons.js +1507 -0
  199. package/dist/input-BQZUpTEY.js +42 -0
  200. package/dist/input-DSmxdfq5.cjs +21 -0
  201. package/dist/input-group.cjs +76 -1
  202. package/dist/input-group.js +99 -24
  203. package/dist/input.cjs +1 -1
  204. package/dist/input.js +1 -1
  205. package/dist/kbd.cjs +10 -1
  206. package/dist/kbd.js +11 -2
  207. package/dist/{label-CmwGvhy1.js → label-BJ8Yf6Ft.js} +7 -1
  208. package/dist/{label-BjXORCBM.cjs → label-CNGQhi5L.cjs} +7 -1
  209. package/dist/label.cjs +1 -1
  210. package/dist/label.js +1 -1
  211. package/dist/pagination.cjs +13 -1
  212. package/dist/pagination.js +30 -6
  213. package/dist/{popover-FCKBtFo-.cjs → popover-CYbik-H4.cjs} +15 -1
  214. package/dist/{popover-3rIoNCXs.js → popover-DAwH8jUh.js} +15 -1
  215. package/dist/popover.cjs +1 -1
  216. package/dist/popover.js +1 -1
  217. package/dist/radio-group.cjs +14 -1
  218. package/dist/radio-group.js +20 -2
  219. package/dist/select.cjs +68 -1
  220. package/dist/select.js +83 -10
  221. package/dist/{separator-BaZqZZ9R.cjs → separator-Brpax0EI.cjs} +7 -1
  222. package/dist/{separator-DR7lQjv9.js → separator-DVypR3Qf.js} +7 -1
  223. package/dist/separator.cjs +1 -1
  224. package/dist/separator.js +1 -1
  225. package/dist/sheet-CGahUP7F.cjs +41 -0
  226. package/dist/sheet-Q3dBOQG-.js +174 -0
  227. package/dist/sheet.cjs +1 -1
  228. package/dist/sheet.js +1 -1
  229. package/dist/sidebar.cjs +20 -2
  230. package/dist/sidebar.js +58 -26
  231. package/dist/skeleton.cjs +1 -1
  232. package/dist/skeleton.js +1 -1
  233. package/dist/slider.cjs +27 -1
  234. package/dist/slider.js +30 -4
  235. package/dist/space.css +1 -1
  236. package/dist/styles.css +1 -1
  237. package/dist/switch.cjs +18 -1
  238. package/dist/switch.js +19 -2
  239. package/dist/table.cjs +20 -1
  240. package/dist/table.js +26 -7
  241. package/dist/tabs-underline.cjs +21 -1
  242. package/dist/tabs-underline.js +23 -3
  243. package/dist/tabs.cjs +22 -1
  244. package/dist/tabs.js +24 -3
  245. package/dist/textarea-CG7iQcb3.cjs +14 -0
  246. package/dist/textarea-CUPWKl-S.js +32 -0
  247. package/dist/textarea.cjs +1 -1
  248. package/dist/textarea.js +1 -1
  249. package/dist/toaster.cjs +4 -1
  250. package/dist/toaster.js +9 -6
  251. package/dist/toggle.cjs +17 -1
  252. package/dist/toggle.js +25 -9
  253. package/dist/tooltip.cjs +16 -1
  254. package/dist/tooltip.js +22 -2
  255. package/dist/typography.cjs +1 -1
  256. package/dist/typography.js +6 -6
  257. package/docs/AI-GUIDE.md +321 -321
  258. package/docs/components/layout/sidebar.md +404 -404
  259. package/docs/components/layout/toaster.md +436 -436
  260. package/docs/components/ui/accordion-rounded.md +583 -583
  261. package/docs/components/ui/accordion.md +267 -267
  262. package/docs/components/ui/alert.md +671 -671
  263. package/docs/components/ui/avatar.md +588 -588
  264. package/docs/components/ui/badge.md +1024 -1024
  265. package/docs/components/ui/button-group.md +1002 -1002
  266. package/docs/components/ui/button.md +1078 -1078
  267. package/docs/components/ui/calendar.md +1159 -1159
  268. package/docs/components/ui/card.md +1265 -1265
  269. package/docs/components/ui/checkbox.md +292 -292
  270. package/docs/components/ui/collapsible.md +320 -320
  271. package/docs/components/ui/command.md +454 -454
  272. package/docs/components/ui/context-menu.md +540 -540
  273. package/docs/components/ui/dialog.md +628 -628
  274. package/docs/components/ui/dropdown-menu.md +731 -731
  275. package/docs/components/ui/field.md +706 -706
  276. package/docs/components/ui/hover-card.md +446 -446
  277. package/docs/components/ui/input-group.md +509 -509
  278. package/docs/components/ui/input.md +362 -362
  279. package/docs/components/ui/kbd.md +434 -434
  280. package/docs/components/ui/label.md +359 -359
  281. package/docs/components/ui/pagination.md +650 -650
  282. package/docs/components/ui/popover.md +536 -536
  283. package/docs/components/ui/progress.md +182 -182
  284. package/docs/components/ui/radio-group.md +311 -311
  285. package/docs/components/ui/select.md +352 -352
  286. package/docs/components/ui/separator.md +214 -214
  287. package/docs/components/ui/sheet.md +142 -142
  288. package/docs/components/ui/skeleton.md +140 -140
  289. package/docs/components/ui/slider.md +341 -341
  290. package/docs/components/ui/spinner.md +170 -170
  291. package/docs/components/ui/switch.md +402 -402
  292. package/docs/components/ui/table.md +183 -183
  293. package/docs/components/ui/tabs-underline.md +106 -106
  294. package/docs/components/ui/tabs.md +122 -122
  295. package/docs/components/ui/textarea.md +243 -243
  296. package/docs/components/ui/toggle.md +243 -243
  297. package/docs/components/ui/tooltip.md +320 -320
  298. package/docs/components/ui/typography.md +191 -191
  299. package/package.json +7 -1
  300. package/dist/button-2GdKenQI.js +0 -58
  301. package/dist/button-DEQVHMrX.cjs +0 -1
  302. package/dist/input-BF73maXg.cjs +0 -1
  303. package/dist/input-C04hsVXE.js +0 -22
  304. package/dist/sheet-B-9YHdR5.js +0 -128
  305. package/dist/sheet-CU-sFSaJ.cjs +0 -1
  306. package/dist/textarea-3ZdbFRDN.cjs +0 -1
  307. package/dist/textarea-BZbcAAAu.js +0 -19
@@ -1,588 +1,588 @@
1
- # Avatar Component
2
-
3
- ## Descripción
4
-
5
- Componente para mostrar **imágenes de perfil de usuario** con sistema de fallback automático a iniciales o iconos cuando la imagen no está disponible o falla al cargar. Basado en Radix UI Avatar primitives con carga lazy, estado de error manejado, y diseño circular responsive.
6
-
7
- ## Características
8
-
9
- - ✅ Fallback automático si la imagen falla
10
- - ✅ Carga lazy de imágenes
11
- - ✅ Soporte para iniciales o iconos como fallback
12
- - ✅ Tamaños personalizables
13
- - ✅ Formas: circular (default) o cuadrado/rectangular
14
- - ✅ Grupos de avatares con solapamiento
15
- - ✅ Integración con Tooltip
16
- - ✅ Accesibilidad: alt text y ARIA
17
- - ✅ Diseño responsive y flexible
18
-
19
- ## Importación
20
-
21
- ```typescript
22
- import {
23
- Avatar,
24
- AvatarImage,
25
- AvatarFallback,
26
- } from "@adamosuiteservices/ui/avatar";
27
- ```
28
-
29
- ## Uso Básico
30
-
31
- ### Avatar con Imagen y Fallback
32
-
33
- ```tsx
34
- <Avatar>
35
- <AvatarImage src="https://github.com/shadcn.png" alt="@shadcn" />
36
- <AvatarFallback>CN</AvatarFallback>
37
- </Avatar>
38
- ```
39
-
40
- **Comportamiento**:
41
-
42
- 1. Intenta cargar la imagen del `src`
43
- 2. Si falla o no carga, muestra el `AvatarFallback` automáticamente
44
- 3. Radix UI maneja el estado de carga internamente
45
-
46
- ### Solo Fallback (Sin Imagen)
47
-
48
- ```tsx
49
- <Avatar>
50
- <AvatarFallback>JD</AvatarFallback>
51
- </Avatar>
52
- ```
53
-
54
- **Uso**: Cuando no hay imagen disponible o solo quieres mostrar iniciales.
55
-
56
- ### Imagen Rota (Graceful Degradation)
57
-
58
- ```tsx
59
- <Avatar>
60
- <AvatarImage src="https://broken-link.com/image.jpg" alt="Broken" />
61
- <AvatarFallback>BK</AvatarFallback>
62
- </Avatar>
63
- ```
64
-
65
- **Resultado**: Automáticamente muestra "BK" si la imagen no carga.
66
-
67
- ## Props
68
-
69
- ### Avatar (Root)
70
-
71
- Contenedor principal del avatar.
72
-
73
- | Prop | Tipo | Descripción |
74
- | --------- | -------------------------- | --------------------------- |
75
- | className | `string` | Clases CSS adicionales |
76
- | ...props | Props de Radix Avatar.Root | Props nativas del primitivo |
77
-
78
- **Estilos por defecto**:
79
-
80
- - `size-8`: 2rem (32x32px) - tamaño base
81
- - `rounded-full`: Forma circular
82
- - `shrink-0`: No se encoge en flex/grid
83
- - `overflow-hidden`: Recorta contenido fuera del círculo
84
- - `relative`: Para posicionamiento interno
85
- - `flex`: Contenedor flex
86
-
87
- **Atributos automáticos**:
88
-
89
- - `data-slot="avatar"`: Para identificación interna
90
-
91
- ### AvatarImage
92
-
93
- Imagen del avatar con carga lazy.
94
-
95
- | Prop | Tipo | Descripción |
96
- | --------- | --------------------------- | --------------------------------------------------- |
97
- | src | `string` | **Requerido**. URL de la imagen |
98
- | alt | `string` | **Requerido**. Texto alternativo para accesibilidad |
99
- | className | `string` | Clases CSS adicionales |
100
- | ...props | Props de Radix Avatar.Image | Props nativas del primitivo |
101
-
102
- **Estilos aplicados**:
103
-
104
- - `aspect-square`: Mantiene aspecto cuadrado
105
- - `size-full`: Ocupa todo el contenedor (100% width/height)
106
-
107
- **Comportamiento**:
108
-
109
- - Carga lazy automática
110
- - Emite eventos `onLoadingStatusChange`
111
- - Estados: `idle`, `loading`, `loaded`, `error`
112
- - Si falla, muestra AvatarFallback automáticamente
113
-
114
- **Atributos automáticos**:
115
-
116
- - `data-slot="avatar-image"`: Para identificación interna
117
-
118
- ### AvatarFallback
119
-
120
- Contenido mostrado cuando la imagen no carga o no existe.
121
-
122
- | Prop | Tipo | Descripción |
123
- | --------- | ------------------------------ | ------------------------------------------------------ |
124
- | children | `ReactNode` | **Requerido**. Iniciales, icono, o cualquier contenido |
125
- | delayMs | `number` | Delay antes de mostrar el fallback (ms) |
126
- | className | `string` | Clases CSS adicionales |
127
- | ...props | Props de Radix Avatar.Fallback | Props nativas del primitivo |
128
-
129
- **Estilos por defecto**:
130
-
131
- - `bg-muted`: Fondo gris claro
132
- - `rounded-full`: Forma circular (coincide con el contenedor)
133
- - `size-full`: Ocupa todo el espacio
134
- - `flex items-center justify-center`: Centra el contenido
135
-
136
- **Contenido común**:
137
-
138
- - Iniciales (2 letras): "JD", "AB", "CN"
139
- - Iconos: `<UserIcon />`, `<PersonIcon />`
140
- - Texto: "+5" (para grupos)
141
-
142
- **Atributos automáticos**:
143
-
144
- - `data-slot="avatar-fallback"`: Para identificación interna
145
-
146
- ## Tamaños Personalizados
147
-
148
- El tamaño por defecto es `size-8` (32px). Personaliza con className:
149
-
150
- ### Tamaños Predefinidos
151
-
152
- ```tsx
153
- {
154
- /* Extra Small - 24px */
155
- }
156
- <Avatar className="size-6">
157
- <AvatarImage src={url} alt="User" />
158
- <AvatarFallback className="text-xs">CN</AvatarFallback>
159
- </Avatar>;
160
-
161
- {
162
- /* Small - 32px (default) */
163
- }
164
- <Avatar className="size-8">
165
- <AvatarImage src={url} alt="User" />
166
- <AvatarFallback>ER</AvatarFallback>
167
- </Avatar>;
168
-
169
- {
170
- /* Medium - 48px */
171
- }
172
- <Avatar className="size-12">
173
- <AvatarImage src={url} alt="User" />
174
- <AvatarFallback>ML</AvatarFallback>
175
- </Avatar>;
176
-
177
- {
178
- /* Large - 64px */
179
- }
180
- <Avatar className="size-16">
181
- <AvatarImage src={url} alt="User" />
182
- <AvatarFallback className="text-lg">VC</AvatarFallback>
183
- </Avatar>;
184
-
185
- {
186
- /* Extra Large - 80px */
187
- }
188
- <Avatar className="size-20">
189
- <AvatarImage src={url} alt="User" />
190
- <AvatarFallback className="text-xl">NJ</AvatarFallback>
191
- </Avatar>;
192
- ```
193
-
194
- **Nota**: Ajusta el tamaño del texto del fallback según el tamaño del avatar para mantener proporciones.
195
-
196
- ### Tamaño Personalizado
197
-
198
- ```tsx
199
- <Avatar className="h-24 w-24">
200
- <AvatarImage src={url} alt="User" />
201
- <AvatarFallback className="text-2xl">AB</AvatarFallback>
202
- </Avatar>
203
- ```
204
-
205
- ## Formas Personalizadas
206
-
207
- ### Avatar Cuadrado
208
-
209
- ```tsx
210
- {
211
- /* Rounded large */
212
- }
213
- <Avatar className="rounded-lg">
214
- <AvatarImage src={url} alt="User" />
215
- <AvatarFallback>CN</AvatarFallback>
216
- </Avatar>;
217
-
218
- {
219
- /* Rounded medium */
220
- }
221
- <Avatar className="rounded-md">
222
- <AvatarImage src={url} alt="User" />
223
- <AvatarFallback>ER</AvatarFallback>
224
- </Avatar>;
225
-
226
- {
227
- /* Rounded small */
228
- }
229
- <Avatar className="rounded-sm">
230
- <AvatarImage src={url} alt="User" />
231
- <AvatarFallback>ML</AvatarFallback>
232
- </Avatar>;
233
-
234
- {
235
- /* Completamente cuadrado */
236
- }
237
- <Avatar className="rounded-none">
238
- <AvatarFallback>SQ</AvatarFallback>
239
- </Avatar>;
240
- ```
241
-
242
- **Uso**: Avatares cuadrados son comunes para logos de empresas o aplicaciones.
243
-
244
- ## Patrones Avanzados
245
-
246
- ### Grupo de Avatares (Overlapping)
247
-
248
- Para mostrar múltiples usuarios con solapamiento:
249
-
250
- ```tsx
251
- <div className="flex -space-x-2">
252
- <Avatar className="ring-2 ring-background">
253
- <AvatarImage src="https://github.com/shadcn.png" alt="@shadcn" />
254
- <AvatarFallback>CN</AvatarFallback>
255
- </Avatar>
256
- <Avatar className="ring-2 ring-background">
257
- <AvatarImage src="https://github.com/evilrabbit.png" alt="@evilrabbit" />
258
- <AvatarFallback>ER</AvatarFallback>
259
- </Avatar>
260
- <Avatar className="ring-2 ring-background">
261
- <AvatarImage src="https://github.com/maxleiter.png" alt="@maxleiter" />
262
- <AvatarFallback>ML</AvatarFallback>
263
- </Avatar>
264
- <Avatar className="ring-2 ring-background bg-muted">
265
- <AvatarFallback>+2</AvatarFallback>
266
- </Avatar>
267
- </div>
268
- ```
269
-
270
- **Técnicas**:
271
-
272
- - `-space-x-2`: Espacio negativo para solapar
273
- - `ring-2 ring-background`: Borde blanco para separación visual
274
- - Último avatar muestra contador "+N" para usuarios adicionales
275
-
276
- ### Avatar con Tooltip
277
-
278
- Para mostrar información adicional al hover:
279
-
280
- ```tsx
281
- import {
282
- Tooltip,
283
- TooltipContent,
284
- TooltipProvider,
285
- TooltipTrigger,
286
- } from "@adamosuiteservices/ui/tooltip";
287
-
288
- <TooltipProvider>
289
- <Tooltip>
290
- <TooltipTrigger asChild>
291
- <Avatar className="cursor-pointer">
292
- <AvatarImage src="https://github.com/shadcn.png" alt="@shadcn" />
293
- <AvatarFallback>CN</AvatarFallback>
294
- </Avatar>
295
- </TooltipTrigger>
296
- <TooltipContent>
297
- <p>shadcn - UI Engineer</p>
298
- </TooltipContent>
299
- </Tooltip>
300
- </TooltipProvider>;
301
- ```
302
-
303
- **Nota**: Agrega `cursor-pointer` para indicar interactividad.
304
-
305
- ### Card de Perfil de Usuario
306
-
307
- Avatar como parte de un perfil completo:
308
-
309
- ```tsx
310
- import { Badge } from "@adamosuiteservices/ui/badge";
311
- import { Button } from "@adamosuiteservices/ui/button";
312
-
313
- <div className="flex items-center gap-4 p-6 rounded-lg border max-w-md">
314
- <Avatar className="size-16">
315
- <AvatarImage src="https://github.com/shadcn.png" alt="@shadcn" />
316
- <AvatarFallback className="text-lg">CN</AvatarFallback>
317
- </Avatar>
318
- <div className="flex-1">
319
- <h3 className="text-lg font-semibold">Colin Northcott</h3>
320
- <p className="text-sm text-muted-foreground">@shadcn • UI Engineer</p>
321
- <div className="flex gap-2 mt-2">
322
- <Badge variant="secondary">React</Badge>
323
- <Badge variant="secondary">TypeScript</Badge>
324
- </div>
325
- </div>
326
- <Button size="sm">Follow</Button>
327
- </div>;
328
- ```
329
-
330
- ### Sistema de Comentarios
331
-
332
- Avatares en un layout de conversación:
333
-
334
- ```tsx
335
- const comments = [
336
- {
337
- id: 1,
338
- author: "John Doe",
339
- avatar: "https://github.com/shadcn.png",
340
- fallback: "JD",
341
- time: "2 hours ago",
342
- content:
343
- "This looks great! Really excited to see this feature in production.",
344
- },
345
- // ... más comentarios
346
- ];
347
-
348
- <div className="space-y-4 max-w-2xl">
349
- {comments.map((comment) => (
350
- <div key={comment.id} className="flex gap-3">
351
- <Avatar>
352
- {comment.avatar && (
353
- <AvatarImage src={comment.avatar} alt={comment.author} />
354
- )}
355
- <AvatarFallback>{comment.fallback}</AvatarFallback>
356
- </Avatar>
357
- <div className="flex-1 space-y-1">
358
- <div className="flex items-center gap-2">
359
- <span className="text-sm font-medium">{comment.author}</span>
360
- <span className="text-xs text-muted-foreground">{comment.time}</span>
361
- </div>
362
- <p className="text-sm">{comment.content}</p>
363
- </div>
364
- </div>
365
- ))}
366
- </div>;
367
- ```
368
-
369
- ### Avatar con Indicador de Estado
370
-
371
- Para mostrar estado online/offline/busy:
372
-
373
- ```tsx
374
- <div className="relative inline-block">
375
- <Avatar>
376
- <AvatarImage src={url} alt="User" />
377
- <AvatarFallback>JD</AvatarFallback>
378
- </Avatar>
379
- {/* Indicador de estado */}
380
- <span className="absolute bottom-0 right-0 block h-3 w-3 rounded-full bg-green-500 ring-2 ring-background" />
381
- </div>
382
- ```
383
-
384
- **Variantes de estado**:
385
-
386
- - `bg-green-500`: Online
387
- - `bg-gray-400`: Offline
388
- - `bg-yellow-500`: Away/Idle
389
- - `bg-red-500`: Busy/Do Not Disturb
390
-
391
- ### Avatar con Badge
392
-
393
- Para notificaciones o roles:
394
-
395
- ```tsx
396
- import { Badge } from "@adamosuiteservices/ui/badge";
397
-
398
- <div className="relative inline-block">
399
- <Avatar className="size-12">
400
- <AvatarImage src={url} alt="User" />
401
- <AvatarFallback>AD</AvatarFallback>
402
- </Avatar>
403
- <Badge
404
- variant="destructive"
405
- className="absolute -top-1 -right-1 h-5 w-5 rounded-full p-0 flex items-center justify-center text-xs"
406
- >
407
- 5
408
- </Badge>
409
- </div>;
410
- ```
411
-
412
- ### Avatar con Icono de Fallback
413
-
414
- Para usuarios sin nombre o genéricos:
415
-
416
- ```tsx
417
- import { UserIcon } from "lucide-react";
418
-
419
- <Avatar>
420
- <AvatarImage src={url} alt="User" />
421
- <AvatarFallback>
422
- <UserIcon className="h-4 w-4" />
423
- </AvatarFallback>
424
- </Avatar>;
425
- ```
426
-
427
- ## Casos de Uso Comunes
428
-
429
- ### Lista de Miembros del Equipo
430
-
431
- ```tsx
432
- const team = [
433
- { name: "John Doe", image: url1, initials: "JD" },
434
- { name: "Jane Smith", image: url2, initials: "JS" },
435
- // ...
436
- ];
437
-
438
- <div className="grid grid-cols-3 gap-4">
439
- {team.map((member) => (
440
- <div key={member.name} className="flex flex-col items-center gap-2">
441
- <Avatar className="size-16">
442
- <AvatarImage src={member.image} alt={member.name} />
443
- <AvatarFallback className="text-lg">{member.initials}</AvatarFallback>
444
- </Avatar>
445
- <span className="text-sm font-medium">{member.name}</span>
446
- </div>
447
- ))}
448
- </div>;
449
- ```
450
-
451
- ### Chat de Mensajería
452
-
453
- ```tsx
454
- <div className="flex items-start gap-3">
455
- <Avatar>
456
- <AvatarImage src={senderAvatar} alt={senderName} />
457
- <AvatarFallback>{senderInitials}</AvatarFallback>
458
- </Avatar>
459
- <div className="flex-1">
460
- <div className="flex items-center gap-2">
461
- <span className="font-medium text-sm">{senderName}</span>
462
- <span className="text-xs text-muted-foreground">{timestamp}</span>
463
- </div>
464
- <p className="text-sm mt-1">{messageContent}</p>
465
- </div>
466
- </div>
467
- ```
468
-
469
- ### Selector de Usuario
470
-
471
- ```tsx
472
- <div className="flex items-center gap-3 p-2 rounded-lg hover:bg-muted cursor-pointer">
473
- <Avatar className="size-10">
474
- <AvatarImage src={userAvatar} alt={userName} />
475
- <AvatarFallback>{userInitials}</AvatarFallback>
476
- </Avatar>
477
- <div className="flex-1">
478
- <p className="text-sm font-medium">{userName}</p>
479
- <p className="text-xs text-muted-foreground">{userEmail}</p>
480
- </div>
481
- </div>
482
- ```
483
-
484
- ## Mejores Prácticas
485
-
486
- ### Generación de Iniciales
487
-
488
- ```typescript
489
- function getInitials(name: string): string {
490
- return name
491
- .split(" ")
492
- .map((part) => part[0])
493
- .join("")
494
- .toUpperCase()
495
- .slice(0, 2);
496
- }
497
-
498
- // Uso
499
- <AvatarFallback>{getInitials("John Doe")}</AvatarFallback>; // "JD"
500
- ```
501
-
502
- ### Prop alt Descriptiva
503
-
504
- ```tsx
505
- // ✅ Correcto - descriptivo
506
- <AvatarImage src={url} alt="John Doe" />
507
- <AvatarImage src={url} alt="@johndoe profile picture" />
508
-
509
- // ❌ Incorrecto - genérico
510
- <AvatarImage src={url} alt="avatar" />
511
- <AvatarImage src={url} alt="user" />
512
- ```
513
-
514
- ### Consistencia de Tamaños
515
-
516
- Mantén tamaños consistentes por contexto:
517
-
518
- - **Listas pequeñas**: `size-8` (32px)
519
- - **Perfiles**: `size-16` (64px)
520
- - **Headers/Nav**: `size-10` (40px)
521
- - **Comentarios**: `size-8` o `size-10`
522
- - **Grupos**: `size-8` o más pequeños
523
-
524
- ### Colores de Fallback Personalizados
525
-
526
- ```tsx
527
- <Avatar>
528
- <AvatarImage src={url} alt="User" />
529
- <AvatarFallback className="bg-blue-500 text-white">AB</AvatarFallback>
530
- </Avatar>
531
- ```
532
-
533
- **Patrón común**: Asignar colores basados en el nombre del usuario:
534
-
535
- ```typescript
536
- function getAvatarColor(name: string): string {
537
- const colors = [
538
- "bg-red-500",
539
- "bg-blue-500",
540
- "bg-green-500",
541
- "bg-yellow-500",
542
- "bg-purple-500",
543
- ];
544
- const index = name.charCodeAt(0) % colors.length;
545
- return colors[index];
546
- }
547
- ```
548
-
549
- ## Notas de Implementación
550
-
551
- - Basado en Radix UI Avatar primitives
552
- - Lazy loading de imágenes por defecto
553
- - Fallback se muestra automáticamente en error de carga
554
- - `aspect-square` mantiene proporción 1:1
555
- - `overflow-hidden` con `rounded-full` crea forma circular
556
- - `shrink-0` evita que el avatar se encoja en layouts flex
557
- - Sistema de slots con `data-slot` para composición
558
- - Tamaño por defecto: 32x32px (`size-8`)
559
-
560
- ## Accesibilidad
561
-
562
- - ✅ **SIEMPRE** incluye prop `alt` en `AvatarImage` con texto descriptivo
563
- - ✅ Radix UI maneja ARIA attributes automáticamente
564
- - ✅ El fallback es accesible por screen readers
565
- - ✅ Usa texto real en fallback (no iconos decorativos solos) cuando sea posible
566
- - ✅ Si el avatar es clickeable, agrégalo dentro de un `<button>` o `<a>` con aria-label
567
- - ⚠️ No uses solo color para indicar estado (combina con iconos/texto)
568
-
569
- ### Avatar Clickeable Accesible
570
-
571
- ```tsx
572
- <button
573
- type="button"
574
- aria-label="View John Doe's profile"
575
- className="rounded-full focus:outline-none focus:ring-2 focus:ring-offset-2"
576
- >
577
- <Avatar>
578
- <AvatarImage src={url} alt="John Doe" />
579
- <AvatarFallback>JD</AvatarFallback>
580
- </Avatar>
581
- </button>
582
- ```
583
-
584
- ## Referencias
585
-
586
- - Radix UI Avatar: https://www.radix-ui.com/primitives/docs/components/avatar
587
- - shadcn/ui Avatar: https://ui.shadcn.com/docs/components/avatar
588
- - WCAG Image Alternative Text: https://www.w3.org/WAI/tutorials/images/
1
+ # Avatar Component
2
+
3
+ ## Descripción
4
+
5
+ Componente para mostrar **imágenes de perfil de usuario** con sistema de fallback automático a iniciales o iconos cuando la imagen no está disponible o falla al cargar. Basado en Radix UI Avatar primitives con carga lazy, estado de error manejado, y diseño circular responsive.
6
+
7
+ ## Características
8
+
9
+ - ✅ Fallback automático si la imagen falla
10
+ - ✅ Carga lazy de imágenes
11
+ - ✅ Soporte para iniciales o iconos como fallback
12
+ - ✅ Tamaños personalizables
13
+ - ✅ Formas: circular (default) o cuadrado/rectangular
14
+ - ✅ Grupos de avatares con solapamiento
15
+ - ✅ Integración con Tooltip
16
+ - ✅ Accesibilidad: alt text y ARIA
17
+ - ✅ Diseño responsive y flexible
18
+
19
+ ## Importación
20
+
21
+ ```typescript
22
+ import {
23
+ Avatar,
24
+ AvatarImage,
25
+ AvatarFallback,
26
+ } from "@adamosuiteservices/ui/avatar";
27
+ ```
28
+
29
+ ## Uso Básico
30
+
31
+ ### Avatar con Imagen y Fallback
32
+
33
+ ```tsx
34
+ <Avatar>
35
+ <AvatarImage src="https://github.com/shadcn.png" alt="@shadcn" />
36
+ <AvatarFallback>CN</AvatarFallback>
37
+ </Avatar>
38
+ ```
39
+
40
+ **Comportamiento**:
41
+
42
+ 1. Intenta cargar la imagen del `src`
43
+ 2. Si falla o no carga, muestra el `AvatarFallback` automáticamente
44
+ 3. Radix UI maneja el estado de carga internamente
45
+
46
+ ### Solo Fallback (Sin Imagen)
47
+
48
+ ```tsx
49
+ <Avatar>
50
+ <AvatarFallback>JD</AvatarFallback>
51
+ </Avatar>
52
+ ```
53
+
54
+ **Uso**: Cuando no hay imagen disponible o solo quieres mostrar iniciales.
55
+
56
+ ### Imagen Rota (Graceful Degradation)
57
+
58
+ ```tsx
59
+ <Avatar>
60
+ <AvatarImage src="https://broken-link.com/image.jpg" alt="Broken" />
61
+ <AvatarFallback>BK</AvatarFallback>
62
+ </Avatar>
63
+ ```
64
+
65
+ **Resultado**: Automáticamente muestra "BK" si la imagen no carga.
66
+
67
+ ## Props
68
+
69
+ ### Avatar (Root)
70
+
71
+ Contenedor principal del avatar.
72
+
73
+ | Prop | Tipo | Descripción |
74
+ | --------- | -------------------------- | --------------------------- |
75
+ | className | `string` | Clases CSS adicionales |
76
+ | ...props | Props de Radix Avatar.Root | Props nativas del primitivo |
77
+
78
+ **Estilos por defecto**:
79
+
80
+ - `size-8`: 2rem (32x32px) - tamaño base
81
+ - `rounded-full`: Forma circular
82
+ - `shrink-0`: No se encoge en flex/grid
83
+ - `overflow-hidden`: Recorta contenido fuera del círculo
84
+ - `relative`: Para posicionamiento interno
85
+ - `flex`: Contenedor flex
86
+
87
+ **Atributos automáticos**:
88
+
89
+ - `data-slot="avatar"`: Para identificación interna
90
+
91
+ ### AvatarImage
92
+
93
+ Imagen del avatar con carga lazy.
94
+
95
+ | Prop | Tipo | Descripción |
96
+ | --------- | --------------------------- | --------------------------------------------------- |
97
+ | src | `string` | **Requerido**. URL de la imagen |
98
+ | alt | `string` | **Requerido**. Texto alternativo para accesibilidad |
99
+ | className | `string` | Clases CSS adicionales |
100
+ | ...props | Props de Radix Avatar.Image | Props nativas del primitivo |
101
+
102
+ **Estilos aplicados**:
103
+
104
+ - `aspect-square`: Mantiene aspecto cuadrado
105
+ - `size-full`: Ocupa todo el contenedor (100% width/height)
106
+
107
+ **Comportamiento**:
108
+
109
+ - Carga lazy automática
110
+ - Emite eventos `onLoadingStatusChange`
111
+ - Estados: `idle`, `loading`, `loaded`, `error`
112
+ - Si falla, muestra AvatarFallback automáticamente
113
+
114
+ **Atributos automáticos**:
115
+
116
+ - `data-slot="avatar-image"`: Para identificación interna
117
+
118
+ ### AvatarFallback
119
+
120
+ Contenido mostrado cuando la imagen no carga o no existe.
121
+
122
+ | Prop | Tipo | Descripción |
123
+ | --------- | ------------------------------ | ------------------------------------------------------ |
124
+ | children | `ReactNode` | **Requerido**. Iniciales, icono, o cualquier contenido |
125
+ | delayMs | `number` | Delay antes de mostrar el fallback (ms) |
126
+ | className | `string` | Clases CSS adicionales |
127
+ | ...props | Props de Radix Avatar.Fallback | Props nativas del primitivo |
128
+
129
+ **Estilos por defecto**:
130
+
131
+ - `bg-muted`: Fondo gris claro
132
+ - `rounded-full`: Forma circular (coincide con el contenedor)
133
+ - `size-full`: Ocupa todo el espacio
134
+ - `flex items-center justify-center`: Centra el contenido
135
+
136
+ **Contenido común**:
137
+
138
+ - Iniciales (2 letras): "JD", "AB", "CN"
139
+ - Iconos: `<UserIcon />`, `<PersonIcon />`
140
+ - Texto: "+5" (para grupos)
141
+
142
+ **Atributos automáticos**:
143
+
144
+ - `data-slot="avatar-fallback"`: Para identificación interna
145
+
146
+ ## Tamaños Personalizados
147
+
148
+ El tamaño por defecto es `size-8` (32px). Personaliza con className:
149
+
150
+ ### Tamaños Predefinidos
151
+
152
+ ```tsx
153
+ {
154
+ /* Extra Small - 24px */
155
+ }
156
+ <Avatar className="size-6">
157
+ <AvatarImage src={url} alt="User" />
158
+ <AvatarFallback className="text-xs">CN</AvatarFallback>
159
+ </Avatar>;
160
+
161
+ {
162
+ /* Small - 32px (default) */
163
+ }
164
+ <Avatar className="size-8">
165
+ <AvatarImage src={url} alt="User" />
166
+ <AvatarFallback>ER</AvatarFallback>
167
+ </Avatar>;
168
+
169
+ {
170
+ /* Medium - 48px */
171
+ }
172
+ <Avatar className="size-12">
173
+ <AvatarImage src={url} alt="User" />
174
+ <AvatarFallback>ML</AvatarFallback>
175
+ </Avatar>;
176
+
177
+ {
178
+ /* Large - 64px */
179
+ }
180
+ <Avatar className="size-16">
181
+ <AvatarImage src={url} alt="User" />
182
+ <AvatarFallback className="text-lg">VC</AvatarFallback>
183
+ </Avatar>;
184
+
185
+ {
186
+ /* Extra Large - 80px */
187
+ }
188
+ <Avatar className="size-20">
189
+ <AvatarImage src={url} alt="User" />
190
+ <AvatarFallback className="text-xl">NJ</AvatarFallback>
191
+ </Avatar>;
192
+ ```
193
+
194
+ **Nota**: Ajusta el tamaño del texto del fallback según el tamaño del avatar para mantener proporciones.
195
+
196
+ ### Tamaño Personalizado
197
+
198
+ ```tsx
199
+ <Avatar className="h-24 w-24">
200
+ <AvatarImage src={url} alt="User" />
201
+ <AvatarFallback className="text-2xl">AB</AvatarFallback>
202
+ </Avatar>
203
+ ```
204
+
205
+ ## Formas Personalizadas
206
+
207
+ ### Avatar Cuadrado
208
+
209
+ ```tsx
210
+ {
211
+ /* Rounded large */
212
+ }
213
+ <Avatar className="rounded-lg">
214
+ <AvatarImage src={url} alt="User" />
215
+ <AvatarFallback>CN</AvatarFallback>
216
+ </Avatar>;
217
+
218
+ {
219
+ /* Rounded medium */
220
+ }
221
+ <Avatar className="rounded-md">
222
+ <AvatarImage src={url} alt="User" />
223
+ <AvatarFallback>ER</AvatarFallback>
224
+ </Avatar>;
225
+
226
+ {
227
+ /* Rounded small */
228
+ }
229
+ <Avatar className="rounded-sm">
230
+ <AvatarImage src={url} alt="User" />
231
+ <AvatarFallback>ML</AvatarFallback>
232
+ </Avatar>;
233
+
234
+ {
235
+ /* Completamente cuadrado */
236
+ }
237
+ <Avatar className="rounded-none">
238
+ <AvatarFallback>SQ</AvatarFallback>
239
+ </Avatar>;
240
+ ```
241
+
242
+ **Uso**: Avatares cuadrados son comunes para logos de empresas o aplicaciones.
243
+
244
+ ## Patrones Avanzados
245
+
246
+ ### Grupo de Avatares (Overlapping)
247
+
248
+ Para mostrar múltiples usuarios con solapamiento:
249
+
250
+ ```tsx
251
+ <div className="flex -space-x-2">
252
+ <Avatar className="ring-2 ring-background">
253
+ <AvatarImage src="https://github.com/shadcn.png" alt="@shadcn" />
254
+ <AvatarFallback>CN</AvatarFallback>
255
+ </Avatar>
256
+ <Avatar className="ring-2 ring-background">
257
+ <AvatarImage src="https://github.com/evilrabbit.png" alt="@evilrabbit" />
258
+ <AvatarFallback>ER</AvatarFallback>
259
+ </Avatar>
260
+ <Avatar className="ring-2 ring-background">
261
+ <AvatarImage src="https://github.com/maxleiter.png" alt="@maxleiter" />
262
+ <AvatarFallback>ML</AvatarFallback>
263
+ </Avatar>
264
+ <Avatar className="ring-2 ring-background bg-muted">
265
+ <AvatarFallback>+2</AvatarFallback>
266
+ </Avatar>
267
+ </div>
268
+ ```
269
+
270
+ **Técnicas**:
271
+
272
+ - `-space-x-2`: Espacio negativo para solapar
273
+ - `ring-2 ring-background`: Borde blanco para separación visual
274
+ - Último avatar muestra contador "+N" para usuarios adicionales
275
+
276
+ ### Avatar con Tooltip
277
+
278
+ Para mostrar información adicional al hover:
279
+
280
+ ```tsx
281
+ import {
282
+ Tooltip,
283
+ TooltipContent,
284
+ TooltipProvider,
285
+ TooltipTrigger,
286
+ } from "@adamosuiteservices/ui/tooltip";
287
+
288
+ <TooltipProvider>
289
+ <Tooltip>
290
+ <TooltipTrigger asChild>
291
+ <Avatar className="cursor-pointer">
292
+ <AvatarImage src="https://github.com/shadcn.png" alt="@shadcn" />
293
+ <AvatarFallback>CN</AvatarFallback>
294
+ </Avatar>
295
+ </TooltipTrigger>
296
+ <TooltipContent>
297
+ <p>shadcn - UI Engineer</p>
298
+ </TooltipContent>
299
+ </Tooltip>
300
+ </TooltipProvider>;
301
+ ```
302
+
303
+ **Nota**: Agrega `cursor-pointer` para indicar interactividad.
304
+
305
+ ### Card de Perfil de Usuario
306
+
307
+ Avatar como parte de un perfil completo:
308
+
309
+ ```tsx
310
+ import { Badge } from "@adamosuiteservices/ui/badge";
311
+ import { Button } from "@adamosuiteservices/ui/button";
312
+
313
+ <div className="flex items-center gap-4 p-6 rounded-lg border max-w-md">
314
+ <Avatar className="size-16">
315
+ <AvatarImage src="https://github.com/shadcn.png" alt="@shadcn" />
316
+ <AvatarFallback className="text-lg">CN</AvatarFallback>
317
+ </Avatar>
318
+ <div className="flex-1">
319
+ <h3 className="text-lg font-semibold">Colin Northcott</h3>
320
+ <p className="text-sm text-muted-foreground">@shadcn • UI Engineer</p>
321
+ <div className="flex gap-2 mt-2">
322
+ <Badge variant="secondary">React</Badge>
323
+ <Badge variant="secondary">TypeScript</Badge>
324
+ </div>
325
+ </div>
326
+ <Button size="sm">Follow</Button>
327
+ </div>;
328
+ ```
329
+
330
+ ### Sistema de Comentarios
331
+
332
+ Avatares en un layout de conversación:
333
+
334
+ ```tsx
335
+ const comments = [
336
+ {
337
+ id: 1,
338
+ author: "John Doe",
339
+ avatar: "https://github.com/shadcn.png",
340
+ fallback: "JD",
341
+ time: "2 hours ago",
342
+ content:
343
+ "This looks great! Really excited to see this feature in production.",
344
+ },
345
+ // ... más comentarios
346
+ ];
347
+
348
+ <div className="space-y-4 max-w-2xl">
349
+ {comments.map((comment) => (
350
+ <div key={comment.id} className="flex gap-3">
351
+ <Avatar>
352
+ {comment.avatar && (
353
+ <AvatarImage src={comment.avatar} alt={comment.author} />
354
+ )}
355
+ <AvatarFallback>{comment.fallback}</AvatarFallback>
356
+ </Avatar>
357
+ <div className="flex-1 space-y-1">
358
+ <div className="flex items-center gap-2">
359
+ <span className="text-sm font-medium">{comment.author}</span>
360
+ <span className="text-xs text-muted-foreground">{comment.time}</span>
361
+ </div>
362
+ <p className="text-sm">{comment.content}</p>
363
+ </div>
364
+ </div>
365
+ ))}
366
+ </div>;
367
+ ```
368
+
369
+ ### Avatar con Indicador de Estado
370
+
371
+ Para mostrar estado online/offline/busy:
372
+
373
+ ```tsx
374
+ <div className="relative inline-block">
375
+ <Avatar>
376
+ <AvatarImage src={url} alt="User" />
377
+ <AvatarFallback>JD</AvatarFallback>
378
+ </Avatar>
379
+ {/* Indicador de estado */}
380
+ <span className="absolute bottom-0 right-0 block h-3 w-3 rounded-full bg-green-500 ring-2 ring-background" />
381
+ </div>
382
+ ```
383
+
384
+ **Variantes de estado**:
385
+
386
+ - `bg-green-500`: Online
387
+ - `bg-gray-400`: Offline
388
+ - `bg-yellow-500`: Away/Idle
389
+ - `bg-red-500`: Busy/Do Not Disturb
390
+
391
+ ### Avatar con Badge
392
+
393
+ Para notificaciones o roles:
394
+
395
+ ```tsx
396
+ import { Badge } from "@adamosuiteservices/ui/badge";
397
+
398
+ <div className="relative inline-block">
399
+ <Avatar className="size-12">
400
+ <AvatarImage src={url} alt="User" />
401
+ <AvatarFallback>AD</AvatarFallback>
402
+ </Avatar>
403
+ <Badge
404
+ variant="destructive"
405
+ className="absolute -top-1 -right-1 h-5 w-5 rounded-full p-0 flex items-center justify-center text-xs"
406
+ >
407
+ 5
408
+ </Badge>
409
+ </div>;
410
+ ```
411
+
412
+ ### Avatar con Icono de Fallback
413
+
414
+ Para usuarios sin nombre o genéricos:
415
+
416
+ ```tsx
417
+ import { UserIcon } from "lucide-react";
418
+
419
+ <Avatar>
420
+ <AvatarImage src={url} alt="User" />
421
+ <AvatarFallback>
422
+ <UserIcon className="h-4 w-4" />
423
+ </AvatarFallback>
424
+ </Avatar>;
425
+ ```
426
+
427
+ ## Casos de Uso Comunes
428
+
429
+ ### Lista de Miembros del Equipo
430
+
431
+ ```tsx
432
+ const team = [
433
+ { name: "John Doe", image: url1, initials: "JD" },
434
+ { name: "Jane Smith", image: url2, initials: "JS" },
435
+ // ...
436
+ ];
437
+
438
+ <div className="grid grid-cols-3 gap-4">
439
+ {team.map((member) => (
440
+ <div key={member.name} className="flex flex-col items-center gap-2">
441
+ <Avatar className="size-16">
442
+ <AvatarImage src={member.image} alt={member.name} />
443
+ <AvatarFallback className="text-lg">{member.initials}</AvatarFallback>
444
+ </Avatar>
445
+ <span className="text-sm font-medium">{member.name}</span>
446
+ </div>
447
+ ))}
448
+ </div>;
449
+ ```
450
+
451
+ ### Chat de Mensajería
452
+
453
+ ```tsx
454
+ <div className="flex items-start gap-3">
455
+ <Avatar>
456
+ <AvatarImage src={senderAvatar} alt={senderName} />
457
+ <AvatarFallback>{senderInitials}</AvatarFallback>
458
+ </Avatar>
459
+ <div className="flex-1">
460
+ <div className="flex items-center gap-2">
461
+ <span className="font-medium text-sm">{senderName}</span>
462
+ <span className="text-xs text-muted-foreground">{timestamp}</span>
463
+ </div>
464
+ <p className="text-sm mt-1">{messageContent}</p>
465
+ </div>
466
+ </div>
467
+ ```
468
+
469
+ ### Selector de Usuario
470
+
471
+ ```tsx
472
+ <div className="flex items-center gap-3 p-2 rounded-lg hover:bg-muted cursor-pointer">
473
+ <Avatar className="size-10">
474
+ <AvatarImage src={userAvatar} alt={userName} />
475
+ <AvatarFallback>{userInitials}</AvatarFallback>
476
+ </Avatar>
477
+ <div className="flex-1">
478
+ <p className="text-sm font-medium">{userName}</p>
479
+ <p className="text-xs text-muted-foreground">{userEmail}</p>
480
+ </div>
481
+ </div>
482
+ ```
483
+
484
+ ## Mejores Prácticas
485
+
486
+ ### Generación de Iniciales
487
+
488
+ ```typescript
489
+ function getInitials(name: string): string {
490
+ return name
491
+ .split(" ")
492
+ .map((part) => part[0])
493
+ .join("")
494
+ .toUpperCase()
495
+ .slice(0, 2);
496
+ }
497
+
498
+ // Uso
499
+ <AvatarFallback>{getInitials("John Doe")}</AvatarFallback>; // "JD"
500
+ ```
501
+
502
+ ### Prop alt Descriptiva
503
+
504
+ ```tsx
505
+ // ✅ Correcto - descriptivo
506
+ <AvatarImage src={url} alt="John Doe" />
507
+ <AvatarImage src={url} alt="@johndoe profile picture" />
508
+
509
+ // ❌ Incorrecto - genérico
510
+ <AvatarImage src={url} alt="avatar" />
511
+ <AvatarImage src={url} alt="user" />
512
+ ```
513
+
514
+ ### Consistencia de Tamaños
515
+
516
+ Mantén tamaños consistentes por contexto:
517
+
518
+ - **Listas pequeñas**: `size-8` (32px)
519
+ - **Perfiles**: `size-16` (64px)
520
+ - **Headers/Nav**: `size-10` (40px)
521
+ - **Comentarios**: `size-8` o `size-10`
522
+ - **Grupos**: `size-8` o más pequeños
523
+
524
+ ### Colores de Fallback Personalizados
525
+
526
+ ```tsx
527
+ <Avatar>
528
+ <AvatarImage src={url} alt="User" />
529
+ <AvatarFallback className="bg-blue-500 text-white">AB</AvatarFallback>
530
+ </Avatar>
531
+ ```
532
+
533
+ **Patrón común**: Asignar colores basados en el nombre del usuario:
534
+
535
+ ```typescript
536
+ function getAvatarColor(name: string): string {
537
+ const colors = [
538
+ "bg-red-500",
539
+ "bg-blue-500",
540
+ "bg-green-500",
541
+ "bg-yellow-500",
542
+ "bg-purple-500",
543
+ ];
544
+ const index = name.charCodeAt(0) % colors.length;
545
+ return colors[index];
546
+ }
547
+ ```
548
+
549
+ ## Notas de Implementación
550
+
551
+ - Basado en Radix UI Avatar primitives
552
+ - Lazy loading de imágenes por defecto
553
+ - Fallback se muestra automáticamente en error de carga
554
+ - `aspect-square` mantiene proporción 1:1
555
+ - `overflow-hidden` con `rounded-full` crea forma circular
556
+ - `shrink-0` evita que el avatar se encoja en layouts flex
557
+ - Sistema de slots con `data-slot` para composición
558
+ - Tamaño por defecto: 32x32px (`size-8`)
559
+
560
+ ## Accesibilidad
561
+
562
+ - ✅ **SIEMPRE** incluye prop `alt` en `AvatarImage` con texto descriptivo
563
+ - ✅ Radix UI maneja ARIA attributes automáticamente
564
+ - ✅ El fallback es accesible por screen readers
565
+ - ✅ Usa texto real en fallback (no iconos decorativos solos) cuando sea posible
566
+ - ✅ Si el avatar es clickeable, agrégalo dentro de un `<button>` o `<a>` con aria-label
567
+ - ⚠️ No uses solo color para indicar estado (combina con iconos/texto)
568
+
569
+ ### Avatar Clickeable Accesible
570
+
571
+ ```tsx
572
+ <button
573
+ type="button"
574
+ aria-label="View John Doe's profile"
575
+ className="rounded-full focus:outline-none focus:ring-2 focus:ring-offset-2"
576
+ >
577
+ <Avatar>
578
+ <AvatarImage src={url} alt="John Doe" />
579
+ <AvatarFallback>JD</AvatarFallback>
580
+ </Avatar>
581
+ </button>
582
+ ```
583
+
584
+ ## Referencias
585
+
586
+ - Radix UI Avatar: https://www.radix-ui.com/primitives/docs/components/avatar
587
+ - shadcn/ui Avatar: https://ui.shadcn.com/docs/components/avatar
588
+ - WCAG Image Alternative Text: https://www.w3.org/WAI/tutorials/images/