@adamosuiteservices/ui 1.7.13 → 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 +62 -22
  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,454 +1,454 @@
1
- # Command
2
-
3
- Paleta de comandos estilo Cmd+K basada en `cmdk` con búsqueda fuzzy, navegación por teclado, grupos, separadores, y shortcuts. Útil para command palettes, búsqueda rápida, y navegación.
4
-
5
- ## Importación
6
-
7
- ```tsx
8
- import {
9
- Command,
10
- CommandInput,
11
- CommandList,
12
- CommandEmpty,
13
- CommandGroup,
14
- CommandItem,
15
- CommandSeparator,
16
- CommandShortcut,
17
- CommandDialog,
18
- } from "@adamosuiteservices/ui/command";
19
- ```
20
-
21
- ## Anatomía
22
-
23
- ```tsx
24
- <Command>
25
- <CommandInput placeholder="Search..." />
26
- <CommandList>
27
- <CommandEmpty>No results found.</CommandEmpty>
28
- <CommandGroup heading="Actions">
29
- <CommandItem>
30
- New File
31
- <CommandShortcut>⌘N</CommandShortcut>
32
- </CommandItem>
33
- <CommandItem>Open</CommandItem>
34
- </CommandGroup>
35
- <CommandSeparator />
36
- <CommandGroup heading="Settings">
37
- <CommandItem>Preferences</CommandItem>
38
- </CommandGroup>
39
- </CommandList>
40
- </Command>
41
- ```
42
-
43
- **Componentes**: 8 (Command, CommandInput, CommandList, CommandEmpty, CommandGroup, CommandItem, CommandSeparator, CommandShortcut)
44
-
45
- ## Props Principales
46
-
47
- ### Command (Root)
48
-
49
- | Prop | Tipo | Default | Descripción |
50
- | --------------- | ------------------------------------------- | ----------- | -------------------------------------- |
51
- | `value` | `string` | - | Valor controlado del item seleccionado |
52
- | `onValueChange` | `(value: string) => void` | - | Callback cuando cambia selección |
53
- | `filter` | `(value: string, search: string) => number` | Fuzzy match | Función de filtrado custom |
54
- | `shouldFilter` | `boolean` | `true` | Habilita filtrado automático |
55
- | `loop` | `boolean` | `false` | Navegación circular con arrow keys |
56
- | `className` | `string` | - | Clases CSS adicionales |
57
-
58
- ### CommandInput
59
-
60
- | Prop | Tipo | Descripción |
61
- | --------------- | -------------------------- | -------------------------- |
62
- | `placeholder` | `string` | Texto placeholder |
63
- | `value` | `string` | Valor controlado del input |
64
- | `onValueChange` | `(search: string) => void` | Callback al escribir |
65
- | `className` | `string` | Clases CSS adicionales |
66
-
67
- ### CommandList
68
-
69
- | Prop | Tipo | Default | Descripción |
70
- | ----------- | ----------- | ------- | -------------------------- |
71
- | `className` | `string` | - | Clases CSS adicionales |
72
- | `children` | `ReactNode` | - | Grupos, items, separadores |
73
-
74
- **Estilos default**: `max-h-[300px]`, scroll vertical automático
75
-
76
- ### CommandItem
77
-
78
- | Prop | Tipo | Descripción |
79
- | ----------- | ------------------------- | ------------------------------------------ |
80
- | `value` | `string` | Valor único del item (usado para búsqueda) |
81
- | `onSelect` | `(value: string) => void` | Callback al seleccionar |
82
- | `disabled` | `boolean` | Desactiva selección |
83
- | `keywords` | `string[]` | Palabras clave adicionales para búsqueda |
84
- | `className` | `string` | Clases CSS adicionales |
85
-
86
- ### CommandDialog
87
-
88
- | Prop | Tipo | Default | Descripción |
89
- | ----------------- | ------------------------- | ------------------- | ------------------------ |
90
- | `open` | `boolean` | - | Estado del dialog |
91
- | `onOpenChange` | `(open: boolean) => void` | - | Callback al abrir/cerrar |
92
- | `title` | `string` | `"Command Palette"` | Título (sr-only) |
93
- | `description` | `string` | `"Search for..."` | Descripción (sr-only) |
94
- | `showCloseButton` | `boolean` | `true` | Muestra botón de cerrar |
95
- | `className` | `string` | - | Clases CSS adicionales |
96
-
97
- ## Patrones de Uso
98
-
99
- ### Básico (Inline)
100
-
101
- ```tsx
102
- <Command>
103
- <CommandInput placeholder="Type to search..." />
104
- <CommandList>
105
- <CommandEmpty>No results found.</CommandEmpty>
106
- <CommandGroup heading="Suggestions">
107
- <CommandItem>Calendar</CommandItem>
108
- <CommandItem>Search Emoji</CommandItem>
109
- <CommandItem>Calculator</CommandItem>
110
- </CommandGroup>
111
- </CommandList>
112
- </Command>
113
- ```
114
-
115
- ### Command Dialog (Cmd+K)
116
-
117
- ```tsx
118
- import { useEffect, useState } from "react";
119
-
120
- function CommandMenu() {
121
- const [open, setOpen] = useState(false);
122
-
123
- useEffect(() => {
124
- const down = (e: KeyboardEvent) => {
125
- if (e.key === "k" && (e.metaKey || e.ctrlKey)) {
126
- e.preventDefault();
127
- setOpen((open) => !open);
128
- }
129
- };
130
-
131
- document.addEventListener("keydown", down);
132
- return () => document.removeEventListener("keydown", down);
133
- }, []);
134
-
135
- return (
136
- <CommandDialog open={open} onOpenChange={setOpen}>
137
- <CommandInput placeholder="Type a command or search..." />
138
- <CommandList>
139
- <CommandEmpty>No results found.</CommandEmpty>
140
- <CommandGroup heading="Actions">
141
- <CommandItem>
142
- New File
143
- <CommandShortcut>⌘N</CommandShortcut>
144
- </CommandItem>
145
- <CommandItem>
146
- Open File
147
- <CommandShortcut>⌘O</CommandShortcut>
148
- </CommandItem>
149
- </CommandGroup>
150
- </CommandList>
151
- </CommandDialog>
152
- );
153
- }
154
- ```
155
-
156
- ### Con Iconos
157
-
158
- ```tsx
159
- import { CalendarIcon, FaceIcon, RocketIcon } from "lucide-react";
160
-
161
- <Command>
162
- <CommandInput placeholder="Search..." />
163
- <CommandList>
164
- <CommandGroup heading="Suggestions">
165
- <CommandItem>
166
- <CalendarIcon />
167
- Calendar
168
- </CommandItem>
169
- <CommandItem>
170
- <FaceIcon />
171
- Search Emoji
172
- </CommandItem>
173
- <CommandItem>
174
- <RocketIcon />
175
- Launch
176
- </CommandItem>
177
- </CommandGroup>
178
- </CommandList>
179
- </Command>;
180
- ```
181
-
182
- **Nota**: SVGs tienen `size-4` automático y `text-muted-foreground` si no tienen clase `text-*`.
183
-
184
- ### Múltiples Grupos con Separadores
185
-
186
- ```tsx
187
- <Command>
188
- <CommandInput placeholder="Search..." />
189
- <CommandList>
190
- <CommandGroup heading="Files">
191
- <CommandItem>New File</CommandItem>
192
- <CommandItem>New Folder</CommandItem>
193
- </CommandGroup>
194
-
195
- <CommandSeparator />
196
-
197
- <CommandGroup heading="Edit">
198
- <CommandItem>Copy</CommandItem>
199
- <CommandItem>Paste</CommandItem>
200
- </CommandGroup>
201
-
202
- <CommandSeparator />
203
-
204
- <CommandGroup heading="View">
205
- <CommandItem>Toggle Sidebar</CommandItem>
206
- <CommandItem>Full Screen</CommandItem>
207
- </CommandGroup>
208
- </CommandList>
209
- </Command>
210
- ```
211
-
212
- ### Con Callbacks (Ejecutar Acciones)
213
-
214
- ```tsx
215
- function App() {
216
- const runCommand = (command: string) => {
217
- console.log(`Running: ${command}`);
218
- // Ejecutar acción
219
- };
220
-
221
- return (
222
- <Command>
223
- <CommandInput placeholder="Search..." />
224
- <CommandList>
225
- <CommandGroup heading="Actions">
226
- <CommandItem onSelect={() => runCommand("new-file")}>
227
- New File
228
- </CommandItem>
229
- <CommandItem onSelect={() => runCommand("open-file")}>
230
- Open File
231
- </CommandItem>
232
- <CommandItem onSelect={() => runCommand("save")}>Save</CommandItem>
233
- </CommandGroup>
234
- </CommandList>
235
- </Command>
236
- );
237
- }
238
- ```
239
-
240
- ### Items Deshabilitados
241
-
242
- ```tsx
243
- <Command>
244
- <CommandList>
245
- <CommandGroup>
246
- <CommandItem>Available Option</CommandItem>
247
- <CommandItem disabled>Coming Soon</CommandItem>
248
- <CommandItem disabled>Premium Feature</CommandItem>
249
- </CommandGroup>
250
- </CommandList>
251
- </Command>
252
- ```
253
-
254
- **Estilos**: `opacity-50`, `pointer-events-none`, `data-[disabled=true]`
255
-
256
- ### Con Keywords para Búsqueda
257
-
258
- ```tsx
259
- <Command>
260
- <CommandInput placeholder="Search settings..." />
261
- <CommandList>
262
- <CommandGroup heading="Settings">
263
- <CommandItem
264
- value="theme"
265
- keywords={["appearance", "dark", "light", "color"]}
266
- >
267
- Theme Settings
268
- </CommandItem>
269
- <CommandItem
270
- value="shortcuts"
271
- keywords={["keyboard", "hotkeys", "bindings"]}
272
- >
273
- Keyboard Shortcuts
274
- </CommandItem>
275
- </CommandGroup>
276
- </CommandList>
277
- </Command>
278
- ```
279
-
280
- **Búsqueda**: Encuentra items por `value`, `children` text, o `keywords[]`
281
-
282
- ### Navegación de Páginas
283
-
284
- ```tsx
285
- function PageSearch() {
286
- const navigate = useNavigate();
287
- const [open, setOpen] = useState(false);
288
-
289
- return (
290
- <CommandDialog open={open} onOpenChange={setOpen}>
291
- <CommandInput placeholder="Search pages..." />
292
- <CommandList>
293
- <CommandGroup heading="Pages">
294
- <CommandItem
295
- onSelect={() => {
296
- navigate("/dashboard");
297
- setOpen(false);
298
- }}
299
- >
300
- Dashboard
301
- </CommandItem>
302
- <CommandItem
303
- onSelect={() => {
304
- navigate("/settings");
305
- setOpen(false);
306
- }}
307
- >
308
- Settings
309
- </CommandItem>
310
- <CommandItem
311
- onSelect={() => {
312
- navigate("/profile");
313
- setOpen(false);
314
- }}
315
- >
316
- Profile
317
- </CommandItem>
318
- </CommandGroup>
319
- </CommandList>
320
- </CommandDialog>
321
- );
322
- }
323
- ```
324
-
325
- ### Filtrado Custom
326
-
327
- ```tsx
328
- // Exacto match en lugar de fuzzy
329
- const exactMatch = (value: string, search: string) => {
330
- return value.toLowerCase().includes(search.toLowerCase()) ? 1 : 0;
331
- };
332
-
333
- <Command filter={exactMatch}>
334
- <CommandInput placeholder="Search..." />
335
- <CommandList>
336
- <CommandGroup>
337
- <CommandItem>Apple</CommandItem>
338
- <CommandItem>Banana</CommandItem>
339
- <CommandItem>Cherry</CommandItem>
340
- </CommandGroup>
341
- </CommandList>
342
- </Command>;
343
- ```
344
-
345
- ### Sin Filtrado Automático
346
-
347
- ```tsx
348
- // Control manual del filtrado
349
- function CustomFilter() {
350
- const [search, setSearch] = useState("");
351
- const [filteredItems, setFilteredItems] = useState(allItems);
352
-
353
- useEffect(() => {
354
- setFilteredItems(
355
- allItems.filter((item) =>
356
- item.toLowerCase().includes(search.toLowerCase())
357
- )
358
- );
359
- }, [search]);
360
-
361
- return (
362
- <Command shouldFilter={false}>
363
- <CommandInput
364
- value={search}
365
- onValueChange={setSearch}
366
- placeholder="Search..."
367
- />
368
- <CommandList>
369
- <CommandGroup>
370
- {filteredItems.map((item) => (
371
- <CommandItem key={item}>{item}</CommandItem>
372
- ))}
373
- </CommandGroup>
374
- </CommandList>
375
- </Command>
376
- );
377
- }
378
- ```
379
-
380
- ## Casos de Uso Comunes
381
-
382
- **Command palette (Cmd+K)**: Búsqueda rápida de acciones/comandos
383
- **Page navigation**: Navegación rápida entre páginas
384
- **File picker**: Búsqueda de archivos en proyecto
385
- **Settings search**: Encontrar configuraciones
386
- **Action menu**: Menú de acciones contextuales
387
- **Spotlight search**: Búsqueda global tipo macOS
388
-
389
- ## Estados y Data Attributes
390
-
391
- ### CommandItem States
392
-
393
- - **Selected**: `data-[selected=true]` → `bg-accent`, `text-accent-foreground`
394
- - **Disabled**: `data-[disabled=true]` → `opacity-50`, `pointer-events-none`
395
-
396
- ### Empty State
397
-
398
- - Automático cuando búsqueda no encuentra resultados
399
- - Personalizable con `<CommandEmpty>`
400
-
401
- ## Navegación por Teclado
402
-
403
- - ✅ **Arrow Up/Down**: Navega entre items
404
- - ✅ **Enter**: Selecciona item enfocado
405
- - ✅ **Escape**: Cierra dialog (si CommandDialog)
406
- - ✅ **Type to search**: Filtrado automático
407
- - ✅ **Tab**: Sale del Command (no navega items)
408
- - ✅ **Home/End**: Primer/último item (si `loop={true}`)
409
-
410
- ## Accesibilidad
411
-
412
- - ✅ **ARIA**: `role="combobox"` en Command, `role="option"` en items
413
- - ✅ **Screen readers**: Anuncia items y cuenta de resultados
414
- - ✅ **Keyboard navigation**: Navegación completa por teclado
415
- - ✅ **Focus management**: Focus visible en items seleccionados
416
- - ✅ **Live regions**: Anuncia cuando cambian resultados
417
- - ✅ **Disabled items**: `aria-disabled` en items deshabilitados
418
-
419
- ## Notas de Implementación
420
-
421
- - **Basado en cmdk**: Librería `cmdk` de Paco Coursey
422
- - **Fuzzy search**: Búsqueda difusa por defecto (typo-tolerant)
423
- - **Performance**: Virtualización automática con muchos items
424
- - **SearchIcon**: Incluido automáticamente en CommandInput
425
- - **CommandDialog**: Wrapper de Command + Dialog con estilos predefinidos
426
- - **Data slots**: Cada componente tiene `data-slot` para CSS targeting
427
- - **SVG auto-sizing**: Iconos dentro de items automáticamente `size-4`
428
- - **CommandShortcut**: Elemento visual para shortcuts (no ejecuta código)
429
- - **Max height**: CommandList tiene `max-h-[300px]` default
430
- - **Scroll behavior**: `scroll-py-1` para padding al scrollear
431
-
432
- ## Estilos Especiales en CommandDialog
433
-
434
- Cuando se usa en Dialog, aplica estilos adicionales:
435
-
436
- - Items con `py-3` (más padding)
437
- - Input con `h-12`
438
- - SVGs con `h-5 w-5` (más grandes)
439
- - Groups con heading más prominente
440
-
441
- ## Troubleshooting
442
-
443
- **Búsqueda no funciona**: Verifica que `shouldFilter={true}` (default) o implementa filtrado manual
444
- **Items no se ven**: Asegúrate de envolver en `<CommandList>` y `<CommandGroup>`
445
- **Cmd+K no abre dialog**: Verifica que el `useEffect` esté ejecutándose y no haya conflictos con otros shortcuts
446
- **Empty no aparece**: Solo se muestra cuando no hay resultados después de búsqueda
447
- **Shortcuts no ejecutan**: `CommandShortcut` es solo visual, implementa lógica aparte
448
- **Dialog no cierra**: Asegúrate de llamar `setOpen(false)` en `onSelect` de items
449
- **Navegación circular no funciona**: Activa `loop={true}` en Command root
450
-
451
- ## Referencias
452
-
453
- - **cmdk**: https://cmdk.paco.me
454
- - **ARIA Combobox**: https://www.w3.org/WAI/ARIA/apg/patterns/combobox/
1
+ # Command
2
+
3
+ Paleta de comandos estilo Cmd+K basada en `cmdk` con búsqueda fuzzy, navegación por teclado, grupos, separadores, y shortcuts. Útil para command palettes, búsqueda rápida, y navegación.
4
+
5
+ ## Importación
6
+
7
+ ```tsx
8
+ import {
9
+ Command,
10
+ CommandInput,
11
+ CommandList,
12
+ CommandEmpty,
13
+ CommandGroup,
14
+ CommandItem,
15
+ CommandSeparator,
16
+ CommandShortcut,
17
+ CommandDialog,
18
+ } from "@adamosuiteservices/ui/command";
19
+ ```
20
+
21
+ ## Anatomía
22
+
23
+ ```tsx
24
+ <Command>
25
+ <CommandInput placeholder="Search..." />
26
+ <CommandList>
27
+ <CommandEmpty>No results found.</CommandEmpty>
28
+ <CommandGroup heading="Actions">
29
+ <CommandItem>
30
+ New File
31
+ <CommandShortcut>⌘N</CommandShortcut>
32
+ </CommandItem>
33
+ <CommandItem>Open</CommandItem>
34
+ </CommandGroup>
35
+ <CommandSeparator />
36
+ <CommandGroup heading="Settings">
37
+ <CommandItem>Preferences</CommandItem>
38
+ </CommandGroup>
39
+ </CommandList>
40
+ </Command>
41
+ ```
42
+
43
+ **Componentes**: 8 (Command, CommandInput, CommandList, CommandEmpty, CommandGroup, CommandItem, CommandSeparator, CommandShortcut)
44
+
45
+ ## Props Principales
46
+
47
+ ### Command (Root)
48
+
49
+ | Prop | Tipo | Default | Descripción |
50
+ | --------------- | ------------------------------------------- | ----------- | -------------------------------------- |
51
+ | `value` | `string` | - | Valor controlado del item seleccionado |
52
+ | `onValueChange` | `(value: string) => void` | - | Callback cuando cambia selección |
53
+ | `filter` | `(value: string, search: string) => number` | Fuzzy match | Función de filtrado custom |
54
+ | `shouldFilter` | `boolean` | `true` | Habilita filtrado automático |
55
+ | `loop` | `boolean` | `false` | Navegación circular con arrow keys |
56
+ | `className` | `string` | - | Clases CSS adicionales |
57
+
58
+ ### CommandInput
59
+
60
+ | Prop | Tipo | Descripción |
61
+ | --------------- | -------------------------- | -------------------------- |
62
+ | `placeholder` | `string` | Texto placeholder |
63
+ | `value` | `string` | Valor controlado del input |
64
+ | `onValueChange` | `(search: string) => void` | Callback al escribir |
65
+ | `className` | `string` | Clases CSS adicionales |
66
+
67
+ ### CommandList
68
+
69
+ | Prop | Tipo | Default | Descripción |
70
+ | ----------- | ----------- | ------- | -------------------------- |
71
+ | `className` | `string` | - | Clases CSS adicionales |
72
+ | `children` | `ReactNode` | - | Grupos, items, separadores |
73
+
74
+ **Estilos default**: `max-h-[300px]`, scroll vertical automático
75
+
76
+ ### CommandItem
77
+
78
+ | Prop | Tipo | Descripción |
79
+ | ----------- | ------------------------- | ------------------------------------------ |
80
+ | `value` | `string` | Valor único del item (usado para búsqueda) |
81
+ | `onSelect` | `(value: string) => void` | Callback al seleccionar |
82
+ | `disabled` | `boolean` | Desactiva selección |
83
+ | `keywords` | `string[]` | Palabras clave adicionales para búsqueda |
84
+ | `className` | `string` | Clases CSS adicionales |
85
+
86
+ ### CommandDialog
87
+
88
+ | Prop | Tipo | Default | Descripción |
89
+ | ----------------- | ------------------------- | ------------------- | ------------------------ |
90
+ | `open` | `boolean` | - | Estado del dialog |
91
+ | `onOpenChange` | `(open: boolean) => void` | - | Callback al abrir/cerrar |
92
+ | `title` | `string` | `"Command Palette"` | Título (sr-only) |
93
+ | `description` | `string` | `"Search for..."` | Descripción (sr-only) |
94
+ | `showCloseButton` | `boolean` | `true` | Muestra botón de cerrar |
95
+ | `className` | `string` | - | Clases CSS adicionales |
96
+
97
+ ## Patrones de Uso
98
+
99
+ ### Básico (Inline)
100
+
101
+ ```tsx
102
+ <Command>
103
+ <CommandInput placeholder="Type to search..." />
104
+ <CommandList>
105
+ <CommandEmpty>No results found.</CommandEmpty>
106
+ <CommandGroup heading="Suggestions">
107
+ <CommandItem>Calendar</CommandItem>
108
+ <CommandItem>Search Emoji</CommandItem>
109
+ <CommandItem>Calculator</CommandItem>
110
+ </CommandGroup>
111
+ </CommandList>
112
+ </Command>
113
+ ```
114
+
115
+ ### Command Dialog (Cmd+K)
116
+
117
+ ```tsx
118
+ import { useEffect, useState } from "react";
119
+
120
+ function CommandMenu() {
121
+ const [open, setOpen] = useState(false);
122
+
123
+ useEffect(() => {
124
+ const down = (e: KeyboardEvent) => {
125
+ if (e.key === "k" && (e.metaKey || e.ctrlKey)) {
126
+ e.preventDefault();
127
+ setOpen((open) => !open);
128
+ }
129
+ };
130
+
131
+ document.addEventListener("keydown", down);
132
+ return () => document.removeEventListener("keydown", down);
133
+ }, []);
134
+
135
+ return (
136
+ <CommandDialog open={open} onOpenChange={setOpen}>
137
+ <CommandInput placeholder="Type a command or search..." />
138
+ <CommandList>
139
+ <CommandEmpty>No results found.</CommandEmpty>
140
+ <CommandGroup heading="Actions">
141
+ <CommandItem>
142
+ New File
143
+ <CommandShortcut>⌘N</CommandShortcut>
144
+ </CommandItem>
145
+ <CommandItem>
146
+ Open File
147
+ <CommandShortcut>⌘O</CommandShortcut>
148
+ </CommandItem>
149
+ </CommandGroup>
150
+ </CommandList>
151
+ </CommandDialog>
152
+ );
153
+ }
154
+ ```
155
+
156
+ ### Con Iconos
157
+
158
+ ```tsx
159
+ import { CalendarIcon, FaceIcon, RocketIcon } from "lucide-react";
160
+
161
+ <Command>
162
+ <CommandInput placeholder="Search..." />
163
+ <CommandList>
164
+ <CommandGroup heading="Suggestions">
165
+ <CommandItem>
166
+ <CalendarIcon />
167
+ Calendar
168
+ </CommandItem>
169
+ <CommandItem>
170
+ <FaceIcon />
171
+ Search Emoji
172
+ </CommandItem>
173
+ <CommandItem>
174
+ <RocketIcon />
175
+ Launch
176
+ </CommandItem>
177
+ </CommandGroup>
178
+ </CommandList>
179
+ </Command>;
180
+ ```
181
+
182
+ **Nota**: SVGs tienen `size-4` automático y `text-muted-foreground` si no tienen clase `text-*`.
183
+
184
+ ### Múltiples Grupos con Separadores
185
+
186
+ ```tsx
187
+ <Command>
188
+ <CommandInput placeholder="Search..." />
189
+ <CommandList>
190
+ <CommandGroup heading="Files">
191
+ <CommandItem>New File</CommandItem>
192
+ <CommandItem>New Folder</CommandItem>
193
+ </CommandGroup>
194
+
195
+ <CommandSeparator />
196
+
197
+ <CommandGroup heading="Edit">
198
+ <CommandItem>Copy</CommandItem>
199
+ <CommandItem>Paste</CommandItem>
200
+ </CommandGroup>
201
+
202
+ <CommandSeparator />
203
+
204
+ <CommandGroup heading="View">
205
+ <CommandItem>Toggle Sidebar</CommandItem>
206
+ <CommandItem>Full Screen</CommandItem>
207
+ </CommandGroup>
208
+ </CommandList>
209
+ </Command>
210
+ ```
211
+
212
+ ### Con Callbacks (Ejecutar Acciones)
213
+
214
+ ```tsx
215
+ function App() {
216
+ const runCommand = (command: string) => {
217
+ console.log(`Running: ${command}`);
218
+ // Ejecutar acción
219
+ };
220
+
221
+ return (
222
+ <Command>
223
+ <CommandInput placeholder="Search..." />
224
+ <CommandList>
225
+ <CommandGroup heading="Actions">
226
+ <CommandItem onSelect={() => runCommand("new-file")}>
227
+ New File
228
+ </CommandItem>
229
+ <CommandItem onSelect={() => runCommand("open-file")}>
230
+ Open File
231
+ </CommandItem>
232
+ <CommandItem onSelect={() => runCommand("save")}>Save</CommandItem>
233
+ </CommandGroup>
234
+ </CommandList>
235
+ </Command>
236
+ );
237
+ }
238
+ ```
239
+
240
+ ### Items Deshabilitados
241
+
242
+ ```tsx
243
+ <Command>
244
+ <CommandList>
245
+ <CommandGroup>
246
+ <CommandItem>Available Option</CommandItem>
247
+ <CommandItem disabled>Coming Soon</CommandItem>
248
+ <CommandItem disabled>Premium Feature</CommandItem>
249
+ </CommandGroup>
250
+ </CommandList>
251
+ </Command>
252
+ ```
253
+
254
+ **Estilos**: `opacity-50`, `pointer-events-none`, `data-[disabled=true]`
255
+
256
+ ### Con Keywords para Búsqueda
257
+
258
+ ```tsx
259
+ <Command>
260
+ <CommandInput placeholder="Search settings..." />
261
+ <CommandList>
262
+ <CommandGroup heading="Settings">
263
+ <CommandItem
264
+ value="theme"
265
+ keywords={["appearance", "dark", "light", "color"]}
266
+ >
267
+ Theme Settings
268
+ </CommandItem>
269
+ <CommandItem
270
+ value="shortcuts"
271
+ keywords={["keyboard", "hotkeys", "bindings"]}
272
+ >
273
+ Keyboard Shortcuts
274
+ </CommandItem>
275
+ </CommandGroup>
276
+ </CommandList>
277
+ </Command>
278
+ ```
279
+
280
+ **Búsqueda**: Encuentra items por `value`, `children` text, o `keywords[]`
281
+
282
+ ### Navegación de Páginas
283
+
284
+ ```tsx
285
+ function PageSearch() {
286
+ const navigate = useNavigate();
287
+ const [open, setOpen] = useState(false);
288
+
289
+ return (
290
+ <CommandDialog open={open} onOpenChange={setOpen}>
291
+ <CommandInput placeholder="Search pages..." />
292
+ <CommandList>
293
+ <CommandGroup heading="Pages">
294
+ <CommandItem
295
+ onSelect={() => {
296
+ navigate("/dashboard");
297
+ setOpen(false);
298
+ }}
299
+ >
300
+ Dashboard
301
+ </CommandItem>
302
+ <CommandItem
303
+ onSelect={() => {
304
+ navigate("/settings");
305
+ setOpen(false);
306
+ }}
307
+ >
308
+ Settings
309
+ </CommandItem>
310
+ <CommandItem
311
+ onSelect={() => {
312
+ navigate("/profile");
313
+ setOpen(false);
314
+ }}
315
+ >
316
+ Profile
317
+ </CommandItem>
318
+ </CommandGroup>
319
+ </CommandList>
320
+ </CommandDialog>
321
+ );
322
+ }
323
+ ```
324
+
325
+ ### Filtrado Custom
326
+
327
+ ```tsx
328
+ // Exacto match en lugar de fuzzy
329
+ const exactMatch = (value: string, search: string) => {
330
+ return value.toLowerCase().includes(search.toLowerCase()) ? 1 : 0;
331
+ };
332
+
333
+ <Command filter={exactMatch}>
334
+ <CommandInput placeholder="Search..." />
335
+ <CommandList>
336
+ <CommandGroup>
337
+ <CommandItem>Apple</CommandItem>
338
+ <CommandItem>Banana</CommandItem>
339
+ <CommandItem>Cherry</CommandItem>
340
+ </CommandGroup>
341
+ </CommandList>
342
+ </Command>;
343
+ ```
344
+
345
+ ### Sin Filtrado Automático
346
+
347
+ ```tsx
348
+ // Control manual del filtrado
349
+ function CustomFilter() {
350
+ const [search, setSearch] = useState("");
351
+ const [filteredItems, setFilteredItems] = useState(allItems);
352
+
353
+ useEffect(() => {
354
+ setFilteredItems(
355
+ allItems.filter((item) =>
356
+ item.toLowerCase().includes(search.toLowerCase())
357
+ )
358
+ );
359
+ }, [search]);
360
+
361
+ return (
362
+ <Command shouldFilter={false}>
363
+ <CommandInput
364
+ value={search}
365
+ onValueChange={setSearch}
366
+ placeholder="Search..."
367
+ />
368
+ <CommandList>
369
+ <CommandGroup>
370
+ {filteredItems.map((item) => (
371
+ <CommandItem key={item}>{item}</CommandItem>
372
+ ))}
373
+ </CommandGroup>
374
+ </CommandList>
375
+ </Command>
376
+ );
377
+ }
378
+ ```
379
+
380
+ ## Casos de Uso Comunes
381
+
382
+ **Command palette (Cmd+K)**: Búsqueda rápida de acciones/comandos
383
+ **Page navigation**: Navegación rápida entre páginas
384
+ **File picker**: Búsqueda de archivos en proyecto
385
+ **Settings search**: Encontrar configuraciones
386
+ **Action menu**: Menú de acciones contextuales
387
+ **Spotlight search**: Búsqueda global tipo macOS
388
+
389
+ ## Estados y Data Attributes
390
+
391
+ ### CommandItem States
392
+
393
+ - **Selected**: `data-[selected=true]` → `bg-accent`, `text-accent-foreground`
394
+ - **Disabled**: `data-[disabled=true]` → `opacity-50`, `pointer-events-none`
395
+
396
+ ### Empty State
397
+
398
+ - Automático cuando búsqueda no encuentra resultados
399
+ - Personalizable con `<CommandEmpty>`
400
+
401
+ ## Navegación por Teclado
402
+
403
+ - ✅ **Arrow Up/Down**: Navega entre items
404
+ - ✅ **Enter**: Selecciona item enfocado
405
+ - ✅ **Escape**: Cierra dialog (si CommandDialog)
406
+ - ✅ **Type to search**: Filtrado automático
407
+ - ✅ **Tab**: Sale del Command (no navega items)
408
+ - ✅ **Home/End**: Primer/último item (si `loop={true}`)
409
+
410
+ ## Accesibilidad
411
+
412
+ - ✅ **ARIA**: `role="combobox"` en Command, `role="option"` en items
413
+ - ✅ **Screen readers**: Anuncia items y cuenta de resultados
414
+ - ✅ **Keyboard navigation**: Navegación completa por teclado
415
+ - ✅ **Focus management**: Focus visible en items seleccionados
416
+ - ✅ **Live regions**: Anuncia cuando cambian resultados
417
+ - ✅ **Disabled items**: `aria-disabled` en items deshabilitados
418
+
419
+ ## Notas de Implementación
420
+
421
+ - **Basado en cmdk**: Librería `cmdk` de Paco Coursey
422
+ - **Fuzzy search**: Búsqueda difusa por defecto (typo-tolerant)
423
+ - **Performance**: Virtualización automática con muchos items
424
+ - **SearchIcon**: Incluido automáticamente en CommandInput
425
+ - **CommandDialog**: Wrapper de Command + Dialog con estilos predefinidos
426
+ - **Data slots**: Cada componente tiene `data-slot` para CSS targeting
427
+ - **SVG auto-sizing**: Iconos dentro de items automáticamente `size-4`
428
+ - **CommandShortcut**: Elemento visual para shortcuts (no ejecuta código)
429
+ - **Max height**: CommandList tiene `max-h-[300px]` default
430
+ - **Scroll behavior**: `scroll-py-1` para padding al scrollear
431
+
432
+ ## Estilos Especiales en CommandDialog
433
+
434
+ Cuando se usa en Dialog, aplica estilos adicionales:
435
+
436
+ - Items con `py-3` (más padding)
437
+ - Input con `h-12`
438
+ - SVGs con `h-5 w-5` (más grandes)
439
+ - Groups con heading más prominente
440
+
441
+ ## Troubleshooting
442
+
443
+ **Búsqueda no funciona**: Verifica que `shouldFilter={true}` (default) o implementa filtrado manual
444
+ **Items no se ven**: Asegúrate de envolver en `<CommandList>` y `<CommandGroup>`
445
+ **Cmd+K no abre dialog**: Verifica que el `useEffect` esté ejecutándose y no haya conflictos con otros shortcuts
446
+ **Empty no aparece**: Solo se muestra cuando no hay resultados después de búsqueda
447
+ **Shortcuts no ejecutan**: `CommandShortcut` es solo visual, implementa lógica aparte
448
+ **Dialog no cierra**: Asegúrate de llamar `setOpen(false)` en `onSelect` de items
449
+ **Navegación circular no funciona**: Activa `loop={true}` en Command root
450
+
451
+ ## Referencias
452
+
453
+ - **cmdk**: https://cmdk.paco.me
454
+ - **ARIA Combobox**: https://www.w3.org/WAI/ARIA/apg/patterns/combobox/