@ajuarezso/sui-design-system 0.20.0 → 0.21.0
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/docs/INDEX.md +51 -51
- package/docs/sui-alert/README.md +13 -0
- package/docs/sui-badge/README.md +17 -0
- package/docs/sui-banner/README.md +190 -0
- package/docs/sui-breadcrumb-item/README.md +96 -0
- package/docs/sui-breadcrumbs/README.md +122 -0
- package/docs/sui-button/README.md +17 -0
- package/docs/sui-card/README.md +168 -0
- package/docs/sui-chart-legend/README.md +140 -0
- package/docs/sui-chart-legend-dot/README.md +118 -0
- package/docs/sui-checkbox-card/README.md +150 -0
- package/docs/sui-compact-select/README.md +127 -0
- package/docs/sui-compact-select-for-input/README.md +117 -0
- package/docs/sui-content-card/README.md +147 -0
- package/docs/sui-content-label/README.md +148 -0
- package/docs/sui-counter-input/README.md +145 -0
- package/docs/sui-date-selector/README.md +98 -0
- package/docs/sui-datepicker/README.md +193 -0
- package/docs/sui-day-cell/README.md +118 -0
- package/docs/sui-day-label/README.md +81 -0
- package/docs/sui-drawer-footer/README.md +127 -0
- package/docs/sui-drawer-header/README.md +140 -0
- package/docs/sui-empty-state/README.md +145 -0
- package/docs/sui-file-upload/README.md +154 -0
- package/docs/sui-file-upload-card/README.md +129 -0
- package/docs/sui-image-upload/README.md +200 -0
- package/docs/sui-image-upload-profile/README.md +145 -0
- package/docs/sui-inline-input/README.md +104 -0
- package/docs/sui-inline-select/README.md +101 -0
- package/docs/sui-input/README.md +244 -0
- package/docs/sui-integration-switch/README.md +142 -0
- package/docs/sui-notification/README.md +179 -0
- package/docs/sui-notification-footer/README.md +98 -0
- package/docs/sui-notification-tab-menu/README.md +112 -0
- package/docs/sui-otp-input/README.md +116 -0
- package/docs/sui-pagination/README.md +146 -0
- package/docs/sui-password-strength/README.md +99 -0
- package/docs/sui-period-range/README.md +93 -0
- package/docs/sui-popover/README.md +178 -0
- package/docs/sui-product-card/README.md +173 -0
- package/docs/sui-radio-card/README.md +160 -0
- package/docs/sui-rating/README.md +7 -6
- package/docs/sui-rich-editor/README.md +114 -0
- package/docs/sui-select/README.md +180 -0
- package/docs/sui-stepper/README.md +166 -0
- package/docs/sui-store-card/README.md +147 -0
- package/docs/sui-switch-card/README.md +149 -0
- package/docs/sui-tab-chips/README.md +185 -0
- package/docs/sui-tab-menu-horizontal/README.md +142 -0
- package/docs/sui-tab-menu-vertical/README.md +136 -0
- package/docs/sui-tag-input/README.md +120 -0
- package/docs/sui-textarea/README.md +157 -0
- package/docs/sui-time-picker/README.md +237 -0
- package/docs/sui-toast/README.md +190 -0
- package/docs/sui-tooltip/README.md +201 -0
- package/fesm2022/ajuarezso-sui-design-system.mjs +273 -231
- package/fesm2022/ajuarezso-sui-design-system.mjs.map +1 -1
- package/package.json +1 -1
- package/types/ajuarezso-sui-design-system.d.ts +208 -52
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: sui-store-card
|
|
3
|
+
selector: sui-store-card
|
|
4
|
+
resumen: Tarjeta de un local para los listados del cliente con portada, logo, abierto/cerrado, favorito, nota, ubicación, envío y distancia
|
|
5
|
+
alternativas: [sui-product-card (un producto, no un local), sui-content-card (un local en una fila de un panel, sin portada), sui-card (cualquier otro contenido)]
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# sui-store-card
|
|
9
|
+
|
|
10
|
+
Story: [Molecules/Card/Store Card](https://sui-design-system.web.app/?path=/docs/molecules-card-store-card--docs)
|
|
11
|
+
|
|
12
|
+
## Cuándo usarlo / cuándo no
|
|
13
|
+
|
|
14
|
+
**Úsalo** para un local en un listado que ve el cliente (favoritos) y para la vista previa de un
|
|
15
|
+
local que el super admin aprueba o que el dueño revisa antes de publicar.
|
|
16
|
+
|
|
17
|
+
**No lo uses** para:
|
|
18
|
+
|
|
19
|
+
- Un local en una tabla o un ranking de un panel: `sui-content-card` o una fila (sin portada).
|
|
20
|
+
- Un producto: `sui-product-card`.
|
|
21
|
+
- Fuera de la app de Master Pedidos: el link va fijo a `/cliente/restaurante/:id` (ver Trampas).
|
|
22
|
+
|
|
23
|
+
Regla corta: **local en un listado del cliente → store-card · local en un panel → content-card.**
|
|
24
|
+
|
|
25
|
+
## Qué variante usar
|
|
26
|
+
|
|
27
|
+
> **La guía del DS no tiene página de la store card.** Es un componente propio de SUI. Igual que
|
|
28
|
+
> la product card, **dibuja, no decide**: el texto del envío y de la distancia le llega escrito
|
|
29
|
+
> (`deliveryText`, `distanceText`) desde que la tarjeta y el checkout cobraban distinto.
|
|
30
|
+
>
|
|
31
|
+
> Uso medido el 03-10-2026 en `master-pedidos/src/app` (misma exclusión que `sui-card`): **2
|
|
32
|
+
> store-cards en 2 archivos**: favoritos del cliente (`pages/customer/favorites/favorites.html:121`,
|
|
33
|
+
> con `deliveryText` y `distanceText`) y la cola de aprobación
|
|
34
|
+
> (`pages/super-admin/master-approvals/master-approvals.html:32`, en vista previa). El inicio del
|
|
35
|
+
> cliente arma sus filas de locales con clases propias.
|
|
36
|
+
|
|
37
|
+
### Los estados (salen de `store`)
|
|
38
|
+
|
|
39
|
+
| estado | cuándo | fuente |
|
|
40
|
+
|---|---|---|
|
|
41
|
+
| `isOpen: true` | Abierto: chip verde «Abierto». | propuesta |
|
|
42
|
+
| `isOpen: false` | Cerrado: chip «Cerrado» y la portada en gris; sigue abriendo la carta (se puede mirar). | propuesta |
|
|
43
|
+
| `isSuspended: true` | No se puede pedir: «No disponible», toda la tarjeta al 60 % y sin link. | propuesta |
|
|
44
|
+
| `isOwnerPreview` + `ownerPreviewStatus` | Vista previa: «Borrador», «En revisión» o «Rechazado»; sin corazón, sin nota ni distancia (solo ubicación y envío). | propuesta |
|
|
45
|
+
|
|
46
|
+
### Las piezas
|
|
47
|
+
|
|
48
|
+
| prop | cuándo | fuente |
|
|
49
|
+
|---|---|---|
|
|
50
|
+
| `store` (obligatorio) | Siempre, con `SuiStoreCardData`. | propuesta |
|
|
51
|
+
| `deliveryText` string | **Siempre en pantallas nuevas**: el texto del envío calculado por la app (`StateService.computeDeliveryFee`). | propuesta (precedente: favoritos) |
|
|
52
|
+
| `deliveryText = null` | No hay envío que mostrar: la columna desaparece y el distrito deja de cortarse. | propuesta |
|
|
53
|
+
| `deliveryText` sin pasar | La tarjeta lo deduce de `deliveryType` (Gratis / Recojo / Courier / S/ X). Solo para no romper lo viejo. | propuesta |
|
|
54
|
+
| `distanceText` | Lo mismo para la distancia: un rango mientras es estimada («menos de 500 m»), el número cuando la ruta se midió («475 m»). `null` la quita. | propuesta |
|
|
55
|
+
| `isFavorite` + `(toggleFavorite)` | El corazón lleno o vacío; el padre guarda el favorito. | propuesta |
|
|
56
|
+
| `(ratingClicked)` | La nota abre las opiniones y la info del local (`StoreRatingsModalService`). | propuesta |
|
|
57
|
+
| `disableLink` | La tarjeta no navega (una vitrina, una lámina, una vista previa). | propuesta |
|
|
58
|
+
|
|
59
|
+
**Usos de hoy que rompen las reglas:** 0. A mirar: la cola de aprobación no pasa
|
|
60
|
+
`deliveryText` (deduce el envío del `deliveryType`).
|
|
61
|
+
|
|
62
|
+
## Tamaño en mobile y en web
|
|
63
|
+
|
|
64
|
+
El ancho lo da el contenedor. El `size` cambia **el corazón de favorito**, en la escala del
|
|
65
|
+
`sui-button`:
|
|
66
|
+
|
|
67
|
+
| size | corazón | glyph | fuente |
|
|
68
|
+
|---|---|---|---|
|
|
69
|
+
| `small` (default) | 36 × 36 | 18 | lo que había en el DS |
|
|
70
|
+
| `medium` | 40 × 40 | 20 | canon (aprobado por el dueño, 03-10-2026): extensión SUI |
|
|
71
|
+
|
|
72
|
+
| uso | mobile | web | fuente |
|
|
73
|
+
|---|---|---|---|
|
|
74
|
+
| tarjeta | ancho completo | celda de una grilla de 2–3 columnas (≥ 300 de ancho) | lo que hay en la app |
|
|
75
|
+
| corazón de favorito | `medium` (40) | `small` (36) | propuesta: el tamaño es extensión SUI aprobada (03-10-2026); el «cuándo» falta aprobarlo |
|
|
76
|
+
| nota (abre las opiniones) | el alto de su columna (~40) | ~40 | lo que hay en el DS |
|
|
77
|
+
|
|
78
|
+
```html
|
|
79
|
+
<sui-store-card [store]="local" [size]="bp.isMobile() ? 'medium' : 'small'" />
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## «No usar»: por qué no hoy y cuándo sí
|
|
83
|
+
|
|
84
|
+
| qué | por qué no hoy | cuándo sí, en un flujo nuevo |
|
|
85
|
+
|---|---|---|
|
|
86
|
+
| `deliveryText` / `distanceText` sin pasar | la tarjeta deduciría un precio distinto del checkout | nunca en pantallas nuevas |
|
|
87
|
+
| la tarjeta en un ancho menor a ~300 | la fila de 4 datos se pisa | nunca: con menos ancho, pasa `null` a la distancia o al envío |
|
|
88
|
+
|
|
89
|
+
## API
|
|
90
|
+
|
|
91
|
+
<!-- api:inicio -->
|
|
92
|
+
<!-- generada: no editar a mano — `npm run docs` -->
|
|
93
|
+
|
|
94
|
+
| input | tipo | default |
|
|
95
|
+
|---|---|---|
|
|
96
|
+
| `store` | `SuiStoreCardData` | — (requerido) |
|
|
97
|
+
| `isFavorite` | `boolean` | `false` |
|
|
98
|
+
| `disableLink` | `boolean` | `false` |
|
|
99
|
+
| `linkBase` | `string` | `'/cliente/restaurante'` |
|
|
100
|
+
| `size` | `'small' \| 'medium'` | `'small'` |
|
|
101
|
+
| `deliveryText` | `string \| null` | `undefined` |
|
|
102
|
+
| `distanceText` | `string \| null` | `undefined` |
|
|
103
|
+
|
|
104
|
+
| output | payload |
|
|
105
|
+
|---|---|
|
|
106
|
+
| `toggleFavorite` | `Event` |
|
|
107
|
+
| `ratingClicked` | `{ id: string; name: string; logoUrl: string \| null }` |
|
|
108
|
+
<!-- api:fin -->
|
|
109
|
+
|
|
110
|
+
`SuiStoreCardData`: `id`, `name` y opcionales `businessType`, `district`, `rating`,
|
|
111
|
+
`reviewCount`, `distanceKm`, `deliveryFee`, `deliveryType`, `offersPickup`, `isOpen`,
|
|
112
|
+
`isSuspended`, `isOwnerPreview`, `ownerPreviewStatus`, `ownerRejectionReason`,
|
|
113
|
+
`isOwnerApproved`, `logoUrl`, `coverUrl`.
|
|
114
|
+
|
|
115
|
+
## Trampas
|
|
116
|
+
|
|
117
|
+
- **El link va a `[linkBase, store.id]`** (`RouterLink` adentro). `linkBase` es
|
|
118
|
+
`'/cliente/restaurante'` por defecto (la ruta del cliente de Master Pedidos); otra app pasa la
|
|
119
|
+
suya. Para no navegar, `disableLink`.
|
|
120
|
+
- **Los botones (corazón, nota) viven dentro del `<a>`** de la tarjeta: un control interactivo
|
|
121
|
+
dentro de un link es HTML inválido. Cortan la propagación y el `preventDefault`, así que
|
|
122
|
+
funcionan; queda pendiente pasarla al patrón de `sui-product-card` (link estirado).
|
|
123
|
+
- **`null` y «no pasar» no son lo mismo** en `deliveryText` / `distanceText`: `null` quita la
|
|
124
|
+
columna, `undefined` la deduce.
|
|
125
|
+
- La nota sale como «4.62 (38)», con punto y hasta dos decimales; **sin opiniones dice «5.0
|
|
126
|
+
(0)»** a propósito (el cero se ve).
|
|
127
|
+
- `ownerRejectionReason` e `isOwnerApproved` están en la interfaz pero la tarjeta **no los
|
|
128
|
+
dibuja**: el motivo del rechazo y el aviso de «ya estás público» van afuera.
|
|
129
|
+
- Un `distanceText` largo («menos de 500 m») en una tarjeta angosta **parte en dos líneas** por
|
|
130
|
+
palabras (desde 03-10-2026; antes se salía de su columna). La columna no baja de 64 px; la nota
|
|
131
|
+
y el envío no se encogen, y el distrito se recorta con «…».
|
|
132
|
+
- La portada carga con `loading="lazy"` y reintenta sola (`suiImgRetry`); sin portada queda el
|
|
133
|
+
degradé oscuro.
|
|
134
|
+
- Los íconos usan `color="var(--sui-primary-base, #fa7319)"`: el hex es respaldo, no se repite
|
|
135
|
+
afuera.
|
|
136
|
+
|
|
137
|
+
## Ejemplo
|
|
138
|
+
|
|
139
|
+
```html
|
|
140
|
+
<sui-store-card
|
|
141
|
+
[store]="local"
|
|
142
|
+
[isFavorite]="true"
|
|
143
|
+
[deliveryText]="envioDeLaTarjeta(local)"
|
|
144
|
+
[distanceText]="distanciaDeLaTarjeta(local)"
|
|
145
|
+
(toggleFavorite)="quitarFavorito(local.id)"
|
|
146
|
+
(ratingClicked)="abrirOpiniones($event)" />
|
|
147
|
+
```
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: sui-switch-card
|
|
3
|
+
selector: sui-switch-card
|
|
4
|
+
resumen: Ajuste con tarjeta (ícono, título, descripción y el interruptor) que se aplica al instante
|
|
5
|
+
alternativas: [sui-switch-label (el mismo ajuste sin tarjeta, en una lista de ajustes), sui-integration-switch (una integración con logo y «Administrar»), sui-checkbox-card (varias opciones que se guardan con «Guardar»)]
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# sui-switch-card
|
|
9
|
+
|
|
10
|
+
Story: [Molecules/Card/Switch Card](https://sui-design-system.web.app/?path=/docs/molecules-card-switch-card--docs)
|
|
11
|
+
|
|
12
|
+
## Cuándo usarlo / cuándo no
|
|
13
|
+
|
|
14
|
+
**Úsalo** para un ajuste que se prende o se apaga **al toque**, sin botón de guardar, y que merece
|
|
15
|
+
su propia tarjeta: «Notificaciones», «Ubicación siempre», «Recibir pedidos de la plataforma»,
|
|
16
|
+
«Repartidores propios», «Disponible».
|
|
17
|
+
|
|
18
|
+
**No lo uses** para:
|
|
19
|
+
|
|
20
|
+
- Algo que se confirma después con «Guardar»: `sui-checkbox-card` (canon del switch-label).
|
|
21
|
+
- Una lista larga de ajustes parecidos: `sui-switch-label` con `flip`, uno por fila.
|
|
22
|
+
- Una integración con otro servicio (logo + «Administrar»): `sui-integration-switch`.
|
|
23
|
+
- Algo destructivo o que no se deshace: un botón con confirmación.
|
|
24
|
+
|
|
25
|
+
Regla corta: **ajuste con peso, al toque → switch-card · lista de ajustes → switch-label con flip
|
|
26
|
+
· se guarda después → checkbox-card.**
|
|
27
|
+
|
|
28
|
+
## Qué variante usar
|
|
29
|
+
|
|
30
|
+
> **La guía del DS no tiene página de la switch card.** De la guía sale lo del switch que lleva
|
|
31
|
+
> adentro: **«para prender o apagar un ajuste de forma inmediata»**.
|
|
32
|
+
>
|
|
33
|
+
> Uso medido el 03-10-2026 en `master-pedidos/src/app` (misma exclusión que `sui-card`): **26
|
|
34
|
+
> switch-cards en 8 archivos**. Tipos: 19 `left-icon` (los 19 con el ícono proyectado), 7 `basic`
|
|
35
|
+
> (5 de ellos sin `type`). Tamaños: 20 `bp.controlSize()`, 6 sin `size`. 10 viven en formularios
|
|
36
|
+
> que se guardan con un botón.
|
|
37
|
+
|
|
38
|
+
### `type` (el leading)
|
|
39
|
+
|
|
40
|
+
| type | cuándo | fuente |
|
|
41
|
+
|---|---|---|
|
|
42
|
+
| `left-icon` + ícono proyectado | Lo normal: `<sui-icon sui-switch-card-leading name="…" [size]="20" />`. | propuesta (19 de 26) |
|
|
43
|
+
| `left-icon` + `emoji` | Ver «No usar». | propuesta |
|
|
44
|
+
| `basic` | El ajuste es EL tema de la pantalla y no necesita ícono («Disponible» en el inicio del repartidor, «Disponibilidad automática»). | propuesta |
|
|
45
|
+
| `avatar` (`imageUrl`) | Ver «No usar». | propuesta |
|
|
46
|
+
| `card-provider`, `brand`, `company` (`imageUrl` o proyectado) | Ver «No usar». | propuesta |
|
|
47
|
+
|
|
48
|
+
### Las piezas
|
|
49
|
+
|
|
50
|
+
| prop | cuándo | fuente |
|
|
51
|
+
|---|---|---|
|
|
52
|
+
| `label` | Siempre. Qué hace prenderlo, sin cambiar con el estado: «Notificaciones», no «Activadas / Desactivadas». | propuesta (misma regla que el switch-label) |
|
|
53
|
+
| `description` | La consecuencia o el estado real del permiso: «Push activado — recibes alertas cuando se te asigna un pedido.» | propuesta |
|
|
54
|
+
| `sublabel` | Precisión corta: «(beta)». | propuesta |
|
|
55
|
+
| `badge` | Solo novedad. Con string sale azul `light`. | propuesta |
|
|
56
|
+
| `disabled` | Mientras se guarda el cambio, o cuando no aplica (no puedes estar disponible sin saldo). | propuesta |
|
|
57
|
+
| `checked` + `(checkedChange)` | Siempre los dos: es controlada. | propuesta |
|
|
58
|
+
|
|
59
|
+
### `size` (el interruptor de adentro)
|
|
60
|
+
|
|
61
|
+
| size | cuándo | fuente |
|
|
62
|
+
|---|---|---|
|
|
63
|
+
| `xlarge` (48 × 28) | Mobile, vía `bp.controlSize()`. | canon (aprobado por el dueño, 28-09-2026: «componentes grandes») |
|
|
64
|
+
| `large` (40 × 24) | Desktop, vía `bp.controlSize()`. | canon (aprobado por el dueño, 28-09-2026) |
|
|
65
|
+
| `medium` (default) | No usar en pantallas nuevas. | canon (aprobado por el dueño, 28-09-2026) |
|
|
66
|
+
|
|
67
|
+
**Usos de hoy que rompen las reglas:**
|
|
68
|
+
|
|
69
|
+
- **10 switch-cards en formularios que se guardan con un botón** (van `sui-checkbox-card`): los 5
|
|
70
|
+
métodos de pago de `pages/mi-negocio/mi-negocio.html:1181`–`:1217` («Guardar cambios») y 5 de
|
|
71
|
+
`pages/super-admin/master-settings/master-settings.html` (`:36` «Pausar los pedidos», `:179`,
|
|
72
|
+
`:336`, `:342`, `:349`, cada uno con su «Guardar…» abajo).
|
|
73
|
+
- **6 sin `size`**: los 5 de `master-settings` de arriba y `pages/notifications/notifications.html:59`
|
|
74
|
+
(«Sonidos de la app»).
|
|
75
|
+
|
|
76
|
+
## Tamaño en mobile y en web
|
|
77
|
+
|
|
78
|
+
La card entera se toca (≥ 72 con descripción): llega al piso de 44 sola. El `size` cambia solo el
|
|
79
|
+
interruptor.
|
|
80
|
+
|
|
81
|
+
| uso | mobile | web |
|
|
82
|
+
|---|---|---|
|
|
83
|
+
| toda switch-card | `xlarge` (48 × 28) | `large` (40 × 24) |
|
|
84
|
+
|
|
85
|
+
```html
|
|
86
|
+
<sui-switch-card [size]="bp.controlSize()" … /> <!-- isMobile() ? 'xlarge' : 'large' -->
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## «No usar»: por qué no hoy y cuándo sí
|
|
90
|
+
|
|
91
|
+
| qué | por qué no hoy | cuándo sí, en un flujo nuevo |
|
|
92
|
+
|---|---|---|
|
|
93
|
+
| `emoji` (0 usos) | los ajustes de hoy llevan un ícono Remix | un ajuste de los grandes del rol que quiera el emoji animado del catálogo (`SuiEmoji`) |
|
|
94
|
+
| `type="avatar"` (0 usos) | no se prende ni apaga a una persona | prender o apagar a un repartidor de tu flota |
|
|
95
|
+
| `type="brand"` / `"company"` / `"card-provider"` (0 usos) | no hay integraciones | casi nunca: una integración es `sui-integration-switch` |
|
|
96
|
+
| `size="medium"` | el interruptor de 32 × 20 se pierde en el teléfono | una tabla densa solo de desktop |
|
|
97
|
+
|
|
98
|
+
## API
|
|
99
|
+
|
|
100
|
+
<!-- api:inicio -->
|
|
101
|
+
<!-- generada: no editar a mano — `npm run docs` -->
|
|
102
|
+
|
|
103
|
+
| input | tipo | default |
|
|
104
|
+
|---|---|---|
|
|
105
|
+
| `type` | `'basic' \| 'left-icon' \| 'avatar' \| 'card-provider' \| 'brand' \| 'company'` | `'basic'` |
|
|
106
|
+
| `size` | `'medium' \| 'large' \| 'xlarge'` | `'medium'` |
|
|
107
|
+
| `label` | `string` | `''` |
|
|
108
|
+
| `sublabel` | `string \| null` | `null` |
|
|
109
|
+
| `description` | `string \| null` | `null` |
|
|
110
|
+
| `emoji` | `SuiEmojiName \| null` | `null` |
|
|
111
|
+
| `imageUrl` | `string \| null` | `null` |
|
|
112
|
+
| `badge` | `SuiBadgeConfig \| string \| null` | `null` |
|
|
113
|
+
| `checked` | `boolean` | `false` |
|
|
114
|
+
| `disabled` | `boolean` | `false` |
|
|
115
|
+
|
|
116
|
+
| output | payload |
|
|
117
|
+
|---|---|
|
|
118
|
+
| `checkedChange` | `boolean` |
|
|
119
|
+
<!-- api:fin -->
|
|
120
|
+
|
|
121
|
+
Slot: `[sui-switch-card-leading]` (el ícono o el logo). Implementa `ControlValueAccessor`.
|
|
122
|
+
|
|
123
|
+
## Trampas
|
|
124
|
+
|
|
125
|
+
- **Es controlada**: `checked` es input y `checkedChange` solo avisa. Si no actualizas tu señal,
|
|
126
|
+
el interruptor no se mueve (al revés que `sui-checkbox-card`).
|
|
127
|
+
- **`type="left-icon"` sin `emoji` ni nada proyectado deja el círculo vacío.** El ícono se
|
|
128
|
+
proyecta con el atributo **`sui-switch-card-leading`** (no `slot=`).
|
|
129
|
+
- No tiene `icon` como input (la radio y la checkbox card sí): el ícono siempre va proyectado.
|
|
130
|
+
- `avatar` siempre dibuja un `sui-avatar` con `imageUrl` (si falla, las iniciales del `label`): no usa lo
|
|
131
|
+
proyectado. `card-provider`, `brand` y `company` leen `imageUrl` y, sin ella, usan lo proyectado.
|
|
132
|
+
- Toda la card togglea; el toque sobre el propio switch no cuenta doble.
|
|
133
|
+
- El interruptor siempre va a la derecha (no hay `flip`).
|
|
134
|
+
- `badge` con string sale **azul `light` `small`** (en `sui-switch-label` sale naranja).
|
|
135
|
+
|
|
136
|
+
## Ejemplo
|
|
137
|
+
|
|
138
|
+
```html
|
|
139
|
+
<sui-switch-card
|
|
140
|
+
[size]="bp.controlSize()"
|
|
141
|
+
type="left-icon"
|
|
142
|
+
label="Ubicación siempre"
|
|
143
|
+
[description]="ubicacionTexto()"
|
|
144
|
+
[checked]="ubicacionSiempre()"
|
|
145
|
+
[disabled]="guardando()"
|
|
146
|
+
(checkedChange)="cambiarUbicacion($event)">
|
|
147
|
+
<sui-icon sui-switch-card-leading name="map-pin-line" [size]="20" />
|
|
148
|
+
</sui-switch-card>
|
|
149
|
+
```
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: sui-tab-chips
|
|
3
|
+
selector: sui-tab-chips
|
|
4
|
+
resumen: Fila de chips que se desliza en horizontal para filtrar una lista o saltar entre categorías; siempre hay uno elegido
|
|
5
|
+
alternativas: [sui-segmented-control (2 a 4 modos de la misma vista), sui-tab-menu-horizontal (secciones de contenido distinto), sui-radio-card (elegir un valor de un formulario), sui-tag (chip que se quita)]
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# sui-tab-chips
|
|
9
|
+
|
|
10
|
+
Story: [Molecules/Tabs/Tab Chips](https://sui-design-system.web.app/?path=/docs/molecules-tabs-tab-chips--docs)
|
|
11
|
+
|
|
12
|
+
## Cuándo usarlo / cuándo no
|
|
13
|
+
|
|
14
|
+
**Úsalo** para:
|
|
15
|
+
|
|
16
|
+
- **Filtrar una lista** por estado, período, rol o zona: «Todos · Activos · Entregados · Cancelados»,
|
|
17
|
+
«Hoy · 7 días · 30 días», los meses de la central.
|
|
18
|
+
- **Saltar entre categorías** de un catálogo que viene de la base («Hamburguesas · Pizzas ·
|
|
19
|
+
Bebidas»), con `sticky` en la carta del local.
|
|
20
|
+
|
|
21
|
+
Sirve cuando las opciones son muchas, cambian según los datos o no caben y tienen que deslizarse.
|
|
22
|
+
|
|
23
|
+
**No lo uses** para:
|
|
24
|
+
|
|
25
|
+
- **2 a 4 modos de la misma vista** (por semana / día vs día): `sui-segmented-control`.
|
|
26
|
+
- **Secciones de contenido distinto** (Ventas · Productos · Repartidores): `sui-tab-menu-horizontal`.
|
|
27
|
+
- **Elegir un valor que se guarda** con un botón (radio de visibilidad, motivo de rechazo,
|
|
28
|
+
sumar o descontar): `sui-radio-card` o `sui-segmented-control`. El tab-chips **siempre tiene uno
|
|
29
|
+
elegido** y no puede quedar vacío (ver Trampas).
|
|
30
|
+
- Un chip que la persona quita: `sui-tag`.
|
|
31
|
+
|
|
32
|
+
Regla corta (la misma del README de `sui-segmented-control`, 03-10-2026): **2-4 modos de la misma
|
|
33
|
+
vista → segmented · secciones → tab menu · filtros o categorías → tab-chips.**
|
|
34
|
+
|
|
35
|
+
## Qué variante usar
|
|
36
|
+
|
|
37
|
+
> **La guía del DS no tiene este componente**: es una extensión de SUI (la «cat nav» de las apps de
|
|
38
|
+
> delivery). Todo lo que sigue es propuesta salvo lo marcado como canon.
|
|
39
|
+
>
|
|
40
|
+
> Uso medido el 03-10-2026 en `master-pedidos/src/app` (sin `master-preview`, `master-prototipos`,
|
|
41
|
+
> `mockup-*`, `dx/*`, `_guia-*`, `master-rutina`, `master-medico`, `master-ejercicios`):
|
|
42
|
+
> **41 usos en 28 archivos `.html`**. `[sticky]="true"`: 1 (carta del local). `count`: 5 listas.
|
|
43
|
+
> `[(value)]`: 2; el resto `[value]` + `(valueChange)`. `autoScroll`: 0. `size`: 0 (no existe en
|
|
44
|
+
> la versión publicada).
|
|
45
|
+
|
|
46
|
+
### Para qué se usa (el contenido de los chips)
|
|
47
|
+
|
|
48
|
+
| caso | cuándo | ejemplo real de la app | fuente |
|
|
49
|
+
|---|---|---|---|
|
|
50
|
+
| filtro de estado | La lista es la misma; los chips la recortan. «Todos» va primero y es el elegido por defecto. | `pages/envios/envios.html:98` («Todos · Activos · Entregados · Cancelados») · `pages/orders/orders.html:64` | propuesta, falta aprobación |
|
|
51
|
+
| filtro de período | Rango de fechas de un reporte o gráfico. | `pages/super-admin/master-earnings/master-earnings.html:11` · `pages/central/central-gastos/central-gastos.html:10` (meses) | propuesta, falta aprobación |
|
|
52
|
+
| categorías del catálogo | Saltar a una categoría de la carta; con `sticky` y `autoScroll`. | `pages/customer/restaurant-menu/restaurant-menu.html:226` | propuesta, falta aprobación |
|
|
53
|
+
| sugerencias rápidas | **No.** Un motivo frecuente que completa un texto no es una selección: el chip elige el primero solo. Si se usa, el primer chip es el neutro («Otro motivo») y el texto lleva su propio signal. | `pages/super-admin/master-orders/master-orders.html:898` (bien resuelto) | propuesta, falta aprobación |
|
|
54
|
+
|
|
55
|
+
### `sticky`
|
|
56
|
+
|
|
57
|
+
| valor | cuándo | fuente |
|
|
58
|
+
|---|---|---|
|
|
59
|
+
| `false` (default) | Filtros arriba de una lista corta o dentro de un modal o sheet. | propuesta, falta aprobación |
|
|
60
|
+
| `true` | Solo la navegación de categorías de una lista larga que scrollea (la carta). Se pega arriba del contenedor de scroll y, pegado, pinta fondo `bg-weak-50`. | propuesta, falta aprobación |
|
|
61
|
+
|
|
62
|
+
### `autoScroll`
|
|
63
|
+
|
|
64
|
+
| valor | cuándo | fuente |
|
|
65
|
+
|---|---|---|
|
|
66
|
+
| `true` (default) | Siempre: centra el chip elegido cuando cambia `value` (también si lo cambia el scroll de la carta). | propuesta, falta aprobación |
|
|
67
|
+
| `false` | Solo si el `value` cambia muy seguido por código y el movimiento distrae. Hoy ningún caso. | propuesta, falta aprobación |
|
|
68
|
+
|
|
69
|
+
### Ítems (`chips`)
|
|
70
|
+
|
|
71
|
+
| qué | cuándo | fuente |
|
|
72
|
+
|---|---|---|
|
|
73
|
+
| `string[]` | Cuando el texto es el valor (meses, provincias). | propuesta, falta aprobación |
|
|
74
|
+
| `{ value, label }` | Cuando el valor es un id o una clave en inglés (`'active'` → «Activos»). | propuesta, falta aprobación |
|
|
75
|
+
| `count` | El número de ítems detrás del filtro, cuando ayuda a decidir («Recargas 3»). `0` o `undefined` no se dibuja. **El número va en `count`, no dentro del `label`.** | propuesta, falta aprobación |
|
|
76
|
+
| texto | Una o dos palabras, sentence case, sin punto. Plural si filtra («Activos»). | canon (copy de `docs/CANON-SUI.md`) |
|
|
77
|
+
|
|
78
|
+
**Usos de hoy que rompen las reglas:**
|
|
79
|
+
|
|
80
|
+
- **3 con un bug real: el motivo escrito a mano rebota al primer chip.** En los modales de rechazo
|
|
81
|
+
del super admin, los chips y el textarea comparten el mismo signal. Cada tecla deja un texto que
|
|
82
|
+
no es ningún chip; el componente vuelve al primero y lo emite, así que el textarea se reescribe con
|
|
83
|
+
«El comprobante no se lee». No se puede escribir un motivo propio, y al abrir el modal ya hay un
|
|
84
|
+
motivo elegido sin que nadie lo toque. `pages/super-admin/master-drivers/master-drivers.html:652`,
|
|
85
|
+
`:924` y `:1002`. Es el mismo bug que se arregló en `master-orders` el 01-09-2026 (signal propio
|
|
86
|
+
para los chips y «Otro motivo» primero).
|
|
87
|
+
- **4 son secciones de contenido distinto** (→ `sui-tab-menu-horizontal` en web; en mobile, a
|
|
88
|
+
discutir porque el tab menu no se desliza, ver su README): `pages/products/products.html:6`
|
|
89
|
+
(«Categorías · Productos · Secciones reutilizables»), `pages/promociones/promociones.html:7`
|
|
90
|
+
(«Carrusel pagado · Push notifications»), `pages/super-admin/master-drivers/master-drivers.html:16`,
|
|
91
|
+
`pages/reports/reports.html:98` («Ventas · Productos · Repartidores · Clientes»).
|
|
92
|
+
- **2 son modos de la misma vista** (→ `sui-segmented-control`):
|
|
93
|
+
`pages/super-admin/master-semanas/master-semanas.html:67` (3 métricas del mismo gráfico) y `:72`
|
|
94
|
+
(«Por semana · Día vs día»).
|
|
95
|
+
- **4 eligen un valor de un formulario** (→ `sui-radio-card` o `sui-segmented-control`):
|
|
96
|
+
`components/option-sections-manager/option-sections-manager.html:175` (a qué se aplica),
|
|
97
|
+
`pages/super-admin/master-drivers/master-drivers.html:98` («Sumar · Descontar»),
|
|
98
|
+
`pages/mi-negocio/mi-negocio.html:938` (radio de visibilidad) y `:973` (tiempo para confirmar).
|
|
99
|
+
A discutir: `pages/customer/checkout/checkout.html:468` (día del pedido programado), que filtra
|
|
100
|
+
las franjas de abajo y se parece más a un filtro.
|
|
101
|
+
- **1 con el número dentro del texto:** `pages/notifications/notifications.ts:191`
|
|
102
|
+
(`No leídas (3)` → `count: 3`).
|
|
103
|
+
- **41 sin tamaño por plataforma** (el input todavía no está publicado): cuando se publique, los de
|
|
104
|
+
pantallas del cliente y del repartidor pasan a `large`.
|
|
105
|
+
|
|
106
|
+
## Tamaño en mobile y en web
|
|
107
|
+
|
|
108
|
+
> `size` está **en el repo del DS (03-10-2026) y no en la versión publicada 0.19.0**. Hasta que se
|
|
109
|
+
> publique, todos miden lo de `medium`.
|
|
110
|
+
|
|
111
|
+
Alto del chip: `small` 32 px · `medium` 36 px (el de siempre, default) · `large` 40 px. Los tres
|
|
112
|
+
con texto de 14 px; cambia el alto y el aire lateral. El scroller suma 12 px arriba y abajo.
|
|
113
|
+
|
|
114
|
+
| uso | mobile | web | fuente |
|
|
115
|
+
|---|---|---|---|
|
|
116
|
+
| filtros y categorías | `large` (40; con el aire del scroller llega a 44+ de área táctil) | `medium` | canon (dueño: tamaño por plataforma, 03-10-2026) |
|
|
117
|
+
| filtros densos en la cabecera de una tabla | — | `small` | propuesta, falta aprobación |
|
|
118
|
+
|
|
119
|
+
```html
|
|
120
|
+
<sui-tab-chips [chips]="filtros" [(value)]="filtro" [size]="bp.isMobile() ? 'large' : 'medium'" />
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## «No usar»: por qué no hoy y cuándo sí
|
|
124
|
+
|
|
125
|
+
| qué | por qué no hoy | cuándo sí, en un flujo nuevo |
|
|
126
|
+
|---|---|---|
|
|
127
|
+
| `autoScroll` en `false` | ningún caso cambia el valor tan seguido como para que moleste | una vista que sincroniza el chip con un scroll muy rápido y el movimiento distrae |
|
|
128
|
+
| `sticky` fuera de la carta | en una lista corta tapa contenido sin ayudar | otra lista larga por categorías (un catálogo de bodega con muchas secciones) |
|
|
129
|
+
| `small` en mobile | 32 px no llega al dedo | nunca en mobile |
|
|
130
|
+
|
|
131
|
+
## API
|
|
132
|
+
|
|
133
|
+
<!-- api:inicio -->
|
|
134
|
+
<!-- generada: no editar a mano — `npm run docs` -->
|
|
135
|
+
|
|
136
|
+
| input | tipo | default |
|
|
137
|
+
|---|---|---|
|
|
138
|
+
| `chips` | `readonly (string \| SuiTabChipItem)[]` | — (requerido) |
|
|
139
|
+
| `value` · model, `[(value)]` | `string` | `''` |
|
|
140
|
+
| `sticky` | `boolean` | `false` |
|
|
141
|
+
| `size` | `'small' \| 'medium' \| 'large'` | `'medium'` |
|
|
142
|
+
| `autoScroll` | `boolean` | `true` |
|
|
143
|
+
|
|
144
|
+
Outputs: ninguno.
|
|
145
|
+
<!-- api:fin -->
|
|
146
|
+
|
|
147
|
+
```ts
|
|
148
|
+
interface SuiTabChipItem {
|
|
149
|
+
value: string;
|
|
150
|
+
label: string;
|
|
151
|
+
count?: number; // 0 o undefined no se dibuja
|
|
152
|
+
}
|
|
153
|
+
type SuiTabChipsSize = 'small' | 'medium' | 'large'; // repo del DS, no en 0.19.0
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
## Trampas
|
|
157
|
+
|
|
158
|
+
- **Siempre hay uno elegido.** Si `value` está vacío o no coincide con ningún chip, el componente
|
|
159
|
+
elige el **primero y lo emite** por `valueChange`. No existe «ninguno». Si el valor también lo
|
|
160
|
+
escribe otro control (un textarea), cada tecla rebota al primer chip: usa un signal propio para
|
|
161
|
+
los chips.
|
|
162
|
+
- **`value` es `string`.** Para números (km, minutos) hay que convertir en los dos sentidos
|
|
163
|
+
(`radioEfectivo() + ''` y `+$event`).
|
|
164
|
+
- **Lleva `role="tablist"`** aunque se use como filtro: el lector de pantalla lo anuncia como pestañas.
|
|
165
|
+
- **No tiene padding lateral propio**: lo pone la pantalla. Sí trae 12 px arriba y abajo.
|
|
166
|
+
- **`sticky` cambia el host a `display: contents`**: las clases que le pongas al host dejan de
|
|
167
|
+
pintar caja (márgenes, anchos). Pon el estilo en un contenedor.
|
|
168
|
+
- **Pegado, el fondo es `bg-weak-50`**: sobre una página blanca se nota la franja gris.
|
|
169
|
+
Con `sticky` el sentinel agrega 16 px arriba.
|
|
170
|
+
- **`count` en 0 no se dibuja**: no sirve para decir «0 pendientes».
|
|
171
|
+
- **El chip activo es oscuro** (`bg-strong-950`), no naranja: es el estilo del componente, no se
|
|
172
|
+
cambia por pantalla.
|
|
173
|
+
|
|
174
|
+
## Ejemplo
|
|
175
|
+
|
|
176
|
+
```html
|
|
177
|
+
<!-- Filtro de estado: «Todos» primero -->
|
|
178
|
+
<sui-tab-chips
|
|
179
|
+
[chips]="[{ value: 'todos', label: 'Todos' }, { value: 'activos', label: 'Activos' },
|
|
180
|
+
{ value: 'entregados', label: 'Entregados' }, { value: 'cancelados', label: 'Cancelados' }]"
|
|
181
|
+
[(value)]="filtro" />
|
|
182
|
+
|
|
183
|
+
<!-- Categorías de la carta -->
|
|
184
|
+
<sui-tab-chips [chips]="categorias()" [value]="categoria()" (valueChange)="irA($event)" [sticky]="true" />
|
|
185
|
+
```
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: sui-tab-menu-horizontal
|
|
3
|
+
selector: sui-tab-menu-horizontal
|
|
4
|
+
resumen: Pestañas subrayadas para cambiar entre secciones de contenido distinto dentro de una pantalla
|
|
5
|
+
alternativas: [sui-tab-chips (filtros o categorías que se deslizan), sui-segmented-control (2 a 4 modos de la misma vista), sui-tab-menu-vertical (menú lateral de ajustes en web)]
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# sui-tab-menu-horizontal
|
|
9
|
+
|
|
10
|
+
Story: [Molecules/Tabs/Tab Menu Horizontal](https://sui-design-system.web.app/?path=/docs/molecules-tabs-tab-menu-horizontal--docs)
|
|
11
|
+
|
|
12
|
+
## Cuándo usarlo / cuándo no
|
|
13
|
+
|
|
14
|
+
**Úsalo** para cambiar entre **secciones de contenido distinto** de la misma pantalla o detalle:
|
|
15
|
+
«Opiniones · Información» en el modal del local, «Ventas · Productos · Repartidores · Clientes» en
|
|
16
|
+
reportes. Cada pestaña muestra otra cosa, no la misma lista recortada.
|
|
17
|
+
|
|
18
|
+
**No lo uses** para:
|
|
19
|
+
|
|
20
|
+
- **Filtrar una lista** o saltar entre categorías: `sui-tab-chips`.
|
|
21
|
+
- **2 a 4 modos de la misma vista** (cuadrícula o lista): `sui-segmented-control`.
|
|
22
|
+
- **Secciones que no entran a lo ancho en mobile** (4 con nombres largos o con `number`, o 5+): el
|
|
23
|
+
componente no se desliza y las pestañas se salen de la pantalla (ver Trampas). Ahí, por ahora,
|
|
24
|
+
`sui-tab-chips`.
|
|
25
|
+
- Un menú lateral de ajustes en web: `sui-tab-menu-vertical`.
|
|
26
|
+
|
|
27
|
+
Regla corta (README de `sui-segmented-control`, 03-10-2026): **2-4 modos de la misma vista →
|
|
28
|
+
segmented · secciones → tab menu · filtros → tab-chips.**
|
|
29
|
+
|
|
30
|
+
## Qué variante usar
|
|
31
|
+
|
|
32
|
+
> **Lo que dice la guía del DS**: es un layout lineal para **cambiar entre secciones o categorías**.
|
|
33
|
+
> Muestra un ejemplo con pestañas que **desbordan y se deslizan**, y su pestaña mide 48 px de alto
|
|
34
|
+
> (toda la franja es tocable). No trae do/don't ni tamaños.
|
|
35
|
+
>
|
|
36
|
+
> Uso medido el 03-10-2026 en `master-pedidos/src/app` (misma exclusión que `sui-badge`):
|
|
37
|
+
> **1 uso**: `components/store-ratings-modal/store-ratings-modal.html:43` («Opiniones ·
|
|
38
|
+
> Información»), sin `size`, sin ícono, sin `number`.
|
|
39
|
+
|
|
40
|
+
### Ítems (`tabs`)
|
|
41
|
+
|
|
42
|
+
| qué | cuándo | fuente |
|
|
43
|
+
|---|---|---|
|
|
44
|
+
| texto | Lo normal: el nombre de la sección, una o dos palabras. | según la guía del DS (ejemplos con texto) |
|
|
45
|
+
| `icon` | Solo si **todas** las pestañas llevan ícono y ayuda a reconocerlas. Nunca en una sola. | propuesta, falta aprobación |
|
|
46
|
+
| `number` | Pendientes **que piden acción** dentro de esa sección («Solicitudes 3»). Es un círculo rojo: no lo uses para totales neutros. | propuesta, falta aprobación |
|
|
47
|
+
| `rightIcon` | No: la flecha dice «te lleva a otra pantalla» y una pestaña no navega. | propuesta, falta aprobación |
|
|
48
|
+
| `disabled` | Una sección que existe pero no aplica todavía (depende del plan). | propuesta, falta aprobación |
|
|
49
|
+
|
|
50
|
+
### `size`
|
|
51
|
+
|
|
52
|
+
| size | cuándo | fuente |
|
|
53
|
+
|---|---|---|
|
|
54
|
+
| `medium` (default) | El único que cambia algo: **ninguno**. El input existe pero no tiene estilos; los cuatro valores se ven igual. No lo pases. | según el código (`sui-tab-menu-horizontal.scss`: no hay reglas por tamaño) |
|
|
55
|
+
| `small` · `large` · `xlarge` | No usar: no hacen nada. | según el código |
|
|
56
|
+
|
|
57
|
+
**Usos de hoy que rompen las reglas:**
|
|
58
|
+
|
|
59
|
+
- **0** en este componente. Los casos que deberían ser tab menu y hoy son `sui-tab-chips` están en el
|
|
60
|
+
README de `sui-tab-chips` (4: `pages/products/products.html:6`, `pages/promociones/promociones.html:7`,
|
|
61
|
+
`pages/super-admin/master-drivers/master-drivers.html:16`, `pages/reports/reports.html:98`).
|
|
62
|
+
- **A verificar en mobile:** el uso actual es del modal del local, que el cliente abre en el
|
|
63
|
+
teléfono. La pestaña mide 20 px de alto tocable (ver Tamaño).
|
|
64
|
+
|
|
65
|
+
## Tamaño en mobile y en web
|
|
66
|
+
|
|
67
|
+
Cada pestaña ocupa **todo el alto de la franja**, así que lo tocable es la franja entera (desde
|
|
68
|
+
03-10-2026; antes eran solo los 20 px del texto). El `size` cambia ese alto y el texto:
|
|
69
|
+
|
|
70
|
+
| size | franja tocable (+ 2 de bordes) | texto | ícono | gap | fuente |
|
|
71
|
+
|---|---|---|---|---|---|
|
|
72
|
+
| `small` | 40 | `label-sm` 14/20 | 20 | 20 | canon (aprobado por el dueño, 03-10-2026): extensión SUI |
|
|
73
|
+
| `medium` (default) | 48 | `label-sm` 14/20 | 20 | 24 | Figma |
|
|
74
|
+
| `large` | 52 | `label-md` 16/24 | 20 | 24 | canon (aprobado por el dueño, 03-10-2026): extensión SUI |
|
|
75
|
+
| `xlarge` | 56 | `label-md` 16/24 | 24 | 28 | canon (aprobado por el dueño, 03-10-2026): extensión SUI |
|
|
76
|
+
|
|
77
|
+
| uso | mobile | web | fuente |
|
|
78
|
+
|---|---|---|---|
|
|
79
|
+
| 2-3 secciones | `large` (52, texto 16) | `medium` (48) | propuesta: el tamaño es extensión SUI aprobada (03-10-2026); el «cuándo» falta aprobarlo |
|
|
80
|
+
| 4+ secciones | si no entran a 390 px, se salen sin poder deslizarse (las 4 del panel de repartidores, con sus números, ya no entran a 360): va `sui-tab-chips` | el mismo | según el código |
|
|
81
|
+
|
|
82
|
+
```html
|
|
83
|
+
<sui-tab-menu-horizontal [tabs]="secciones" [(active)]="seccion" [size]="bp.isMobile() ? 'large' : 'medium'" />
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## «No usar»: por qué no hoy y cuándo sí
|
|
87
|
+
|
|
88
|
+
| qué | por qué no hoy | cuándo sí, en un flujo nuevo |
|
|
89
|
+
|---|---|---|
|
|
90
|
+
| `rightIcon` | una pestaña no lleva a otra pantalla | nunca en pestañas; es del tab menu vertical cuando cada ítem abre una página |
|
|
91
|
+
| `icon` | ningún caso de hoy lo necesita | secciones con ícono reconocible en las tres (Mapa · Lista · Fotos) en web |
|
|
92
|
+
| `number` | ninguna sección del único uso tiene pendientes | «Solicitudes» o «Recargas» del panel de repartidores, si se pasa a tab menu |
|
|
93
|
+
| `disabled` | ninguna sección bloqueada | una sección que depende del plan («Reportes» en plan básico) |
|
|
94
|
+
|
|
95
|
+
## API
|
|
96
|
+
|
|
97
|
+
<!-- api:inicio -->
|
|
98
|
+
<!-- generada: no editar a mano — `npm run docs` -->
|
|
99
|
+
|
|
100
|
+
| input | tipo | default |
|
|
101
|
+
|---|---|---|
|
|
102
|
+
| `tabs` | `SuiTabMenuHorizontalItem<T>[]` | — (requerido) |
|
|
103
|
+
| `active` · model, `[(active)]` | `T` | `undefined` |
|
|
104
|
+
| `size` | `'small' \| 'medium' \| 'large' \| 'xlarge'` | `'medium'` |
|
|
105
|
+
|
|
106
|
+
| output | payload |
|
|
107
|
+
|---|---|
|
|
108
|
+
| `tabChange` | `T` |
|
|
109
|
+
<!-- api:fin -->
|
|
110
|
+
|
|
111
|
+
```ts
|
|
112
|
+
interface SuiTabMenuHorizontalItem<T = string> {
|
|
113
|
+
value: T;
|
|
114
|
+
label: string;
|
|
115
|
+
icon?: string; // RemixIcon, 20 px
|
|
116
|
+
rightIcon?: boolean; // flecha en píldora
|
|
117
|
+
number?: number; // círculo rojo; 0/undefined no se dibuja
|
|
118
|
+
disabled?: boolean;
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## Trampas
|
|
123
|
+
|
|
124
|
+
- **Sin `active` no se marca ninguna pestaña.** Pásale siempre un valor inicial.
|
|
125
|
+
- **No se desliza.** El track no tiene `overflow-x`: con muchas pestañas en un ancho chico se salen
|
|
126
|
+
del contenedor. La guía del DS sí lo resuelve; SUI todavía no.
|
|
127
|
+
- **El área tocable es toda la franja** (40–56 según `size`), desde 03-10-2026: el aire de 14 px
|
|
128
|
+
que Figma pone en el contenedor ahora va dentro de cada pestaña. Si algo de afuera le pone
|
|
129
|
+
padding al `.sui-tab-menu-horizontal__track`, la franja crece al doble.
|
|
130
|
+
- **Emite dos veces**: `tabChange` y `activeChange`. Con `[(active)]` no hace falta `(tabChange)`.
|
|
131
|
+
- **Trae bordes arriba y abajo** (`stroke-soft-200`) y fondo blanco: no lo metas en una card que ya
|
|
132
|
+
tiene borde, o quedan dos líneas.
|
|
133
|
+
- El ícono de la pestaña activa es `strong-950`, no naranja; en el tab menu vertical es naranja.
|
|
134
|
+
Es a propósito.
|
|
135
|
+
|
|
136
|
+
## Ejemplo
|
|
137
|
+
|
|
138
|
+
```html
|
|
139
|
+
<sui-tab-menu-horizontal
|
|
140
|
+
[tabs]="[{ value: 'opiniones', label: 'Opiniones' }, { value: 'info', label: 'Información' }]"
|
|
141
|
+
[(active)]="tab" />
|
|
142
|
+
```
|