siesa-ui-kit 1.0.5 → 1.0.6
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/dist/index.cjs +1479 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.js +1479 -0
- package/dist/index.js.map +1 -0
- package/package.json +23 -14
- package/claude/agents/siesa-ui-kit-specialist.md +0 -2401
- package/claude/prompts/component-template.md +0 -121
- package/claude/settings.local.json +0 -61
- package/docs/border-radius.md +0 -1261
- package/docs/colors.md +0 -832
- package/docs/dark-mode-guide.md +0 -1426
- package/docs/filters.md +0 -1243
- package/docs/icons.md +0 -1283
- package/docs/shadows.md +0 -1377
- package/docs/spacing.md +0 -1684
- package/docs/typography.md +0 -1268
- package/postcss.config.cjs +0 -6
- package/src/App.css +0 -42
- package/src/App.tsx +0 -8
- package/src/ButtonTest.tsx +0 -147
- package/src/assets/fonts/README.md +0 -261
- package/src/assets/fonts/SiesaBT/SiesaBT-Bold.otf +0 -0
- package/src/assets/fonts/SiesaBT/SiesaBT-Light.otf +0 -0
- package/src/assets/fonts/SiesaBT/SiesaBT-Regular.otf +0 -0
- package/src/assets/react.svg +0 -1
- package/src/components/Alert/Alert.stories.tsx +0 -332
- package/src/components/Alert/Alert.tsx +0 -106
- package/src/components/Alert/Alert.types.ts +0 -54
- package/src/components/Avatar/Avatar.stories.tsx +0 -494
- package/src/components/Avatar/Avatar.tsx +0 -143
- package/src/components/Avatar/Avatar.types.ts +0 -53
- package/src/components/Badge/Badge.stories.tsx +0 -339
- package/src/components/Badge/Badge.tsx +0 -278
- package/src/components/Badge/Badge.types.ts +0 -58
- package/src/components/Button/Button.stories.tsx +0 -950
- package/src/components/Button/Button.tsx +0 -337
- package/src/components/Button/Button.types.ts +0 -180
- package/src/components/Button/icons.tsx +0 -87
- package/src/components/Button/index.ts +0 -3
- package/src/components/Checkbox/Checkbox.stories.tsx +0 -453
- package/src/components/Checkbox/Checkbox.tsx +0 -208
- package/src/components/Checkbox/Checkbox.types.ts +0 -61
- package/src/components/DescriptionList/DescriptionList.stories.tsx +0 -250
- package/src/components/DescriptionList/DescriptionList.tsx +0 -96
- package/src/components/DescriptionList/DescriptionList.types.ts +0 -29
- package/src/components/Divider/Divider.stories.tsx +0 -263
- package/src/components/Divider/Divider.tsx +0 -80
- package/src/components/Divider/Divider.types.ts +0 -24
- package/src/components/Dropdown/Dropdown.stories.tsx +0 -552
- package/src/components/Dropdown/Dropdown.tsx +0 -422
- package/src/components/Dropdown/Dropdown.types.ts +0 -146
- package/src/components/Dropdown/README.md +0 -266
- package/src/components/Dropdown/icons.tsx +0 -72
- package/src/components/Dropdown/index.ts +0 -8
- package/src/components/Input/Input.stories.tsx +0 -583
- package/src/components/Input/Input.tsx +0 -204
- package/src/components/Input/Input.types.ts +0 -80
- package/src/components/Input/icons.tsx +0 -145
- package/src/components/Input/index.ts +0 -2
- package/src/components/LoginView/LoginView.stories.tsx +0 -148
- package/src/components/LoginView/LoginView.tsx +0 -426
- package/src/components/LoginView/LoginView.types.ts +0 -52
- package/src/components/LoginView/README.md +0 -396
- package/src/components/LoginView/icons.tsx +0 -85
- package/src/components/LoginView/index.ts +0 -3
- package/src/components/Navbar/Navbar.stories.tsx +0 -810
- package/src/components/Navbar/Navbar.tsx +0 -755
- package/src/components/Navbar/Navbar.types.ts +0 -219
- package/src/components/Navbar/README.md +0 -279
- package/src/components/Navbar/icons.tsx +0 -102
- package/src/components/Navbar/index.ts +0 -8
- package/src/components/NavigationBar/NavigationBar.stories.tsx +0 -406
- package/src/components/NavigationBar/NavigationBar.tsx +0 -246
- package/src/components/NavigationBar/NavigationBar.types.ts +0 -74
- package/src/components/NavigationBar/README.md +0 -469
- package/src/components/NavigationBar/index.ts +0 -2
- package/src/components/NavigationRail/NavigationRail.stories.tsx +0 -417
- package/src/components/NavigationRail/NavigationRail.tsx +0 -418
- package/src/components/NavigationRail/NavigationRail.types.ts +0 -109
- package/src/components/NavigationRail/README.md +0 -224
- package/src/components/NavigationRail/index.ts +0 -2
- package/src/components/Notification/Notification.stories.tsx +0 -513
- package/src/components/Notification/Notification.tsx +0 -145
- package/src/components/Notification/Notification.types.ts +0 -142
- package/src/components/Notification/README.md +0 -409
- package/src/components/Notification/index.ts +0 -3
- package/src/components/POSConvention/POSConvention.stories.tsx +0 -235
- package/src/components/POSConvention/POSConvention.tsx +0 -129
- package/src/components/POSConvention/POSConvention.types.ts +0 -38
- package/src/components/POSConvention/README.md +0 -123
- package/src/components/POSConvention/icons.tsx +0 -45
- package/src/components/POSConvention/index.ts +0 -3
- package/src/components/POSLocationButton/POSLocationButton.stories.tsx +0 -531
- package/src/components/POSLocationButton/POSLocationButton.tsx +0 -247
- package/src/components/POSLocationButton/POSLocationButton.types.ts +0 -87
- package/src/components/POSLocationButton/README.md +0 -253
- package/src/components/POSLocationButton/icons.tsx +0 -120
- package/src/components/POSLocationButton/index.ts +0 -14
- package/src/components/POSNumberButton/POSNumberButton.stories.tsx +0 -415
- package/src/components/POSNumberButton/POSNumberButton.tsx +0 -179
- package/src/components/POSNumberButton/POSNumberButton.types.ts +0 -51
- package/src/components/POSNumberButton/README.md +0 -321
- package/src/components/POSNumberButton/index.ts +0 -3
- package/src/components/POSProductButton/POSProductButton.stories.tsx +0 -318
- package/src/components/POSProductButton/POSProductButton.tsx +0 -152
- package/src/components/POSProductButton/POSProductButton.types.ts +0 -46
- package/src/components/POSProductButton/README.md +0 -269
- package/src/components/POSProductButton/index.ts +0 -2
- package/src/components/POSProductCard/POSProductCard.stories.tsx +0 -642
- package/src/components/POSProductCard/POSProductCard.tsx +0 -208
- package/src/components/POSProductCard/POSProductCard.types.ts +0 -76
- package/src/components/POSProductCard/README.md +0 -179
- package/src/components/POSProductCard/icons.tsx +0 -26
- package/src/components/POSProductCard/index.ts +0 -2
- package/src/components/POSProductSidebarItems/POSProductSidebarItems.stories.tsx +0 -753
- package/src/components/POSProductSidebarItems/POSProductSidebarItems.tsx +0 -332
- package/src/components/POSProductSidebarItems/POSProductSidebarItems.types.ts +0 -119
- package/src/components/POSProductSidebarItems/README.md +0 -198
- package/src/components/POSProductSidebarItems/icons.tsx +0 -21
- package/src/components/POSProductSidebarItems/index.ts +0 -3
- package/src/components/POSTable/POSTable.stories.tsx +0 -737
- package/src/components/POSTable/POSTable.tsx +0 -401
- package/src/components/POSTable/POSTable.types.ts +0 -83
- package/src/components/POSTable/README.md +0 -286
- package/src/components/POSTable/index.ts +0 -7
- package/src/components/Pagination/Pagination.stories.tsx +0 -555
- package/src/components/Pagination/Pagination.tsx +0 -286
- package/src/components/Pagination/Pagination.types.ts +0 -93
- package/src/components/Pagination/README.md +0 -298
- package/src/components/Pagination/icons.tsx +0 -47
- package/src/components/Pagination/index.ts +0 -3
- package/src/components/Quantity/Quantity.stories.tsx +0 -457
- package/src/components/Quantity/Quantity.tsx +0 -289
- package/src/components/Quantity/Quantity.types.ts +0 -70
- package/src/components/Radio/Radio.stories.tsx +0 -523
- package/src/components/Radio/Radio.tsx +0 -170
- package/src/components/Radio/Radio.types.ts +0 -122
- package/src/components/Select/README.md +0 -299
- package/src/components/Select/Select.stories.tsx +0 -673
- package/src/components/Select/Select.tsx +0 -454
- package/src/components/Select/Select.types.ts +0 -148
- package/src/components/Select/icons.tsx +0 -50
- package/src/components/Select/index.ts +0 -3
- package/src/components/SignUpView/SignUpView.stories.tsx +0 -129
- package/src/components/SignUpView/SignUpView.tsx +0 -503
- package/src/components/SignUpView/SignUpView.types.ts +0 -58
- package/src/components/SignUpView/icons.tsx +0 -71
- package/src/components/SignUpView/index.ts +0 -3
- package/src/components/Switch/README.md +0 -112
- package/src/components/Switch/Switch.stories.tsx +0 -550
- package/src/components/Switch/Switch.tsx +0 -246
- package/src/components/Switch/Switch.types.ts +0 -67
- package/src/components/Table/README.md +0 -369
- package/src/components/Table/Table.stories.tsx +0 -805
- package/src/components/Table/Table.tsx +0 -688
- package/src/components/Table/Table.types.ts +0 -204
- package/src/components/Table/index.ts +0 -9
- package/src/components/Tabs/README.md +0 -201
- package/src/components/Tabs/Tabs.stories.tsx +0 -580
- package/src/components/Tabs/Tabs.tsx +0 -356
- package/src/components/Tabs/Tabs.types.ts +0 -127
- package/src/components/Tabs/icons.tsx +0 -129
- package/src/components/Tabs/index.ts +0 -11
- package/src/components/Textarea/Textarea.stories.tsx +0 -535
- package/src/components/Textarea/Textarea.tsx +0 -188
- package/src/components/Textarea/Textarea.types.ts +0 -54
- package/src/context/ThemeContext.tsx +0 -99
- package/src/context/index.ts +0 -1
- package/src/index.css +0 -29
- package/src/index.ts +0 -39
- package/src/main.tsx +0 -10
- package/src/views/ProductsView/ProductsView.stories.tsx +0 -344
- package/src/views/ProductsView/ProductsView.tsx +0 -480
- package/src/views/ProductsView/ProductsView.types.ts +0 -238
- package/src/views/ProductsView/README.md +0 -312
- package/src/views/ProductsView/icons.tsx +0 -38
- package/src/views/ProductsView/index.ts +0 -8
- package/src/views/RecoverPasswordView/README.md +0 -269
- package/src/views/RecoverPasswordView/RecoverPasswordView.stories.tsx +0 -131
- package/src/views/RecoverPasswordView/RecoverPasswordView.tsx +0 -376
- package/src/views/RecoverPasswordView/RecoverPasswordView.types.ts +0 -56
- package/src/views/RecoverPasswordView/icons.tsx +0 -17
- package/src/views/RecoverPasswordView/index.ts +0 -2
- package/src/views/TableLayoutView/README.md +0 -268
- package/src/views/TableLayoutView/TableLayoutView.stories.tsx +0 -235
- package/src/views/TableLayoutView/TableLayoutView.tsx +0 -461
- package/src/views/TableLayoutView/TableLayoutView.types.ts +0 -209
- package/src/views/TableLayoutView/icons.tsx +0 -113
- package/src/views/TableLayoutView/index.ts +0 -6
- package/storybook/main.ts +0 -20
- package/storybook/preview.tsx +0 -84
- package/storybook/vitest.setup.ts +0 -7
- package/tailwind.config.js +0 -128
- /package/{public → dist}/,Business Logo.png +0 -0
- /package/{public → dist}/.Siesa Logo.png +0 -0
- /package/{public → dist}/bg_siesa.png +0 -0
- /package/{public → dist}/siesa_logo_mobile.png +0 -0
- /package/{public → dist}/vite.svg +0 -0
|
@@ -1,418 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import type { NavigationRailProps, NavigationRailItemProps } from './NavigationRail.types';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* NavigationRail del sistema de diseño Siesa
|
|
6
|
-
*
|
|
7
|
-
* Componente de navegación vertical (rail) para aplicaciones. Proporciona acceso
|
|
8
|
-
* rápido a destinos principales mediante iconos y labels opcionales.
|
|
9
|
-
*
|
|
10
|
-
* **Características:**
|
|
11
|
-
* - Ancho fijo de 80px para navegación compacta
|
|
12
|
-
* - Soporte para FAB (Floating Action Button) en la parte superior
|
|
13
|
-
* - Estados: normal, hover, selected, disabled
|
|
14
|
-
* - Badges de notificación con contador opcional
|
|
15
|
-
* - Alineación flexible: top, center, bottom
|
|
16
|
-
* - Dark mode completo
|
|
17
|
-
*
|
|
18
|
-
* **Mejores prácticas implementadas:**
|
|
19
|
-
* - Orden de modificadores: {responsive}:{dark}:{state}:{utility}
|
|
20
|
-
* - Dark mode con estrategia 'class' (darkMode: 'class')
|
|
21
|
-
* - Tokens de color consistentes con la documentación
|
|
22
|
-
* - Tipografía Label XXSmall (10px Bold) según sistema de diseño
|
|
23
|
-
* - Estados interactivos completos (hover, focus, active)
|
|
24
|
-
*
|
|
25
|
-
* @see docs/colors.md - Sistema de colores
|
|
26
|
-
* @see docs/typography.md - Sistema tipográfico (Label XXSmall)
|
|
27
|
-
* @see docs/spacing.md - Sistema de espaciado
|
|
28
|
-
*
|
|
29
|
-
* @example
|
|
30
|
-
* ```tsx
|
|
31
|
-
* // Navigation Rail básico
|
|
32
|
-
* <NavigationRail
|
|
33
|
-
* items={[
|
|
34
|
-
* { id: 'home', icon: <HomeIcon />, label: 'Inicio', selected: true },
|
|
35
|
-
* { id: 'search', icon: <SearchIcon />, label: 'Buscar' },
|
|
36
|
-
* { id: 'notifications', icon: <BellIcon />, label: 'Notificaciones', badgeCount: 5 },
|
|
37
|
-
* ]}
|
|
38
|
-
* alignment="top"
|
|
39
|
-
* />
|
|
40
|
-
*
|
|
41
|
-
* // Con FAB button
|
|
42
|
-
* <NavigationRail
|
|
43
|
-
* showFab
|
|
44
|
-
* fabIcon={<PlusIcon />}
|
|
45
|
-
* onFabClick={() => console.log('Create new')}
|
|
46
|
-
* items={[...]}
|
|
47
|
-
* />
|
|
48
|
-
* ```
|
|
49
|
-
*/
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* NavigationRailItem - Componente interno para items individuales
|
|
53
|
-
*/
|
|
54
|
-
const NavigationRailItem: React.FC<NavigationRailItemProps> = ({
|
|
55
|
-
icon,
|
|
56
|
-
label,
|
|
57
|
-
selected = false,
|
|
58
|
-
disabled = false,
|
|
59
|
-
badge = false,
|
|
60
|
-
badgeCount,
|
|
61
|
-
onClick,
|
|
62
|
-
ariaLabel,
|
|
63
|
-
id,
|
|
64
|
-
}) => {
|
|
65
|
-
// ===== CLASES DEL ICON CONTAINER =====
|
|
66
|
-
// Estado selected usa background con overlay según Figma
|
|
67
|
-
const iconContainerClasses = [
|
|
68
|
-
// Base
|
|
69
|
-
'flex',
|
|
70
|
-
'flex-col',
|
|
71
|
-
'items-center',
|
|
72
|
-
'justify-center',
|
|
73
|
-
'px-4',
|
|
74
|
-
'py-1',
|
|
75
|
-
'rounded-full',
|
|
76
|
-
'overflow-hidden',
|
|
77
|
-
'shrink-0',
|
|
78
|
-
|
|
79
|
-
// Estados
|
|
80
|
-
selected
|
|
81
|
-
? // Selected: bg-primary-custom-100 con overlay de rgba(0,0,0,0.024)
|
|
82
|
-
'bg-primary-custom-100 dark:bg-primary-custom-600/30'
|
|
83
|
-
: // Default/Hover: transparent → hover:bg-primary-custom-100
|
|
84
|
-
'bg-transparent hover:bg-primary-custom-100 dark:hover:bg-primary-custom-600/20',
|
|
85
|
-
|
|
86
|
-
// Transiciones
|
|
87
|
-
'transition-colors',
|
|
88
|
-
'duration-150',
|
|
89
|
-
].join(' ');
|
|
90
|
-
|
|
91
|
-
// ===== CLASES DEL ICONO =====
|
|
92
|
-
const iconClasses = [
|
|
93
|
-
'w-4',
|
|
94
|
-
'h-4',
|
|
95
|
-
'shrink-0',
|
|
96
|
-
|
|
97
|
-
// Colores según estado
|
|
98
|
-
selected || !disabled
|
|
99
|
-
? // Selected o habilitado con hover: content-primary → hover:primary-custom-600
|
|
100
|
-
selected
|
|
101
|
-
? 'text-primary-custom-600 dark:text-white'
|
|
102
|
-
: 'text-content-primary hover:text-primary-custom-600 dark:text-dark-content-primary dark:hover:text-white'
|
|
103
|
-
: // Disabled
|
|
104
|
-
'text-content-tertiary dark:text-content-tertiary',
|
|
105
|
-
|
|
106
|
-
'transition-colors',
|
|
107
|
-
'duration-150',
|
|
108
|
-
].join(' ');
|
|
109
|
-
|
|
110
|
-
// ===== CLASES DEL LABEL =====
|
|
111
|
-
const labelClasses = [
|
|
112
|
-
// Tipografía: Label XXSmall (10px Bold, leading 12px)
|
|
113
|
-
'text-[10px]',
|
|
114
|
-
'leading-3',
|
|
115
|
-
'font-bold',
|
|
116
|
-
'text-center',
|
|
117
|
-
'w-full',
|
|
118
|
-
'min-w-full',
|
|
119
|
-
|
|
120
|
-
// Colores
|
|
121
|
-
'text-content-primary',
|
|
122
|
-
'dark:text-dark-content-primary',
|
|
123
|
-
].join(' ');
|
|
124
|
-
|
|
125
|
-
// ===== CLASES DEL CONTENEDOR PRINCIPAL =====
|
|
126
|
-
const containerClasses = [
|
|
127
|
-
'relative',
|
|
128
|
-
'flex',
|
|
129
|
-
'flex-col',
|
|
130
|
-
'items-center',
|
|
131
|
-
'gap-1',
|
|
132
|
-
'px-0.5',
|
|
133
|
-
'py-0',
|
|
134
|
-
'w-14', // 56px según Figma
|
|
135
|
-
'shrink-0',
|
|
136
|
-
|
|
137
|
-
// Interactividad
|
|
138
|
-
disabled
|
|
139
|
-
? 'cursor-not-allowed opacity-50 pointer-events-none'
|
|
140
|
-
: 'cursor-pointer',
|
|
141
|
-
|
|
142
|
-
// Focus
|
|
143
|
-
'focus:outline-none',
|
|
144
|
-
'focus-visible:ring-2',
|
|
145
|
-
'focus-visible:ring-primary-custom-400',
|
|
146
|
-
'focus-visible:ring-offset-2',
|
|
147
|
-
'dark:focus-visible:ring-dark-border-custom',
|
|
148
|
-
'dark:focus-visible:ring-offset-dark-bg-primary',
|
|
149
|
-
'rounded-lg',
|
|
150
|
-
].join(' ');
|
|
151
|
-
|
|
152
|
-
// ===== RENDERIZAR BADGE =====
|
|
153
|
-
const renderBadge = () => {
|
|
154
|
-
if (!badge && badgeCount === undefined) return null;
|
|
155
|
-
|
|
156
|
-
// Badge con número
|
|
157
|
-
if (badgeCount !== undefined) {
|
|
158
|
-
return (
|
|
159
|
-
<span
|
|
160
|
-
className="
|
|
161
|
-
absolute
|
|
162
|
-
-top-0.5
|
|
163
|
-
left-[34px]
|
|
164
|
-
flex
|
|
165
|
-
items-center
|
|
166
|
-
justify-center
|
|
167
|
-
min-w-[13px]
|
|
168
|
-
h-[13px]
|
|
169
|
-
px-1
|
|
170
|
-
rounded-full
|
|
171
|
-
text-[10px]
|
|
172
|
-
font-bold
|
|
173
|
-
leading-none
|
|
174
|
-
bg-red-700
|
|
175
|
-
text-white
|
|
176
|
-
dark:bg-red-700
|
|
177
|
-
dark:text-white
|
|
178
|
-
pointer-events-none
|
|
179
|
-
"
|
|
180
|
-
aria-label={`${badgeCount} notificaciones`}
|
|
181
|
-
>
|
|
182
|
-
{badgeCount > 99 ? '99+' : badgeCount}
|
|
183
|
-
</span>
|
|
184
|
-
);
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
// Badge dot simple
|
|
188
|
-
return (
|
|
189
|
-
<span
|
|
190
|
-
className="
|
|
191
|
-
absolute
|
|
192
|
-
-top-0.5
|
|
193
|
-
left-[34px]
|
|
194
|
-
w-[13px]
|
|
195
|
-
h-[13px]
|
|
196
|
-
rounded-full
|
|
197
|
-
bg-red-700
|
|
198
|
-
dark:bg-red-700
|
|
199
|
-
pointer-events-none
|
|
200
|
-
"
|
|
201
|
-
aria-label="Notificación"
|
|
202
|
-
/>
|
|
203
|
-
);
|
|
204
|
-
};
|
|
205
|
-
|
|
206
|
-
return (
|
|
207
|
-
<button
|
|
208
|
-
type="button"
|
|
209
|
-
className={containerClasses}
|
|
210
|
-
disabled={disabled}
|
|
211
|
-
onClick={onClick}
|
|
212
|
-
aria-label={ariaLabel || label}
|
|
213
|
-
aria-current={selected ? 'page' : undefined}
|
|
214
|
-
data-item-id={id}
|
|
215
|
-
>
|
|
216
|
-
{/* Icon Container */}
|
|
217
|
-
<div className={iconContainerClasses}>
|
|
218
|
-
<span className={iconClasses}>
|
|
219
|
-
{icon}
|
|
220
|
-
</span>
|
|
221
|
-
</div>
|
|
222
|
-
|
|
223
|
-
{/* Label */}
|
|
224
|
-
<p className={labelClasses}>
|
|
225
|
-
{label}
|
|
226
|
-
</p>
|
|
227
|
-
|
|
228
|
-
{/* Badge */}
|
|
229
|
-
{renderBadge()}
|
|
230
|
-
</button>
|
|
231
|
-
);
|
|
232
|
-
};
|
|
233
|
-
|
|
234
|
-
/**
|
|
235
|
-
* NavigationRail - Componente principal
|
|
236
|
-
*/
|
|
237
|
-
export const NavigationRail: React.FC<NavigationRailProps> = ({
|
|
238
|
-
items,
|
|
239
|
-
alignment = 'top',
|
|
240
|
-
showFab = false,
|
|
241
|
-
fabIcon,
|
|
242
|
-
onFabClick,
|
|
243
|
-
fabAriaLabel = 'Crear nuevo',
|
|
244
|
-
className = '',
|
|
245
|
-
selectedId,
|
|
246
|
-
onItemSelect,
|
|
247
|
-
}) => {
|
|
248
|
-
// ===== CLASES DEL CONTENEDOR PRINCIPAL =====
|
|
249
|
-
const containerClasses = [
|
|
250
|
-
// Layout
|
|
251
|
-
'flex',
|
|
252
|
-
'flex-col',
|
|
253
|
-
'items-center',
|
|
254
|
-
'relative',
|
|
255
|
-
|
|
256
|
-
// Tamaño fijo según Figma
|
|
257
|
-
'w-20', // 80px
|
|
258
|
-
'h-full',
|
|
259
|
-
|
|
260
|
-
// Fondo y bordes
|
|
261
|
-
'bg-white',
|
|
262
|
-
'dark:bg-dark-bg-primary',
|
|
263
|
-
'border-r',
|
|
264
|
-
'border-border-primary',
|
|
265
|
-
'dark:border-dark-border-primary',
|
|
266
|
-
|
|
267
|
-
className,
|
|
268
|
-
].join(' ');
|
|
269
|
-
|
|
270
|
-
// ===== CLASES DEL WRAPPER CON PADDING =====
|
|
271
|
-
// Según Figma, cada alineación funciona diferente:
|
|
272
|
-
// - top: flujo normal desde arriba
|
|
273
|
-
// - center: wrapper con grow y items absolutamente centrados
|
|
274
|
-
// - bottom: wrapper con grow y items con justify-end
|
|
275
|
-
const wrapperClasses = [
|
|
276
|
-
'flex',
|
|
277
|
-
'flex-col',
|
|
278
|
-
'items-center',
|
|
279
|
-
'gap-10', // 40px entre FAB y items según Figma
|
|
280
|
-
'w-20', // 80px
|
|
281
|
-
'pb-10', // 40px padding bottom según Figma
|
|
282
|
-
'pt-2', // 8px padding top según Figma
|
|
283
|
-
|
|
284
|
-
// Para center y bottom, el wrapper debe crecer para ocupar espacio
|
|
285
|
-
alignment !== 'top' && 'grow',
|
|
286
|
-
alignment !== 'top' && 'basis-0',
|
|
287
|
-
alignment !== 'top' && 'min-h-0',
|
|
288
|
-
].filter(Boolean).join(' ');
|
|
289
|
-
|
|
290
|
-
// ===== CLASES DEL CONTENEDOR DE ITEMS =====
|
|
291
|
-
// Para cada alineación, los items se posicionan diferente
|
|
292
|
-
const getItemsContainerClasses = () => {
|
|
293
|
-
const baseClasses = [
|
|
294
|
-
'flex',
|
|
295
|
-
'flex-col',
|
|
296
|
-
'items-center',
|
|
297
|
-
'gap-3', // 12px según Figma
|
|
298
|
-
'w-20', // 80px
|
|
299
|
-
];
|
|
300
|
-
|
|
301
|
-
if (alignment === 'top') {
|
|
302
|
-
return [...baseClasses, 'shrink-0'].join(' ');
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
if (alignment === 'center') {
|
|
306
|
-
// Items absolutamente centrados según Figma
|
|
307
|
-
return [
|
|
308
|
-
...baseClasses,
|
|
309
|
-
'absolute',
|
|
310
|
-
'left-1/2',
|
|
311
|
-
'top-1/2',
|
|
312
|
-
'-translate-x-1/2',
|
|
313
|
-
'-translate-y-1/2',
|
|
314
|
-
].join(' ');
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
if (alignment === 'bottom') {
|
|
318
|
-
// Items al final con grow y justify-end según Figma
|
|
319
|
-
return [
|
|
320
|
-
...baseClasses,
|
|
321
|
-
'grow',
|
|
322
|
-
'basis-0',
|
|
323
|
-
'min-h-0',
|
|
324
|
-
'justify-end',
|
|
325
|
-
'shrink-0',
|
|
326
|
-
].join(' ');
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
return baseClasses.join(' ');
|
|
330
|
-
};
|
|
331
|
-
|
|
332
|
-
const itemsContainerClasses = getItemsContainerClasses();
|
|
333
|
-
|
|
334
|
-
// ===== CLASES DEL FAB BUTTON =====
|
|
335
|
-
const fabClasses = [
|
|
336
|
-
// Layout
|
|
337
|
-
'flex',
|
|
338
|
-
'items-center',
|
|
339
|
-
'justify-center',
|
|
340
|
-
'p-3', // 12px padding según Figma
|
|
341
|
-
'shrink-0',
|
|
342
|
-
|
|
343
|
-
// Estilo
|
|
344
|
-
'rounded-md',
|
|
345
|
-
'bg-primary-custom-600',
|
|
346
|
-
'text-primary-inverse-content',
|
|
347
|
-
'border',
|
|
348
|
-
'border-primary-custom-600',
|
|
349
|
-
'shadow-button-inset',
|
|
350
|
-
|
|
351
|
-
// Estados
|
|
352
|
-
'hover:bg-primary-custom-500',
|
|
353
|
-
'active:scale-95',
|
|
354
|
-
'focus:outline-none',
|
|
355
|
-
'focus:ring-2',
|
|
356
|
-
'focus:ring-primary-custom-400',
|
|
357
|
-
'focus:ring-offset-2',
|
|
358
|
-
|
|
359
|
-
// Dark mode
|
|
360
|
-
'dark:bg-dark-bg-inverse',
|
|
361
|
-
'dark:text-dark-content-inverse',
|
|
362
|
-
'dark:border-dark-bg-inverse',
|
|
363
|
-
'dark:hover:bg-dark-bg-inverse/90',
|
|
364
|
-
'dark:focus:ring-dark-border-custom',
|
|
365
|
-
'dark:focus:ring-offset-dark-bg-primary',
|
|
366
|
-
|
|
367
|
-
// Transiciones
|
|
368
|
-
'transition-all',
|
|
369
|
-
'duration-150',
|
|
370
|
-
].join(' ');
|
|
371
|
-
|
|
372
|
-
// ===== MANEJAR SELECCIÓN DE ITEM =====
|
|
373
|
-
const handleItemClick = (item: NavigationRailItemProps) => {
|
|
374
|
-
if (item.disabled) return;
|
|
375
|
-
|
|
376
|
-
if (item.onClick) {
|
|
377
|
-
item.onClick();
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
if (onItemSelect && item.id) {
|
|
381
|
-
onItemSelect(item.id);
|
|
382
|
-
}
|
|
383
|
-
};
|
|
384
|
-
|
|
385
|
-
return (
|
|
386
|
-
<nav className={containerClasses} aria-label="Navegación principal">
|
|
387
|
-
<div className={wrapperClasses}>
|
|
388
|
-
{/* FAB Button (opcional) */}
|
|
389
|
-
{showFab && (
|
|
390
|
-
<div className="flex items-start gap-2.5 shrink-0">
|
|
391
|
-
<button
|
|
392
|
-
type="button"
|
|
393
|
-
className={fabClasses}
|
|
394
|
-
onClick={onFabClick}
|
|
395
|
-
aria-label={fabAriaLabel}
|
|
396
|
-
>
|
|
397
|
-
<span className="w-4 h-4 flex items-center justify-center">
|
|
398
|
-
{fabIcon}
|
|
399
|
-
</span>
|
|
400
|
-
</button>
|
|
401
|
-
</div>
|
|
402
|
-
)}
|
|
403
|
-
|
|
404
|
-
{/* Navigation Items */}
|
|
405
|
-
<div className={itemsContainerClasses}>
|
|
406
|
-
{items.map((item, index) => (
|
|
407
|
-
<NavigationRailItem
|
|
408
|
-
key={item.id || index}
|
|
409
|
-
{...item}
|
|
410
|
-
selected={item.selected || (selectedId !== undefined && item.id === selectedId)}
|
|
411
|
-
onClick={() => handleItemClick(item)}
|
|
412
|
-
/>
|
|
413
|
-
))}
|
|
414
|
-
</div>
|
|
415
|
-
</div>
|
|
416
|
-
</nav>
|
|
417
|
-
);
|
|
418
|
-
};
|
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
import type { ReactNode } from 'react';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Props para NavigationRailItem
|
|
5
|
-
*/
|
|
6
|
-
export interface NavigationRailItemProps {
|
|
7
|
-
/**
|
|
8
|
-
* Icono a mostrar en el item
|
|
9
|
-
*/
|
|
10
|
-
icon: ReactNode;
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Label del item de navegación
|
|
14
|
-
*/
|
|
15
|
-
label: string;
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Si el item está seleccionado actualmente
|
|
19
|
-
* @default false
|
|
20
|
-
*/
|
|
21
|
-
selected?: boolean;
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Si el item está deshabilitado
|
|
25
|
-
* @default false
|
|
26
|
-
*/
|
|
27
|
-
disabled?: boolean;
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Mostrar badge de notificación (dot rojo)
|
|
31
|
-
* @default false
|
|
32
|
-
*/
|
|
33
|
-
badge?: boolean;
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Número a mostrar en el badge (reemplaza el dot)
|
|
37
|
-
*/
|
|
38
|
-
badgeCount?: number;
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Handler para evento click
|
|
42
|
-
*/
|
|
43
|
-
onClick?: () => void;
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Label para accesibilidad (ARIA)
|
|
47
|
-
*/
|
|
48
|
-
ariaLabel?: string;
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* ID único del item (para navegación)
|
|
52
|
-
*/
|
|
53
|
-
id?: string;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* Props del componente NavigationRail
|
|
58
|
-
*/
|
|
59
|
-
export interface NavigationRailProps {
|
|
60
|
-
/**
|
|
61
|
-
* Items de navegación a mostrar
|
|
62
|
-
*/
|
|
63
|
-
items: NavigationRailItemProps[];
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* Alineación vertical de los items
|
|
67
|
-
* - `top`: Items alineados arriba (debajo del FAB)
|
|
68
|
-
* - `center`: Items centrados verticalmente
|
|
69
|
-
* - `bottom`: Items alineados abajo
|
|
70
|
-
* @default 'top'
|
|
71
|
-
*/
|
|
72
|
-
alignment?: 'top' | 'center' | 'bottom';
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* Mostrar botón FAB (Floating Action Button) en la parte superior
|
|
76
|
-
* @default false
|
|
77
|
-
*/
|
|
78
|
-
showFab?: boolean;
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* Icono del botón FAB
|
|
82
|
-
*/
|
|
83
|
-
fabIcon?: ReactNode;
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* Handler para click en el FAB
|
|
87
|
-
*/
|
|
88
|
-
onFabClick?: () => void;
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* Label del FAB para accesibilidad
|
|
92
|
-
*/
|
|
93
|
-
fabAriaLabel?: string;
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* Clases CSS adicionales para el contenedor
|
|
97
|
-
*/
|
|
98
|
-
className?: string;
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
* ID del item seleccionado actualmente
|
|
102
|
-
*/
|
|
103
|
-
selectedId?: string;
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* Handler cuando se selecciona un item
|
|
107
|
-
*/
|
|
108
|
-
onItemSelect?: (id: string) => void;
|
|
109
|
-
}
|