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,476 +1,476 @@
|
|
|
1
|
-
# NavigationRailItem
|
|
2
|
-
|
|
3
|
-
Componente individual de item para la barra de navegación vertical (NavigationRail) del sistema de diseño Siesa UI Kit.
|
|
4
|
-
|
|
5
|
-
## 📋 Descripción
|
|
6
|
-
|
|
7
|
-
`NavigationRailItem` es un componente independiente que representa un item seleccionable dentro de una `NavigationRail`. Proporciona acceso rápido a destinos principales mediante un icono, label opcional y badges de notificación.
|
|
8
|
-
|
|
9
|
-
**Implementación pixel-perfect** según Figma (node 4294-22931) con soporte completo para todos los estados, dark mode y accesibilidad.
|
|
10
|
-
|
|
11
|
-
## 🎯 Características
|
|
12
|
-
|
|
13
|
-
- ✅ **Ancho fijo de 56px** según especificaciones de Figma
|
|
14
|
-
- ✅ **Estados completos**: Enabled, Hover, Selected, Focus, Disabled
|
|
15
|
-
- ✅ **Badges de notificación**: Dot simple o contador numérico (99+ para >99)
|
|
16
|
-
- ✅ **Tipografía del sistema**: Label XXSmall (10px Bold, leading 12px)
|
|
17
|
-
- ✅ **Dark Mode completo**: Colores invertidos en todos los estados
|
|
18
|
-
- ✅ **Focus rings adaptativos**: Accesibilidad y keyboard navigation
|
|
19
|
-
- ✅ **Iconos flexibles**: Soporta cualquier librería (Heroicons, React Icons, etc.)
|
|
20
|
-
- ✅ **ARIA completo**: aria-label, aria-current, aria-disabled
|
|
21
|
-
- ✅ **Tokens del sistema**: NO colores hardcodeados
|
|
22
|
-
|
|
23
|
-
## 📐 Especificaciones de Figma
|
|
24
|
-
|
|
25
|
-
### Dimensiones
|
|
26
|
-
- **Ancho**: 56px (w-14)
|
|
27
|
-
- **Altura**: Auto (flex-col)
|
|
28
|
-
- **Icon container**: 32px altura, 16px padding horizontal
|
|
29
|
-
- **Gap icon-label**: 4px (gap-1)
|
|
30
|
-
- **Border radius icon**: 9999px (rounded-full)
|
|
31
|
-
|
|
32
|
-
### Estados Visuales
|
|
33
|
-
|
|
34
|
-
| Estado | Background | Icon Color | Label Color | Cursor |
|
|
35
|
-
|--------|-----------|-----------|-----------|--------|
|
|
36
|
-
| **Enabled** | Transparent | content-primary | content-primary | pointer |
|
|
37
|
-
| **Hover** | primary-custom-100 | primary-custom-600 | content-primary | pointer |
|
|
38
|
-
| **Selected** | primary-custom-100 | primary-custom-600 | content-primary | pointer |
|
|
39
|
-
| **Focus** | primary-custom-100 + ring | primary-custom-600 | content-primary | pointer |
|
|
40
|
-
| **Disabled** | Transparent (opacity 55%) | content-tertiary | content-tertiary | not-allowed |
|
|
41
|
-
|
|
42
|
-
### Badge
|
|
43
|
-
|
|
44
|
-
- **Tamaño**: 13x13px
|
|
45
|
-
- **Border radius**: rounded-full (9999px)
|
|
46
|
-
- **Posición**: Absoluta (-top-0.5, left-[34px])
|
|
47
|
-
- **Color**: Red 700 (#b91c1c)
|
|
48
|
-
- **Tipografía**: 10px Bold
|
|
49
|
-
- **Tipos**:
|
|
50
|
-
- **Dot**: Badge simple sin número
|
|
51
|
-
- **Contador**: Número 1-99+
|
|
52
|
-
|
|
53
|
-
### Focus Ring (Accesibilidad)
|
|
54
|
-
|
|
55
|
-
Según Figma node 4294-22931, el focus ring tiene estas características:
|
|
56
|
-
|
|
57
|
-
```css
|
|
58
|
-
ring: 2px (#60b6fa)
|
|
59
|
-
offset: 2px (#dbeefe)
|
|
60
|
-
shadow: 0px_0px_0px_2px_#dbeefe, 0px_1px_2px_0px_rgba(0,0,0,0.05), 0px_0px_0px_4px_#60b6fa
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
## 🎨 Dark Mode
|
|
64
|
-
|
|
65
|
-
El componente invierte automáticamente sus colores en dark mode:
|
|
66
|
-
|
|
67
|
-
- **Background**: bg-primary-custom-600/30
|
|
68
|
-
- **Icon**: text-white (selected), dark-content-primary (default)
|
|
69
|
-
- **Label**: dark-content-primary
|
|
70
|
-
- **Focus ring**: dark-border-custom
|
|
71
|
-
|
|
72
|
-
Usa la estrategia `class` de Tailwind CSS:
|
|
73
|
-
|
|
74
|
-
```tsx
|
|
75
|
-
<div className="dark">
|
|
76
|
-
<NavigationRailItem label="Inicio" selected={true} />
|
|
77
|
-
</div>
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
## 💻 Uso
|
|
81
|
-
|
|
82
|
-
### Instalación
|
|
83
|
-
|
|
84
|
-
```bash
|
|
85
|
-
npm install siesa-ui-kit
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
### Ejemplo Básico
|
|
89
|
-
|
|
90
|
-
```tsx
|
|
91
|
-
import { NavigationRailItem } from 'siesa-ui-kit/components/NavigationRailItem';
|
|
92
|
-
import { HomeIcon } from '@heroicons/react/24/outline';
|
|
93
|
-
|
|
94
|
-
export function App() {
|
|
95
|
-
return (
|
|
96
|
-
<NavigationRailItem
|
|
97
|
-
id="home"
|
|
98
|
-
icon={<HomeIcon />}
|
|
99
|
-
label="Inicio"
|
|
100
|
-
selected={true}
|
|
101
|
-
onClick={() => navigate('/')}
|
|
102
|
-
/>
|
|
103
|
-
);
|
|
104
|
-
}
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
### Con Badge
|
|
108
|
-
|
|
109
|
-
```tsx
|
|
110
|
-
import { BellIcon } from '@heroicons/react/24/outline';
|
|
111
|
-
|
|
112
|
-
<NavigationRailItem
|
|
113
|
-
id="notifications"
|
|
114
|
-
icon={<BellIcon />}
|
|
115
|
-
label="Notificaciones"
|
|
116
|
-
badgeCount={5}
|
|
117
|
-
/>
|
|
118
|
-
```
|
|
119
|
-
|
|
120
|
-
### Deshabilitado
|
|
121
|
-
|
|
122
|
-
```tsx
|
|
123
|
-
import { StarIcon } from '@heroicons/react/24/outline';
|
|
124
|
-
|
|
125
|
-
<NavigationRailItem
|
|
126
|
-
id="premium"
|
|
127
|
-
icon={<StarIcon />}
|
|
128
|
-
label="Premium"
|
|
129
|
-
disabled={true}
|
|
130
|
-
/>
|
|
131
|
-
```
|
|
132
|
-
|
|
133
|
-
### Solo Icono
|
|
134
|
-
|
|
135
|
-
```tsx
|
|
136
|
-
<NavigationRailItem
|
|
137
|
-
id="home"
|
|
138
|
-
icon={<HomeIcon />}
|
|
139
|
-
label="Inicio"
|
|
140
|
-
showLabelText={false}
|
|
141
|
-
/>
|
|
142
|
-
```
|
|
143
|
-
|
|
144
|
-
### En un NavigationRail
|
|
145
|
-
|
|
146
|
-
```tsx
|
|
147
|
-
import { NavigationRail } from 'siesa-ui-kit/components/NavigationRail';
|
|
148
|
-
import { NavigationRailItem } from 'siesa-ui-kit/components/NavigationRailItem';
|
|
149
|
-
|
|
150
|
-
export function Navbar() {
|
|
151
|
-
const [selected, setSelected] = React.useState('home');
|
|
152
|
-
|
|
153
|
-
const items = [
|
|
154
|
-
{ id: 'home', icon: <HomeIcon />, label: 'Inicio' },
|
|
155
|
-
{ id: 'search', icon: <SearchIcon />, label: 'Buscar' },
|
|
156
|
-
{ id: 'notifications', icon: <BellIcon />, label: 'Notificaciones', badgeCount: 3 },
|
|
157
|
-
];
|
|
158
|
-
|
|
159
|
-
return (
|
|
160
|
-
<nav className="flex gap-3">
|
|
161
|
-
{items.map((item) => (
|
|
162
|
-
<NavigationRailItem
|
|
163
|
-
key={item.id}
|
|
164
|
-
id={item.id}
|
|
165
|
-
icon={item.icon}
|
|
166
|
-
label={item.label}
|
|
167
|
-
badgeCount={item.badgeCount}
|
|
168
|
-
selected={selected === item.id}
|
|
169
|
-
onClick={() => setSelected(item.id)}
|
|
170
|
-
/>
|
|
171
|
-
))}
|
|
172
|
-
</nav>
|
|
173
|
-
);
|
|
174
|
-
}
|
|
175
|
-
```
|
|
176
|
-
|
|
177
|
-
## 📖 Props
|
|
178
|
-
|
|
179
|
-
### `icon` (Required)
|
|
180
|
-
|
|
181
|
-
```typescript
|
|
182
|
-
icon: ReactNode
|
|
183
|
-
```
|
|
184
|
-
|
|
185
|
-
Icono a mostrar. Tamaño recomendado: 16x16px.
|
|
186
|
-
|
|
187
|
-
**Ejemplos:**
|
|
188
|
-
- Heroicons: `<HomeIcon />`
|
|
189
|
-
- React Icons: `<FiHome />`
|
|
190
|
-
- SVG inline: `<svg>...</svg>`
|
|
191
|
-
|
|
192
|
-
### `label` (Required)
|
|
193
|
-
|
|
194
|
-
```typescript
|
|
195
|
-
label: string
|
|
196
|
-
```
|
|
197
|
-
|
|
198
|
-
Texto del label que aparece debajo del icono. Se muestra en tipografía Label XXSmall (10px Bold).
|
|
199
|
-
|
|
200
|
-
### `selected`
|
|
201
|
-
|
|
202
|
-
```typescript
|
|
203
|
-
selected?: boolean
|
|
204
|
-
// default: false
|
|
205
|
-
```
|
|
206
|
-
|
|
207
|
-
Si el item está seleccionado actualmente. Cambia el background a primary-custom-100 y el icono a primary-custom-600.
|
|
208
|
-
|
|
209
|
-
### `disabled`
|
|
210
|
-
|
|
211
|
-
```typescript
|
|
212
|
-
disabled?: boolean
|
|
213
|
-
// default: false
|
|
214
|
-
```
|
|
215
|
-
|
|
216
|
-
Si el item está deshabilitado. Reduce la opacidad a 55%, cambia el cursor a not-allowed y desactiva la interactividad.
|
|
217
|
-
|
|
218
|
-
### `badge`
|
|
219
|
-
|
|
220
|
-
```typescript
|
|
221
|
-
badge?: boolean
|
|
222
|
-
// default: false
|
|
223
|
-
```
|
|
224
|
-
|
|
225
|
-
Mostrar badge de notificación simple (dot rojo). Se ignora si `badgeCount` está definido.
|
|
226
|
-
|
|
227
|
-
### `badgeCount`
|
|
228
|
-
|
|
229
|
-
```typescript
|
|
230
|
-
badgeCount?: number
|
|
231
|
-
```
|
|
232
|
-
|
|
233
|
-
Número a mostrar en el badge. Reemplaza el dot simple. Si es mayor a 99, muestra "99+".
|
|
234
|
-
|
|
235
|
-
### `onClick`
|
|
236
|
-
|
|
237
|
-
```typescript
|
|
238
|
-
onClick?: () => void
|
|
239
|
-
```
|
|
240
|
-
|
|
241
|
-
Callback cuando se hace click en el item.
|
|
242
|
-
|
|
243
|
-
**Nota:** Se ejecuta incluso si el item está disabled (pero el botón no es clickeable).
|
|
244
|
-
|
|
245
|
-
### `ariaLabel`
|
|
246
|
-
|
|
247
|
-
```typescript
|
|
248
|
-
ariaLabel?: string
|
|
249
|
-
```
|
|
250
|
-
|
|
251
|
-
Label para accesibilidad (ARIA). Si no se proporciona, usa el valor de `label`.
|
|
252
|
-
|
|
253
|
-
**Ejemplo:**
|
|
254
|
-
```tsx
|
|
255
|
-
<NavigationRailItem
|
|
256
|
-
label="Inicio"
|
|
257
|
-
ariaLabel="Ir a la página de inicio del sitio web"
|
|
258
|
-
/>
|
|
259
|
-
```
|
|
260
|
-
|
|
261
|
-
### `id`
|
|
262
|
-
|
|
263
|
-
```typescript
|
|
264
|
-
id?: string
|
|
265
|
-
```
|
|
266
|
-
|
|
267
|
-
ID único del item. Se usa para identificarlo en navegación y se añade como atributo `data-item-id`.
|
|
268
|
-
|
|
269
|
-
**Ejemplo:**
|
|
270
|
-
```tsx
|
|
271
|
-
<NavigationRailItem id="home" label="Inicio" />
|
|
272
|
-
// Genera: <button data-item-id="home">...</button>
|
|
273
|
-
```
|
|
274
|
-
|
|
275
|
-
### `showLabelText`
|
|
276
|
-
|
|
277
|
-
```typescript
|
|
278
|
-
showLabelText?: boolean
|
|
279
|
-
// default: true
|
|
280
|
-
```
|
|
281
|
-
|
|
282
|
-
Si el label debe ser visible. Útil para crear variaciones icon-only.
|
|
283
|
-
|
|
284
|
-
### `showIcon`
|
|
285
|
-
|
|
286
|
-
```typescript
|
|
287
|
-
showIcon?: boolean
|
|
288
|
-
// default: true
|
|
289
|
-
```
|
|
290
|
-
|
|
291
|
-
Si el icono debe ser visible. Útil para crear variaciones label-only.
|
|
292
|
-
|
|
293
|
-
### `className`
|
|
294
|
-
|
|
295
|
-
```typescript
|
|
296
|
-
className?: string
|
|
297
|
-
// default: ''
|
|
298
|
-
```
|
|
299
|
-
|
|
300
|
-
Clases CSS adicionales personalizadas.
|
|
301
|
-
|
|
302
|
-
## 🎨 Diseño del Sistema
|
|
303
|
-
|
|
304
|
-
### Colores (según `docs/colors.md`)
|
|
305
|
-
|
|
306
|
-
| Token | Valor | Uso |
|
|
307
|
-
|-------|-------|-----|
|
|
308
|
-
| `primary-custom-600` | #0e79fd | Color principal del icono en estados selected/hover |
|
|
309
|
-
| `primary-custom-100` | #dbeefe | Background del icon container en hover/selected |
|
|
310
|
-
| `content-primary` | - | Color del texto y iconos por defecto |
|
|
311
|
-
| `content-tertiary` | - | Color del texto deshabilitado |
|
|
312
|
-
| `red-700` | #b91c1c | Color del badge |
|
|
313
|
-
|
|
314
|
-
### Tipografía (según `docs/typography.md`)
|
|
315
|
-
|
|
316
|
-
| Elemento | Estilo | Valores |
|
|
317
|
-
|----------|--------|--------|
|
|
318
|
-
| Label | Label XXSmall | 10px Bold, leading 12px |
|
|
319
|
-
| Badge | Label Tiny | 10px Bold |
|
|
320
|
-
|
|
321
|
-
### Espaciado (según `docs/spacing.md`)
|
|
322
|
-
|
|
323
|
-
| Elemento | Espaciado |
|
|
324
|
-
|----------|-----------|
|
|
325
|
-
| Icon container padding | px-4 py-1 (16px h, 4px v) |
|
|
326
|
-
| Gap icon-label | gap-1 (4px) |
|
|
327
|
-
| Contenedor padding | px-0.5 (2px) |
|
|
328
|
-
|
|
329
|
-
### Sombras (según `docs/shadows.md`)
|
|
330
|
-
|
|
331
|
-
| Estado | Sombra |
|
|
332
|
-
|--------|--------|
|
|
333
|
-
| Focus | shadow-[0px_0px_0px_2px_rgba(219,238,254,1),0px_1px_2px_0px_rgba(0,0,0,0.05),0px_0px_0px_4px_rgba(96,182,250,1)] |
|
|
334
|
-
|
|
335
|
-
## ♿ Accesibilidad
|
|
336
|
-
|
|
337
|
-
El componente cumple con estándares WCAG:
|
|
338
|
-
|
|
339
|
-
- ✅ **ARIA Labels**: `aria-label` personalizable
|
|
340
|
-
- ✅ **ARIA State**: `aria-current="page"` cuando está selected
|
|
341
|
-
- ✅ **Disabled State**: `aria-disabled` y `disabled` attributes
|
|
342
|
-
- ✅ **Keyboard Navigation**: Focus ring adaptativo (2px)
|
|
343
|
-
- ✅ **Color Contrast**: Ratios WCAG AA/AAA en light y dark mode
|
|
344
|
-
- ✅ **Touch Targets**: Mínimo 44x44px (56x56px real)
|
|
345
|
-
|
|
346
|
-
### Keyboard Navigation
|
|
347
|
-
|
|
348
|
-
```html
|
|
349
|
-
<!-- Tab para navegar -->
|
|
350
|
-
<!-- Enter/Space para activar -->
|
|
351
|
-
<!-- Navega entre items del NavigationRail -->
|
|
352
|
-
```
|
|
353
|
-
|
|
354
|
-
## 🔄 Relación con Otros Componentes
|
|
355
|
-
|
|
356
|
-
### NavigationRail
|
|
357
|
-
|
|
358
|
-
`NavigationRailItem` está diseñado para usarse dentro de `NavigationRail`, aunque puede usarse de forma independiente.
|
|
359
|
-
|
|
360
|
-
```tsx
|
|
361
|
-
import { NavigationRail } from 'siesa-ui-kit/components/NavigationRail';
|
|
362
|
-
|
|
363
|
-
<NavigationRail
|
|
364
|
-
items={[
|
|
365
|
-
{ id: 'home', icon: <HomeIcon />, label: 'Inicio', selected: true },
|
|
366
|
-
{ id: 'search', icon: <SearchIcon />, label: 'Buscar' },
|
|
367
|
-
]}
|
|
368
|
-
/>
|
|
369
|
-
```
|
|
370
|
-
|
|
371
|
-
### Button
|
|
372
|
-
|
|
373
|
-
Comparte la misma estructura de estados y tokens que el componente `Button`:
|
|
374
|
-
|
|
375
|
-
- Estados similares (default, hover, selected, focus, disabled)
|
|
376
|
-
- Tipografía del sistema (aunque tamaños diferentes)
|
|
377
|
-
- Focus rings adaptativos
|
|
378
|
-
- Dark mode completo
|
|
379
|
-
|
|
380
|
-
## 🧪 Testing
|
|
381
|
-
|
|
382
|
-
### Data Attributes
|
|
383
|
-
|
|
384
|
-
Para facilitar testing:
|
|
385
|
-
|
|
386
|
-
```html
|
|
387
|
-
<button data-item-id="home" data-testid="navigation-rail-item-home" data-badge>
|
|
388
|
-
...
|
|
389
|
-
</button>
|
|
390
|
-
```
|
|
391
|
-
|
|
392
|
-
### Ejemplos de Tests
|
|
393
|
-
|
|
394
|
-
```typescript
|
|
395
|
-
// Vitest / Jest
|
|
396
|
-
import { render, screen } from '@testing-library/react';
|
|
397
|
-
import { NavigationRailItem } from './NavigationRailItem';
|
|
398
|
-
import { HomeIcon } from '@heroicons/react/24/outline';
|
|
399
|
-
|
|
400
|
-
describe('NavigationRailItem', () => {
|
|
401
|
-
it('renders with label', () => {
|
|
402
|
-
render(<NavigationRailItem icon={<HomeIcon />} label="Inicio" id="home" />);
|
|
403
|
-
expect(screen.getByText('Inicio')).toBeInTheDocument();
|
|
404
|
-
});
|
|
405
|
-
|
|
406
|
-
it('shows badge count', () => {
|
|
407
|
-
render(
|
|
408
|
-
<NavigationRailItem
|
|
409
|
-
icon={<HomeIcon />}
|
|
410
|
-
label="Inicio"
|
|
411
|
-
id="home"
|
|
412
|
-
badgeCount={5}
|
|
413
|
-
/>
|
|
414
|
-
);
|
|
415
|
-
expect(screen.getByText('5')).toBeInTheDocument();
|
|
416
|
-
});
|
|
417
|
-
|
|
418
|
-
it('disables when disabled prop is true', () => {
|
|
419
|
-
render(
|
|
420
|
-
<NavigationRailItem
|
|
421
|
-
icon={<HomeIcon />}
|
|
422
|
-
label="Inicio"
|
|
423
|
-
id="home"
|
|
424
|
-
disabled={true}
|
|
425
|
-
/>
|
|
426
|
-
);
|
|
427
|
-
expect(screen.getByRole('button')).toBeDisabled();
|
|
428
|
-
});
|
|
429
|
-
|
|
430
|
-
it('calls onClick when clicked', () => {
|
|
431
|
-
const handleClick = vi.fn();
|
|
432
|
-
render(
|
|
433
|
-
<NavigationRailItem
|
|
434
|
-
icon={<HomeIcon />}
|
|
435
|
-
label="Inicio"
|
|
436
|
-
id="home"
|
|
437
|
-
onClick={handleClick}
|
|
438
|
-
/>
|
|
439
|
-
);
|
|
440
|
-
screen.getByRole('button').click();
|
|
441
|
-
expect(handleClick).toHaveBeenCalled();
|
|
442
|
-
});
|
|
443
|
-
});
|
|
444
|
-
```
|
|
445
|
-
|
|
446
|
-
## 📚 Referencias
|
|
447
|
-
|
|
448
|
-
- **Figma**: [node 4294-22931](https://www.figma.com/design/5XNqf2YTxvwemxwo1LMQ6j/Siesa-UI-Kit?node-id=4294-22931)
|
|
449
|
-
- **Docs de colores**: [docs/colors.md](../../docs/colors.md)
|
|
450
|
-
- **Docs de tipografía**: [docs/typography.md](../../docs/typography.md)
|
|
451
|
-
- **Docs de espaciado**: [docs/spacing.md](../../docs/spacing.md)
|
|
452
|
-
- **Docs de sombras**: [docs/shadows.md](../../docs/shadows.md)
|
|
453
|
-
- **Componente NavigationRail**: [NavigationRail](../NavigationRail/README.md)
|
|
454
|
-
- **Componente Button**: [Button](../Button/README.md) (referencia de estructura)
|
|
455
|
-
|
|
456
|
-
## 📝 Changelog
|
|
457
|
-
|
|
458
|
-
### v1.0.0 (Inicial)
|
|
459
|
-
|
|
460
|
-
- ✨ Componente NavigationRailItem creado
|
|
461
|
-
- ✨ Todos los estados implementados (Enabled, Hover, Selected, Focus, Disabled)
|
|
462
|
-
- ✨ Badges de notificación (dot y contador)
|
|
463
|
-
- ✨ Dark Mode completo
|
|
464
|
-
- ✨ Accesibilidad WCAG completa
|
|
465
|
-
- ✨ Stories completas en Storybook
|
|
466
|
-
- ✨ TypeScript types
|
|
467
|
-
- ✨ JSDoc completo
|
|
468
|
-
- ✨ README documentado
|
|
469
|
-
|
|
470
|
-
## 📄 Licencia
|
|
471
|
-
|
|
472
|
-
Parte del Sistema de Diseño Siesa UI Kit. © 2024 Siesa.
|
|
473
|
-
|
|
474
|
-
---
|
|
475
|
-
|
|
476
|
-
**Última actualización**: 24 de diciembre de 2024
|
|
1
|
+
# NavigationRailItem
|
|
2
|
+
|
|
3
|
+
Componente individual de item para la barra de navegación vertical (NavigationRail) del sistema de diseño Siesa UI Kit.
|
|
4
|
+
|
|
5
|
+
## 📋 Descripción
|
|
6
|
+
|
|
7
|
+
`NavigationRailItem` es un componente independiente que representa un item seleccionable dentro de una `NavigationRail`. Proporciona acceso rápido a destinos principales mediante un icono, label opcional y badges de notificación.
|
|
8
|
+
|
|
9
|
+
**Implementación pixel-perfect** según Figma (node 4294-22931) con soporte completo para todos los estados, dark mode y accesibilidad.
|
|
10
|
+
|
|
11
|
+
## 🎯 Características
|
|
12
|
+
|
|
13
|
+
- ✅ **Ancho fijo de 56px** según especificaciones de Figma
|
|
14
|
+
- ✅ **Estados completos**: Enabled, Hover, Selected, Focus, Disabled
|
|
15
|
+
- ✅ **Badges de notificación**: Dot simple o contador numérico (99+ para >99)
|
|
16
|
+
- ✅ **Tipografía del sistema**: Label XXSmall (10px Bold, leading 12px)
|
|
17
|
+
- ✅ **Dark Mode completo**: Colores invertidos en todos los estados
|
|
18
|
+
- ✅ **Focus rings adaptativos**: Accesibilidad y keyboard navigation
|
|
19
|
+
- ✅ **Iconos flexibles**: Soporta cualquier librería (Heroicons, React Icons, etc.)
|
|
20
|
+
- ✅ **ARIA completo**: aria-label, aria-current, aria-disabled
|
|
21
|
+
- ✅ **Tokens del sistema**: NO colores hardcodeados
|
|
22
|
+
|
|
23
|
+
## 📐 Especificaciones de Figma
|
|
24
|
+
|
|
25
|
+
### Dimensiones
|
|
26
|
+
- **Ancho**: 56px (w-14)
|
|
27
|
+
- **Altura**: Auto (flex-col)
|
|
28
|
+
- **Icon container**: 32px altura, 16px padding horizontal
|
|
29
|
+
- **Gap icon-label**: 4px (gap-1)
|
|
30
|
+
- **Border radius icon**: 9999px (rounded-full)
|
|
31
|
+
|
|
32
|
+
### Estados Visuales
|
|
33
|
+
|
|
34
|
+
| Estado | Background | Icon Color | Label Color | Cursor |
|
|
35
|
+
|--------|-----------|-----------|-----------|--------|
|
|
36
|
+
| **Enabled** | Transparent | content-primary | content-primary | pointer |
|
|
37
|
+
| **Hover** | primary-custom-100 | primary-custom-600 | content-primary | pointer |
|
|
38
|
+
| **Selected** | primary-custom-100 | primary-custom-600 | content-primary | pointer |
|
|
39
|
+
| **Focus** | primary-custom-100 + ring | primary-custom-600 | content-primary | pointer |
|
|
40
|
+
| **Disabled** | Transparent (opacity 55%) | content-tertiary | content-tertiary | not-allowed |
|
|
41
|
+
|
|
42
|
+
### Badge
|
|
43
|
+
|
|
44
|
+
- **Tamaño**: 13x13px
|
|
45
|
+
- **Border radius**: rounded-full (9999px)
|
|
46
|
+
- **Posición**: Absoluta (-top-0.5, left-[34px])
|
|
47
|
+
- **Color**: Red 700 (#b91c1c)
|
|
48
|
+
- **Tipografía**: 10px Bold
|
|
49
|
+
- **Tipos**:
|
|
50
|
+
- **Dot**: Badge simple sin número
|
|
51
|
+
- **Contador**: Número 1-99+
|
|
52
|
+
|
|
53
|
+
### Focus Ring (Accesibilidad)
|
|
54
|
+
|
|
55
|
+
Según Figma node 4294-22931, el focus ring tiene estas características:
|
|
56
|
+
|
|
57
|
+
```css
|
|
58
|
+
ring: 2px (#60b6fa)
|
|
59
|
+
offset: 2px (#dbeefe)
|
|
60
|
+
shadow: 0px_0px_0px_2px_#dbeefe, 0px_1px_2px_0px_rgba(0,0,0,0.05), 0px_0px_0px_4px_#60b6fa
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## 🎨 Dark Mode
|
|
64
|
+
|
|
65
|
+
El componente invierte automáticamente sus colores en dark mode:
|
|
66
|
+
|
|
67
|
+
- **Background**: bg-primary-custom-600/30
|
|
68
|
+
- **Icon**: text-white (selected), dark-content-primary (default)
|
|
69
|
+
- **Label**: dark-content-primary
|
|
70
|
+
- **Focus ring**: dark-border-custom
|
|
71
|
+
|
|
72
|
+
Usa la estrategia `class` de Tailwind CSS:
|
|
73
|
+
|
|
74
|
+
```tsx
|
|
75
|
+
<div className="dark">
|
|
76
|
+
<NavigationRailItem label="Inicio" selected={true} />
|
|
77
|
+
</div>
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## 💻 Uso
|
|
81
|
+
|
|
82
|
+
### Instalación
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
npm install siesa-ui-kit
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Ejemplo Básico
|
|
89
|
+
|
|
90
|
+
```tsx
|
|
91
|
+
import { NavigationRailItem } from 'siesa-ui-kit/components/NavigationRailItem';
|
|
92
|
+
import { HomeIcon } from '@heroicons/react/24/outline';
|
|
93
|
+
|
|
94
|
+
export function App() {
|
|
95
|
+
return (
|
|
96
|
+
<NavigationRailItem
|
|
97
|
+
id="home"
|
|
98
|
+
icon={<HomeIcon />}
|
|
99
|
+
label="Inicio"
|
|
100
|
+
selected={true}
|
|
101
|
+
onClick={() => navigate('/')}
|
|
102
|
+
/>
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Con Badge
|
|
108
|
+
|
|
109
|
+
```tsx
|
|
110
|
+
import { BellIcon } from '@heroicons/react/24/outline';
|
|
111
|
+
|
|
112
|
+
<NavigationRailItem
|
|
113
|
+
id="notifications"
|
|
114
|
+
icon={<BellIcon />}
|
|
115
|
+
label="Notificaciones"
|
|
116
|
+
badgeCount={5}
|
|
117
|
+
/>
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Deshabilitado
|
|
121
|
+
|
|
122
|
+
```tsx
|
|
123
|
+
import { StarIcon } from '@heroicons/react/24/outline';
|
|
124
|
+
|
|
125
|
+
<NavigationRailItem
|
|
126
|
+
id="premium"
|
|
127
|
+
icon={<StarIcon />}
|
|
128
|
+
label="Premium"
|
|
129
|
+
disabled={true}
|
|
130
|
+
/>
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### Solo Icono
|
|
134
|
+
|
|
135
|
+
```tsx
|
|
136
|
+
<NavigationRailItem
|
|
137
|
+
id="home"
|
|
138
|
+
icon={<HomeIcon />}
|
|
139
|
+
label="Inicio"
|
|
140
|
+
showLabelText={false}
|
|
141
|
+
/>
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### En un NavigationRail
|
|
145
|
+
|
|
146
|
+
```tsx
|
|
147
|
+
import { NavigationRail } from 'siesa-ui-kit/components/NavigationRail';
|
|
148
|
+
import { NavigationRailItem } from 'siesa-ui-kit/components/NavigationRailItem';
|
|
149
|
+
|
|
150
|
+
export function Navbar() {
|
|
151
|
+
const [selected, setSelected] = React.useState('home');
|
|
152
|
+
|
|
153
|
+
const items = [
|
|
154
|
+
{ id: 'home', icon: <HomeIcon />, label: 'Inicio' },
|
|
155
|
+
{ id: 'search', icon: <SearchIcon />, label: 'Buscar' },
|
|
156
|
+
{ id: 'notifications', icon: <BellIcon />, label: 'Notificaciones', badgeCount: 3 },
|
|
157
|
+
];
|
|
158
|
+
|
|
159
|
+
return (
|
|
160
|
+
<nav className="flex gap-3">
|
|
161
|
+
{items.map((item) => (
|
|
162
|
+
<NavigationRailItem
|
|
163
|
+
key={item.id}
|
|
164
|
+
id={item.id}
|
|
165
|
+
icon={item.icon}
|
|
166
|
+
label={item.label}
|
|
167
|
+
badgeCount={item.badgeCount}
|
|
168
|
+
selected={selected === item.id}
|
|
169
|
+
onClick={() => setSelected(item.id)}
|
|
170
|
+
/>
|
|
171
|
+
))}
|
|
172
|
+
</nav>
|
|
173
|
+
);
|
|
174
|
+
}
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
## 📖 Props
|
|
178
|
+
|
|
179
|
+
### `icon` (Required)
|
|
180
|
+
|
|
181
|
+
```typescript
|
|
182
|
+
icon: ReactNode
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
Icono a mostrar. Tamaño recomendado: 16x16px.
|
|
186
|
+
|
|
187
|
+
**Ejemplos:**
|
|
188
|
+
- Heroicons: `<HomeIcon />`
|
|
189
|
+
- React Icons: `<FiHome />`
|
|
190
|
+
- SVG inline: `<svg>...</svg>`
|
|
191
|
+
|
|
192
|
+
### `label` (Required)
|
|
193
|
+
|
|
194
|
+
```typescript
|
|
195
|
+
label: string
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
Texto del label que aparece debajo del icono. Se muestra en tipografía Label XXSmall (10px Bold).
|
|
199
|
+
|
|
200
|
+
### `selected`
|
|
201
|
+
|
|
202
|
+
```typescript
|
|
203
|
+
selected?: boolean
|
|
204
|
+
// default: false
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
Si el item está seleccionado actualmente. Cambia el background a primary-custom-100 y el icono a primary-custom-600.
|
|
208
|
+
|
|
209
|
+
### `disabled`
|
|
210
|
+
|
|
211
|
+
```typescript
|
|
212
|
+
disabled?: boolean
|
|
213
|
+
// default: false
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
Si el item está deshabilitado. Reduce la opacidad a 55%, cambia el cursor a not-allowed y desactiva la interactividad.
|
|
217
|
+
|
|
218
|
+
### `badge`
|
|
219
|
+
|
|
220
|
+
```typescript
|
|
221
|
+
badge?: boolean
|
|
222
|
+
// default: false
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
Mostrar badge de notificación simple (dot rojo). Se ignora si `badgeCount` está definido.
|
|
226
|
+
|
|
227
|
+
### `badgeCount`
|
|
228
|
+
|
|
229
|
+
```typescript
|
|
230
|
+
badgeCount?: number
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
Número a mostrar en el badge. Reemplaza el dot simple. Si es mayor a 99, muestra "99+".
|
|
234
|
+
|
|
235
|
+
### `onClick`
|
|
236
|
+
|
|
237
|
+
```typescript
|
|
238
|
+
onClick?: () => void
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
Callback cuando se hace click en el item.
|
|
242
|
+
|
|
243
|
+
**Nota:** Se ejecuta incluso si el item está disabled (pero el botón no es clickeable).
|
|
244
|
+
|
|
245
|
+
### `ariaLabel`
|
|
246
|
+
|
|
247
|
+
```typescript
|
|
248
|
+
ariaLabel?: string
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
Label para accesibilidad (ARIA). Si no se proporciona, usa el valor de `label`.
|
|
252
|
+
|
|
253
|
+
**Ejemplo:**
|
|
254
|
+
```tsx
|
|
255
|
+
<NavigationRailItem
|
|
256
|
+
label="Inicio"
|
|
257
|
+
ariaLabel="Ir a la página de inicio del sitio web"
|
|
258
|
+
/>
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
### `id`
|
|
262
|
+
|
|
263
|
+
```typescript
|
|
264
|
+
id?: string
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
ID único del item. Se usa para identificarlo en navegación y se añade como atributo `data-item-id`.
|
|
268
|
+
|
|
269
|
+
**Ejemplo:**
|
|
270
|
+
```tsx
|
|
271
|
+
<NavigationRailItem id="home" label="Inicio" />
|
|
272
|
+
// Genera: <button data-item-id="home">...</button>
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
### `showLabelText`
|
|
276
|
+
|
|
277
|
+
```typescript
|
|
278
|
+
showLabelText?: boolean
|
|
279
|
+
// default: true
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
Si el label debe ser visible. Útil para crear variaciones icon-only.
|
|
283
|
+
|
|
284
|
+
### `showIcon`
|
|
285
|
+
|
|
286
|
+
```typescript
|
|
287
|
+
showIcon?: boolean
|
|
288
|
+
// default: true
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
Si el icono debe ser visible. Útil para crear variaciones label-only.
|
|
292
|
+
|
|
293
|
+
### `className`
|
|
294
|
+
|
|
295
|
+
```typescript
|
|
296
|
+
className?: string
|
|
297
|
+
// default: ''
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
Clases CSS adicionales personalizadas.
|
|
301
|
+
|
|
302
|
+
## 🎨 Diseño del Sistema
|
|
303
|
+
|
|
304
|
+
### Colores (según `docs/colors.md`)
|
|
305
|
+
|
|
306
|
+
| Token | Valor | Uso |
|
|
307
|
+
|-------|-------|-----|
|
|
308
|
+
| `primary-custom-600` | #0e79fd | Color principal del icono en estados selected/hover |
|
|
309
|
+
| `primary-custom-100` | #dbeefe | Background del icon container en hover/selected |
|
|
310
|
+
| `content-primary` | - | Color del texto y iconos por defecto |
|
|
311
|
+
| `content-tertiary` | - | Color del texto deshabilitado |
|
|
312
|
+
| `red-700` | #b91c1c | Color del badge |
|
|
313
|
+
|
|
314
|
+
### Tipografía (según `docs/typography.md`)
|
|
315
|
+
|
|
316
|
+
| Elemento | Estilo | Valores |
|
|
317
|
+
|----------|--------|--------|
|
|
318
|
+
| Label | Label XXSmall | 10px Bold, leading 12px |
|
|
319
|
+
| Badge | Label Tiny | 10px Bold |
|
|
320
|
+
|
|
321
|
+
### Espaciado (según `docs/spacing.md`)
|
|
322
|
+
|
|
323
|
+
| Elemento | Espaciado |
|
|
324
|
+
|----------|-----------|
|
|
325
|
+
| Icon container padding | px-4 py-1 (16px h, 4px v) |
|
|
326
|
+
| Gap icon-label | gap-1 (4px) |
|
|
327
|
+
| Contenedor padding | px-0.5 (2px) |
|
|
328
|
+
|
|
329
|
+
### Sombras (según `docs/shadows.md`)
|
|
330
|
+
|
|
331
|
+
| Estado | Sombra |
|
|
332
|
+
|--------|--------|
|
|
333
|
+
| Focus | shadow-[0px_0px_0px_2px_rgba(219,238,254,1),0px_1px_2px_0px_rgba(0,0,0,0.05),0px_0px_0px_4px_rgba(96,182,250,1)] |
|
|
334
|
+
|
|
335
|
+
## ♿ Accesibilidad
|
|
336
|
+
|
|
337
|
+
El componente cumple con estándares WCAG:
|
|
338
|
+
|
|
339
|
+
- ✅ **ARIA Labels**: `aria-label` personalizable
|
|
340
|
+
- ✅ **ARIA State**: `aria-current="page"` cuando está selected
|
|
341
|
+
- ✅ **Disabled State**: `aria-disabled` y `disabled` attributes
|
|
342
|
+
- ✅ **Keyboard Navigation**: Focus ring adaptativo (2px)
|
|
343
|
+
- ✅ **Color Contrast**: Ratios WCAG AA/AAA en light y dark mode
|
|
344
|
+
- ✅ **Touch Targets**: Mínimo 44x44px (56x56px real)
|
|
345
|
+
|
|
346
|
+
### Keyboard Navigation
|
|
347
|
+
|
|
348
|
+
```html
|
|
349
|
+
<!-- Tab para navegar -->
|
|
350
|
+
<!-- Enter/Space para activar -->
|
|
351
|
+
<!-- Navega entre items del NavigationRail -->
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
## 🔄 Relación con Otros Componentes
|
|
355
|
+
|
|
356
|
+
### NavigationRail
|
|
357
|
+
|
|
358
|
+
`NavigationRailItem` está diseñado para usarse dentro de `NavigationRail`, aunque puede usarse de forma independiente.
|
|
359
|
+
|
|
360
|
+
```tsx
|
|
361
|
+
import { NavigationRail } from 'siesa-ui-kit/components/NavigationRail';
|
|
362
|
+
|
|
363
|
+
<NavigationRail
|
|
364
|
+
items={[
|
|
365
|
+
{ id: 'home', icon: <HomeIcon />, label: 'Inicio', selected: true },
|
|
366
|
+
{ id: 'search', icon: <SearchIcon />, label: 'Buscar' },
|
|
367
|
+
]}
|
|
368
|
+
/>
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
### Button
|
|
372
|
+
|
|
373
|
+
Comparte la misma estructura de estados y tokens que el componente `Button`:
|
|
374
|
+
|
|
375
|
+
- Estados similares (default, hover, selected, focus, disabled)
|
|
376
|
+
- Tipografía del sistema (aunque tamaños diferentes)
|
|
377
|
+
- Focus rings adaptativos
|
|
378
|
+
- Dark mode completo
|
|
379
|
+
|
|
380
|
+
## 🧪 Testing
|
|
381
|
+
|
|
382
|
+
### Data Attributes
|
|
383
|
+
|
|
384
|
+
Para facilitar testing:
|
|
385
|
+
|
|
386
|
+
```html
|
|
387
|
+
<button data-item-id="home" data-testid="navigation-rail-item-home" data-badge>
|
|
388
|
+
...
|
|
389
|
+
</button>
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
### Ejemplos de Tests
|
|
393
|
+
|
|
394
|
+
```typescript
|
|
395
|
+
// Vitest / Jest
|
|
396
|
+
import { render, screen } from '@testing-library/react';
|
|
397
|
+
import { NavigationRailItem } from './NavigationRailItem';
|
|
398
|
+
import { HomeIcon } from '@heroicons/react/24/outline';
|
|
399
|
+
|
|
400
|
+
describe('NavigationRailItem', () => {
|
|
401
|
+
it('renders with label', () => {
|
|
402
|
+
render(<NavigationRailItem icon={<HomeIcon />} label="Inicio" id="home" />);
|
|
403
|
+
expect(screen.getByText('Inicio')).toBeInTheDocument();
|
|
404
|
+
});
|
|
405
|
+
|
|
406
|
+
it('shows badge count', () => {
|
|
407
|
+
render(
|
|
408
|
+
<NavigationRailItem
|
|
409
|
+
icon={<HomeIcon />}
|
|
410
|
+
label="Inicio"
|
|
411
|
+
id="home"
|
|
412
|
+
badgeCount={5}
|
|
413
|
+
/>
|
|
414
|
+
);
|
|
415
|
+
expect(screen.getByText('5')).toBeInTheDocument();
|
|
416
|
+
});
|
|
417
|
+
|
|
418
|
+
it('disables when disabled prop is true', () => {
|
|
419
|
+
render(
|
|
420
|
+
<NavigationRailItem
|
|
421
|
+
icon={<HomeIcon />}
|
|
422
|
+
label="Inicio"
|
|
423
|
+
id="home"
|
|
424
|
+
disabled={true}
|
|
425
|
+
/>
|
|
426
|
+
);
|
|
427
|
+
expect(screen.getByRole('button')).toBeDisabled();
|
|
428
|
+
});
|
|
429
|
+
|
|
430
|
+
it('calls onClick when clicked', () => {
|
|
431
|
+
const handleClick = vi.fn();
|
|
432
|
+
render(
|
|
433
|
+
<NavigationRailItem
|
|
434
|
+
icon={<HomeIcon />}
|
|
435
|
+
label="Inicio"
|
|
436
|
+
id="home"
|
|
437
|
+
onClick={handleClick}
|
|
438
|
+
/>
|
|
439
|
+
);
|
|
440
|
+
screen.getByRole('button').click();
|
|
441
|
+
expect(handleClick).toHaveBeenCalled();
|
|
442
|
+
});
|
|
443
|
+
});
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
## 📚 Referencias
|
|
447
|
+
|
|
448
|
+
- **Figma**: [node 4294-22931](https://www.figma.com/design/5XNqf2YTxvwemxwo1LMQ6j/Siesa-UI-Kit?node-id=4294-22931)
|
|
449
|
+
- **Docs de colores**: [docs/colors.md](../../docs/colors.md)
|
|
450
|
+
- **Docs de tipografía**: [docs/typography.md](../../docs/typography.md)
|
|
451
|
+
- **Docs de espaciado**: [docs/spacing.md](../../docs/spacing.md)
|
|
452
|
+
- **Docs de sombras**: [docs/shadows.md](../../docs/shadows.md)
|
|
453
|
+
- **Componente NavigationRail**: [NavigationRail](../NavigationRail/README.md)
|
|
454
|
+
- **Componente Button**: [Button](../Button/README.md) (referencia de estructura)
|
|
455
|
+
|
|
456
|
+
## 📝 Changelog
|
|
457
|
+
|
|
458
|
+
### v1.0.0 (Inicial)
|
|
459
|
+
|
|
460
|
+
- ✨ Componente NavigationRailItem creado
|
|
461
|
+
- ✨ Todos los estados implementados (Enabled, Hover, Selected, Focus, Disabled)
|
|
462
|
+
- ✨ Badges de notificación (dot y contador)
|
|
463
|
+
- ✨ Dark Mode completo
|
|
464
|
+
- ✨ Accesibilidad WCAG completa
|
|
465
|
+
- ✨ Stories completas en Storybook
|
|
466
|
+
- ✨ TypeScript types
|
|
467
|
+
- ✨ JSDoc completo
|
|
468
|
+
- ✨ README documentado
|
|
469
|
+
|
|
470
|
+
## 📄 Licencia
|
|
471
|
+
|
|
472
|
+
Parte del Sistema de Diseño Siesa UI Kit. © 2024 Siesa.
|
|
473
|
+
|
|
474
|
+
---
|
|
475
|
+
|
|
476
|
+
**Última actualización**: 24 de diciembre de 2024
|