siesa-ui-kit 1.0.2 → 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +115 -115
- package/bin/install.cjs +502 -502
- package/bin/prepare-publish.cjs +28 -28
- package/bin/restore-folders.cjs +28 -28
- package/claude/agents/siesa-ui-kit-specialist.md +2445 -0
- package/claude/prompts/component-template.md +121 -0
- package/claude/prompts/siesa-ui-kit.md +28 -0
- package/claude/settings.local.json +67 -2
- package/dist/components/Button/icons.d.ts +6 -5
- package/dist/components/Button/icons.d.ts.map +1 -1
- package/dist/components/DropdownItemCollapsible/DropdownItemCollapsible.d.ts.map +1 -1
- package/dist/components/DropdownItemCollapsible/DropdownItemCollapsible.types.d.ts +21 -0
- package/dist/components/DropdownItemCollapsible/DropdownItemCollapsible.types.d.ts.map +1 -1
- package/dist/components/NavigationRailCommercial/NavigationRailCommercial.d.ts +122 -0
- package/dist/components/NavigationRailCommercial/NavigationRailCommercial.d.ts.map +1 -0
- package/dist/components/NavigationRailCommercial/NavigationRailCommercial.types.d.ts +139 -0
- package/dist/components/NavigationRailCommercial/NavigationRailCommercial.types.d.ts.map +1 -0
- package/dist/components/NavigationRailCommercial/icons.d.ts +33 -0
- package/dist/components/NavigationRailCommercial/icons.d.ts.map +1 -0
- package/dist/components/NavigationRailCommercial/index.d.ts +4 -0
- package/dist/components/NavigationRailCommercial/index.d.ts.map +1 -0
- package/dist/components/NavigationRailItem/NavigationRailItem.d.ts.map +1 -1
- package/dist/components/NavigationRailItem/NavigationRailItem.types.d.ts +7 -0
- package/dist/components/NavigationRailItem/NavigationRailItem.types.d.ts.map +1 -1
- package/dist/components/NavigationRailTypes/NavigationRailTypes.d.ts.map +1 -1
- package/dist/components/NavigationRailTypes/NavigationRailTypes.types.d.ts +41 -0
- package/dist/components/NavigationRailTypes/NavigationRailTypes.types.d.ts.map +1 -1
- package/dist/components/NavigationRailTypes/icons.d.ts +15 -29
- package/dist/components/NavigationRailTypes/icons.d.ts.map +1 -1
- package/dist/components/Select/Select.d.ts.map +1 -1
- package/dist/components/Select/icons.d.ts +6 -2
- package/dist/components/Select/icons.d.ts.map +1 -1
- package/dist/index.d.ts +32 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/siesa-ui-kit.cjs +404 -190
- package/dist/siesa-ui-kit.cjs.map +1 -1
- package/dist/siesa-ui-kit.mjs +6590 -1506
- package/dist/siesa-ui-kit.mjs.map +1 -1
- package/dist/views/LayoutCommercial/LayoutCommercial.d.ts +48 -0
- package/dist/views/LayoutCommercial/LayoutCommercial.d.ts.map +1 -0
- package/dist/views/LayoutCommercial/LayoutCommercial.types.d.ts +49 -0
- package/dist/views/LayoutCommercial/LayoutCommercial.types.d.ts.map +1 -0
- package/dist/views/LayoutCommercial/index.d.ts +3 -0
- package/dist/views/LayoutCommercial/index.d.ts.map +1 -0
- package/docs/icons.md +12 -31
- package/package.json +111 -110
- package/src/components/Avatar/Avatar.stories.tsx +494 -494
- package/src/components/Button/Button.stories.tsx +950 -950
- package/src/components/Button/Button.tsx +337 -337
- package/src/components/Button/Button.types.ts +180 -180
- package/src/components/Button/icons.tsx +23 -62
- package/src/components/DescriptionList/DescriptionList.stories.tsx +250 -250
- package/src/components/Divider/Divider.stories.tsx +263 -263
- package/src/components/DropdownItemCollapsible/DropdownItemCollapsible.stories.tsx +317 -317
- package/src/components/DropdownItemCollapsible/DropdownItemCollapsible.tsx +307 -287
- package/src/components/DropdownItemCollapsible/DropdownItemCollapsible.types.ts +136 -111
- package/src/components/DropdownItemCollapsible/README.md +264 -264
- package/src/components/DropdownItemCollapsible/icons.tsx +57 -57
- package/src/components/DropdownItemCollapsible/index.ts +12 -12
- package/src/components/DropdownItemHeading/DropdownItemHeading.stories.tsx +386 -386
- package/src/components/DropdownItemHeading/DropdownItemHeading.tsx +216 -216
- package/src/components/DropdownItemHeading/DropdownItemHeading.types.ts +93 -93
- package/src/components/DropdownItemHeading/README.md +573 -573
- package/src/components/DropdownItemHeading/icons.tsx +125 -125
- package/src/components/DropdownItemHeading/index.ts +3 -3
- package/src/components/Input/Input.stories.tsx +583 -583
- package/src/components/LoginView/LoginView.stories.tsx +148 -148
- package/src/components/LoginView/LoginView.tsx +426 -426
- package/src/components/LoginView/LoginView.types.ts +52 -52
- package/src/components/LoginView/README.md +396 -396
- package/src/components/LoginView/icons.tsx +85 -85
- package/src/components/LoginView/index.ts +3 -3
- package/src/components/Navbar/Navbar.stories.tsx +810 -810
- package/src/components/Navbar/Navbar.tsx +755 -755
- package/src/components/Navbar/Navbar.types.ts +219 -219
- package/src/components/Navbar/README.md +279 -279
- package/src/components/Navbar/index.ts +8 -8
- package/src/components/NavigationRailCommercial/NavigationRailCommercial.stories.tsx +464 -0
- package/src/components/NavigationRailCommercial/NavigationRailCommercial.tsx +301 -0
- package/src/components/NavigationRailCommercial/NavigationRailCommercial.types.ts +162 -0
- package/src/components/NavigationRailCommercial/README.md +251 -0
- package/src/components/NavigationRailCommercial/icons.tsx +54 -0
- package/src/components/NavigationRailCommercial/index.ts +6 -0
- package/src/components/NavigationRailItem/NavigationRailItem.stories.tsx +667 -667
- package/src/components/NavigationRailItem/NavigationRailItem.tsx +314 -313
- package/src/components/NavigationRailItem/NavigationRailItem.types.ts +175 -167
- package/src/components/NavigationRailItem/README.md +476 -476
- package/src/components/NavigationRailItem/index.ts +2 -2
- package/src/components/NavigationRailPanel/NavigationRailPanel.stories.tsx +462 -462
- package/src/components/NavigationRailPanel/NavigationRailPanel.tsx +332 -332
- package/src/components/NavigationRailPanel/NavigationRailPanel.types.ts +178 -178
- package/src/components/NavigationRailPanel/README.md +461 -461
- package/src/components/NavigationRailPanel/index.ts +6 -6
- package/src/components/NavigationRailTypes/NavigationRailTypes.stories.tsx +682 -528
- package/src/components/NavigationRailTypes/NavigationRailTypes.tsx +363 -378
- package/src/components/NavigationRailTypes/NavigationRailTypes.types.ts +178 -130
- package/src/components/NavigationRailTypes/README.md +573 -573
- package/src/components/NavigationRailTypes/icons.tsx +76 -141
- package/src/components/NavigationRailTypes/index.ts +7 -7
- package/src/components/Notification/Notification.stories.tsx +513 -513
- package/src/components/Notification/Notification.tsx +145 -145
- package/src/components/Notification/Notification.types.ts +142 -142
- package/src/components/Notification/README.md +409 -409
- package/src/components/POSConvention/POSConvention.stories.tsx +235 -235
- package/src/components/POSConvention/POSConvention.tsx +129 -129
- package/src/components/POSConvention/POSConvention.types.ts +38 -38
- package/src/components/POSConvention/README.md +123 -123
- package/src/components/POSConvention/icons.tsx +45 -45
- package/src/components/POSConvention/index.ts +3 -3
- package/src/components/POSLocationButton/POSLocationButton.stories.tsx +531 -531
- package/src/components/POSLocationButton/POSLocationButton.tsx +247 -247
- package/src/components/POSLocationButton/POSLocationButton.types.ts +87 -87
- package/src/components/POSLocationButton/README.md +253 -253
- package/src/components/POSLocationButton/icons.tsx +120 -120
- package/src/components/POSLocationButton/index.ts +14 -14
- package/src/components/POSNumberButton/POSNumberButton.stories.tsx +415 -415
- package/src/components/POSNumberButton/POSNumberButton.tsx +179 -179
- package/src/components/POSNumberButton/POSNumberButton.types.ts +51 -51
- package/src/components/POSNumberButton/README.md +321 -321
- package/src/components/POSNumberButton/index.ts +3 -3
- package/src/components/POSProductButton/POSProductButton.stories.tsx +318 -318
- package/src/components/POSProductCard/POSProductCard.stories.tsx +642 -642
- package/src/components/POSProductCard/POSProductCard.tsx +208 -208
- package/src/components/POSProductCard/POSProductCard.types.ts +76 -76
- package/src/components/POSProductCard/README.md +179 -179
- package/src/components/POSProductCard/icons.tsx +26 -26
- package/src/components/POSProductCard/index.ts +2 -2
- package/src/components/POSProductSidebarItems/POSProductSidebarItems.stories.tsx +753 -753
- package/src/components/POSProductSidebarItems/POSProductSidebarItems.tsx +332 -332
- package/src/components/POSProductSidebarItems/POSProductSidebarItems.types.ts +119 -119
- package/src/components/POSProductSidebarItems/README.md +198 -198
- package/src/components/POSProductSidebarItems/icons.tsx +21 -21
- package/src/components/POSProductSidebarItems/index.ts +3 -3
- package/src/components/POSTable/POSTable.stories.tsx +737 -737
- package/src/components/POSTable/POSTable.tsx +401 -401
- package/src/components/POSTable/README.md +286 -286
- package/src/components/Quantity/Quantity.stories.tsx +457 -457
- package/src/components/Radio/Radio.stories.tsx +523 -523
- package/src/components/Radio/Radio.tsx +1 -1
- package/src/components/Select/Select.stories.tsx +32 -0
- package/src/components/Select/Select.tsx +457 -454
- package/src/components/Select/icons.tsx +16 -41
- package/src/components/SignUpView/SignUpView.stories.tsx +129 -129
- package/src/components/SignUpView/SignUpView.tsx +503 -503
- package/src/components/SignUpView/SignUpView.types.ts +58 -58
- package/src/components/SignUpView/icons.tsx +71 -71
- package/src/components/SignUpView/index.ts +3 -3
- package/src/components/Switch/README.md +112 -112
- package/src/components/Switch/Switch.stories.tsx +550 -550
- package/src/components/Switch/Switch.tsx +246 -246
- package/src/components/Switch/Switch.types.ts +67 -67
- package/src/components/Table/Table.stories.tsx +805 -805
- package/src/components/Tabs/README.md +201 -201
- package/src/components/Tabs/Tabs.stories.tsx +580 -580
- package/src/components/Tabs/Tabs.tsx +356 -356
- package/src/components/Tabs/Tabs.types.ts +127 -127
- package/src/components/Tabs/icons.tsx +129 -129
- package/src/components/Tabs/index.ts +11 -11
- package/src/components/Textarea/Textarea.stories.tsx +535 -535
- package/src/index.ts +133 -102
- package/src/views/LayoutCommercial/LayoutCommercial.stories.tsx +374 -0
- package/src/views/LayoutCommercial/LayoutCommercial.tsx +125 -0
- package/src/views/LayoutCommercial/LayoutCommercial.types.ts +54 -0
- package/src/views/LayoutCommercial/README.md +286 -0
- package/src/views/LayoutCommercial/index.ts +2 -0
- package/src/views/ListView/ListView.stories.tsx +329 -329
- package/src/views/ListView/ListView.tsx +570 -570
- package/src/views/ListView/ListView.types.ts +211 -211
- package/src/views/ListView/icons.tsx +282 -282
- package/src/views/ListView/index.ts +11 -11
- package/src/views/LoginView/LoginView.tsx +426 -426
- package/src/views/ProductsView/ProductsView.stories.tsx +344 -344
- package/src/views/ProductsView/ProductsView.tsx +480 -480
- package/src/views/ProductsView/ProductsView.types.ts +238 -238
- package/src/views/ProductsView/README.md +312 -312
- package/src/views/ProductsView/icons.tsx +38 -38
- package/src/views/ProductsView/index.ts +8 -8
- package/src/views/RecoverPasswordView/RecoverPasswordView.tsx +376 -376
- package/src/views/SignUpView/SignUpView.tsx +503 -503
- package/src/views/TableLayoutView/README.md +268 -268
- package/src/views/TableLayoutView/TableLayoutView.stories.tsx +235 -235
- package/src/views/TableLayoutView/TableLayoutView.tsx +461 -461
- package/src/views/TableLayoutView/TableLayoutView.types.ts +209 -209
- package/src/views/TableLayoutView/icons.tsx +113 -113
- package/src/views/TableLayoutView/index.ts +6 -6
- package/storybook/main.ts +19 -19
- package/storybook/preview.tsx +84 -84
- package/storybook/vitest.setup.ts +6 -6
- package/tailwind.config.js +128 -128
|
@@ -1,313 +1,314 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import type { NavigationRailItemProps } from './NavigationRailItem.types';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* NavigationRailItem - Componente independiente para items de NavigationRail
|
|
6
|
-
*
|
|
7
|
-
* Item individual de navegación vertical (rail) para aplicaciones. Proporciona
|
|
8
|
-
* un punto de acceso a destinos mediante un icono, label opcional y badges.
|
|
9
|
-
*
|
|
10
|
-
* **Características principales:**
|
|
11
|
-
* - Ancho fijo de 56px según Figma
|
|
12
|
-
* - Estados completos: normal, hover, selected, focus, disabled
|
|
13
|
-
* - Badges de notificación con contador opcional
|
|
14
|
-
* - Tipografía Label XXSmall (10px Bold) según sistema de diseño
|
|
15
|
-
* - Dark mode completo con estrategia 'class'
|
|
16
|
-
* - Focus rings adaptativos para accesibilidad
|
|
17
|
-
* - Soporte para iconos 16x16px
|
|
18
|
-
*
|
|
19
|
-
* **Especificaciones de Figma (node 4294-22931):**
|
|
20
|
-
* - Ancho: 56px (w-14)
|
|
21
|
-
* - Icon container: 32px altura, px-4 py-1, rounded-full
|
|
22
|
-
* - Label: 10px Bold, leading 12px (Label XXSmall)
|
|
23
|
-
* - Gap: 4px (gap-1)
|
|
24
|
-
* - Badge: 13x13px, posición absolute
|
|
25
|
-
*
|
|
26
|
-
* **Estados visuales (según Figma):**
|
|
27
|
-
* - **Enabled**: Icon transparent, label text-content-primary
|
|
28
|
-
* - **Hover**: Icon container bg-primary-custom-100 (#dbeefe), icon text-primary-custom-600
|
|
29
|
-
* - **Selected**: Icon container bg-primary-custom-100 con overlay, icon text-primary-custom-600
|
|
30
|
-
* - **Focus**: Focus ring 2px (#60b6fa) con offset 2px (#dbeefe), sombras combinadas
|
|
31
|
-
* - **Disabled**: Opacity 55%, no interactivo
|
|
32
|
-
*
|
|
33
|
-
* **Dark Mode:**
|
|
34
|
-
* - Background: dark-bg-primary
|
|
35
|
-
* - Hover icon container: dark-bg-primary/20
|
|
36
|
-
* - Selected icon container: dark-primary-custom-600/30
|
|
37
|
-
* - Icon colors: dark-content-primary, dark-white on selected
|
|
38
|
-
* - Focus ring: dark-border-custom
|
|
39
|
-
*
|
|
40
|
-
* **Mejores prácticas implementadas:**
|
|
41
|
-
* - Orden de modificadores: {responsive}:{dark}:{state}:{utility}
|
|
42
|
-
* - Tokens de color consistentes con documentación
|
|
43
|
-
* - Accesibilidad ARIA completa
|
|
44
|
-
* - Focus visible para keyboard navigation
|
|
45
|
-
* - Badge positioning absoluto para no afectar layout
|
|
46
|
-
*
|
|
47
|
-
* @see docs/colors.md - Sistema de colores (primary-custom, dark-*, content-*)
|
|
48
|
-
* @see docs/typography.md - Tipografía (Label XXSmall)
|
|
49
|
-
* @see docs/spacing.md - Sistema de espaciado
|
|
50
|
-
* @see docs/shadows.md - Sistema de sombras y focus rings
|
|
51
|
-
* @see https://www.figma.com/design/5XNqf2YTxvwemxwo1LMQ6j/Siesa-UI-Kit?node-id=4294-22931
|
|
52
|
-
*
|
|
53
|
-
* @example
|
|
54
|
-
* ```tsx
|
|
55
|
-
* // Item básico
|
|
56
|
-
* <NavigationRailItem
|
|
57
|
-
* id="home"
|
|
58
|
-
* icon={<HomeIcon />}
|
|
59
|
-
* label="Inicio"
|
|
60
|
-
* selected={true}
|
|
61
|
-
* onClick={() => navigate('/')}
|
|
62
|
-
* />
|
|
63
|
-
*
|
|
64
|
-
* // Con badge de notificación
|
|
65
|
-
* <NavigationRailItem
|
|
66
|
-
* id="notifications"
|
|
67
|
-
* icon={<BellIcon />}
|
|
68
|
-
* label="Notificaciones"
|
|
69
|
-
* badgeCount={5}
|
|
70
|
-
* onClick={() => navigate('/notifications')}
|
|
71
|
-
* />
|
|
72
|
-
*
|
|
73
|
-
* // Item deshabilitado
|
|
74
|
-
* <NavigationRailItem
|
|
75
|
-
* id="premium"
|
|
76
|
-
* icon={<StarIcon />}
|
|
77
|
-
* label="Premium"
|
|
78
|
-
* disabled={true}
|
|
79
|
-
* />
|
|
80
|
-
*
|
|
81
|
-
* // Solo icono (sin label)
|
|
82
|
-
* <NavigationRailItem
|
|
83
|
-
* id="home"
|
|
84
|
-
* icon={<HomeIcon />}
|
|
85
|
-
* label="Inicio"
|
|
86
|
-
* showLabelText={false}
|
|
87
|
-
* />
|
|
88
|
-
* ```
|
|
89
|
-
*/
|
|
90
|
-
export const NavigationRailItem: React.FC<NavigationRailItemProps> = ({
|
|
91
|
-
icon,
|
|
92
|
-
label,
|
|
93
|
-
selected = false,
|
|
94
|
-
disabled = false,
|
|
95
|
-
badge = false,
|
|
96
|
-
badgeCount,
|
|
97
|
-
onClick,
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
//
|
|
106
|
-
//
|
|
107
|
-
//
|
|
108
|
-
// -
|
|
109
|
-
// -
|
|
110
|
-
// -
|
|
111
|
-
// -
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
'flex
|
|
116
|
-
'
|
|
117
|
-
'
|
|
118
|
-
'
|
|
119
|
-
'
|
|
120
|
-
'
|
|
121
|
-
'
|
|
122
|
-
'
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
'
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
//
|
|
138
|
-
//
|
|
139
|
-
//
|
|
140
|
-
// -
|
|
141
|
-
// -
|
|
142
|
-
// -
|
|
143
|
-
//
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
'
|
|
147
|
-
'
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
'
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
//
|
|
165
|
-
//
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
'
|
|
170
|
-
'
|
|
171
|
-
'
|
|
172
|
-
'
|
|
173
|
-
'
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
'
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
//
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
'
|
|
188
|
-
'flex
|
|
189
|
-
'
|
|
190
|
-
'
|
|
191
|
-
'
|
|
192
|
-
'
|
|
193
|
-
'
|
|
194
|
-
'
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
'focus
|
|
204
|
-
'focus-visible:ring-
|
|
205
|
-
'focus-visible:ring-
|
|
206
|
-
'focus-visible:ring-offset-
|
|
207
|
-
'
|
|
208
|
-
'dark:focus-visible:ring-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
//
|
|
212
|
-
'focus-visible:shadow-
|
|
213
|
-
'dark:focus-visible:shadow-
|
|
214
|
-
|
|
215
|
-
'rounded-lg',
|
|
216
|
-
|
|
217
|
-
// Clases personalizadas
|
|
218
|
-
className,
|
|
219
|
-
].join(' ');
|
|
220
|
-
|
|
221
|
-
// ===== RENDERIZAR BADGE =====
|
|
222
|
-
const renderBadge = () => {
|
|
223
|
-
if (!badge && badgeCount === undefined) return null;
|
|
224
|
-
|
|
225
|
-
// Badge con número
|
|
226
|
-
if (badgeCount !== undefined) {
|
|
227
|
-
return (
|
|
228
|
-
<span
|
|
229
|
-
className="
|
|
230
|
-
absolute
|
|
231
|
-
-top-0.5
|
|
232
|
-
left-
|
|
233
|
-
flex
|
|
234
|
-
items-center
|
|
235
|
-
justify-center
|
|
236
|
-
min-w-
|
|
237
|
-
h-
|
|
238
|
-
px-1
|
|
239
|
-
rounded-full
|
|
240
|
-
text-
|
|
241
|
-
font-bold
|
|
242
|
-
leading-none
|
|
243
|
-
bg-red-700
|
|
244
|
-
text-white
|
|
245
|
-
dark:bg-red-700
|
|
246
|
-
dark:text-white
|
|
247
|
-
pointer-events-none
|
|
248
|
-
select-none
|
|
249
|
-
"
|
|
250
|
-
aria-label={`${badgeCount} notificaciones`}
|
|
251
|
-
data-badge
|
|
252
|
-
>
|
|
253
|
-
{badgeCount > 99 ? '99+' : badgeCount}
|
|
254
|
-
</span>
|
|
255
|
-
);
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
// Badge dot simple
|
|
259
|
-
return (
|
|
260
|
-
<span
|
|
261
|
-
className="
|
|
262
|
-
absolute
|
|
263
|
-
-top-0.5
|
|
264
|
-
left-
|
|
265
|
-
w-
|
|
266
|
-
h-
|
|
267
|
-
rounded-full
|
|
268
|
-
bg-red-700
|
|
269
|
-
dark:bg-red-700
|
|
270
|
-
pointer-events-none
|
|
271
|
-
select-none
|
|
272
|
-
"
|
|
273
|
-
aria-label="Notificación"
|
|
274
|
-
data-badge
|
|
275
|
-
/>
|
|
276
|
-
);
|
|
277
|
-
};
|
|
278
|
-
|
|
279
|
-
return (
|
|
280
|
-
<button
|
|
281
|
-
type="button"
|
|
282
|
-
className={containerClasses}
|
|
283
|
-
disabled={disabled}
|
|
284
|
-
onClick={onClick}
|
|
285
|
-
|
|
286
|
-
aria-
|
|
287
|
-
aria-
|
|
288
|
-
|
|
289
|
-
data-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
{
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
{
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
{
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { NavigationRailItemProps } from './NavigationRailItem.types';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* NavigationRailItem - Componente independiente para items de NavigationRail
|
|
6
|
+
*
|
|
7
|
+
* Item individual de navegación vertical (rail) para aplicaciones. Proporciona
|
|
8
|
+
* un punto de acceso a destinos mediante un icono, label opcional y badges.
|
|
9
|
+
*
|
|
10
|
+
* **Características principales:**
|
|
11
|
+
* - Ancho fijo de 56px según Figma
|
|
12
|
+
* - Estados completos: normal, hover, selected, focus, disabled
|
|
13
|
+
* - Badges de notificación con contador opcional
|
|
14
|
+
* - Tipografía Label XXSmall (10px Bold) según sistema de diseño
|
|
15
|
+
* - Dark mode completo con estrategia 'class'
|
|
16
|
+
* - Focus rings adaptativos para accesibilidad
|
|
17
|
+
* - Soporte para iconos 16x16px
|
|
18
|
+
*
|
|
19
|
+
* **Especificaciones de Figma (node 4294-22931):**
|
|
20
|
+
* - Ancho: 56px (w-14)
|
|
21
|
+
* - Icon container: 32px altura, px-4 py-1, rounded-full
|
|
22
|
+
* - Label: 10px Bold, leading 12px (Label XXSmall)
|
|
23
|
+
* - Gap: 4px (gap-1)
|
|
24
|
+
* - Badge: 13x13px, posición absolute
|
|
25
|
+
*
|
|
26
|
+
* **Estados visuales (según Figma):**
|
|
27
|
+
* - **Enabled**: Icon transparent, label text-content-primary
|
|
28
|
+
* - **Hover**: Icon container bg-primary-custom-100 (#dbeefe), icon text-primary-custom-600
|
|
29
|
+
* - **Selected**: Icon container bg-primary-custom-100 con overlay, icon text-primary-custom-600
|
|
30
|
+
* - **Focus**: Focus ring 2px (#60b6fa) con offset 2px (#dbeefe), sombras combinadas
|
|
31
|
+
* - **Disabled**: Opacity 55%, no interactivo
|
|
32
|
+
*
|
|
33
|
+
* **Dark Mode:**
|
|
34
|
+
* - Background: dark-bg-primary
|
|
35
|
+
* - Hover icon container: dark-bg-primary/20
|
|
36
|
+
* - Selected icon container: dark-primary-custom-600/30
|
|
37
|
+
* - Icon colors: dark-content-primary, dark-white on selected
|
|
38
|
+
* - Focus ring: dark-border-custom
|
|
39
|
+
*
|
|
40
|
+
* **Mejores prácticas implementadas:**
|
|
41
|
+
* - Orden de modificadores: {responsive}:{dark}:{state}:{utility}
|
|
42
|
+
* - Tokens de color consistentes con documentación
|
|
43
|
+
* - Accesibilidad ARIA completa
|
|
44
|
+
* - Focus visible para keyboard navigation
|
|
45
|
+
* - Badge positioning absoluto para no afectar layout
|
|
46
|
+
*
|
|
47
|
+
* @see docs/colors.md - Sistema de colores (primary-custom, dark-*, content-*)
|
|
48
|
+
* @see docs/typography.md - Tipografía (Label XXSmall)
|
|
49
|
+
* @see docs/spacing.md - Sistema de espaciado
|
|
50
|
+
* @see docs/shadows.md - Sistema de sombras y focus rings
|
|
51
|
+
* @see https://www.figma.com/design/5XNqf2YTxvwemxwo1LMQ6j/Siesa-UI-Kit?node-id=4294-22931
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```tsx
|
|
55
|
+
* // Item básico
|
|
56
|
+
* <NavigationRailItem
|
|
57
|
+
* id="home"
|
|
58
|
+
* icon={<HomeIcon />}
|
|
59
|
+
* label="Inicio"
|
|
60
|
+
* selected={true}
|
|
61
|
+
* onClick={() => navigate('/')}
|
|
62
|
+
* />
|
|
63
|
+
*
|
|
64
|
+
* // Con badge de notificación
|
|
65
|
+
* <NavigationRailItem
|
|
66
|
+
* id="notifications"
|
|
67
|
+
* icon={<BellIcon />}
|
|
68
|
+
* label="Notificaciones"
|
|
69
|
+
* badgeCount={5}
|
|
70
|
+
* onClick={() => navigate('/notifications')}
|
|
71
|
+
* />
|
|
72
|
+
*
|
|
73
|
+
* // Item deshabilitado
|
|
74
|
+
* <NavigationRailItem
|
|
75
|
+
* id="premium"
|
|
76
|
+
* icon={<StarIcon />}
|
|
77
|
+
* label="Premium"
|
|
78
|
+
* disabled={true}
|
|
79
|
+
* />
|
|
80
|
+
*
|
|
81
|
+
* // Solo icono (sin label)
|
|
82
|
+
* <NavigationRailItem
|
|
83
|
+
* id="home"
|
|
84
|
+
* icon={<HomeIcon />}
|
|
85
|
+
* label="Inicio"
|
|
86
|
+
* showLabelText={false}
|
|
87
|
+
* />
|
|
88
|
+
* ```
|
|
89
|
+
*/
|
|
90
|
+
export const NavigationRailItem: React.FC<NavigationRailItemProps> = ({
|
|
91
|
+
icon,
|
|
92
|
+
label,
|
|
93
|
+
selected = false,
|
|
94
|
+
disabled = false,
|
|
95
|
+
badge = false,
|
|
96
|
+
badgeCount,
|
|
97
|
+
onClick,
|
|
98
|
+
onMouseEnter,
|
|
99
|
+
ariaLabel,
|
|
100
|
+
id,
|
|
101
|
+
showLabelText = true,
|
|
102
|
+
showIcon = true,
|
|
103
|
+
className = '',
|
|
104
|
+
}) => {
|
|
105
|
+
// ===== CLASES DEL ICON CONTAINER =====
|
|
106
|
+
// Según Figma node 4294-22931, el icon container tiene comportamiento diferente
|
|
107
|
+
// según el estado:
|
|
108
|
+
// - Enabled: bg-transparent, hover:bg-primary-custom-100
|
|
109
|
+
// - Hover: bg-primary-custom-100
|
|
110
|
+
// - Selected: bg-primary-custom-100 con overlay (rgba(0,0,0,0.024))
|
|
111
|
+
// - Focus: bg-primary-custom-100 con focus ring y sombras
|
|
112
|
+
// - Disabled: opacidad 55%
|
|
113
|
+
const iconContainerClasses = [
|
|
114
|
+
// Base layout
|
|
115
|
+
'flex',
|
|
116
|
+
'flex-col',
|
|
117
|
+
'items-center',
|
|
118
|
+
'justify-center',
|
|
119
|
+
'px-4', // 16px horizontal según Figma
|
|
120
|
+
'py-1', // 4px vertical según Figma
|
|
121
|
+
'rounded-full',
|
|
122
|
+
'overflow-hidden',
|
|
123
|
+
'shrink-0',
|
|
124
|
+
|
|
125
|
+
// Estados - Background
|
|
126
|
+
selected
|
|
127
|
+
? // Selected: bg-primary-custom-100 con overlay
|
|
128
|
+
'bg-primary-custom-100 dark:bg-primary-custom-600/30'
|
|
129
|
+
: // Default/Hover: transparent → hover:bg-primary-custom-100
|
|
130
|
+
'bg-transparent hover:bg-primary-custom-100 dark:hover:bg-primary-custom-600/20',
|
|
131
|
+
|
|
132
|
+
// Transiciones
|
|
133
|
+
'transition-colors',
|
|
134
|
+
'duration-150',
|
|
135
|
+
].join(' ');
|
|
136
|
+
|
|
137
|
+
// ===== CLASES DEL ICONO =====
|
|
138
|
+
// Tamaño fijo 16x16px según Figma
|
|
139
|
+
// Colores según estado:
|
|
140
|
+
// - Default: text-content-primary
|
|
141
|
+
// - Hover: text-primary-custom-600
|
|
142
|
+
// - Selected: text-primary-custom-600
|
|
143
|
+
// - Disabled: text-content-tertiary
|
|
144
|
+
// Dark mode: invierte colores
|
|
145
|
+
const iconClasses = [
|
|
146
|
+
'w-4', // 16px
|
|
147
|
+
'h-4', // 16px
|
|
148
|
+
'shrink-0',
|
|
149
|
+
|
|
150
|
+
// Colores según estado
|
|
151
|
+
selected
|
|
152
|
+
? // Selected: primary-custom-600 (azul oscuro)
|
|
153
|
+
'text-primary-custom-600 dark:text-white'
|
|
154
|
+
: disabled
|
|
155
|
+
? // Disabled: content-tertiary
|
|
156
|
+
'text-content-tertiary dark:text-content-tertiary'
|
|
157
|
+
: // Default/Hover: content-primary → hover:primary-custom-600
|
|
158
|
+
'text-content-primary hover:text-primary-custom-600 dark:text-dark-content-primary dark:hover:text-white',
|
|
159
|
+
|
|
160
|
+
'transition-colors',
|
|
161
|
+
'duration-150',
|
|
162
|
+
].join(' ');
|
|
163
|
+
|
|
164
|
+
// ===== CLASES DEL LABEL =====
|
|
165
|
+
// Tipografía: Label XXSmall (10px Bold, leading 12px) según Figma
|
|
166
|
+
// Color: text-content-primary, dark:text-dark-content-primary
|
|
167
|
+
const labelClasses = [
|
|
168
|
+
// Tipografía: Label XXSmall (10px Bold)
|
|
169
|
+
'text-xs', // 12px en lugar de text-[10px]
|
|
170
|
+
'leading-3', // 12px
|
|
171
|
+
'font-bold',
|
|
172
|
+
'text-center',
|
|
173
|
+
'w-full',
|
|
174
|
+
'min-w-full',
|
|
175
|
+
|
|
176
|
+
// Colores
|
|
177
|
+
'text-content-primary',
|
|
178
|
+
'dark:text-dark-content-primary',
|
|
179
|
+
|
|
180
|
+
// Para multiline labels, agregar truncate o text-nowrap si es necesario
|
|
181
|
+
'break-words',
|
|
182
|
+
].join(' ');
|
|
183
|
+
|
|
184
|
+
// ===== CLASES DEL CONTENEDOR PRINCIPAL =====
|
|
185
|
+
// Según Figma: ancho 56px, flex-col, gap-1, items-center
|
|
186
|
+
const containerClasses = [
|
|
187
|
+
'relative',
|
|
188
|
+
'flex',
|
|
189
|
+
'flex-col',
|
|
190
|
+
'items-center',
|
|
191
|
+
'gap-1', // 4px según Figma
|
|
192
|
+
'px-0.5', // 2px horizontal según Figma
|
|
193
|
+
'py-0',
|
|
194
|
+
'w-14', // 56px según Figma
|
|
195
|
+
'shrink-0',
|
|
196
|
+
|
|
197
|
+
// Interactividad
|
|
198
|
+
disabled
|
|
199
|
+
? 'cursor-not-allowed opacity-55 pointer-events-none'
|
|
200
|
+
: 'cursor-pointer',
|
|
201
|
+
|
|
202
|
+
// Focus visible (accesibilidad)
|
|
203
|
+
'focus:outline-none',
|
|
204
|
+
'focus-visible:ring-2',
|
|
205
|
+
'focus-visible:ring-primary-custom-400', // 4px ring
|
|
206
|
+
'focus-visible:ring-offset-2',
|
|
207
|
+
'focus-visible:ring-offset-primary-custom-100', // offset #dbeefe según Figma
|
|
208
|
+
'dark:focus-visible:ring-dark-border-custom',
|
|
209
|
+
'dark:focus-visible:ring-offset-dark-bg-primary',
|
|
210
|
+
|
|
211
|
+
// Focus sombras adicionales según Figma:
|
|
212
|
+
'focus-visible:shadow-lg',
|
|
213
|
+
'dark:focus-visible:shadow-2xl',
|
|
214
|
+
|
|
215
|
+
'rounded-lg',
|
|
216
|
+
|
|
217
|
+
// Clases personalizadas
|
|
218
|
+
className,
|
|
219
|
+
].join(' ');
|
|
220
|
+
|
|
221
|
+
// ===== RENDERIZAR BADGE =====
|
|
222
|
+
const renderBadge = () => {
|
|
223
|
+
if (!badge && badgeCount === undefined) return null;
|
|
224
|
+
|
|
225
|
+
// Badge con número
|
|
226
|
+
if (badgeCount !== undefined) {
|
|
227
|
+
return (
|
|
228
|
+
<span
|
|
229
|
+
className="
|
|
230
|
+
absolute
|
|
231
|
+
-top-0.5
|
|
232
|
+
left-8
|
|
233
|
+
flex
|
|
234
|
+
items-center
|
|
235
|
+
justify-center
|
|
236
|
+
min-w-3
|
|
237
|
+
h-3
|
|
238
|
+
px-1
|
|
239
|
+
rounded-full
|
|
240
|
+
text-xs
|
|
241
|
+
font-bold
|
|
242
|
+
leading-none
|
|
243
|
+
bg-red-700
|
|
244
|
+
text-white
|
|
245
|
+
dark:bg-red-700
|
|
246
|
+
dark:text-white
|
|
247
|
+
pointer-events-none
|
|
248
|
+
select-none
|
|
249
|
+
"
|
|
250
|
+
aria-label={`${badgeCount} notificaciones`}
|
|
251
|
+
data-badge
|
|
252
|
+
>
|
|
253
|
+
{badgeCount > 99 ? '99+' : badgeCount}
|
|
254
|
+
</span>
|
|
255
|
+
);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// Badge dot simple
|
|
259
|
+
return (
|
|
260
|
+
<span
|
|
261
|
+
className="
|
|
262
|
+
absolute
|
|
263
|
+
-top-0.5
|
|
264
|
+
left-8
|
|
265
|
+
w-3
|
|
266
|
+
h-3
|
|
267
|
+
rounded-full
|
|
268
|
+
bg-red-700
|
|
269
|
+
dark:bg-red-700
|
|
270
|
+
pointer-events-none
|
|
271
|
+
select-none
|
|
272
|
+
"
|
|
273
|
+
aria-label="Notificación"
|
|
274
|
+
data-badge
|
|
275
|
+
/>
|
|
276
|
+
);
|
|
277
|
+
};
|
|
278
|
+
|
|
279
|
+
return (
|
|
280
|
+
<button
|
|
281
|
+
type="button"
|
|
282
|
+
className={containerClasses}
|
|
283
|
+
disabled={disabled}
|
|
284
|
+
onClick={onClick}
|
|
285
|
+
onMouseEnter={onMouseEnter}
|
|
286
|
+
aria-label={ariaLabel || label}
|
|
287
|
+
aria-current={selected ? 'page' : undefined}
|
|
288
|
+
aria-disabled={disabled}
|
|
289
|
+
data-item-id={id}
|
|
290
|
+
data-testid={`navigation-rail-item-${id}`}
|
|
291
|
+
>
|
|
292
|
+
{/* Icon Container */}
|
|
293
|
+
{showIcon && (
|
|
294
|
+
<div className={iconContainerClasses}>
|
|
295
|
+
<span className={iconClasses}>
|
|
296
|
+
{icon}
|
|
297
|
+
</span>
|
|
298
|
+
</div>
|
|
299
|
+
)}
|
|
300
|
+
|
|
301
|
+
{/* Label */}
|
|
302
|
+
{showLabelText && (
|
|
303
|
+
<p className={labelClasses}>
|
|
304
|
+
{label}
|
|
305
|
+
</p>
|
|
306
|
+
)}
|
|
307
|
+
|
|
308
|
+
{/* Badge */}
|
|
309
|
+
{renderBadge()}
|
|
310
|
+
</button>
|
|
311
|
+
);
|
|
312
|
+
};
|
|
313
|
+
|
|
314
|
+
NavigationRailItem.displayName = 'NavigationRailItem';
|