siesa-ui-kit 1.0.4 → 1.0.5

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 (541) hide show
  1. package/README.md +89 -115
  2. package/bin/install.cjs +502 -502
  3. package/bin/prepare-publish.cjs +28 -28
  4. package/bin/restore-folders.cjs +28 -28
  5. package/claude/agents/siesa-ui-kit-specialist.md +2401 -2445
  6. package/claude/prompts/component-template.md +121 -121
  7. package/claude/settings.local.json +61 -72
  8. package/docs/border-radius.md +1261 -1261
  9. package/docs/colors.md +832 -832
  10. package/docs/dark-mode-guide.md +1426 -1426
  11. package/docs/filters.md +1243 -1243
  12. package/docs/icons.md +1283 -1264
  13. package/docs/shadows.md +1377 -1377
  14. package/docs/spacing.md +1684 -1684
  15. package/docs/typography.md +1268 -1268
  16. package/package.json +83 -111
  17. package/postcss.config.cjs +6 -6
  18. package/src/App.css +42 -42
  19. package/src/App.tsx +8 -8
  20. package/src/ButtonTest.tsx +147 -147
  21. package/src/assets/fonts/README.md +261 -261
  22. package/src/components/Alert/Alert.stories.tsx +332 -332
  23. package/src/components/Alert/Alert.tsx +106 -106
  24. package/src/components/Alert/Alert.types.ts +54 -54
  25. package/src/components/Avatar/Avatar.stories.tsx +494 -494
  26. package/src/components/Avatar/Avatar.tsx +143 -143
  27. package/src/components/Avatar/Avatar.types.ts +53 -53
  28. package/src/components/Badge/Badge.stories.tsx +339 -339
  29. package/src/components/Badge/Badge.tsx +278 -278
  30. package/src/components/Badge/Badge.types.ts +58 -58
  31. package/src/components/Button/Button.stories.tsx +950 -950
  32. package/src/components/Button/Button.tsx +337 -337
  33. package/src/components/Button/Button.types.ts +180 -180
  34. package/src/components/Button/icons.tsx +87 -48
  35. package/src/components/Button/index.ts +3 -3
  36. package/src/components/Checkbox/Checkbox.stories.tsx +453 -453
  37. package/src/components/Checkbox/Checkbox.tsx +208 -208
  38. package/src/components/Checkbox/Checkbox.types.ts +61 -61
  39. package/src/components/DescriptionList/DescriptionList.stories.tsx +250 -250
  40. package/src/components/DescriptionList/DescriptionList.tsx +96 -96
  41. package/src/components/DescriptionList/DescriptionList.types.ts +29 -29
  42. package/src/components/Divider/Divider.stories.tsx +263 -263
  43. package/src/components/Divider/Divider.tsx +80 -80
  44. package/src/components/Divider/Divider.types.ts +24 -24
  45. package/src/components/Dropdown/Dropdown.stories.tsx +552 -552
  46. package/src/components/Dropdown/Dropdown.tsx +422 -422
  47. package/src/components/Dropdown/Dropdown.types.ts +146 -146
  48. package/src/components/Dropdown/README.md +266 -266
  49. package/src/components/Dropdown/icons.tsx +72 -72
  50. package/src/components/Dropdown/index.ts +8 -8
  51. package/src/components/Input/Input.stories.tsx +583 -583
  52. package/src/components/Input/Input.tsx +204 -204
  53. package/src/components/Input/Input.types.ts +80 -80
  54. package/src/components/Input/icons.tsx +145 -145
  55. package/src/components/Input/index.ts +2 -2
  56. package/src/components/LoginView/LoginView.stories.tsx +148 -148
  57. package/src/components/LoginView/LoginView.tsx +426 -426
  58. package/src/components/LoginView/LoginView.types.ts +52 -52
  59. package/src/components/LoginView/README.md +396 -396
  60. package/src/components/LoginView/icons.tsx +85 -85
  61. package/src/components/LoginView/index.ts +3 -3
  62. package/src/components/Navbar/Navbar.stories.tsx +810 -810
  63. package/src/components/Navbar/Navbar.tsx +755 -755
  64. package/src/components/Navbar/Navbar.types.ts +219 -219
  65. package/src/components/Navbar/README.md +279 -279
  66. package/src/components/Navbar/icons.tsx +102 -102
  67. package/src/components/Navbar/index.ts +8 -8
  68. package/src/components/NavigationBar/NavigationBar.stories.tsx +406 -406
  69. package/src/components/NavigationBar/NavigationBar.tsx +246 -246
  70. package/src/components/NavigationBar/NavigationBar.types.ts +74 -74
  71. package/src/components/NavigationBar/README.md +469 -469
  72. package/src/components/NavigationBar/index.ts +2 -2
  73. package/src/components/NavigationRail/NavigationRail.stories.tsx +417 -417
  74. package/src/components/NavigationRail/NavigationRail.tsx +418 -418
  75. package/src/components/NavigationRail/NavigationRail.types.ts +109 -109
  76. package/src/components/NavigationRail/README.md +224 -224
  77. package/src/components/NavigationRail/index.ts +2 -2
  78. package/src/components/Notification/Notification.stories.tsx +513 -513
  79. package/src/components/Notification/Notification.tsx +145 -145
  80. package/src/components/Notification/Notification.types.ts +142 -142
  81. package/src/components/Notification/README.md +409 -409
  82. package/src/components/Notification/index.ts +3 -3
  83. package/src/components/POSConvention/POSConvention.stories.tsx +235 -235
  84. package/src/components/POSConvention/POSConvention.tsx +129 -129
  85. package/src/components/POSConvention/POSConvention.types.ts +38 -38
  86. package/src/components/POSConvention/README.md +123 -123
  87. package/src/components/POSConvention/icons.tsx +45 -45
  88. package/src/components/POSConvention/index.ts +3 -3
  89. package/src/components/POSLocationButton/POSLocationButton.stories.tsx +531 -531
  90. package/src/components/POSLocationButton/POSLocationButton.tsx +247 -247
  91. package/src/components/POSLocationButton/POSLocationButton.types.ts +87 -87
  92. package/src/components/POSLocationButton/README.md +253 -253
  93. package/src/components/POSLocationButton/icons.tsx +120 -120
  94. package/src/components/POSLocationButton/index.ts +14 -14
  95. package/src/components/POSNumberButton/POSNumberButton.stories.tsx +415 -415
  96. package/src/components/POSNumberButton/POSNumberButton.tsx +179 -179
  97. package/src/components/POSNumberButton/POSNumberButton.types.ts +51 -51
  98. package/src/components/POSNumberButton/README.md +321 -321
  99. package/src/components/POSNumberButton/index.ts +3 -3
  100. package/src/components/POSProductButton/POSProductButton.stories.tsx +318 -318
  101. package/src/components/POSProductButton/POSProductButton.tsx +152 -152
  102. package/src/components/POSProductButton/POSProductButton.types.ts +46 -46
  103. package/src/components/POSProductButton/README.md +269 -269
  104. package/src/components/POSProductButton/index.ts +2 -2
  105. package/src/components/POSProductCard/POSProductCard.stories.tsx +642 -642
  106. package/src/components/POSProductCard/POSProductCard.tsx +208 -208
  107. package/src/components/POSProductCard/POSProductCard.types.ts +76 -76
  108. package/src/components/POSProductCard/README.md +179 -179
  109. package/src/components/POSProductCard/icons.tsx +26 -26
  110. package/src/components/POSProductCard/index.ts +2 -2
  111. package/src/components/POSProductSidebarItems/POSProductSidebarItems.stories.tsx +753 -753
  112. package/src/components/POSProductSidebarItems/POSProductSidebarItems.tsx +332 -332
  113. package/src/components/POSProductSidebarItems/POSProductSidebarItems.types.ts +119 -119
  114. package/src/components/POSProductSidebarItems/README.md +198 -198
  115. package/src/components/POSProductSidebarItems/icons.tsx +21 -21
  116. package/src/components/POSProductSidebarItems/index.ts +3 -3
  117. package/src/components/POSTable/POSTable.stories.tsx +737 -737
  118. package/src/components/POSTable/POSTable.tsx +401 -401
  119. package/src/components/POSTable/POSTable.types.ts +83 -83
  120. package/src/components/POSTable/README.md +286 -286
  121. package/src/components/POSTable/index.ts +7 -7
  122. package/src/components/Pagination/Pagination.stories.tsx +555 -555
  123. package/src/components/Pagination/Pagination.tsx +286 -286
  124. package/src/components/Pagination/Pagination.types.ts +93 -93
  125. package/src/components/Pagination/README.md +298 -298
  126. package/src/components/Pagination/icons.tsx +47 -47
  127. package/src/components/Pagination/index.ts +3 -3
  128. package/src/components/Quantity/Quantity.stories.tsx +457 -457
  129. package/src/components/Quantity/Quantity.tsx +289 -289
  130. package/src/components/Quantity/Quantity.types.ts +70 -70
  131. package/src/components/Radio/Radio.stories.tsx +523 -523
  132. package/src/components/Radio/Radio.tsx +170 -170
  133. package/src/components/Radio/Radio.types.ts +122 -122
  134. package/src/components/Select/README.md +299 -299
  135. package/src/components/Select/Select.stories.tsx +673 -705
  136. package/src/components/Select/Select.tsx +454 -457
  137. package/src/components/Select/Select.types.ts +148 -148
  138. package/src/components/Select/icons.tsx +50 -25
  139. package/src/components/Select/index.ts +3 -3
  140. package/src/components/SignUpView/SignUpView.stories.tsx +129 -129
  141. package/src/components/SignUpView/SignUpView.tsx +503 -503
  142. package/src/components/SignUpView/SignUpView.types.ts +58 -58
  143. package/src/components/SignUpView/icons.tsx +71 -71
  144. package/src/components/SignUpView/index.ts +3 -3
  145. package/src/components/Switch/README.md +112 -112
  146. package/src/components/Switch/Switch.stories.tsx +550 -550
  147. package/src/components/Switch/Switch.tsx +246 -246
  148. package/src/components/Switch/Switch.types.ts +67 -67
  149. package/src/components/Table/README.md +369 -369
  150. package/src/components/Table/Table.stories.tsx +805 -805
  151. package/src/components/Table/Table.tsx +688 -688
  152. package/src/components/Table/Table.types.ts +204 -204
  153. package/src/components/Table/index.ts +9 -9
  154. package/src/components/Tabs/README.md +201 -201
  155. package/src/components/Tabs/Tabs.stories.tsx +580 -580
  156. package/src/components/Tabs/Tabs.tsx +356 -356
  157. package/src/components/Tabs/Tabs.types.ts +127 -127
  158. package/src/components/Tabs/icons.tsx +129 -129
  159. package/src/components/Tabs/index.ts +11 -11
  160. package/src/components/Textarea/Textarea.stories.tsx +535 -535
  161. package/src/components/Textarea/Textarea.tsx +188 -188
  162. package/src/components/Textarea/Textarea.types.ts +54 -54
  163. package/src/context/ThemeContext.tsx +99 -99
  164. package/src/context/index.ts +1 -1
  165. package/src/index.css +29 -29
  166. package/src/index.ts +39 -133
  167. package/src/main.tsx +10 -10
  168. package/src/views/ProductsView/ProductsView.stories.tsx +344 -344
  169. package/src/views/ProductsView/ProductsView.tsx +480 -480
  170. package/src/views/ProductsView/ProductsView.types.ts +238 -238
  171. package/src/views/ProductsView/README.md +312 -312
  172. package/src/views/ProductsView/icons.tsx +38 -38
  173. package/src/views/ProductsView/index.ts +8 -8
  174. package/src/views/RecoverPasswordView/README.md +269 -269
  175. package/src/views/RecoverPasswordView/RecoverPasswordView.stories.tsx +131 -131
  176. package/src/views/RecoverPasswordView/RecoverPasswordView.tsx +376 -376
  177. package/src/views/RecoverPasswordView/RecoverPasswordView.types.ts +56 -56
  178. package/src/views/RecoverPasswordView/icons.tsx +17 -17
  179. package/src/views/RecoverPasswordView/index.ts +2 -2
  180. package/src/views/TableLayoutView/README.md +268 -268
  181. package/src/views/TableLayoutView/TableLayoutView.stories.tsx +235 -235
  182. package/src/views/TableLayoutView/TableLayoutView.tsx +461 -461
  183. package/src/views/TableLayoutView/TableLayoutView.types.ts +209 -209
  184. package/src/views/TableLayoutView/icons.tsx +113 -113
  185. package/src/views/TableLayoutView/index.ts +6 -6
  186. package/storybook/main.ts +19 -19
  187. package/storybook/preview.tsx +84 -84
  188. package/storybook/vitest.setup.ts +6 -6
  189. package/tailwind.config.js +128 -128
  190. package/claude/prompts/siesa-ui-kit.md +0 -28
  191. package/dist/ButtonTest.d.ts +0 -6
  192. package/dist/ButtonTest.d.ts.map +0 -1
  193. package/dist/components/Alert/Alert.d.ts +0 -23
  194. package/dist/components/Alert/Alert.d.ts.map +0 -1
  195. package/dist/components/Alert/Alert.types.d.ts +0 -46
  196. package/dist/components/Alert/Alert.types.d.ts.map +0 -1
  197. package/dist/components/Avatar/Avatar.d.ts +0 -41
  198. package/dist/components/Avatar/Avatar.d.ts.map +0 -1
  199. package/dist/components/Avatar/Avatar.types.d.ts +0 -46
  200. package/dist/components/Avatar/Avatar.types.d.ts.map +0 -1
  201. package/dist/components/Badge/Badge.d.ts +0 -42
  202. package/dist/components/Badge/Badge.d.ts.map +0 -1
  203. package/dist/components/Badge/Badge.types.d.ts +0 -32
  204. package/dist/components/Badge/Badge.types.d.ts.map +0 -1
  205. package/dist/components/Button/Button.d.ts +0 -84
  206. package/dist/components/Button/Button.d.ts.map +0 -1
  207. package/dist/components/Button/Button.types.d.ts +0 -162
  208. package/dist/components/Button/Button.types.d.ts.map +0 -1
  209. package/dist/components/Button/icons.d.ts +0 -27
  210. package/dist/components/Button/icons.d.ts.map +0 -1
  211. package/dist/components/Button/index.d.ts +0 -4
  212. package/dist/components/Button/index.d.ts.map +0 -1
  213. package/dist/components/Checkbox/Checkbox.d.ts +0 -31
  214. package/dist/components/Checkbox/Checkbox.d.ts.map +0 -1
  215. package/dist/components/Checkbox/Checkbox.types.d.ts +0 -53
  216. package/dist/components/Checkbox/Checkbox.types.d.ts.map +0 -1
  217. package/dist/components/DescriptionList/DescriptionList.d.ts +0 -38
  218. package/dist/components/DescriptionList/DescriptionList.d.ts.map +0 -1
  219. package/dist/components/DescriptionList/DescriptionList.types.d.ts +0 -27
  220. package/dist/components/DescriptionList/DescriptionList.types.d.ts.map +0 -1
  221. package/dist/components/Divider/Divider.d.ts +0 -33
  222. package/dist/components/Divider/Divider.d.ts.map +0 -1
  223. package/dist/components/Divider/Divider.types.d.ts +0 -22
  224. package/dist/components/Divider/Divider.types.d.ts.map +0 -1
  225. package/dist/components/Dropdown/Dropdown.d.ts +0 -66
  226. package/dist/components/Dropdown/Dropdown.d.ts.map +0 -1
  227. package/dist/components/Dropdown/Dropdown.types.d.ts +0 -124
  228. package/dist/components/Dropdown/Dropdown.types.d.ts.map +0 -1
  229. package/dist/components/Dropdown/icons.d.ts +0 -10
  230. package/dist/components/Dropdown/icons.d.ts.map +0 -1
  231. package/dist/components/Dropdown/index.d.ts +0 -4
  232. package/dist/components/Dropdown/index.d.ts.map +0 -1
  233. package/dist/components/DropdownItemCollapsible/DropdownItemCollapsible.d.ts +0 -101
  234. package/dist/components/DropdownItemCollapsible/DropdownItemCollapsible.d.ts.map +0 -1
  235. package/dist/components/DropdownItemCollapsible/DropdownItemCollapsible.types.d.ts +0 -116
  236. package/dist/components/DropdownItemCollapsible/DropdownItemCollapsible.types.d.ts.map +0 -1
  237. package/dist/components/DropdownItemCollapsible/icons.d.ts +0 -19
  238. package/dist/components/DropdownItemCollapsible/icons.d.ts.map +0 -1
  239. package/dist/components/DropdownItemCollapsible/index.d.ts +0 -9
  240. package/dist/components/DropdownItemCollapsible/index.d.ts.map +0 -1
  241. package/dist/components/DropdownItemHeading/DropdownItemHeading.d.ts +0 -75
  242. package/dist/components/DropdownItemHeading/DropdownItemHeading.d.ts.map +0 -1
  243. package/dist/components/DropdownItemHeading/DropdownItemHeading.types.d.ts +0 -85
  244. package/dist/components/DropdownItemHeading/DropdownItemHeading.types.d.ts.map +0 -1
  245. package/dist/components/DropdownItemHeading/icons.d.ts +0 -48
  246. package/dist/components/DropdownItemHeading/icons.d.ts.map +0 -1
  247. package/dist/components/DropdownItemHeading/index.d.ts +0 -4
  248. package/dist/components/DropdownItemHeading/index.d.ts.map +0 -1
  249. package/dist/components/Input/Input.d.ts +0 -40
  250. package/dist/components/Input/Input.d.ts.map +0 -1
  251. package/dist/components/Input/Input.types.d.ts +0 -71
  252. package/dist/components/Input/Input.types.d.ts.map +0 -1
  253. package/dist/components/Input/icons.d.ts +0 -15
  254. package/dist/components/Input/icons.d.ts.map +0 -1
  255. package/dist/components/Input/index.d.ts +0 -3
  256. package/dist/components/Input/index.d.ts.map +0 -1
  257. package/dist/components/LoginView/LoginView.d.ts +0 -36
  258. package/dist/components/LoginView/LoginView.d.ts.map +0 -1
  259. package/dist/components/LoginView/LoginView.types.d.ts +0 -46
  260. package/dist/components/LoginView/LoginView.types.d.ts.map +0 -1
  261. package/dist/components/LoginView/icons.d.ts +0 -18
  262. package/dist/components/LoginView/icons.d.ts.map +0 -1
  263. package/dist/components/LoginView/index.d.ts +0 -4
  264. package/dist/components/LoginView/index.d.ts.map +0 -1
  265. package/dist/components/Navbar/Navbar.d.ts +0 -63
  266. package/dist/components/Navbar/Navbar.d.ts.map +0 -1
  267. package/dist/components/Navbar/Navbar.types.d.ts +0 -194
  268. package/dist/components/Navbar/Navbar.types.d.ts.map +0 -1
  269. package/dist/components/Navbar/icons.d.ts +0 -12
  270. package/dist/components/Navbar/icons.d.ts.map +0 -1
  271. package/dist/components/Navbar/index.d.ts +0 -4
  272. package/dist/components/Navbar/index.d.ts.map +0 -1
  273. package/dist/components/NavigationBar/NavigationBar.d.ts +0 -75
  274. package/dist/components/NavigationBar/NavigationBar.d.ts.map +0 -1
  275. package/dist/components/NavigationBar/NavigationBar.types.d.ts +0 -63
  276. package/dist/components/NavigationBar/NavigationBar.types.d.ts.map +0 -1
  277. package/dist/components/NavigationBar/index.d.ts +0 -3
  278. package/dist/components/NavigationBar/index.d.ts.map +0 -1
  279. package/dist/components/NavigationRail/NavigationRail.d.ts +0 -7
  280. package/dist/components/NavigationRail/NavigationRail.d.ts.map +0 -1
  281. package/dist/components/NavigationRail/NavigationRail.types.d.ts +0 -92
  282. package/dist/components/NavigationRail/NavigationRail.types.d.ts.map +0 -1
  283. package/dist/components/NavigationRail/index.d.ts +0 -3
  284. package/dist/components/NavigationRail/index.d.ts.map +0 -1
  285. package/dist/components/NavigationRailCommercial/NavigationRailCommercial.d.ts +0 -122
  286. package/dist/components/NavigationRailCommercial/NavigationRailCommercial.d.ts.map +0 -1
  287. package/dist/components/NavigationRailCommercial/NavigationRailCommercial.types.d.ts +0 -139
  288. package/dist/components/NavigationRailCommercial/NavigationRailCommercial.types.d.ts.map +0 -1
  289. package/dist/components/NavigationRailCommercial/icons.d.ts +0 -33
  290. package/dist/components/NavigationRailCommercial/icons.d.ts.map +0 -1
  291. package/dist/components/NavigationRailCommercial/index.d.ts +0 -4
  292. package/dist/components/NavigationRailCommercial/index.d.ts.map +0 -1
  293. package/dist/components/NavigationRailItem/NavigationRailItem.d.ts +0 -90
  294. package/dist/components/NavigationRailItem/NavigationRailItem.d.ts.map +0 -1
  295. package/dist/components/NavigationRailItem/NavigationRailItem.types.d.ts +0 -162
  296. package/dist/components/NavigationRailItem/NavigationRailItem.types.d.ts.map +0 -1
  297. package/dist/components/NavigationRailItem/index.d.ts +0 -3
  298. package/dist/components/NavigationRailItem/index.d.ts.map +0 -1
  299. package/dist/components/NavigationRailPanel/NavigationRailPanel.d.ts +0 -124
  300. package/dist/components/NavigationRailPanel/NavigationRailPanel.d.ts.map +0 -1
  301. package/dist/components/NavigationRailPanel/NavigationRailPanel.types.d.ts +0 -154
  302. package/dist/components/NavigationRailPanel/NavigationRailPanel.types.d.ts.map +0 -1
  303. package/dist/components/NavigationRailPanel/index.d.ts +0 -3
  304. package/dist/components/NavigationRailPanel/index.d.ts.map +0 -1
  305. package/dist/components/NavigationRailTypes/NavigationRailTypes.d.ts +0 -99
  306. package/dist/components/NavigationRailTypes/NavigationRailTypes.d.ts.map +0 -1
  307. package/dist/components/NavigationRailTypes/NavigationRailTypes.types.d.ts +0 -152
  308. package/dist/components/NavigationRailTypes/NavigationRailTypes.types.d.ts.map +0 -1
  309. package/dist/components/NavigationRailTypes/icons.d.ts +0 -44
  310. package/dist/components/NavigationRailTypes/icons.d.ts.map +0 -1
  311. package/dist/components/NavigationRailTypes/index.d.ts +0 -4
  312. package/dist/components/NavigationRailTypes/index.d.ts.map +0 -1
  313. package/dist/components/Notification/Notification.d.ts +0 -52
  314. package/dist/components/Notification/Notification.d.ts.map +0 -1
  315. package/dist/components/Notification/Notification.types.d.ts +0 -138
  316. package/dist/components/Notification/Notification.types.d.ts.map +0 -1
  317. package/dist/components/Notification/index.d.ts +0 -3
  318. package/dist/components/Notification/index.d.ts.map +0 -1
  319. package/dist/components/POSConvention/POSConvention.d.ts +0 -55
  320. package/dist/components/POSConvention/POSConvention.d.ts.map +0 -1
  321. package/dist/components/POSConvention/POSConvention.types.d.ts +0 -37
  322. package/dist/components/POSConvention/POSConvention.types.d.ts.map +0 -1
  323. package/dist/components/POSConvention/icons.d.ts +0 -21
  324. package/dist/components/POSConvention/icons.d.ts.map +0 -1
  325. package/dist/components/POSConvention/index.d.ts +0 -4
  326. package/dist/components/POSConvention/index.d.ts.map +0 -1
  327. package/dist/components/POSLocationButton/POSLocationButton.d.ts +0 -73
  328. package/dist/components/POSLocationButton/POSLocationButton.d.ts.map +0 -1
  329. package/dist/components/POSLocationButton/POSLocationButton.types.d.ts +0 -75
  330. package/dist/components/POSLocationButton/POSLocationButton.types.d.ts.map +0 -1
  331. package/dist/components/POSLocationButton/icons.d.ts +0 -37
  332. package/dist/components/POSLocationButton/icons.d.ts.map +0 -1
  333. package/dist/components/POSLocationButton/index.d.ts +0 -4
  334. package/dist/components/POSLocationButton/index.d.ts.map +0 -1
  335. package/dist/components/POSNumberButton/POSNumberButton.d.ts +0 -61
  336. package/dist/components/POSNumberButton/POSNumberButton.d.ts.map +0 -1
  337. package/dist/components/POSNumberButton/POSNumberButton.types.d.ts +0 -43
  338. package/dist/components/POSNumberButton/POSNumberButton.types.d.ts.map +0 -1
  339. package/dist/components/POSNumberButton/index.d.ts +0 -3
  340. package/dist/components/POSNumberButton/index.d.ts.map +0 -1
  341. package/dist/components/POSProductButton/POSProductButton.d.ts +0 -59
  342. package/dist/components/POSProductButton/POSProductButton.d.ts.map +0 -1
  343. package/dist/components/POSProductButton/POSProductButton.types.d.ts +0 -40
  344. package/dist/components/POSProductButton/POSProductButton.types.d.ts.map +0 -1
  345. package/dist/components/POSProductButton/index.d.ts +0 -3
  346. package/dist/components/POSProductButton/index.d.ts.map +0 -1
  347. package/dist/components/POSProductCard/POSProductCard.d.ts +0 -68
  348. package/dist/components/POSProductCard/POSProductCard.d.ts.map +0 -1
  349. package/dist/components/POSProductCard/POSProductCard.types.d.ts +0 -67
  350. package/dist/components/POSProductCard/POSProductCard.types.d.ts.map +0 -1
  351. package/dist/components/POSProductCard/icons.d.ts +0 -10
  352. package/dist/components/POSProductCard/icons.d.ts.map +0 -1
  353. package/dist/components/POSProductCard/index.d.ts +0 -3
  354. package/dist/components/POSProductCard/index.d.ts.map +0 -1
  355. package/dist/components/POSProductSidebarItems/POSProductSidebarItems.d.ts +0 -57
  356. package/dist/components/POSProductSidebarItems/POSProductSidebarItems.d.ts.map +0 -1
  357. package/dist/components/POSProductSidebarItems/POSProductSidebarItems.types.d.ts +0 -85
  358. package/dist/components/POSProductSidebarItems/POSProductSidebarItems.types.d.ts.map +0 -1
  359. package/dist/components/POSProductSidebarItems/icons.d.ts +0 -9
  360. package/dist/components/POSProductSidebarItems/icons.d.ts.map +0 -1
  361. package/dist/components/POSProductSidebarItems/index.d.ts +0 -4
  362. package/dist/components/POSProductSidebarItems/index.d.ts.map +0 -1
  363. package/dist/components/POSTable/POSTable.d.ts +0 -75
  364. package/dist/components/POSTable/POSTable.d.ts.map +0 -1
  365. package/dist/components/POSTable/POSTable.types.d.ts +0 -71
  366. package/dist/components/POSTable/POSTable.types.d.ts.map +0 -1
  367. package/dist/components/POSTable/index.d.ts +0 -3
  368. package/dist/components/POSTable/index.d.ts.map +0 -1
  369. package/dist/components/Pagination/Pagination.d.ts +0 -29
  370. package/dist/components/Pagination/Pagination.d.ts.map +0 -1
  371. package/dist/components/Pagination/Pagination.types.d.ts +0 -79
  372. package/dist/components/Pagination/Pagination.types.d.ts.map +0 -1
  373. package/dist/components/Pagination/icons.d.ts +0 -18
  374. package/dist/components/Pagination/icons.d.ts.map +0 -1
  375. package/dist/components/Pagination/index.d.ts +0 -4
  376. package/dist/components/Pagination/index.d.ts.map +0 -1
  377. package/dist/components/Quantity/Quantity.d.ts +0 -38
  378. package/dist/components/Quantity/Quantity.d.ts.map +0 -1
  379. package/dist/components/Quantity/Quantity.types.d.ts +0 -59
  380. package/dist/components/Quantity/Quantity.types.d.ts.map +0 -1
  381. package/dist/components/Radio/Radio.d.ts +0 -45
  382. package/dist/components/Radio/Radio.d.ts.map +0 -1
  383. package/dist/components/Radio/Radio.types.d.ts +0 -115
  384. package/dist/components/Radio/Radio.types.d.ts.map +0 -1
  385. package/dist/components/Select/Select.d.ts +0 -37
  386. package/dist/components/Select/Select.d.ts.map +0 -1
  387. package/dist/components/Select/Select.types.d.ts +0 -124
  388. package/dist/components/Select/Select.types.d.ts.map +0 -1
  389. package/dist/components/Select/icons.d.ts +0 -20
  390. package/dist/components/Select/icons.d.ts.map +0 -1
  391. package/dist/components/Select/index.d.ts +0 -4
  392. package/dist/components/Select/index.d.ts.map +0 -1
  393. package/dist/components/SignUpView/SignUpView.d.ts +0 -38
  394. package/dist/components/SignUpView/SignUpView.d.ts.map +0 -1
  395. package/dist/components/SignUpView/SignUpView.types.d.ts +0 -51
  396. package/dist/components/SignUpView/SignUpView.types.d.ts.map +0 -1
  397. package/dist/components/SignUpView/icons.d.ts +0 -18
  398. package/dist/components/SignUpView/icons.d.ts.map +0 -1
  399. package/dist/components/SignUpView/index.d.ts +0 -4
  400. package/dist/components/SignUpView/index.d.ts.map +0 -1
  401. package/dist/components/Switch/Switch.d.ts +0 -46
  402. package/dist/components/Switch/Switch.d.ts.map +0 -1
  403. package/dist/components/Switch/Switch.types.d.ts +0 -58
  404. package/dist/components/Switch/Switch.types.d.ts.map +0 -1
  405. package/dist/components/Table/Table.d.ts +0 -64
  406. package/dist/components/Table/Table.d.ts.map +0 -1
  407. package/dist/components/Table/Table.types.d.ts +0 -173
  408. package/dist/components/Table/Table.types.d.ts.map +0 -1
  409. package/dist/components/Table/index.d.ts +0 -3
  410. package/dist/components/Table/index.d.ts.map +0 -1
  411. package/dist/components/Tabs/Tabs.d.ts +0 -76
  412. package/dist/components/Tabs/Tabs.d.ts.map +0 -1
  413. package/dist/components/Tabs/Tabs.types.d.ts +0 -107
  414. package/dist/components/Tabs/Tabs.types.d.ts.map +0 -1
  415. package/dist/components/Tabs/icons.d.ts +0 -45
  416. package/dist/components/Tabs/icons.d.ts.map +0 -1
  417. package/dist/components/Tabs/index.d.ts +0 -4
  418. package/dist/components/Tabs/index.d.ts.map +0 -1
  419. package/dist/components/Textarea/Textarea.d.ts +0 -38
  420. package/dist/components/Textarea/Textarea.d.ts.map +0 -1
  421. package/dist/components/Textarea/Textarea.types.d.ts +0 -46
  422. package/dist/components/Textarea/Textarea.types.d.ts.map +0 -1
  423. package/dist/context/ThemeContext.d.ts +0 -46
  424. package/dist/context/ThemeContext.d.ts.map +0 -1
  425. package/dist/context/index.d.ts +0 -2
  426. package/dist/context/index.d.ts.map +0 -1
  427. package/dist/index.d.ts +0 -88
  428. package/dist/index.d.ts.map +0 -1
  429. package/dist/siesa-ui-kit.cjs +0 -1474
  430. package/dist/siesa-ui-kit.cjs.map +0 -1
  431. package/dist/siesa-ui-kit.mjs +0 -9580
  432. package/dist/siesa-ui-kit.mjs.map +0 -1
  433. package/dist/views/LayoutCommercial/LayoutCommercial.d.ts +0 -48
  434. package/dist/views/LayoutCommercial/LayoutCommercial.d.ts.map +0 -1
  435. package/dist/views/LayoutCommercial/LayoutCommercial.types.d.ts +0 -49
  436. package/dist/views/LayoutCommercial/LayoutCommercial.types.d.ts.map +0 -1
  437. package/dist/views/LayoutCommercial/index.d.ts +0 -3
  438. package/dist/views/LayoutCommercial/index.d.ts.map +0 -1
  439. package/dist/views/ListView/ListView.d.ts +0 -47
  440. package/dist/views/ListView/ListView.d.ts.map +0 -1
  441. package/dist/views/ListView/ListView.types.d.ts +0 -177
  442. package/dist/views/ListView/ListView.types.d.ts.map +0 -1
  443. package/dist/views/ListView/icons.d.ts +0 -60
  444. package/dist/views/ListView/icons.d.ts.map +0 -1
  445. package/dist/views/ListView/index.d.ts +0 -3
  446. package/dist/views/ListView/index.d.ts.map +0 -1
  447. package/dist/views/LoginView/LoginView.d.ts +0 -36
  448. package/dist/views/LoginView/LoginView.d.ts.map +0 -1
  449. package/dist/views/LoginView/LoginView.types.d.ts +0 -46
  450. package/dist/views/LoginView/LoginView.types.d.ts.map +0 -1
  451. package/dist/views/LoginView/icons.d.ts +0 -18
  452. package/dist/views/LoginView/icons.d.ts.map +0 -1
  453. package/dist/views/LoginView/index.d.ts +0 -4
  454. package/dist/views/LoginView/index.d.ts.map +0 -1
  455. package/dist/views/ProductsView/ProductsView.d.ts +0 -56
  456. package/dist/views/ProductsView/ProductsView.d.ts.map +0 -1
  457. package/dist/views/ProductsView/ProductsView.types.d.ts +0 -184
  458. package/dist/views/ProductsView/ProductsView.types.d.ts.map +0 -1
  459. package/dist/views/ProductsView/icons.d.ts +0 -12
  460. package/dist/views/ProductsView/icons.d.ts.map +0 -1
  461. package/dist/views/ProductsView/index.d.ts +0 -3
  462. package/dist/views/ProductsView/index.d.ts.map +0 -1
  463. package/dist/views/RecoverPasswordView/RecoverPasswordView.d.ts +0 -34
  464. package/dist/views/RecoverPasswordView/RecoverPasswordView.d.ts.map +0 -1
  465. package/dist/views/RecoverPasswordView/RecoverPasswordView.types.d.ts +0 -50
  466. package/dist/views/RecoverPasswordView/RecoverPasswordView.types.d.ts.map +0 -1
  467. package/dist/views/RecoverPasswordView/icons.d.ts +0 -9
  468. package/dist/views/RecoverPasswordView/icons.d.ts.map +0 -1
  469. package/dist/views/RecoverPasswordView/index.d.ts +0 -3
  470. package/dist/views/RecoverPasswordView/index.d.ts.map +0 -1
  471. package/dist/views/SignUpView/SignUpView.d.ts +0 -38
  472. package/dist/views/SignUpView/SignUpView.d.ts.map +0 -1
  473. package/dist/views/SignUpView/SignUpView.types.d.ts +0 -51
  474. package/dist/views/SignUpView/SignUpView.types.d.ts.map +0 -1
  475. package/dist/views/SignUpView/icons.d.ts +0 -18
  476. package/dist/views/SignUpView/icons.d.ts.map +0 -1
  477. package/dist/views/SignUpView/index.d.ts +0 -4
  478. package/dist/views/SignUpView/index.d.ts.map +0 -1
  479. package/dist/views/TableLayoutView/TableLayoutView.d.ts +0 -46
  480. package/dist/views/TableLayoutView/TableLayoutView.d.ts.map +0 -1
  481. package/dist/views/TableLayoutView/TableLayoutView.types.d.ts +0 -170
  482. package/dist/views/TableLayoutView/TableLayoutView.types.d.ts.map +0 -1
  483. package/dist/views/TableLayoutView/icons.d.ts +0 -27
  484. package/dist/views/TableLayoutView/icons.d.ts.map +0 -1
  485. package/dist/views/TableLayoutView/index.d.ts +0 -3
  486. package/dist/views/TableLayoutView/index.d.ts.map +0 -1
  487. package/src/components/DropdownItemCollapsible/DropdownItemCollapsible.stories.tsx +0 -317
  488. package/src/components/DropdownItemCollapsible/DropdownItemCollapsible.tsx +0 -307
  489. package/src/components/DropdownItemCollapsible/DropdownItemCollapsible.types.ts +0 -136
  490. package/src/components/DropdownItemCollapsible/README.md +0 -264
  491. package/src/components/DropdownItemCollapsible/icons.tsx +0 -57
  492. package/src/components/DropdownItemCollapsible/index.ts +0 -12
  493. package/src/components/DropdownItemHeading/DropdownItemHeading.stories.tsx +0 -386
  494. package/src/components/DropdownItemHeading/DropdownItemHeading.tsx +0 -216
  495. package/src/components/DropdownItemHeading/DropdownItemHeading.types.ts +0 -93
  496. package/src/components/DropdownItemHeading/README.md +0 -573
  497. package/src/components/DropdownItemHeading/icons.tsx +0 -125
  498. package/src/components/DropdownItemHeading/index.ts +0 -3
  499. package/src/components/NavigationRailCommercial/NavigationRailCommercial.stories.tsx +0 -464
  500. package/src/components/NavigationRailCommercial/NavigationRailCommercial.tsx +0 -301
  501. package/src/components/NavigationRailCommercial/NavigationRailCommercial.types.ts +0 -162
  502. package/src/components/NavigationRailCommercial/README.md +0 -251
  503. package/src/components/NavigationRailCommercial/icons.tsx +0 -54
  504. package/src/components/NavigationRailCommercial/index.ts +0 -6
  505. package/src/components/NavigationRailItem/NavigationRailItem.stories.tsx +0 -667
  506. package/src/components/NavigationRailItem/NavigationRailItem.tsx +0 -314
  507. package/src/components/NavigationRailItem/NavigationRailItem.types.ts +0 -175
  508. package/src/components/NavigationRailItem/README.md +0 -476
  509. package/src/components/NavigationRailItem/index.ts +0 -2
  510. package/src/components/NavigationRailPanel/NavigationRailPanel.stories.tsx +0 -462
  511. package/src/components/NavigationRailPanel/NavigationRailPanel.tsx +0 -332
  512. package/src/components/NavigationRailPanel/NavigationRailPanel.types.ts +0 -178
  513. package/src/components/NavigationRailPanel/README.md +0 -461
  514. package/src/components/NavigationRailPanel/index.ts +0 -6
  515. package/src/components/NavigationRailTypes/NavigationRailTypes.stories.tsx +0 -682
  516. package/src/components/NavigationRailTypes/NavigationRailTypes.tsx +0 -363
  517. package/src/components/NavigationRailTypes/NavigationRailTypes.types.ts +0 -178
  518. package/src/components/NavigationRailTypes/README.md +0 -573
  519. package/src/components/NavigationRailTypes/icons.tsx +0 -76
  520. package/src/components/NavigationRailTypes/index.ts +0 -7
  521. package/src/views/LayoutCommercial/LayoutCommercial.stories.tsx +0 -374
  522. package/src/views/LayoutCommercial/LayoutCommercial.tsx +0 -125
  523. package/src/views/LayoutCommercial/LayoutCommercial.types.ts +0 -54
  524. package/src/views/LayoutCommercial/README.md +0 -286
  525. package/src/views/LayoutCommercial/index.ts +0 -2
  526. package/src/views/ListView/ListView.stories.tsx +0 -329
  527. package/src/views/ListView/ListView.tsx +0 -570
  528. package/src/views/ListView/ListView.types.ts +0 -211
  529. package/src/views/ListView/icons.tsx +0 -282
  530. package/src/views/ListView/index.ts +0 -11
  531. package/src/views/LoginView/LoginView.stories.tsx +0 -148
  532. package/src/views/LoginView/LoginView.tsx +0 -426
  533. package/src/views/LoginView/LoginView.types.ts +0 -52
  534. package/src/views/LoginView/README.md +0 -396
  535. package/src/views/LoginView/icons.tsx +0 -85
  536. package/src/views/LoginView/index.ts +0 -3
  537. package/src/views/SignUpView/SignUpView.stories.tsx +0 -129
  538. package/src/views/SignUpView/SignUpView.tsx +0 -503
  539. package/src/views/SignUpView/SignUpView.types.ts +0 -58
  540. package/src/views/SignUpView/icons.tsx +0 -71
  541. package/src/views/SignUpView/index.ts +0 -3
package/docs/icons.md CHANGED
@@ -1,1264 +1,1283 @@
1
- # Sistema de Iconos - Siesa UI Kit
2
-
3
- ## 📋 Tabla de Contenidos
4
-
5
- 1. [Introducción](#introducción)
6
- 2. [Librería de Iconos](#librería-de-iconos)
7
- 3. [Catálogo de Iconos](#catálogo-de-iconos)
8
- 4. [Implementación](#implementación)
9
- 5. [Guía de Uso](#guía-de-uso)
10
- 6. [Accesibilidad](#accesibilidad)
11
- 7. [Ejemplos de Código](#ejemplos-de-código)
12
- 8. [Mejores Prácticas](#mejores-prácticas)
13
- 9. [Referencia Rápida](#referencia-rápida)
14
-
15
- ---
16
-
17
- ## Introducción
18
-
19
- El sistema de iconos de Siesa UI Kit está basado en **Heroicons Micro**, una librería de iconos SVG de 16x16px diseñada específicamente para interfaces de usuario modernas. Los iconos están optimizados para claridad a tamaños pequeños y se integran perfectamente con nuestro sistema de diseño.
20
-
21
- ### Objetivos del Sistema de Iconos
22
-
23
- - **Consistencia Visual**: Todos los iconos mantienen el mismo peso visual y estilo
24
- - **Escalabilidad**: Iconos vectoriales que se adaptan a cualquier tamaño
25
- - **Accesibilidad**: Soporte para lectores de pantalla y temas oscuros
26
- - **Rendimiento**: SVG inline para carga rápida sin requests adicionales
27
- - **Flexibilidad**: Fácil personalización de tamaño, color y estilos
28
-
29
- ### Principios de Diseño
30
-
31
- 1. **Simplicidad**: Formas claras y reconocibles
32
- 2. **Peso Consistente**: Todos los iconos tienen el mismo grosor de línea
33
- 3. **Alineación Pixel-Perfect**: Optimizados para 16x16px
34
- 4. **Color Heredado**: Usan `currentColor` para adaptarse al contexto
35
-
36
- ---
37
-
38
- ## Librería de Iconos
39
-
40
- ### Heroicons Micro
41
-
42
- **Especificaciones Técnicas:**
43
- - **Tamaño Base**: 16x16px (viewBox="0 0 16 16")
44
- - **Formato**: SVG inline
45
- - **Estilo**: Solid (relleno completo)
46
- - **Grosor**: 1.5px stroke weight equivalent
47
- - **Licencia**: MIT License
48
-
49
- **Ventajas:**
50
- - ✅ Diseñados específicamente para UI de 16px
51
- - ✅ Optimizados para claridad a tamaños pequeños
52
- - ✅ Mantenidos por el equipo de Tailwind CSS
53
- - ✅ Biblioteca completa y consistente
54
- - ✅ Excelente legibilidad en pantallas de alta densidad
55
-
56
- ---
57
-
58
- ## Catálogo de Iconos
59
-
60
- ### Iconos de Botón (Button)
61
-
62
- Iconos disponibles en `src/components/Button/icons.tsx`
63
-
64
- | Icono | Nombre | Uso Principal | Ubicación |
65
- |-------|--------|---------------|-----------|
66
- | ➕ | `PlusIcon` | Acciones de añadir/crear | Button.tsx:12 |
67
- | 🔽 | `ChevronDownIcon` | Menús desplegables | Button.tsx:12 |
68
- | ➡️ | `ArrowRightIcon` | Navegación/siguiente | Button.tsx:12 |
69
- | ✓ | `CheckIcon` | Confirmación/éxito | Button.tsx:14 |
70
- | ✕ | `XIcon` | Cerrar/cancelar | Button.tsx:14 |
71
-
72
- ### Iconos de Input (Input)
73
-
74
- Iconos disponibles en `src/components/Input/icons.tsx`
75
-
76
- | Icono | Nombre | Uso Principal | Contexto |
77
- |-------|--------|---------------|----------|
78
- | ✉️ | `EnvelopeIcon` | Email input | Campo de correo electrónico |
79
- | ❓ | `QuestionMarkCircleIcon` | Ayuda contextual | Tooltips, hints |
80
- | 👤 | `UserIcon` | Usuario/perfil | Campos de nombre, login |
81
- | 🔒 | `LockClosedIcon` | Seguridad | Password, campos privados |
82
- | 🔍 | `MagnifyingGlassIcon` | Búsqueda | Search inputs |
83
- | 👁️ | `EyeIcon` | Ver contraseña | Toggle password visibility |
84
- | 👁️‍🗨️ | `EyeSlashIcon` | Ocultar contraseña | Toggle password visibility |
85
- | ✕ | `XMarkIcon` | Limpiar campo | Clear input |
86
- | ✓ | `CheckIcon` | Validación exitosa | Estado de éxito |
87
- | ⚠️ | `ExclamationCircleIcon` | Error/advertencia | Estado de error |
88
-
89
- **Total de Iconos Disponibles**: 16 (5 Button + 11 Input)
90
-
91
- ---
92
-
93
- ## Implementación
94
-
95
- ### Patrón de Implementación
96
-
97
- Utilizamos la librería `@heroicons/react` para todos los iconos estándar. El patrón consiste en envolver el icono de la librería para mantener consistencia y facilitar personalizaciones futuras.
98
-
99
- ```typescript
100
- import { BeakerIcon } from '@heroicons/react/24/outline';
101
-
102
- interface IconProps {
103
- className?: string;
104
- }
105
-
106
- export const IconName: React.FC<IconProps> = ({ className = 'size-5' }) => (
107
- <BeakerIcon
108
- className={className}
109
- aria-hidden="true"
110
- />
111
- );
112
- ```
113
-
114
- ### Características Clave
115
-
116
- 1. **Librería Estándar**: Uso de Heroicons Outline (24x24px) vía `@heroicons/react/24/outline`.
117
- 2. **TypeScript**: Interfaz `IconProps` para type safety.
118
- 3. **Color Heredado**: Los iconos de la librería heredan automáticamente `fill="none" stroke="currentColor"`.
119
- 4. **className**: Permite personalización con Tailwind CSS (ej: `size-5`, `text-primary`).
120
- 5. **Accesibilidad**: Inclusión de `aria-hidden="true"` para iconos decorativos.
121
-
122
- ---
123
-
124
- ## Guía de Uso
125
-
126
- ### 1. Importación
127
-
128
- ```typescript
129
- // Importar iconos específicos
130
- import { PlusIcon, CheckIcon } from '@/components/Button/icons';
131
- import { EnvelopeIcon, UserIcon } from '@/components/Input/icons';
132
- ```
133
-
134
- ### 2. Uso Básico
135
-
136
- ```tsx
137
- // Icono básico (hereda color del texto padre)
138
- <PlusIcon />
139
-
140
- // Con tamaño personalizado
141
- <UserIcon className="w-5 h-5" />
142
-
143
- // Con color personalizado
144
- <CheckIcon className="w-4 h-4 text-green-600" />
145
- ```
146
-
147
- ### 3. En Componentes
148
-
149
- #### Button con Iconos
150
-
151
- ```tsx
152
- import { Button } from '@/components/Button';
153
- import { PlusIcon, ArrowRightIcon } from '@/components/Button/icons';
154
-
155
- // Icon only button
156
- <Button iconOnly leftIcon={<PlusIcon />} ariaLabel="Añadir" />
157
-
158
- // Button con icono izquierdo
159
- <Button leftIcon={<PlusIcon />}>
160
- Crear Nuevo
161
- </Button>
162
-
163
- // Button con icono derecho
164
- <Button rightIcon={<ArrowRightIcon />}>
165
- Continuar
166
- </Button>
167
-
168
- // Button con ambos iconos
169
- <Button
170
- leftIcon={<CheckIcon />}
171
- rightIcon={<ArrowRightIcon />}
172
- >
173
- Guardar y Continuar
174
- </Button>
175
- ```
176
-
177
- #### Input con Iconos
178
-
179
- ```tsx
180
- import { Input } from '@/components/Input';
181
- import { EnvelopeIcon, EyeIcon } from '@/components/Input/icons';
182
-
183
- // Input con icono izquierdo
184
- <Input
185
- leftIcon={<EnvelopeIcon />}
186
- placeholder="correo@ejemplo.com"
187
- type="email"
188
- />
189
-
190
- // Input con icono derecho
191
- <Input
192
- rightIcon={<EyeIcon />}
193
- placeholder="Contraseña"
194
- type="password"
195
- />
196
- ```
197
-
198
- ### 4. Estados y Temas
199
-
200
- Los iconos heredan automáticamente el color del contexto:
201
-
202
- ```tsx
203
- // En modo claro (hereda color del texto)
204
- <Button type="default">
205
- <PlusIcon /> {/* Hereda text-primary-inverse-content */}
206
- </Button>
207
-
208
- // En modo oscuro (se adapta automáticamente)
209
- <div className="dark">
210
- <Button type="outline">
211
- <UserIcon /> {/* Hereda dark:text-dark-content-primary */}
212
- </Button>
213
- </div>
214
-
215
- // Estados disabled
216
- <Button disabled>
217
- <CheckIcon /> {/* Hereda opacity-50 del botón */}
218
- </Button>
219
- ```
220
-
221
- ---
222
-
223
- ## Modo Oscuro (Dark Mode)
224
-
225
- ### Configuración de Tailwind CSS
226
-
227
- El modo oscuro en Siesa UI Kit se basa en la estrategia de clases de Tailwind CSS:
228
-
229
- ```javascript
230
- // tailwind.config.js
231
- module.exports = {
232
- darkMode: 'class', // ✅ Estrategia basada en clases (NO 'media')
233
- // ...resto de la configuración
234
- }
235
- ```
236
-
237
- Con esta configuración, el modo oscuro se activa añadiendo la clase `.dark` al elemento `<html>`:
238
-
239
- ```html
240
- <!-- Modo claro -->
241
- <html>
242
- <body>
243
- <!-- Contenido en modo claro -->
244
- </body>
245
- </html>
246
-
247
- <!-- Modo oscuro -->
248
- <html class="dark">
249
- <body>
250
- <!-- Contenido en modo oscuro -->
251
- </body>
252
- </html>
253
- ```
254
-
255
- ### El Modificador `dark:`
256
-
257
- El modificador `dark:` de Tailwind funciona como un **prefijo condicional** que aplica estilos solo cuando la clase `.dark` está presente en un elemento padre (típicamente `<html>`).
258
-
259
- #### Sintaxis Básica
260
-
261
- ```tsx
262
- // Patrón básico
263
- <Icon className="text-content-primary dark:text-dark-content-primary" />
264
-
265
- // El icono usa:
266
- // - text-content-primary en modo claro
267
- // - text-dark-content-primary en modo oscuro
268
- ```
269
-
270
- #### Herencia de Color con currentColor
271
-
272
- Los iconos usan `fill="currentColor"`, lo que significa que heredan el color del texto del elemento padre:
273
-
274
- ```tsx
275
- // El icono hereda el color del div padre
276
- <div className="text-content-primary dark:text-dark-content-primary">
277
- <UserIcon /> {/* Automáticamente se adapta */}
278
- </div>
279
-
280
- // Equivalente a especificar el color directamente en el icono
281
- <UserIcon className="text-content-primary dark:text-dark-content-primary" />
282
- ```
283
-
284
- ### Combinando con Otros Modificadores
285
-
286
- El modificador `dark:` se puede combinar con hover, focus, active, y responsive:
287
-
288
- ```tsx
289
- // Dark mode + Hover
290
- <button className="text-gray-700 hover:text-blue-600 dark:text-gray-300 dark:hover:text-blue-400">
291
- <PlusIcon />
292
- </button>
293
-
294
- // Dark mode + Focus
295
- <input className="text-content-primary focus:text-primary-custom-600 dark:text-dark-content-primary dark:focus:text-blue-400">
296
- <MagnifyingGlassIcon />
297
- </input>
298
-
299
- // Dark mode + Responsive
300
- <div className="text-gray-900 md:text-blue-600 dark:text-white dark:md:text-blue-400">
301
- <CheckIcon />
302
- </div>
303
-
304
- // Dark mode + Group hover
305
- <div className="group">
306
- <button className="text-gray-700 dark:text-gray-300">
307
- <ArrowRightIcon className="
308
- text-gray-500
309
- group-hover:text-blue-600
310
- dark:text-gray-400
311
- dark:group-hover:text-blue-400
312
- " />
313
- </button>
314
- </div>
315
- ```
316
-
317
- ### Orden de Modificadores
318
-
319
- Tailwind CSS recomienda un orden específico para los modificadores:
320
-
321
- **Formato**: `{responsive}:{dark}:{state}:{utility}`
322
-
323
- ```tsx
324
- // ✅ CORRECTO - Orden: responsive → dark → state → utility
325
- <button className="
326
- md:text-gray-700
327
- md:dark:text-gray-300
328
- md:dark:hover:text-blue-400
329
- ">
330
- <PlusIcon />
331
- </button>
332
-
333
- // ❌ INCORRECTO - Orden equivocado
334
- <button className="
335
- dark:md:hover:text-blue-400
336
- ">
337
- <PlusIcon />
338
- </button>
339
- ```
340
-
341
- ### Tabla de Estados con Hover
342
-
343
- | Estado | Light Mode | Dark Mode | Descripción |
344
- |--------|------------|-----------|-------------|
345
- | **Default** | `text-content-primary` | `dark:text-dark-content-primary` | Color principal del icono |
346
- | **Hover** | `hover:text-primary-custom-600` | `dark:hover:text-blue-400` | Color al pasar el mouse |
347
- | **Focus** | `focus:text-primary-custom-600` | `dark:focus:text-blue-400` | Color al enfocar |
348
- | **Active** | `active:text-primary-custom-700` | `dark:active:text-blue-500` | Color al hacer clic |
349
- | **Disabled** | `text-content-tertiary` | `dark:text-dark-content-tertiary` | Color deshabilitado |
350
- | **Error** | `text-error-content` | `dark:text-red-400` | Color de error |
351
- | **Success** | `text-green-600` | `dark:text-green-400` | Color de éxito |
352
-
353
- ### Implementación del Toggle Dark Mode
354
-
355
- #### Implementación Básica con JavaScript
356
-
357
- ```typescript
358
- // utils/darkMode.ts
359
- export const toggleDarkMode = () => {
360
- const isDark = document.documentElement.classList.contains('dark');
361
-
362
- if (isDark) {
363
- document.documentElement.classList.remove('dark');
364
- localStorage.setItem('theme', 'light');
365
- } else {
366
- document.documentElement.classList.add('dark');
367
- localStorage.setItem('theme', 'dark');
368
- }
369
- };
370
-
371
- // Cargar el tema al iniciar la aplicación
372
- export const loadTheme = () => {
373
- const savedTheme = localStorage.getItem('theme');
374
- const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
375
-
376
- if (savedTheme === 'dark' || (!savedTheme && prefersDark)) {
377
- document.documentElement.classList.add('dark');
378
- } else {
379
- document.documentElement.classList.remove('dark');
380
- }
381
- };
382
- ```
383
-
384
- #### Prevenir Flash de Contenido (FOUC)
385
-
386
- Añadir este script en el `<head>` del HTML antes de que React se cargue:
387
-
388
- ```html
389
- <!-- index.html -->
390
- <head>
391
- <script>
392
- // Aplicar tema inmediatamente antes del render
393
- (function() {
394
- const theme = localStorage.getItem('theme');
395
- const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
396
-
397
- if (theme === 'dark' || (!theme && prefersDark)) {
398
- document.documentElement.classList.add('dark');
399
- }
400
- })();
401
- </script>
402
- </head>
403
- ```
404
-
405
- ### Ejemplos Completos
406
-
407
- #### Ejemplo 1: Toolbar de Iconos con Dark Mode
408
-
409
- ```tsx
410
- import { Button } from '@/components/Button';
411
- import { PlusIcon, CheckIcon, XIcon } from '@/components/Button/icons';
412
-
413
- export const IconToolbar = () => {
414
- return (
415
- <div className="
416
- flex gap-2 p-4
417
- bg-white dark:bg-dark-bg-primary
418
- border-b border-border-primary dark:border-dark-border-primary
419
- ">
420
- {/* Icono con hover adaptado */}
421
- <Button
422
- iconOnly
423
- type="outline"
424
- leftIcon={<PlusIcon />}
425
- ariaLabel="Añadir"
426
- className="
427
- text-content-primary dark:text-dark-content-primary
428
- hover:text-primary-custom-600 dark:hover:text-blue-400
429
- hover:bg-gray-100 dark:hover:bg-gray-800
430
- "
431
- />
432
-
433
- {/* Icono de éxito */}
434
- <Button
435
- iconOnly
436
- type="outline"
437
- leftIcon={<CheckIcon />}
438
- ariaLabel="Guardar"
439
- className="
440
- text-green-600 dark:text-green-400
441
- hover:text-green-700 dark:hover:text-green-300
442
- hover:bg-green-50 dark:hover:bg-green-900/20
443
- "
444
- />
445
-
446
- {/* Icono de error */}
447
- <Button
448
- iconOnly
449
- type="outline"
450
- leftIcon={<XIcon />}
451
- ariaLabel="Cancelar"
452
- className="
453
- text-error-content dark:text-red-400
454
- hover:text-red-700 dark:hover:text-red-300
455
- hover:bg-red-50 dark:hover:bg-red-900/20
456
- "
457
- />
458
- </div>
459
- );
460
- };
461
- ```
462
-
463
- #### Ejemplo 2: Formulario con Iconos Adaptativos
464
-
465
- ```tsx
466
- import { Input } from '@/components/Input';
467
- import { UserIcon, LockClosedIcon, EnvelopeIcon } from '@/components/Input/icons';
468
- import { Button } from '@/components/Button';
469
- import { ArrowRightIcon, CheckIcon } from '@/components/Button/icons';
470
-
471
- export const AdaptiveForm = () => {
472
- return (
473
- <div className="
474
- w-full max-w-md p-6
475
- bg-white dark:bg-dark-bg-primary
476
- border border-border-primary dark:border-dark-border-primary
477
- rounded-2xl
478
- shadow-base dark:shadow-lg
479
- ">
480
- <h2 className="
481
- mb-6
482
- text-content-primary dark:text-dark-content-primary
483
- font-bold text-xl
484
- ">
485
- Iniciar Sesión
486
- </h2>
487
-
488
- <form className="space-y-4">
489
- {/* Input de email con icono */}
490
- <Input
491
- label="Correo Electrónico"
492
- type="email"
493
- leftIcon={
494
- <EnvelopeIcon className="
495
- text-content-secondary dark:text-dark-content-secondary
496
- " />
497
- }
498
- placeholder="tu@email.com"
499
- className="
500
- text-content-primary dark:text-dark-content-primary
501
- bg-bg-primary dark:bg-dark-bg-secondary
502
- border-border-primary dark:border-dark-border-primary
503
- focus:border-primary-custom-600 dark:focus:border-blue-400
504
- "
505
- />
506
-
507
- {/* Input de usuario con icono */}
508
- <Input
509
- label="Usuario"
510
- leftIcon={
511
- <UserIcon className="
512
- text-content-secondary dark:text-dark-content-secondary
513
- " />
514
- }
515
- placeholder="Tu usuario"
516
- className="
517
- text-content-primary dark:text-dark-content-primary
518
- bg-bg-primary dark:bg-dark-bg-secondary
519
- "
520
- />
521
-
522
- {/* Input de contraseña con icono */}
523
- <Input
524
- label="Contraseña"
525
- type="password"
526
- leftIcon={
527
- <LockClosedIcon className="
528
- text-content-secondary dark:text-dark-content-secondary
529
- " />
530
- }
531
- placeholder="Tu contraseña"
532
- className="
533
- text-content-primary dark:text-dark-content-primary
534
- bg-bg-primary dark:bg-dark-bg-secondary
535
- "
536
- />
537
-
538
- {/* Botón de submit con icono */}
539
- <Button
540
- type="default"
541
- fullWidth
542
- rightIcon={<ArrowRightIcon />}
543
- className="
544
- bg-primary-custom-600 dark:bg-dark-bg-inverse
545
- text-primary-inverse-content dark:text-dark-content-inverse
546
- hover:bg-primary-custom-500 dark:hover:bg-dark-bg-inverse/90
547
- "
548
- >
549
- Continuar
550
- </Button>
551
- </form>
552
- </div>
553
- );
554
- };
555
- ```
556
-
557
- #### Ejemplo 3: Status Icons con Colores Adaptativos
558
-
559
- ```tsx
560
- import { CheckIcon, ExclamationCircleIcon, XMarkIcon } from '@/components/Input/icons';
561
-
562
- export const StatusMessages = () => {
563
- return (
564
- <div className="space-y-3">
565
- {/* Mensaje de éxito */}
566
- <div className="
567
- flex items-center gap-3 p-4
568
- bg-green-50 dark:bg-green-900/20
569
- border border-green-200 dark:border-green-800
570
- rounded-lg
571
- ">
572
- <CheckIcon className="
573
- w-5 h-5
574
- text-green-600 dark:text-green-400
575
- " />
576
- <p className="
577
- text-green-800 dark:text-green-300
578
- font-medium
579
- ">
580
- Operación completada con éxito
581
- </p>
582
- </div>
583
-
584
- {/* Mensaje de advertencia */}
585
- <div className="
586
- flex items-center gap-3 p-4
587
- bg-yellow-50 dark:bg-yellow-900/20
588
- border border-yellow-200 dark:border-yellow-800
589
- rounded-lg
590
- ">
591
- <ExclamationCircleIcon className="
592
- w-5 h-5
593
- text-yellow-600 dark:text-yellow-400
594
- " />
595
- <p className="
596
- text-yellow-800 dark:text-yellow-300
597
- font-medium
598
- ">
599
- Advertencia: Revisa la información
600
- </p>
601
- </div>
602
-
603
- {/* Mensaje de error */}
604
- <div className="
605
- flex items-center gap-3 p-4
606
- bg-red-50 dark:bg-red-900/20
607
- border border-red-200 dark:border-red-800
608
- rounded-lg
609
- ">
610
- <XMarkIcon className="
611
- w-5 h-5
612
- text-error-content dark:text-red-400
613
- " />
614
- <p className="
615
- text-red-800 dark:text-red-300
616
- font-medium
617
- ">
618
- Error: No se pudo completar la operación
619
- </p>
620
- </div>
621
- </div>
622
- );
623
- };
624
- ```
625
-
626
- #### Ejemplo 4: Icon Button con Group Hover
627
-
628
- ```tsx
629
- import { ArrowRightIcon } from '@/components/Button/icons';
630
-
631
- export const NavigationCard = () => {
632
- return (
633
- <button className="
634
- group
635
- w-full p-6
636
- bg-white dark:bg-dark-bg-primary
637
- border border-border-primary dark:border-dark-border-primary
638
- rounded-xl
639
- hover:border-primary-custom-600 dark:hover:border-blue-400
640
- hover:shadow-lg
641
- transition-all
642
- text-left
643
- ">
644
- <div className="flex items-center justify-between">
645
- <div>
646
- <h3 className="
647
- mb-2
648
- text-content-primary dark:text-dark-content-primary
649
- font-bold text-lg
650
- group-hover:text-primary-custom-600 dark:group-hover:text-blue-400
651
- ">
652
- Ir a la Configuración
653
- </h3>
654
- <p className="
655
- text-content-secondary dark:text-dark-content-secondary
656
- text-sm
657
- ">
658
- Administra las preferencias del sistema
659
- </p>
660
- </div>
661
-
662
- {/* Icono que se anima y cambia de color en hover */}
663
- <ArrowRightIcon className="
664
- w-6 h-6
665
- text-content-tertiary dark:text-dark-content-tertiary
666
- group-hover:text-primary-custom-600 dark:group-hover:text-blue-400
667
- group-hover:translate-x-1
668
- transition-all
669
- " />
670
- </div>
671
- </button>
672
- );
673
- };
674
- ```
675
-
676
- ### Mejores Prácticas para Iconos en Dark Mode
677
-
678
- #### ✅ Hacer
679
-
680
- 1. **Usar tokens semánticos que se adaptan automáticamente**
681
- ```tsx
682
- // ✅ CORRECTO - Los tokens ya incluyen dark mode
683
- <UserIcon className="text-content-primary dark:text-dark-content-primary" />
684
- ```
685
-
686
- 2. **Aprovechar currentColor para heredar colores del padre**
687
- ```tsx
688
- // ✅ CORRECTO - El icono hereda el color
689
- <div className="text-primary-custom-600 dark:text-blue-400">
690
- <EnvelopeIcon />
691
- </div>
692
- ```
693
-
694
- 3. **Usar colores más brillantes en dark mode**
695
- ```tsx
696
- // ✅ CORRECTO - Ajustar intensidad para dark mode
697
- <CheckIcon className="text-green-600 dark:text-green-400" />
698
- ```
699
-
700
- 4. **Combinar con estados hover y focus**
701
- ```tsx
702
- // CORRECTO - Estados completos
703
- <button className="
704
- text-gray-700 dark:text-gray-300
705
- hover:text-blue-600 dark:hover:text-blue-400
706
- ">
707
- <PlusIcon />
708
- </button>
709
- ```
710
-
711
- 5. **Reducir opacidad de iconos secundarios en dark mode**
712
- ```tsx
713
- // CORRECTO - Jerarquía visual
714
- <QuestionMarkCircleIcon className="
715
- text-content-secondary/70 dark:text-dark-content-secondary/60
716
- " />
717
- ```
718
-
719
- #### Evitar
720
-
721
- 1. **No usar el mismo color para light y dark mode**
722
- ```tsx
723
- // ❌ INCORRECTO - Sin dark variant
724
- <UserIcon className="text-gray-900" />
725
-
726
- // ✅ CORRECTO
727
- <UserIcon className="text-gray-900 dark:text-gray-100" />
728
- ```
729
-
730
- 2. **No hardcodear colores sin considerar contraste**
731
- ```tsx
732
- // INCORRECTO - Pobre contraste en dark mode
733
- <CheckIcon className="text-gray-300" />
734
-
735
- // ✅ CORRECTO - Buen contraste en ambos modos
736
- <CheckIcon className="text-green-600 dark:text-green-400" />
737
- ```
738
-
739
- 3. **No olvidar estados interactivos**
740
- ```tsx
741
- // ❌ INCORRECTO - Sin hover para dark mode
742
- <button className="hover:text-blue-600">
743
- <PlusIcon />
744
- </button>
745
-
746
- // CORRECTO
747
- <button className="hover:text-blue-600 dark:hover:text-blue-400">
748
- <PlusIcon />
749
- </button>
750
- ```
751
-
752
- 4. **No usar colores muy oscuros en dark mode**
753
- ```tsx
754
- // INCORRECTO - Invisible en fondo oscuro
755
- <XIcon className="text-gray-900 dark:text-gray-900" />
756
-
757
- // ✅ CORRECTO - Visible en ambos modos
758
- <XIcon className="text-gray-900 dark:text-gray-100" />
759
- ```
760
-
761
- ### Guía Rápida: Colores de Iconos por Contexto
762
-
763
- | Contexto | Light Mode | Dark Mode | Ejemplo |
764
- |----------|------------|-----------|---------|
765
- | **Icono Principal** | `text-content-primary` | `dark:text-dark-content-primary` | Iconos en botones principales |
766
- | **Icono Secundario** | `text-content-secondary` | `dark:text-dark-content-secondary` | Iconos decorativos |
767
- | **Icono Terciario** | `text-content-tertiary` | `dark:text-dark-content-tertiary` | Iconos de ayuda |
768
- | **Icono Interactivo** | `text-gray-700 hover:text-blue-600` | `dark:text-gray-300 dark:hover:text-blue-400` | Botones icon-only |
769
- | **Icono de Éxito** | `text-green-600` | `dark:text-green-400` | Check, confirmación |
770
- | **Icono de Error** | `text-error-content` | `dark:text-red-400` | X, advertencias |
771
- | **Icono de Info** | `text-blue-600` | `dark:text-blue-400` | Información, ayuda |
772
- | **Icono Deshabilitado** | `text-content-tertiary opacity-50` | `dark:text-dark-content-tertiary opacity-50` | Elementos inactivos |
773
-
774
- ### Recursos Adicionales
775
-
776
- Para más información sobre el modo oscuro:
777
- - Ver `docs/dark-mode-guide.md` - Guía completa de Dark Mode en Tailwind CSS
778
- - Ver `docs/colors.md` - Sistema de colores completo con tokens dark mode
779
- - [Documentación oficial de Tailwind Dark Mode](https://tailwindcss.com/docs/dark-mode)
780
-
781
- ---
782
-
783
- ## Accesibilidad
784
-
785
- ### Consideraciones de Accesibilidad
786
-
787
- #### 1. Iconos Decorativos
788
-
789
- Cuando el icono acompaña texto visible, es decorativo:
790
-
791
- ```tsx
792
- // ✅ CORRECTO: El texto describe la acción
793
- <Button leftIcon={<PlusIcon />}>
794
- Crear Usuario
795
- </Button>
796
- // No se necesita aria-label adicional
797
- ```
798
-
799
- #### 2. Iconos Funcionales (Icon-Only)
800
-
801
- Cuando el icono es el único elemento visual:
802
-
803
- ```tsx
804
- // CORRECTO: Usar aria-label
805
- <Button
806
- iconOnly
807
- leftIcon={<PlusIcon />}
808
- ariaLabel="Añadir nuevo elemento"
809
- />
810
-
811
- // INCORRECTO: Sin aria-label
812
- <Button iconOnly leftIcon={<PlusIcon />} />
813
- // Los lectores de pantalla no sabrán la función
814
- ```
815
-
816
- #### 3. Iconos con Significado
817
-
818
- En contextos donde el icono comunica información:
819
-
820
- ```tsx
821
- // ✅ CORRECTO: Añadir rol y aria-label
822
- <span role="img" aria-label="Estado: Exitoso">
823
- <CheckIcon className="text-green-600" />
824
- </span>
825
-
826
- // ✅ CORRECTO: Con texto de soporte visible
827
- <div className="flex items-center gap-2">
828
- <ExclamationCircleIcon className="text-error-content" />
829
- <span>Error en la validación</span>
830
- </div>
831
- ```
832
-
833
- #### 4. Tooltips para Contexto Adicional
834
-
835
- ```tsx
836
- // ✅ MEJOR PRÁCTICA: Icono + Tooltip
837
- <button
838
- className="p-2"
839
- aria-label="Ayuda"
840
- title="Obtener ayuda sobre este campo"
841
- >
842
- <QuestionMarkCircleIcon />
843
- </button>
844
- ```
845
-
846
- ### Directrices WCAG 2.1
847
-
848
- - **Nivel A**: Todos los iconos funcionales deben tener texto alternativo
849
- - **Nivel AA**: Contraste mínimo 3:1 para iconos (se cumple con currentColor)
850
- - **Nivel AAA**: Proveer texto descriptivo adicional cuando sea posible
851
-
852
- ---
853
-
854
- ## Ejemplos de Código
855
-
856
- ### Ejemplo 1: Toolbar de Acciones
857
-
858
- ```tsx
859
- import { Button } from '@/components/Button';
860
- import { PlusIcon, CheckIcon, XIcon } from '@/components/Button/icons';
861
-
862
- export const ActionToolbar = () => {
863
- return (
864
- <div className="flex gap-2 p-4 bg-bg-primary border-b border-border-primary">
865
- {/* Botones icon-only con tooltips */}
866
- <Button
867
- iconOnly
868
- size="base"
869
- type="default"
870
- leftIcon={<PlusIcon />}
871
- ariaLabel="Añadir nuevo registro"
872
- title="Añadir nuevo registro"
873
- />
874
-
875
- <Button
876
- iconOnly
877
- size="base"
878
- type="outline"
879
- leftIcon={<CheckIcon />}
880
- ariaLabel="Guardar cambios"
881
- title="Guardar cambios"
882
- />
883
-
884
- <Button
885
- iconOnly
886
- size="base"
887
- type="plain"
888
- leftIcon={<XIcon />}
889
- ariaLabel="Cancelar operación"
890
- title="Cancelar operación"
891
- />
892
- </div>
893
- );
894
- };
895
- ```
896
-
897
- ### Ejemplo 2: Formulario de Login
898
-
899
- ```tsx
900
- import { Input } from '@/components/Input';
901
- import { Button } from '@/components/Button';
902
- import {
903
- UserIcon,
904
- LockClosedIcon,
905
- EyeIcon,
906
- EyeSlashIcon
907
- } from '@/components/Input/icons';
908
- import { ArrowRightIcon } from '@/components/Button/icons';
909
- import { useState } from 'react';
910
-
911
- export const LoginForm = () => {
912
- const [showPassword, setShowPassword] = useState(false);
913
-
914
- return (
915
- <form className="space-y-4 w-full max-w-sm">
916
- {/* Usuario */}
917
- <Input
918
- label="Usuario"
919
- name="username"
920
- leftIcon={<UserIcon />}
921
- placeholder="Ingrese su usuario"
922
- required
923
- />
924
-
925
- {/* Contraseña con toggle */}
926
- <Input
927
- label="Contraseña"
928
- name="password"
929
- type={showPassword ? 'text' : 'password'}
930
- leftIcon={<LockClosedIcon />}
931
- rightIcon={
932
- <button
933
- type="button"
934
- onClick={() => setShowPassword(!showPassword)}
935
- className="cursor-pointer"
936
- aria-label={showPassword ? 'Ocultar contraseña' : 'Mostrar contraseña'}
937
- >
938
- {showPassword ? <EyeSlashIcon /> : <EyeIcon />}
939
- </button>
940
- }
941
- placeholder="Ingrese su contraseña"
942
- required
943
- />
944
-
945
- {/* Submit */}
946
- <Button
947
- type="default"
948
- size="base"
949
- fullWidth
950
- rightIcon={<ArrowRightIcon />}
951
- htmlType="submit"
952
- >
953
- Iniciar Sesión
954
- </Button>
955
- </form>
956
- );
957
- };
958
- ```
959
-
960
- ### Ejemplo 3: Search Input con Estados
961
-
962
- ```tsx
963
- import { Input } from '@/components/Input';
964
- import {
965
- MagnifyingGlassIcon,
966
- XMarkIcon,
967
- CheckIcon,
968
- ExclamationCircleIcon
969
- } from '@/components/Input/icons';
970
- import { useState } from 'react';
971
-
972
- export const SearchInput = () => {
973
- const [query, setQuery] = useState('');
974
- const [status, setStatus] = useState<'idle' | 'searching' | 'success' | 'error'>('idle');
975
-
976
- const getStatusIcon = () => {
977
- switch (status) {
978
- case 'success':
979
- return <CheckIcon className="text-green-600" />;
980
- case 'error':
981
- return <ExclamationCircleIcon className="text-error-content" />;
982
- default:
983
- return null;
984
- }
985
- };
986
-
987
- return (
988
- <div className="w-full max-w-md">
989
- <Input
990
- label="Búsqueda"
991
- value={query}
992
- onChange={(e) => setQuery(e.target.value)}
993
- leftIcon={<MagnifyingGlassIcon />}
994
- rightIcon={
995
- query ? (
996
- <button
997
- type="button"
998
- onClick={() => setQuery('')}
999
- aria-label="Limpiar búsqueda"
1000
- className="cursor-pointer hover:text-primary-custom-600"
1001
- >
1002
- <XMarkIcon />
1003
- </button>
1004
- ) : (
1005
- getStatusIcon()
1006
- )
1007
- }
1008
- placeholder="Buscar..."
1009
- helperText={
1010
- status === 'error' ? 'No se encontraron resultados' : undefined
1011
- }
1012
- error={status === 'error'}
1013
- />
1014
- </div>
1015
- );
1016
- };
1017
- ```
1018
-
1019
- ---
1020
-
1021
- ## Mejores Prácticas
1022
-
1023
- ### Hacer
1024
-
1025
- 1. **Usar iconos semánticamente apropiados**
1026
- ```tsx
1027
- // ✅ CORRECTO
1028
- <Button leftIcon={<PlusIcon />}>Añadir</Button>
1029
- <Button leftIcon={<CheckIcon />}>Guardar</Button>
1030
- ```
1031
-
1032
- 2. **Mantener el tamaño de 16px en la mayoría de casos**
1033
- ```tsx
1034
- // ✅ CORRECTO - tamaño por defecto
1035
- <UserIcon className="w-4 h-4" />
1036
- ```
1037
-
1038
- 3. **Usar currentColor para heredar el color del contexto**
1039
- ```tsx
1040
- // CORRECTO - el icono hereda el color
1041
- <div className="text-primary-custom-600">
1042
- <EnvelopeIcon />
1043
- </div>
1044
- ```
1045
-
1046
- 4. **Proveer aria-label en botones icon-only**
1047
- ```tsx
1048
- // CORRECTO
1049
- <Button iconOnly leftIcon={<XIcon />} ariaLabel="Cerrar" />
1050
- ```
1051
-
1052
- 5. **Agrupar iconos relacionados en el mismo archivo**
1053
- ```tsx
1054
- // CORRECTO - iconos de un componente juntos
1055
- // src/components/Button/icons.tsx
1056
- ```
1057
-
1058
- ### ❌ Evitar
1059
-
1060
- 1. **No mezclar diferentes estilos de iconos**
1061
- ```tsx
1062
- // ❌ INCORRECTO - mezclar Heroicons con otros
1063
- <PlusIcon /> {/* Heroicons Micro */}
1064
- <SomeOtherIcon /> {/* Otra librería */}
1065
- ```
1066
-
1067
- 2. **No usar tamaños inconsistentes sin razón**
1068
- ```tsx
1069
- // ❌ INCORRECTO - tamaños arbitrarios
1070
- <UserIcon className="w-7 h-7" />
1071
- <EnvelopeIcon className="w-3 h-3" />
1072
- ```
1073
-
1074
- 3. **No hardcodear colores directamente en el SVG**
1075
- ```tsx
1076
- // ❌ INCORRECTO - hardcodear fill
1077
- <svg fill="#0e79fd">...</svg>
1078
-
1079
- // CORRECTO - usar currentColor
1080
- <svg fill="currentColor">...</svg>
1081
- ```
1082
-
1083
- 4. **No omitir aria-label en iconos funcionales**
1084
- ```tsx
1085
- // ❌ INCORRECTO
1086
- <button><XIcon /></button>
1087
-
1088
- // CORRECTO
1089
- <button aria-label="Cerrar"><XIcon /></button>
1090
- ```
1091
-
1092
- 5. **No usar iconos como única forma de comunicación**
1093
- ```tsx
1094
- // ❌ INCORRECTO - solo icono sin contexto
1095
- <div><ExclamationCircleIcon /></div>
1096
-
1097
- // ✅ CORRECTO - icono + texto
1098
- <div className="flex gap-2">
1099
- <ExclamationCircleIcon />
1100
- <span>Error: Campo requerido</span>
1101
- </div>
1102
- ```
1103
-
1104
- ### Rendimiento
1105
-
1106
- - **✅ SVG Inline**: Mejor para iconos que se usan frecuentemente
1107
- - **✅ Tree-shaking**: Importar solo los iconos necesarios
1108
- - **✅ Evitar re-renders**: Los iconos son componentes puros
1109
- - **✅ Memoización**: React.memo si se pasan como props frecuentemente
1110
-
1111
- ```tsx
1112
- // ✅ CORRECTO - memoizar icono si se pasa como prop
1113
- const MemoizedIcon = React.memo(PlusIcon);
1114
-
1115
- // En componente padre
1116
- <Button leftIcon={<MemoizedIcon />}>Añadir</Button>
1117
- ```
1118
-
1119
- ---
1120
-
1121
- ## Referencia Rápida
1122
-
1123
- ### Cheat Sheet: Importaciones
1124
-
1125
- ```typescript
1126
- // Iconos de Button
1127
- import {
1128
- PlusIcon, // Añadir/Crear
1129
- ChevronDownIcon, // Dropdown
1130
- ArrowRightIcon, // Navegación
1131
- CheckIcon, // Confirmar
1132
- XIcon // Cerrar/Cancelar
1133
- } from '@/components/Button/icons';
1134
-
1135
- // Iconos de Input
1136
- import {
1137
- EnvelopeIcon, // Email
1138
- QuestionMarkCircleIcon, // Ayuda
1139
- UserIcon, // Usuario
1140
- LockClosedIcon, // Seguridad
1141
- MagnifyingGlassIcon, // Búsqueda
1142
- EyeIcon, // Ver password
1143
- EyeSlashIcon, // Ocultar password
1144
- XMarkIcon, // Limpiar
1145
- CheckIcon, // Éxito
1146
- ExclamationCircleIcon // Error
1147
- } from '@/components/Input/icons';
1148
- ```
1149
-
1150
- ### Cheat Sheet: Tamaños Comunes
1151
-
1152
- | Clase Tailwind | Tamaño | Uso |
1153
- |----------------|--------|-----|
1154
- | `w-4 h-4` | 16px | **Default** - Botones, inputs |
1155
- | `w-5 h-5` | 20px | Iconos destacados |
1156
- | `w-6 h-6` | 24px | Headers, títulos |
1157
- | `w-8 h-8` | 32px | Iconos grandes, heros |
1158
-
1159
- ### Cheat Sheet: Colores Comunes
1160
-
1161
- ```tsx
1162
- // Primary
1163
- <Icon className="text-primary-custom-600" />
1164
-
1165
- // Éxito (Verde)
1166
- <CheckIcon className="text-green-600" />
1167
-
1168
- // Error (Rojo)
1169
- <ExclamationCircleIcon className="text-error-content" />
1170
-
1171
- // Secundario (Gris)
1172
- <Icon className="text-content-secondary" />
1173
-
1174
- // Dark Mode (automático)
1175
- <Icon className="text-content-primary dark:text-dark-content-primary" />
1176
- ```
1177
-
1178
- ### Cheat Sheet: Patrones de Uso
1179
-
1180
- ```tsx
1181
- // 1. Icon-only Button
1182
- <Button iconOnly leftIcon={<PlusIcon />} ariaLabel="Añadir" />
1183
-
1184
- // 2. Button con texto e icono
1185
- <Button leftIcon={<CheckIcon />}>Guardar</Button>
1186
-
1187
- // 3. Input con icono
1188
- <Input leftIcon={<UserIcon />} placeholder="Usuario" />
1189
-
1190
- // 4. Toggle icon
1191
- {visible ? <EyeIcon /> : <EyeSlashIcon />}
1192
-
1193
- // 5. Status icon
1194
- {status === 'success' ? <CheckIcon /> : <ExclamationCircleIcon />}
1195
- ```
1196
-
1197
- ---
1198
-
1199
- ## Añadir Nuevos Iconos
1200
-
1201
- ### Proceso para Agregar un Icono
1202
-
1203
- 1. **Obtener el SVG de Heroicons Micro**
1204
- - Visitar: https://heroicons.com
1205
- - Seleccionar versión "Micro" (16px)
1206
- - Copiar el código SVG
1207
-
1208
- 2. **Crear el Componente React**
1209
- ```tsx
1210
- // En el archivo icons.tsx correspondiente
1211
- export const NewIcon: React.FC<IconProps> = ({ className = '' }) => (
1212
- <svg
1213
- xmlns="http://www.w3.org/2000/svg"
1214
- viewBox="0 0 16 16"
1215
- fill="currentColor"
1216
- className={className}
1217
- >
1218
- {/* Pegar path(s) del SVG */}
1219
- <path d="..." />
1220
- </svg>
1221
- );
1222
- ```
1223
-
1224
- 3. **Documentar el Nuevo Icono**
1225
- - Añadir a la tabla de catálogo
1226
- - Incluir ejemplo de uso
1227
- - Especificar contexto apropiado
1228
-
1229
- 4. **Testing**
1230
- - Verificar en modo claro y oscuro
1231
- - Probar diferentes tamaños
1232
- - Validar accesibilidad
1233
-
1234
- ### Decisiones de Organización
1235
-
1236
- - **¿Dónde colocar el nuevo icono?**
1237
- - ¿Se usa en Button? → `src/components/Button/icons.tsx`
1238
- - ¿Se usa en Input? → `src/components/Input/icons.tsx`
1239
- - ¿Se usa en múltiples componentes? → Crear `src/shared/icons.tsx`
1240
-
1241
- ---
1242
-
1243
- ## Recursos Adicionales
1244
-
1245
- ### Enlaces Útiles
1246
-
1247
- - **Heroicons**: https://heroicons.com
1248
- - **Documentación Heroicons**: https://github.com/tailwindlabs/heroicons
1249
- - **WCAG Guidelines**: https://www.w3.org/WAI/WCAG21/quickref/
1250
- - **SVG Accessibility**: https://css-tricks.com/accessible-svgs/
1251
-
1252
- ### Archivos Relacionados
1253
-
1254
- - `src/components/Button/icons.tsx` - Iconos de botones
1255
- - `src/components/Input/icons.tsx` - Iconos de inputs
1256
- - `src/components/Button/Button.tsx` - Implementación de iconos en Button
1257
- - `docs/colors.md` - Sistema de colores (para colores de iconos)
1258
- - `docs/typography.md` - Sistema tipográfico
1259
-
1260
- ---
1261
-
1262
- **Última actualización**: 2025-11-11
1263
- **Versión**: 1.0.0
1264
- **Mantenedor**: Siesa UI Kit Team
1
+ # Sistema de Iconos - Siesa UI Kit
2
+
3
+ ## 📋 Tabla de Contenidos
4
+
5
+ 1. [Introducción](#introducción)
6
+ 2. [Librería de Iconos](#librería-de-iconos)
7
+ 3. [Catálogo de Iconos](#catálogo-de-iconos)
8
+ 4. [Implementación](#implementación)
9
+ 5. [Guía de Uso](#guía-de-uso)
10
+ 6. [Accesibilidad](#accesibilidad)
11
+ 7. [Ejemplos de Código](#ejemplos-de-código)
12
+ 8. [Mejores Prácticas](#mejores-prácticas)
13
+ 9. [Referencia Rápida](#referencia-rápida)
14
+
15
+ ---
16
+
17
+ ## Introducción
18
+
19
+ El sistema de iconos de Siesa UI Kit está basado en **Heroicons Micro**, una librería de iconos SVG de 16x16px diseñada específicamente para interfaces de usuario modernas. Los iconos están optimizados para claridad a tamaños pequeños y se integran perfectamente con nuestro sistema de diseño.
20
+
21
+ ### Objetivos del Sistema de Iconos
22
+
23
+ - **Consistencia Visual**: Todos los iconos mantienen el mismo peso visual y estilo
24
+ - **Escalabilidad**: Iconos vectoriales que se adaptan a cualquier tamaño
25
+ - **Accesibilidad**: Soporte para lectores de pantalla y temas oscuros
26
+ - **Rendimiento**: SVG inline para carga rápida sin requests adicionales
27
+ - **Flexibilidad**: Fácil personalización de tamaño, color y estilos
28
+
29
+ ### Principios de Diseño
30
+
31
+ 1. **Simplicidad**: Formas claras y reconocibles
32
+ 2. **Peso Consistente**: Todos los iconos tienen el mismo grosor de línea
33
+ 3. **Alineación Pixel-Perfect**: Optimizados para 16x16px
34
+ 4. **Color Heredado**: Usan `currentColor` para adaptarse al contexto
35
+
36
+ ---
37
+
38
+ ## Librería de Iconos
39
+
40
+ ### Heroicons Micro
41
+
42
+ **Especificaciones Técnicas:**
43
+ - **Tamaño Base**: 16x16px (viewBox="0 0 16 16")
44
+ - **Formato**: SVG inline
45
+ - **Estilo**: Solid (relleno completo)
46
+ - **Grosor**: 1.5px stroke weight equivalent
47
+ - **Licencia**: MIT License
48
+
49
+ **Ventajas:**
50
+ - ✅ Diseñados específicamente para UI de 16px
51
+ - ✅ Optimizados para claridad a tamaños pequeños
52
+ - ✅ Mantenidos por el equipo de Tailwind CSS
53
+ - ✅ Biblioteca completa y consistente
54
+ - ✅ Excelente legibilidad en pantallas de alta densidad
55
+
56
+ ---
57
+
58
+ ## Catálogo de Iconos
59
+
60
+ ### Iconos de Botón (Button)
61
+
62
+ Iconos disponibles en `src/components/Button/icons.tsx`
63
+
64
+ | Icono | Nombre | Uso Principal | Ubicación |
65
+ |-------|--------|---------------|-----------|
66
+ | ➕ | `PlusIcon` | Acciones de añadir/crear | Button.tsx:12 |
67
+ | 🔽 | `ChevronDownIcon` | Menús desplegables | Button.tsx:12 |
68
+ | ➡️ | `ArrowRightIcon` | Navegación/siguiente | Button.tsx:12 |
69
+ | ✓ | `CheckIcon` | Confirmación/éxito | Button.tsx:14 |
70
+ | ✕ | `XIcon` | Cerrar/cancelar | Button.tsx:14 |
71
+
72
+ ### Iconos de Input (Input)
73
+
74
+ Iconos disponibles en `src/components/Input/icons.tsx`
75
+
76
+ | Icono | Nombre | Uso Principal | Contexto |
77
+ |-------|--------|---------------|----------|
78
+ | ✉️ | `EnvelopeIcon` | Email input | Campo de correo electrónico |
79
+ | ❓ | `QuestionMarkCircleIcon` | Ayuda contextual | Tooltips, hints |
80
+ | 👤 | `UserIcon` | Usuario/perfil | Campos de nombre, login |
81
+ | 🔒 | `LockClosedIcon` | Seguridad | Password, campos privados |
82
+ | 🔍 | `MagnifyingGlassIcon` | Búsqueda | Search inputs |
83
+ | 👁️ | `EyeIcon` | Ver contraseña | Toggle password visibility |
84
+ | 👁️‍🗨️ | `EyeSlashIcon` | Ocultar contraseña | Toggle password visibility |
85
+ | ✕ | `XMarkIcon` | Limpiar campo | Clear input |
86
+ | ✓ | `CheckIcon` | Validación exitosa | Estado de éxito |
87
+ | ⚠️ | `ExclamationCircleIcon` | Error/advertencia | Estado de error |
88
+
89
+ **Total de Iconos Disponibles**: 16 (5 Button + 11 Input)
90
+
91
+ ---
92
+
93
+ ## Implementación
94
+
95
+ ### Patrón de Implementación
96
+
97
+ Todos los iconos siguen un patrón consistente:
98
+
99
+ ```typescript
100
+ interface IconProps {
101
+ className?: string;
102
+ }
103
+
104
+ export const IconName: React.FC<IconProps> = ({ className = '' }) => (
105
+ <svg
106
+ xmlns="http://www.w3.org/2000/svg"
107
+ viewBox="0 0 16 16"
108
+ fill="currentColor"
109
+ className={className}
110
+ >
111
+ <path d="..." />
112
+ </svg>
113
+ );
114
+ ```
115
+
116
+ ### Características Clave
117
+
118
+ 1. **TypeScript**: Interfaz `IconProps` para type safety
119
+ 2. **currentColor**: El fill hereda el color del texto padre
120
+ 3. **className**: Permite personalización con Tailwind CSS
121
+ 4. **viewBox 16x16**: Tamaño base optimizado
122
+ 5. **Props mínimos**: Solo className para máxima flexibilidad
123
+
124
+ ### Tamaños de Iconos
125
+
126
+ Los iconos se adaptan usando clases de Tailwind CSS:
127
+
128
+ ```typescript
129
+ // En Button Component
130
+ const iconSizeClasses = {
131
+ xs: 'w-4 h-4', // 16px - todos los tamaños usan 16px
132
+ sm: 'w-4 h-4', // 16px
133
+ base: 'w-4 h-4', // 16px (default)
134
+ l: 'w-4 h-4', // 16px
135
+ xl: 'w-4 h-4', // 16px
136
+ };
137
+ ```
138
+
139
+ **Decisión de Diseño**: Todos los botones usan iconos de 16px independientemente del tamaño del botón, según especificaciones de Figma.
140
+
141
+ ---
142
+
143
+ ## Guía de Uso
144
+
145
+ ### 1. Importación
146
+
147
+ ```typescript
148
+ // Importar iconos específicos
149
+ import { PlusIcon, CheckIcon } from '@/components/Button/icons';
150
+ import { EnvelopeIcon, UserIcon } from '@/components/Input/icons';
151
+ ```
152
+
153
+ ### 2. Uso Básico
154
+
155
+ ```tsx
156
+ // Icono básico (hereda color del texto padre)
157
+ <PlusIcon />
158
+
159
+ // Con tamaño personalizado
160
+ <UserIcon className="w-5 h-5" />
161
+
162
+ // Con color personalizado
163
+ <CheckIcon className="w-4 h-4 text-green-600" />
164
+ ```
165
+
166
+ ### 3. En Componentes
167
+
168
+ #### Button con Iconos
169
+
170
+ ```tsx
171
+ import { Button } from '@/components/Button';
172
+ import { PlusIcon, ArrowRightIcon } from '@/components/Button/icons';
173
+
174
+ // Icon only button
175
+ <Button iconOnly leftIcon={<PlusIcon />} ariaLabel="Añadir" />
176
+
177
+ // Button con icono izquierdo
178
+ <Button leftIcon={<PlusIcon />}>
179
+ Crear Nuevo
180
+ </Button>
181
+
182
+ // Button con icono derecho
183
+ <Button rightIcon={<ArrowRightIcon />}>
184
+ Continuar
185
+ </Button>
186
+
187
+ // Button con ambos iconos
188
+ <Button
189
+ leftIcon={<CheckIcon />}
190
+ rightIcon={<ArrowRightIcon />}
191
+ >
192
+ Guardar y Continuar
193
+ </Button>
194
+ ```
195
+
196
+ #### Input con Iconos
197
+
198
+ ```tsx
199
+ import { Input } from '@/components/Input';
200
+ import { EnvelopeIcon, EyeIcon } from '@/components/Input/icons';
201
+
202
+ // Input con icono izquierdo
203
+ <Input
204
+ leftIcon={<EnvelopeIcon />}
205
+ placeholder="correo@ejemplo.com"
206
+ type="email"
207
+ />
208
+
209
+ // Input con icono derecho
210
+ <Input
211
+ rightIcon={<EyeIcon />}
212
+ placeholder="Contraseña"
213
+ type="password"
214
+ />
215
+ ```
216
+
217
+ ### 4. Estados y Temas
218
+
219
+ Los iconos heredan automáticamente el color del contexto:
220
+
221
+ ```tsx
222
+ // En modo claro (hereda color del texto)
223
+ <Button type="default">
224
+ <PlusIcon /> {/* Hereda text-primary-inverse-content */}
225
+ </Button>
226
+
227
+ // En modo oscuro (se adapta automáticamente)
228
+ <div className="dark">
229
+ <Button type="outline">
230
+ <UserIcon /> {/* Hereda dark:text-dark-content-primary */}
231
+ </Button>
232
+ </div>
233
+
234
+ // Estados disabled
235
+ <Button disabled>
236
+ <CheckIcon /> {/* Hereda opacity-50 del botón */}
237
+ </Button>
238
+ ```
239
+
240
+ ---
241
+
242
+ ## Modo Oscuro (Dark Mode)
243
+
244
+ ### Configuración de Tailwind CSS
245
+
246
+ El modo oscuro en Siesa UI Kit se basa en la estrategia de clases de Tailwind CSS:
247
+
248
+ ```javascript
249
+ // tailwind.config.js
250
+ module.exports = {
251
+ darkMode: 'class', // ✅ Estrategia basada en clases (NO 'media')
252
+ // ...resto de la configuración
253
+ }
254
+ ```
255
+
256
+ Con esta configuración, el modo oscuro se activa añadiendo la clase `.dark` al elemento `<html>`:
257
+
258
+ ```html
259
+ <!-- Modo claro -->
260
+ <html>
261
+ <body>
262
+ <!-- Contenido en modo claro -->
263
+ </body>
264
+ </html>
265
+
266
+ <!-- Modo oscuro -->
267
+ <html class="dark">
268
+ <body>
269
+ <!-- Contenido en modo oscuro -->
270
+ </body>
271
+ </html>
272
+ ```
273
+
274
+ ### El Modificador `dark:`
275
+
276
+ El modificador `dark:` de Tailwind funciona como un **prefijo condicional** que aplica estilos solo cuando la clase `.dark` está presente en un elemento padre (típicamente `<html>`).
277
+
278
+ #### Sintaxis Básica
279
+
280
+ ```tsx
281
+ // Patrón básico
282
+ <Icon className="text-content-primary dark:text-dark-content-primary" />
283
+
284
+ // El icono usa:
285
+ // - text-content-primary en modo claro
286
+ // - text-dark-content-primary en modo oscuro
287
+ ```
288
+
289
+ #### Herencia de Color con currentColor
290
+
291
+ Los iconos usan `fill="currentColor"`, lo que significa que heredan el color del texto del elemento padre:
292
+
293
+ ```tsx
294
+ // El icono hereda el color del div padre
295
+ <div className="text-content-primary dark:text-dark-content-primary">
296
+ <UserIcon /> {/* Automáticamente se adapta */}
297
+ </div>
298
+
299
+ // Equivalente a especificar el color directamente en el icono
300
+ <UserIcon className="text-content-primary dark:text-dark-content-primary" />
301
+ ```
302
+
303
+ ### Combinando con Otros Modificadores
304
+
305
+ El modificador `dark:` se puede combinar con hover, focus, active, y responsive:
306
+
307
+ ```tsx
308
+ // Dark mode + Hover
309
+ <button className="text-gray-700 hover:text-blue-600 dark:text-gray-300 dark:hover:text-blue-400">
310
+ <PlusIcon />
311
+ </button>
312
+
313
+ // Dark mode + Focus
314
+ <input className="text-content-primary focus:text-primary-custom-600 dark:text-dark-content-primary dark:focus:text-blue-400">
315
+ <MagnifyingGlassIcon />
316
+ </input>
317
+
318
+ // Dark mode + Responsive
319
+ <div className="text-gray-900 md:text-blue-600 dark:text-white dark:md:text-blue-400">
320
+ <CheckIcon />
321
+ </div>
322
+
323
+ // Dark mode + Group hover
324
+ <div className="group">
325
+ <button className="text-gray-700 dark:text-gray-300">
326
+ <ArrowRightIcon className="
327
+ text-gray-500
328
+ group-hover:text-blue-600
329
+ dark:text-gray-400
330
+ dark:group-hover:text-blue-400
331
+ " />
332
+ </button>
333
+ </div>
334
+ ```
335
+
336
+ ### Orden de Modificadores
337
+
338
+ Tailwind CSS recomienda un orden específico para los modificadores:
339
+
340
+ **Formato**: `{responsive}:{dark}:{state}:{utility}`
341
+
342
+ ```tsx
343
+ // CORRECTO - Orden: responsive dark state → utility
344
+ <button className="
345
+ md:text-gray-700
346
+ md:dark:text-gray-300
347
+ md:dark:hover:text-blue-400
348
+ ">
349
+ <PlusIcon />
350
+ </button>
351
+
352
+ // ❌ INCORRECTO - Orden equivocado
353
+ <button className="
354
+ dark:md:hover:text-blue-400
355
+ ">
356
+ <PlusIcon />
357
+ </button>
358
+ ```
359
+
360
+ ### Tabla de Estados con Hover
361
+
362
+ | Estado | Light Mode | Dark Mode | Descripción |
363
+ |--------|------------|-----------|-------------|
364
+ | **Default** | `text-content-primary` | `dark:text-dark-content-primary` | Color principal del icono |
365
+ | **Hover** | `hover:text-primary-custom-600` | `dark:hover:text-blue-400` | Color al pasar el mouse |
366
+ | **Focus** | `focus:text-primary-custom-600` | `dark:focus:text-blue-400` | Color al enfocar |
367
+ | **Active** | `active:text-primary-custom-700` | `dark:active:text-blue-500` | Color al hacer clic |
368
+ | **Disabled** | `text-content-tertiary` | `dark:text-dark-content-tertiary` | Color deshabilitado |
369
+ | **Error** | `text-error-content` | `dark:text-red-400` | Color de error |
370
+ | **Success** | `text-green-600` | `dark:text-green-400` | Color de éxito |
371
+
372
+ ### Implementación del Toggle Dark Mode
373
+
374
+ #### Implementación Básica con JavaScript
375
+
376
+ ```typescript
377
+ // utils/darkMode.ts
378
+ export const toggleDarkMode = () => {
379
+ const isDark = document.documentElement.classList.contains('dark');
380
+
381
+ if (isDark) {
382
+ document.documentElement.classList.remove('dark');
383
+ localStorage.setItem('theme', 'light');
384
+ } else {
385
+ document.documentElement.classList.add('dark');
386
+ localStorage.setItem('theme', 'dark');
387
+ }
388
+ };
389
+
390
+ // Cargar el tema al iniciar la aplicación
391
+ export const loadTheme = () => {
392
+ const savedTheme = localStorage.getItem('theme');
393
+ const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
394
+
395
+ if (savedTheme === 'dark' || (!savedTheme && prefersDark)) {
396
+ document.documentElement.classList.add('dark');
397
+ } else {
398
+ document.documentElement.classList.remove('dark');
399
+ }
400
+ };
401
+ ```
402
+
403
+ #### Prevenir Flash de Contenido (FOUC)
404
+
405
+ Añadir este script en el `<head>` del HTML antes de que React se cargue:
406
+
407
+ ```html
408
+ <!-- index.html -->
409
+ <head>
410
+ <script>
411
+ // Aplicar tema inmediatamente antes del render
412
+ (function() {
413
+ const theme = localStorage.getItem('theme');
414
+ const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
415
+
416
+ if (theme === 'dark' || (!theme && prefersDark)) {
417
+ document.documentElement.classList.add('dark');
418
+ }
419
+ })();
420
+ </script>
421
+ </head>
422
+ ```
423
+
424
+ ### Ejemplos Completos
425
+
426
+ #### Ejemplo 1: Toolbar de Iconos con Dark Mode
427
+
428
+ ```tsx
429
+ import { Button } from '@/components/Button';
430
+ import { PlusIcon, CheckIcon, XIcon } from '@/components/Button/icons';
431
+
432
+ export const IconToolbar = () => {
433
+ return (
434
+ <div className="
435
+ flex gap-2 p-4
436
+ bg-white dark:bg-dark-bg-primary
437
+ border-b border-border-primary dark:border-dark-border-primary
438
+ ">
439
+ {/* Icono con hover adaptado */}
440
+ <Button
441
+ iconOnly
442
+ type="outline"
443
+ leftIcon={<PlusIcon />}
444
+ ariaLabel="Añadir"
445
+ className="
446
+ text-content-primary dark:text-dark-content-primary
447
+ hover:text-primary-custom-600 dark:hover:text-blue-400
448
+ hover:bg-gray-100 dark:hover:bg-gray-800
449
+ "
450
+ />
451
+
452
+ {/* Icono de éxito */}
453
+ <Button
454
+ iconOnly
455
+ type="outline"
456
+ leftIcon={<CheckIcon />}
457
+ ariaLabel="Guardar"
458
+ className="
459
+ text-green-600 dark:text-green-400
460
+ hover:text-green-700 dark:hover:text-green-300
461
+ hover:bg-green-50 dark:hover:bg-green-900/20
462
+ "
463
+ />
464
+
465
+ {/* Icono de error */}
466
+ <Button
467
+ iconOnly
468
+ type="outline"
469
+ leftIcon={<XIcon />}
470
+ ariaLabel="Cancelar"
471
+ className="
472
+ text-error-content dark:text-red-400
473
+ hover:text-red-700 dark:hover:text-red-300
474
+ hover:bg-red-50 dark:hover:bg-red-900/20
475
+ "
476
+ />
477
+ </div>
478
+ );
479
+ };
480
+ ```
481
+
482
+ #### Ejemplo 2: Formulario con Iconos Adaptativos
483
+
484
+ ```tsx
485
+ import { Input } from '@/components/Input';
486
+ import { UserIcon, LockClosedIcon, EnvelopeIcon } from '@/components/Input/icons';
487
+ import { Button } from '@/components/Button';
488
+ import { ArrowRightIcon, CheckIcon } from '@/components/Button/icons';
489
+
490
+ export const AdaptiveForm = () => {
491
+ return (
492
+ <div className="
493
+ w-full max-w-md p-6
494
+ bg-white dark:bg-dark-bg-primary
495
+ border border-border-primary dark:border-dark-border-primary
496
+ rounded-2xl
497
+ shadow-base dark:shadow-lg
498
+ ">
499
+ <h2 className="
500
+ mb-6
501
+ text-content-primary dark:text-dark-content-primary
502
+ font-bold text-xl
503
+ ">
504
+ Iniciar Sesión
505
+ </h2>
506
+
507
+ <form className="space-y-4">
508
+ {/* Input de email con icono */}
509
+ <Input
510
+ label="Correo Electrónico"
511
+ type="email"
512
+ leftIcon={
513
+ <EnvelopeIcon className="
514
+ text-content-secondary dark:text-dark-content-secondary
515
+ " />
516
+ }
517
+ placeholder="tu@email.com"
518
+ className="
519
+ text-content-primary dark:text-dark-content-primary
520
+ bg-bg-primary dark:bg-dark-bg-secondary
521
+ border-border-primary dark:border-dark-border-primary
522
+ focus:border-primary-custom-600 dark:focus:border-blue-400
523
+ "
524
+ />
525
+
526
+ {/* Input de usuario con icono */}
527
+ <Input
528
+ label="Usuario"
529
+ leftIcon={
530
+ <UserIcon className="
531
+ text-content-secondary dark:text-dark-content-secondary
532
+ " />
533
+ }
534
+ placeholder="Tu usuario"
535
+ className="
536
+ text-content-primary dark:text-dark-content-primary
537
+ bg-bg-primary dark:bg-dark-bg-secondary
538
+ "
539
+ />
540
+
541
+ {/* Input de contraseña con icono */}
542
+ <Input
543
+ label="Contraseña"
544
+ type="password"
545
+ leftIcon={
546
+ <LockClosedIcon className="
547
+ text-content-secondary dark:text-dark-content-secondary
548
+ " />
549
+ }
550
+ placeholder="Tu contraseña"
551
+ className="
552
+ text-content-primary dark:text-dark-content-primary
553
+ bg-bg-primary dark:bg-dark-bg-secondary
554
+ "
555
+ />
556
+
557
+ {/* Botón de submit con icono */}
558
+ <Button
559
+ type="default"
560
+ fullWidth
561
+ rightIcon={<ArrowRightIcon />}
562
+ className="
563
+ bg-primary-custom-600 dark:bg-dark-bg-inverse
564
+ text-primary-inverse-content dark:text-dark-content-inverse
565
+ hover:bg-primary-custom-500 dark:hover:bg-dark-bg-inverse/90
566
+ "
567
+ >
568
+ Continuar
569
+ </Button>
570
+ </form>
571
+ </div>
572
+ );
573
+ };
574
+ ```
575
+
576
+ #### Ejemplo 3: Status Icons con Colores Adaptativos
577
+
578
+ ```tsx
579
+ import { CheckIcon, ExclamationCircleIcon, XMarkIcon } from '@/components/Input/icons';
580
+
581
+ export const StatusMessages = () => {
582
+ return (
583
+ <div className="space-y-3">
584
+ {/* Mensaje de éxito */}
585
+ <div className="
586
+ flex items-center gap-3 p-4
587
+ bg-green-50 dark:bg-green-900/20
588
+ border border-green-200 dark:border-green-800
589
+ rounded-lg
590
+ ">
591
+ <CheckIcon className="
592
+ w-5 h-5
593
+ text-green-600 dark:text-green-400
594
+ " />
595
+ <p className="
596
+ text-green-800 dark:text-green-300
597
+ font-medium
598
+ ">
599
+ Operación completada con éxito
600
+ </p>
601
+ </div>
602
+
603
+ {/* Mensaje de advertencia */}
604
+ <div className="
605
+ flex items-center gap-3 p-4
606
+ bg-yellow-50 dark:bg-yellow-900/20
607
+ border border-yellow-200 dark:border-yellow-800
608
+ rounded-lg
609
+ ">
610
+ <ExclamationCircleIcon className="
611
+ w-5 h-5
612
+ text-yellow-600 dark:text-yellow-400
613
+ " />
614
+ <p className="
615
+ text-yellow-800 dark:text-yellow-300
616
+ font-medium
617
+ ">
618
+ Advertencia: Revisa la información
619
+ </p>
620
+ </div>
621
+
622
+ {/* Mensaje de error */}
623
+ <div className="
624
+ flex items-center gap-3 p-4
625
+ bg-red-50 dark:bg-red-900/20
626
+ border border-red-200 dark:border-red-800
627
+ rounded-lg
628
+ ">
629
+ <XMarkIcon className="
630
+ w-5 h-5
631
+ text-error-content dark:text-red-400
632
+ " />
633
+ <p className="
634
+ text-red-800 dark:text-red-300
635
+ font-medium
636
+ ">
637
+ Error: No se pudo completar la operación
638
+ </p>
639
+ </div>
640
+ </div>
641
+ );
642
+ };
643
+ ```
644
+
645
+ #### Ejemplo 4: Icon Button con Group Hover
646
+
647
+ ```tsx
648
+ import { ArrowRightIcon } from '@/components/Button/icons';
649
+
650
+ export const NavigationCard = () => {
651
+ return (
652
+ <button className="
653
+ group
654
+ w-full p-6
655
+ bg-white dark:bg-dark-bg-primary
656
+ border border-border-primary dark:border-dark-border-primary
657
+ rounded-xl
658
+ hover:border-primary-custom-600 dark:hover:border-blue-400
659
+ hover:shadow-lg
660
+ transition-all
661
+ text-left
662
+ ">
663
+ <div className="flex items-center justify-between">
664
+ <div>
665
+ <h3 className="
666
+ mb-2
667
+ text-content-primary dark:text-dark-content-primary
668
+ font-bold text-lg
669
+ group-hover:text-primary-custom-600 dark:group-hover:text-blue-400
670
+ ">
671
+ Ir a la Configuración
672
+ </h3>
673
+ <p className="
674
+ text-content-secondary dark:text-dark-content-secondary
675
+ text-sm
676
+ ">
677
+ Administra las preferencias del sistema
678
+ </p>
679
+ </div>
680
+
681
+ {/* Icono que se anima y cambia de color en hover */}
682
+ <ArrowRightIcon className="
683
+ w-6 h-6
684
+ text-content-tertiary dark:text-dark-content-tertiary
685
+ group-hover:text-primary-custom-600 dark:group-hover:text-blue-400
686
+ group-hover:translate-x-1
687
+ transition-all
688
+ " />
689
+ </div>
690
+ </button>
691
+ );
692
+ };
693
+ ```
694
+
695
+ ### Mejores Prácticas para Iconos en Dark Mode
696
+
697
+ #### Hacer
698
+
699
+ 1. **Usar tokens semánticos que se adaptan automáticamente**
700
+ ```tsx
701
+ // ✅ CORRECTO - Los tokens ya incluyen dark mode
702
+ <UserIcon className="text-content-primary dark:text-dark-content-primary" />
703
+ ```
704
+
705
+ 2. **Aprovechar currentColor para heredar colores del padre**
706
+ ```tsx
707
+ // ✅ CORRECTO - El icono hereda el color
708
+ <div className="text-primary-custom-600 dark:text-blue-400">
709
+ <EnvelopeIcon />
710
+ </div>
711
+ ```
712
+
713
+ 3. **Usar colores más brillantes en dark mode**
714
+ ```tsx
715
+ // ✅ CORRECTO - Ajustar intensidad para dark mode
716
+ <CheckIcon className="text-green-600 dark:text-green-400" />
717
+ ```
718
+
719
+ 4. **Combinar con estados hover y focus**
720
+ ```tsx
721
+ // CORRECTO - Estados completos
722
+ <button className="
723
+ text-gray-700 dark:text-gray-300
724
+ hover:text-blue-600 dark:hover:text-blue-400
725
+ ">
726
+ <PlusIcon />
727
+ </button>
728
+ ```
729
+
730
+ 5. **Reducir opacidad de iconos secundarios en dark mode**
731
+ ```tsx
732
+ // CORRECTO - Jerarquía visual
733
+ <QuestionMarkCircleIcon className="
734
+ text-content-secondary/70 dark:text-dark-content-secondary/60
735
+ " />
736
+ ```
737
+
738
+ #### ❌ Evitar
739
+
740
+ 1. **No usar el mismo color para light y dark mode**
741
+ ```tsx
742
+ // ❌ INCORRECTO - Sin dark variant
743
+ <UserIcon className="text-gray-900" />
744
+
745
+ // ✅ CORRECTO
746
+ <UserIcon className="text-gray-900 dark:text-gray-100" />
747
+ ```
748
+
749
+ 2. **No hardcodear colores sin considerar contraste**
750
+ ```tsx
751
+ // ❌ INCORRECTO - Pobre contraste en dark mode
752
+ <CheckIcon className="text-gray-300" />
753
+
754
+ // CORRECTO - Buen contraste en ambos modos
755
+ <CheckIcon className="text-green-600 dark:text-green-400" />
756
+ ```
757
+
758
+ 3. **No olvidar estados interactivos**
759
+ ```tsx
760
+ // ❌ INCORRECTO - Sin hover para dark mode
761
+ <button className="hover:text-blue-600">
762
+ <PlusIcon />
763
+ </button>
764
+
765
+ // CORRECTO
766
+ <button className="hover:text-blue-600 dark:hover:text-blue-400">
767
+ <PlusIcon />
768
+ </button>
769
+ ```
770
+
771
+ 4. **No usar colores muy oscuros en dark mode**
772
+ ```tsx
773
+ // ❌ INCORRECTO - Invisible en fondo oscuro
774
+ <XIcon className="text-gray-900 dark:text-gray-900" />
775
+
776
+ // CORRECTO - Visible en ambos modos
777
+ <XIcon className="text-gray-900 dark:text-gray-100" />
778
+ ```
779
+
780
+ ### Guía Rápida: Colores de Iconos por Contexto
781
+
782
+ | Contexto | Light Mode | Dark Mode | Ejemplo |
783
+ |----------|------------|-----------|---------|
784
+ | **Icono Principal** | `text-content-primary` | `dark:text-dark-content-primary` | Iconos en botones principales |
785
+ | **Icono Secundario** | `text-content-secondary` | `dark:text-dark-content-secondary` | Iconos decorativos |
786
+ | **Icono Terciario** | `text-content-tertiary` | `dark:text-dark-content-tertiary` | Iconos de ayuda |
787
+ | **Icono Interactivo** | `text-gray-700 hover:text-blue-600` | `dark:text-gray-300 dark:hover:text-blue-400` | Botones icon-only |
788
+ | **Icono de Éxito** | `text-green-600` | `dark:text-green-400` | Check, confirmación |
789
+ | **Icono de Error** | `text-error-content` | `dark:text-red-400` | X, advertencias |
790
+ | **Icono de Info** | `text-blue-600` | `dark:text-blue-400` | Información, ayuda |
791
+ | **Icono Deshabilitado** | `text-content-tertiary opacity-50` | `dark:text-dark-content-tertiary opacity-50` | Elementos inactivos |
792
+
793
+ ### Recursos Adicionales
794
+
795
+ Para más información sobre el modo oscuro:
796
+ - Ver `docs/dark-mode-guide.md` - Guía completa de Dark Mode en Tailwind CSS
797
+ - Ver `docs/colors.md` - Sistema de colores completo con tokens dark mode
798
+ - [Documentación oficial de Tailwind Dark Mode](https://tailwindcss.com/docs/dark-mode)
799
+
800
+ ---
801
+
802
+ ## Accesibilidad
803
+
804
+ ### Consideraciones de Accesibilidad
805
+
806
+ #### 1. Iconos Decorativos
807
+
808
+ Cuando el icono acompaña texto visible, es decorativo:
809
+
810
+ ```tsx
811
+ // CORRECTO: El texto describe la acción
812
+ <Button leftIcon={<PlusIcon />}>
813
+ Crear Usuario
814
+ </Button>
815
+ // No se necesita aria-label adicional
816
+ ```
817
+
818
+ #### 2. Iconos Funcionales (Icon-Only)
819
+
820
+ Cuando el icono es el único elemento visual:
821
+
822
+ ```tsx
823
+ // ✅ CORRECTO: Usar aria-label
824
+ <Button
825
+ iconOnly
826
+ leftIcon={<PlusIcon />}
827
+ ariaLabel="Añadir nuevo elemento"
828
+ />
829
+
830
+ // ❌ INCORRECTO: Sin aria-label
831
+ <Button iconOnly leftIcon={<PlusIcon />} />
832
+ // Los lectores de pantalla no sabrán la función
833
+ ```
834
+
835
+ #### 3. Iconos con Significado
836
+
837
+ En contextos donde el icono comunica información:
838
+
839
+ ```tsx
840
+ // CORRECTO: Añadir rol y aria-label
841
+ <span role="img" aria-label="Estado: Exitoso">
842
+ <CheckIcon className="text-green-600" />
843
+ </span>
844
+
845
+ // ✅ CORRECTO: Con texto de soporte visible
846
+ <div className="flex items-center gap-2">
847
+ <ExclamationCircleIcon className="text-error-content" />
848
+ <span>Error en la validación</span>
849
+ </div>
850
+ ```
851
+
852
+ #### 4. Tooltips para Contexto Adicional
853
+
854
+ ```tsx
855
+ // ✅ MEJOR PRÁCTICA: Icono + Tooltip
856
+ <button
857
+ className="p-2"
858
+ aria-label="Ayuda"
859
+ title="Obtener ayuda sobre este campo"
860
+ >
861
+ <QuestionMarkCircleIcon />
862
+ </button>
863
+ ```
864
+
865
+ ### Directrices WCAG 2.1
866
+
867
+ - **Nivel A**: Todos los iconos funcionales deben tener texto alternativo
868
+ - **Nivel AA**: Contraste mínimo 3:1 para iconos (se cumple con currentColor)
869
+ - **Nivel AAA**: Proveer texto descriptivo adicional cuando sea posible
870
+
871
+ ---
872
+
873
+ ## Ejemplos de Código
874
+
875
+ ### Ejemplo 1: Toolbar de Acciones
876
+
877
+ ```tsx
878
+ import { Button } from '@/components/Button';
879
+ import { PlusIcon, CheckIcon, XIcon } from '@/components/Button/icons';
880
+
881
+ export const ActionToolbar = () => {
882
+ return (
883
+ <div className="flex gap-2 p-4 bg-bg-primary border-b border-border-primary">
884
+ {/* Botones icon-only con tooltips */}
885
+ <Button
886
+ iconOnly
887
+ size="base"
888
+ type="default"
889
+ leftIcon={<PlusIcon />}
890
+ ariaLabel="Añadir nuevo registro"
891
+ title="Añadir nuevo registro"
892
+ />
893
+
894
+ <Button
895
+ iconOnly
896
+ size="base"
897
+ type="outline"
898
+ leftIcon={<CheckIcon />}
899
+ ariaLabel="Guardar cambios"
900
+ title="Guardar cambios"
901
+ />
902
+
903
+ <Button
904
+ iconOnly
905
+ size="base"
906
+ type="plain"
907
+ leftIcon={<XIcon />}
908
+ ariaLabel="Cancelar operación"
909
+ title="Cancelar operación"
910
+ />
911
+ </div>
912
+ );
913
+ };
914
+ ```
915
+
916
+ ### Ejemplo 2: Formulario de Login
917
+
918
+ ```tsx
919
+ import { Input } from '@/components/Input';
920
+ import { Button } from '@/components/Button';
921
+ import {
922
+ UserIcon,
923
+ LockClosedIcon,
924
+ EyeIcon,
925
+ EyeSlashIcon
926
+ } from '@/components/Input/icons';
927
+ import { ArrowRightIcon } from '@/components/Button/icons';
928
+ import { useState } from 'react';
929
+
930
+ export const LoginForm = () => {
931
+ const [showPassword, setShowPassword] = useState(false);
932
+
933
+ return (
934
+ <form className="space-y-4 w-full max-w-sm">
935
+ {/* Usuario */}
936
+ <Input
937
+ label="Usuario"
938
+ name="username"
939
+ leftIcon={<UserIcon />}
940
+ placeholder="Ingrese su usuario"
941
+ required
942
+ />
943
+
944
+ {/* Contraseña con toggle */}
945
+ <Input
946
+ label="Contraseña"
947
+ name="password"
948
+ type={showPassword ? 'text' : 'password'}
949
+ leftIcon={<LockClosedIcon />}
950
+ rightIcon={
951
+ <button
952
+ type="button"
953
+ onClick={() => setShowPassword(!showPassword)}
954
+ className="cursor-pointer"
955
+ aria-label={showPassword ? 'Ocultar contraseña' : 'Mostrar contraseña'}
956
+ >
957
+ {showPassword ? <EyeSlashIcon /> : <EyeIcon />}
958
+ </button>
959
+ }
960
+ placeholder="Ingrese su contraseña"
961
+ required
962
+ />
963
+
964
+ {/* Submit */}
965
+ <Button
966
+ type="default"
967
+ size="base"
968
+ fullWidth
969
+ rightIcon={<ArrowRightIcon />}
970
+ htmlType="submit"
971
+ >
972
+ Iniciar Sesión
973
+ </Button>
974
+ </form>
975
+ );
976
+ };
977
+ ```
978
+
979
+ ### Ejemplo 3: Search Input con Estados
980
+
981
+ ```tsx
982
+ import { Input } from '@/components/Input';
983
+ import {
984
+ MagnifyingGlassIcon,
985
+ XMarkIcon,
986
+ CheckIcon,
987
+ ExclamationCircleIcon
988
+ } from '@/components/Input/icons';
989
+ import { useState } from 'react';
990
+
991
+ export const SearchInput = () => {
992
+ const [query, setQuery] = useState('');
993
+ const [status, setStatus] = useState<'idle' | 'searching' | 'success' | 'error'>('idle');
994
+
995
+ const getStatusIcon = () => {
996
+ switch (status) {
997
+ case 'success':
998
+ return <CheckIcon className="text-green-600" />;
999
+ case 'error':
1000
+ return <ExclamationCircleIcon className="text-error-content" />;
1001
+ default:
1002
+ return null;
1003
+ }
1004
+ };
1005
+
1006
+ return (
1007
+ <div className="w-full max-w-md">
1008
+ <Input
1009
+ label="Búsqueda"
1010
+ value={query}
1011
+ onChange={(e) => setQuery(e.target.value)}
1012
+ leftIcon={<MagnifyingGlassIcon />}
1013
+ rightIcon={
1014
+ query ? (
1015
+ <button
1016
+ type="button"
1017
+ onClick={() => setQuery('')}
1018
+ aria-label="Limpiar búsqueda"
1019
+ className="cursor-pointer hover:text-primary-custom-600"
1020
+ >
1021
+ <XMarkIcon />
1022
+ </button>
1023
+ ) : (
1024
+ getStatusIcon()
1025
+ )
1026
+ }
1027
+ placeholder="Buscar..."
1028
+ helperText={
1029
+ status === 'error' ? 'No se encontraron resultados' : undefined
1030
+ }
1031
+ error={status === 'error'}
1032
+ />
1033
+ </div>
1034
+ );
1035
+ };
1036
+ ```
1037
+
1038
+ ---
1039
+
1040
+ ## Mejores Prácticas
1041
+
1042
+ ### ✅ Hacer
1043
+
1044
+ 1. **Usar iconos semánticamente apropiados**
1045
+ ```tsx
1046
+ // CORRECTO
1047
+ <Button leftIcon={<PlusIcon />}>Añadir</Button>
1048
+ <Button leftIcon={<CheckIcon />}>Guardar</Button>
1049
+ ```
1050
+
1051
+ 2. **Mantener el tamaño de 16px en la mayoría de casos**
1052
+ ```tsx
1053
+ // ✅ CORRECTO - tamaño por defecto
1054
+ <UserIcon className="w-4 h-4" />
1055
+ ```
1056
+
1057
+ 3. **Usar currentColor para heredar el color del contexto**
1058
+ ```tsx
1059
+ // ✅ CORRECTO - el icono hereda el color
1060
+ <div className="text-primary-custom-600">
1061
+ <EnvelopeIcon />
1062
+ </div>
1063
+ ```
1064
+
1065
+ 4. **Proveer aria-label en botones icon-only**
1066
+ ```tsx
1067
+ // CORRECTO
1068
+ <Button iconOnly leftIcon={<XIcon />} ariaLabel="Cerrar" />
1069
+ ```
1070
+
1071
+ 5. **Agrupar iconos relacionados en el mismo archivo**
1072
+ ```tsx
1073
+ // ✅ CORRECTO - iconos de un componente juntos
1074
+ // src/components/Button/icons.tsx
1075
+ ```
1076
+
1077
+ ### ❌ Evitar
1078
+
1079
+ 1. **No mezclar diferentes estilos de iconos**
1080
+ ```tsx
1081
+ // ❌ INCORRECTO - mezclar Heroicons con otros
1082
+ <PlusIcon /> {/* Heroicons Micro */}
1083
+ <SomeOtherIcon /> {/* Otra librería */}
1084
+ ```
1085
+
1086
+ 2. **No usar tamaños inconsistentes sin razón**
1087
+ ```tsx
1088
+ // INCORRECTO - tamaños arbitrarios
1089
+ <UserIcon className="w-7 h-7" />
1090
+ <EnvelopeIcon className="w-3 h-3" />
1091
+ ```
1092
+
1093
+ 3. **No hardcodear colores directamente en el SVG**
1094
+ ```tsx
1095
+ // ❌ INCORRECTO - hardcodear fill
1096
+ <svg fill="#0e79fd">...</svg>
1097
+
1098
+ // CORRECTO - usar currentColor
1099
+ <svg fill="currentColor">...</svg>
1100
+ ```
1101
+
1102
+ 4. **No omitir aria-label en iconos funcionales**
1103
+ ```tsx
1104
+ // ❌ INCORRECTO
1105
+ <button><XIcon /></button>
1106
+
1107
+ // CORRECTO
1108
+ <button aria-label="Cerrar"><XIcon /></button>
1109
+ ```
1110
+
1111
+ 5. **No usar iconos como única forma de comunicación**
1112
+ ```tsx
1113
+ // INCORRECTO - solo icono sin contexto
1114
+ <div><ExclamationCircleIcon /></div>
1115
+
1116
+ // CORRECTO - icono + texto
1117
+ <div className="flex gap-2">
1118
+ <ExclamationCircleIcon />
1119
+ <span>Error: Campo requerido</span>
1120
+ </div>
1121
+ ```
1122
+
1123
+ ### Rendimiento
1124
+
1125
+ - **✅ SVG Inline**: Mejor para iconos que se usan frecuentemente
1126
+ - **✅ Tree-shaking**: Importar solo los iconos necesarios
1127
+ - **✅ Evitar re-renders**: Los iconos son componentes puros
1128
+ - **✅ Memoización**: React.memo si se pasan como props frecuentemente
1129
+
1130
+ ```tsx
1131
+ // ✅ CORRECTO - memoizar icono si se pasa como prop
1132
+ const MemoizedIcon = React.memo(PlusIcon);
1133
+
1134
+ // En componente padre
1135
+ <Button leftIcon={<MemoizedIcon />}>Añadir</Button>
1136
+ ```
1137
+
1138
+ ---
1139
+
1140
+ ## Referencia Rápida
1141
+
1142
+ ### Cheat Sheet: Importaciones
1143
+
1144
+ ```typescript
1145
+ // Iconos de Button
1146
+ import {
1147
+ PlusIcon, // Añadir/Crear
1148
+ ChevronDownIcon, // Dropdown
1149
+ ArrowRightIcon, // Navegación
1150
+ CheckIcon, // Confirmar
1151
+ XIcon // Cerrar/Cancelar
1152
+ } from '@/components/Button/icons';
1153
+
1154
+ // Iconos de Input
1155
+ import {
1156
+ EnvelopeIcon, // Email
1157
+ QuestionMarkCircleIcon, // Ayuda
1158
+ UserIcon, // Usuario
1159
+ LockClosedIcon, // Seguridad
1160
+ MagnifyingGlassIcon, // Búsqueda
1161
+ EyeIcon, // Ver password
1162
+ EyeSlashIcon, // Ocultar password
1163
+ XMarkIcon, // Limpiar
1164
+ CheckIcon, // Éxito
1165
+ ExclamationCircleIcon // Error
1166
+ } from '@/components/Input/icons';
1167
+ ```
1168
+
1169
+ ### Cheat Sheet: Tamaños Comunes
1170
+
1171
+ | Clase Tailwind | Tamaño | Uso |
1172
+ |----------------|--------|-----|
1173
+ | `w-4 h-4` | 16px | **Default** - Botones, inputs |
1174
+ | `w-5 h-5` | 20px | Iconos destacados |
1175
+ | `w-6 h-6` | 24px | Headers, títulos |
1176
+ | `w-8 h-8` | 32px | Iconos grandes, heros |
1177
+
1178
+ ### Cheat Sheet: Colores Comunes
1179
+
1180
+ ```tsx
1181
+ // Primary
1182
+ <Icon className="text-primary-custom-600" />
1183
+
1184
+ // Éxito (Verde)
1185
+ <CheckIcon className="text-green-600" />
1186
+
1187
+ // Error (Rojo)
1188
+ <ExclamationCircleIcon className="text-error-content" />
1189
+
1190
+ // Secundario (Gris)
1191
+ <Icon className="text-content-secondary" />
1192
+
1193
+ // Dark Mode (automático)
1194
+ <Icon className="text-content-primary dark:text-dark-content-primary" />
1195
+ ```
1196
+
1197
+ ### Cheat Sheet: Patrones de Uso
1198
+
1199
+ ```tsx
1200
+ // 1. Icon-only Button
1201
+ <Button iconOnly leftIcon={<PlusIcon />} ariaLabel="Añadir" />
1202
+
1203
+ // 2. Button con texto e icono
1204
+ <Button leftIcon={<CheckIcon />}>Guardar</Button>
1205
+
1206
+ // 3. Input con icono
1207
+ <Input leftIcon={<UserIcon />} placeholder="Usuario" />
1208
+
1209
+ // 4. Toggle icon
1210
+ {visible ? <EyeIcon /> : <EyeSlashIcon />}
1211
+
1212
+ // 5. Status icon
1213
+ {status === 'success' ? <CheckIcon /> : <ExclamationCircleIcon />}
1214
+ ```
1215
+
1216
+ ---
1217
+
1218
+ ## Añadir Nuevos Iconos
1219
+
1220
+ ### Proceso para Agregar un Icono
1221
+
1222
+ 1. **Obtener el SVG de Heroicons Micro**
1223
+ - Visitar: https://heroicons.com
1224
+ - Seleccionar versión "Micro" (16px)
1225
+ - Copiar el código SVG
1226
+
1227
+ 2. **Crear el Componente React**
1228
+ ```tsx
1229
+ // En el archivo icons.tsx correspondiente
1230
+ export const NewIcon: React.FC<IconProps> = ({ className = '' }) => (
1231
+ <svg
1232
+ xmlns="http://www.w3.org/2000/svg"
1233
+ viewBox="0 0 16 16"
1234
+ fill="currentColor"
1235
+ className={className}
1236
+ >
1237
+ {/* Pegar path(s) del SVG */}
1238
+ <path d="..." />
1239
+ </svg>
1240
+ );
1241
+ ```
1242
+
1243
+ 3. **Documentar el Nuevo Icono**
1244
+ - Añadir a la tabla de catálogo
1245
+ - Incluir ejemplo de uso
1246
+ - Especificar contexto apropiado
1247
+
1248
+ 4. **Testing**
1249
+ - Verificar en modo claro y oscuro
1250
+ - Probar diferentes tamaños
1251
+ - Validar accesibilidad
1252
+
1253
+ ### Decisiones de Organización
1254
+
1255
+ - **¿Dónde colocar el nuevo icono?**
1256
+ - ¿Se usa en Button? → `src/components/Button/icons.tsx`
1257
+ - ¿Se usa en Input? `src/components/Input/icons.tsx`
1258
+ - ¿Se usa en múltiples componentes? → Crear `src/shared/icons.tsx`
1259
+
1260
+ ---
1261
+
1262
+ ## Recursos Adicionales
1263
+
1264
+ ### Enlaces Útiles
1265
+
1266
+ - **Heroicons**: https://heroicons.com
1267
+ - **Documentación Heroicons**: https://github.com/tailwindlabs/heroicons
1268
+ - **WCAG Guidelines**: https://www.w3.org/WAI/WCAG21/quickref/
1269
+ - **SVG Accessibility**: https://css-tricks.com/accessible-svgs/
1270
+
1271
+ ### Archivos Relacionados
1272
+
1273
+ - `src/components/Button/icons.tsx` - Iconos de botones
1274
+ - `src/components/Input/icons.tsx` - Iconos de inputs
1275
+ - `src/components/Button/Button.tsx` - Implementación de iconos en Button
1276
+ - `docs/colors.md` - Sistema de colores (para colores de iconos)
1277
+ - `docs/typography.md` - Sistema tipográfico
1278
+
1279
+ ---
1280
+
1281
+ **Última actualización**: 2025-11-11
1282
+ **Versión**: 1.0.0
1283
+ **Mantenedor**: Siesa UI Kit Team