@ajuarezso/sui-design-system 0.21.0 → 0.22.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 +25 -30
- package/docs/sui-accordion/README.md +171 -0
- package/docs/sui-activity-feed/README.md +155 -0
- package/docs/sui-activity-filter/README.md +100 -0
- package/docs/sui-button/README.md +19 -0
- package/docs/sui-command-menu-footer/README.md +100 -0
- package/docs/sui-command-menu-item/README.md +140 -0
- package/docs/sui-command-menu-search/README.md +105 -0
- package/docs/sui-compact-select/README.md +4 -1
- package/docs/sui-compact-select-for-input/README.md +3 -0
- package/docs/sui-counter-input/README.md +3 -0
- package/docs/sui-datepicker/README.md +4 -0
- package/docs/sui-dropdown-caption/README.md +92 -0
- package/docs/sui-dropdown-item/README.md +163 -0
- package/docs/sui-dropdown-menu/README.md +196 -0
- package/docs/sui-dropdown-search/README.md +113 -0
- package/docs/sui-filter/README.md +181 -0
- package/docs/sui-href/README.md +85 -0
- package/docs/sui-img-retry/README.md +107 -0
- package/docs/sui-input/README.md +3 -0
- package/docs/sui-modal/README.md +238 -0
- package/docs/sui-modal-footer/README.md +178 -0
- package/docs/sui-modal-header/README.md +115 -0
- package/docs/sui-modal-sheet/README.md +170 -0
- package/docs/sui-page-header/README.md +123 -0
- package/docs/sui-segmented-control/README.md +3 -0
- package/docs/sui-select/README.md +5 -2
- package/docs/sui-sidebar/README.md +217 -0
- package/docs/sui-switch-label/README.md +3 -0
- package/docs/sui-tab-chips/README.md +5 -2
- package/docs/sui-table/README.md +264 -0
- package/docs/sui-tag-input/README.md +3 -0
- package/docs/sui-textarea/README.md +3 -0
- package/docs/sui-time-picker/README.md +3 -0
- package/docs/sui-topbar/README.md +153 -0
- package/docs/sui-topbar-button/README.md +95 -0
- package/docs/sui-topbar-item/README.md +97 -0
- package/docs/sui-topbar-user/README.md +83 -0
- package/fesm2022/ajuarezso-sui-design-system.mjs +32 -29
- package/fesm2022/ajuarezso-sui-design-system.mjs.map +1 -1
- package/package.json +1 -1
- package/types/ajuarezso-sui-design-system.d.ts +18 -16
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: sui-table
|
|
3
|
+
selector: sui-table
|
|
4
|
+
resumen: Tabla de datos — una fila por registro, una columna por dato — para comparar y recorrer listas en web
|
|
5
|
+
alternativas: [tarjetas en grilla con sui-card (la misma lista cuando no entran las columnas), sui-empty-state (no hay nada que listar todavía), sui-pagination (paginar por número de página, debajo de la tabla), sui-activity-feed (historial de quién hizo qué)]
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# sui-table
|
|
9
|
+
|
|
10
|
+
Story: [Organisms/Table](https://sui-design-system.web.app/?path=/docs/organisms-table--docs)
|
|
11
|
+
|
|
12
|
+
## Cuándo usarlo / cuándo no
|
|
13
|
+
|
|
14
|
+
**Úsalo** cuando la persona tiene que **comparar varios registros por las mismas columnas**:
|
|
15
|
+
pedidos, repartidores, gastos, recargas. La tabla sirve si leer en vertical una columna
|
|
16
|
+
(«¿cuál es el monto más alto?», «¿quién no tiene repartidor?») es parte de la decisión.
|
|
17
|
+
|
|
18
|
+
**No lo uses** para:
|
|
19
|
+
|
|
20
|
+
- Una lista donde cada registro se lee solo (sin comparar con el de al lado): tarjetas.
|
|
21
|
+
- Pantallas del cliente o del repartidor en el teléfono: ahí la lista va en tarjetas o
|
|
22
|
+
filas de una columna. La tabla es de las pantallas de gestión (empresa, super admin, central).
|
|
23
|
+
- Un historial de acciones con autor y hora: `sui-activity-feed`.
|
|
24
|
+
- «Todavía no hay nada» a página completa: `sui-empty-state`. La tabla tiene su propio
|
|
25
|
+
vacío (`emptyMessage`), que es otro registro (ver abajo).
|
|
26
|
+
|
|
27
|
+
Regla corta: **comparar por columnas → tabla · leer de a uno → tarjetas · historial → activity feed.**
|
|
28
|
+
|
|
29
|
+
## Qué variante usar
|
|
30
|
+
|
|
31
|
+
> **La guía del DS casi no dice cuándo ni cómo usar la tabla.** Su página la define como «una
|
|
32
|
+
> estructura de dos dimensiones donde cada fila es un ítem y cada columna un dato del ítem»,
|
|
33
|
+
> muestra un solo ejemplo (un directorio de personas **con selección por checkbox**), le pone
|
|
34
|
+
> `overflow-x-auto` al contenedor y deriva el orden, la selección y la paginación a una
|
|
35
|
+
> librería externa. No trae do/don't, tamaños ni comportamiento en mobile. Casi todo lo de
|
|
36
|
+
> abajo es **práctica de la app** o **propuesta, falta aprobación**; lo marcado «canon» sale de
|
|
37
|
+
> `master-pedidos/CLAUDE.md` o de `docs/CANON-SUI.md`.
|
|
38
|
+
>
|
|
39
|
+
> Uso medido el 03-10-2026 en `master-pedidos/src/app`: **9 tablas** en 7 pantallas, sin contar
|
|
40
|
+
> prototipos ni vitrinas (`master-preview`, `master-prototipos`, `mockup-sheets-*`, `dx/*`,
|
|
41
|
+
> `master-rutina`, `master-medico`, `dev-index`). `sortable`, `selectable` y `striped`: 0 usos.
|
|
42
|
+
> `sticky`: 1, en una vitrina.
|
|
43
|
+
|
|
44
|
+
### Lo que sí dice la guía del DS
|
|
45
|
+
|
|
46
|
+
- **Qué es**: filas = ítems, columnas = datos del ítem.
|
|
47
|
+
- **Partes**: cabecera, filas con hover, celdas con esquinas redondeadas y un **divisor entre
|
|
48
|
+
filas**. SUI lo replica (header gris `bg-weak-50`, filas con radio 12 y divisor de 1 px).
|
|
49
|
+
- **Ancho**: el contenedor scrollea en horizontal (`overflow-x-auto`). En SUI eso pasa solo
|
|
50
|
+
**hasta 767 px** o con una columna `sticky` (ver Trampas).
|
|
51
|
+
- **Selección**: su único ejemplo trae checkbox por fila. En SUI es `selectable`.
|
|
52
|
+
|
|
53
|
+
### Las columnas (`SuiTableColumn`)
|
|
54
|
+
|
|
55
|
+
| prop de columna | cuándo | ejemplo real de la app | fuente |
|
|
56
|
+
|---|---|---|---|
|
|
57
|
+
| `priority: 'leading'` + `descriptionKey` | La **primera** columna: el dato que identifica la fila arriba (14/500) y un dato de apoyo debajo (12/400). Se usa en vez de una plantilla propia para la columna principal. | `pages/orders/orders.ts:278` (pedido + «hace 12 min») · `pages/super-admin/master-orders/master-orders.ts:390` | práctica de la app (7 de 9 tablas) |
|
|
58
|
+
| `priority: 'passive'` | Datos de contexto que no deciden nada: fecha, número de comprobante. Se leen en gris (`text-sub-600`). | `pages/super-admin/master-overview/master-overview.ts:192` | propuesta, falta aprobación |
|
|
59
|
+
| `priority: 'none'` | Columna de acciones (íconos) sin texto propio. Con `label: ''` y `width` fijo. | `pages/super-admin/master-gastos/master-gastos.ts:143` | práctica de la app |
|
|
60
|
+
| `align: 'right'` | Montos. Así se comparan en vertical. | `pages/central/central-gastos/central-gastos.ts:82` | propuesta, falta aprobación |
|
|
61
|
+
| `width` | Columnas de largo fijo: monto, estado, fecha, acciones. | `central-gastos.ts:82-83` | práctica de la app |
|
|
62
|
+
| `minWidth` | Columnas de texto que crecen (nombre, concepto): el piso para que no se aplasten. | `master-orders.ts:392` | práctica de la app |
|
|
63
|
+
| `maxWidth` + `truncate` | Nombres que pueden ser muy largos: corta con «…» y el valor completo sale en tooltip. | `master-overview.ts:193` | práctica de la app |
|
|
64
|
+
|
|
65
|
+
**Una ID nunca es el título de la fila** (`CLAUDE.md`, «Pasada de UX/UI»): la columna `leading`
|
|
66
|
+
lleva el nombre o el número legible del pedido, no el uid.
|
|
67
|
+
|
|
68
|
+
### Plantillas por columna (`suiTableCell`)
|
|
69
|
+
|
|
70
|
+
Si una celda necesita algo más que texto, se proyecta un `<ng-template suiTableCell="<key>" let-row>`.
|
|
71
|
+
Dentro va un componente SUI, no HTML a mano:
|
|
72
|
+
|
|
73
|
+
| contenido | componente | fuente |
|
|
74
|
+
|---|---|---|
|
|
75
|
+
| estado o categoría | `<sui-badge variant="lighter" size="small">` | canon (CANON-SUI §0: «Chip de estado») |
|
|
76
|
+
| acciones de la fila | `<sui-button variant="ghost" color="neutral" size="2xsmall" [onlyIcon]="true">` | canon (README de `sui-button`: tabla densa = `2xsmall`) |
|
|
77
|
+
| prender/apagar | `<sui-switch>` | propuesta, falta aprobación |
|
|
78
|
+
| calificación | `<sui-rating>` de solo lectura | propuesta, falta aprobación |
|
|
79
|
+
|
|
80
|
+
Si la columna tiene plantilla, `descriptionKey` y `truncate` **no se aplican**: solo funcionan en
|
|
81
|
+
el render de texto plano. Por eso `orders.html:94` deja la columna del pedido sin plantilla.
|
|
82
|
+
|
|
83
|
+
### Cargar las filas: cuenta + página por cursor
|
|
84
|
+
|
|
85
|
+
**Canon** (`master-pedidos/CLAUDE.md`, «Performance — Firestore reads»): una pantalla con tabla
|
|
86
|
+
**no baja la colección entera** para mostrar 30 filas. Los totales salen de `getCount`, las filas
|
|
87
|
+
de `getCollectionPage` con cursor, y debajo de la tabla va un «Cargar más»
|
|
88
|
+
(`sui-button variant="stroke" color="neutral"`). Referencia: `pages/orders/orders.ts:716`
|
|
89
|
+
(`loadMore`) y `orders.html:132`.
|
|
90
|
+
|
|
91
|
+
- El orden de la tabla lo fija la consulta (`orderBy`). **No uses `sortable`** sobre una lista
|
|
92
|
+
paginada: ordenaría solo lo cargado y mentiría sobre el resto.
|
|
93
|
+
- `sui-pagination` (números de página) no calza con cursor: Firestore no salta a «la página 7».
|
|
94
|
+
|
|
95
|
+
### Vacío y carga
|
|
96
|
+
|
|
97
|
+
- `loading` pinta 5 filas esqueleto con las columnas reales. Úsalo mientras llega la primera
|
|
98
|
+
página. Canon (memoria del proyecto: skeleton obligatorio en pantalla nueva).
|
|
99
|
+
- `emptyMessage` es una línea con un ícono de bandeja, sin ilustración ni botón. **Canon**
|
|
100
|
+
(CANON-SUI §5.6): no se mezcla con `sui-empty-state`. Escríbelo como en la app, una frase con
|
|
101
|
+
punto: «Nadie recargó en este período.», «Sin gastos registrados todavía.». El default
|
|
102
|
+
`'No hay datos'` no dice nada: siempre se pasa uno propio (los 9 usos lo hacen).
|
|
103
|
+
|
|
104
|
+
## Tamaño en mobile y en web
|
|
105
|
+
|
|
106
|
+
`size` cambia **el alto mínimo de la fila**, no la letra (14 px en todos):
|
|
107
|
+
|
|
108
|
+
| size | alto | nombre en el Figma | fuente |
|
|
109
|
+
|---|---|---|---|
|
|
110
|
+
| `small` | 48 | Large | Figma |
|
|
111
|
+
| `medium` (default) | 64 | X-Large | Figma |
|
|
112
|
+
| `large` | 80 | — | extensión SUI |
|
|
113
|
+
| `xlarge` | 96 | — | extensión SUI |
|
|
114
|
+
|
|
115
|
+
Uso de hoy: 2 `medium` explícitos (`orders`, `drivers`), 1 `small` (`master-overview`, una tabla
|
|
116
|
+
secundaria dentro de un tablero) y 6 sin `size` (o sea `medium`).
|
|
117
|
+
|
|
118
|
+
| uso | mobile | web | fuente |
|
|
119
|
+
|---|---|---|---|
|
|
120
|
+
| tabla principal de una pantalla | `medium` | `medium` | práctica de la app |
|
|
121
|
+
| tabla secundaria dentro de un tablero | `small` | `small` | práctica de la app (1 uso) |
|
|
122
|
+
| filas con dos líneas y un badge | `medium` | `medium` | propuesta, falta aprobación |
|
|
123
|
+
|
|
124
|
+
El patrón `[size]="bp.isMobile() ? 'large' : 'medium'"` de los botones **no aplica aquí**: la fila
|
|
125
|
+
ya mide 64 y el toque es sobre toda la fila. `large`/`xlarge` no tienen uso hoy.
|
|
126
|
+
|
|
127
|
+
**Qué pasa en mobile (≤ 767 px):** la tabla scrollea en horizontal dentro de sí misma; la
|
|
128
|
+
cabecera y el cuerpo miden lo mismo y la barra de scroll se oculta. En la app conviven dos
|
|
129
|
+
salidas, y las dos son práctica, no regla:
|
|
130
|
+
|
|
131
|
+
| salida | dónde | cuándo elegirla (propuesta) |
|
|
132
|
+
|---|---|---|
|
|
133
|
+
| la misma tabla, con scroll lateral | `orders`, `master-orders`, `central-gastos`, `central-ingresos` | 3-4 columnas, y la primera (`leading`) ya dice casi todo |
|
|
134
|
+
| tarjetas en grilla por debajo de 1350 px | `drivers` (`drivers.ts:282`), `master-gastos` | 6+ columnas: con el sidebar abierto no entran ni en laptop ni en iPad |
|
|
135
|
+
|
|
136
|
+
**Android (canon del componente, no se repite en la página):** un contenedor con
|
|
137
|
+
`overflow-x: auto` se queda con el gesto vertical y la página deja de scrollear sobre la tabla.
|
|
138
|
+
Ningún `touch-action` solo lo arregla (probado en device). `sui-table` lo resuelve **por dentro y
|
|
139
|
+
solo en Android**: pone `touch-action: pan-x` por JS para que el scroll horizontal sea el nativo,
|
|
140
|
+
y mueve él mismo la página con el gesto vertical (con inercia). En iOS no hace nada: WebKit delega
|
|
141
|
+
el vertical solo. Por eso la página **no** agrega `touch-action` ni un wrapper con `overflow-x`.
|
|
142
|
+
|
|
143
|
+
## «No usar»: por qué no hoy y cuándo sí
|
|
144
|
+
|
|
145
|
+
| qué | por qué no hoy | cuándo sí, en un flujo nuevo |
|
|
146
|
+
|---|---|---|
|
|
147
|
+
| `sortable` | toda tabla de la app es una lista paginada por cursor: el orden lo da la consulta | una tabla chica que se carga entera (≤ 50 filas, un reporte del mes) |
|
|
148
|
+
| `selectable` | no hay acciones en lote | aprobar o rechazar varias recargas de una vez, exportar filas elegidas |
|
|
149
|
+
| `striped` | con divisor entre filas ya se lee la fila; las rayas suman ruido | tablas de muchas columnas numéricas (un reporte contable) |
|
|
150
|
+
| `sticky` | la columna fija tapó otra en 375 px (`central-gastos.ts:80`) | una tabla ancha en desktop donde la primera columna es la única referencia |
|
|
151
|
+
| `large` / `xlarge` | 64 ya alcanza al dedo | filas con avatar grande y tres líneas |
|
|
152
|
+
|
|
153
|
+
## API
|
|
154
|
+
|
|
155
|
+
<!-- api:inicio -->
|
|
156
|
+
<!-- generada: no editar a mano — `npm run docs` -->
|
|
157
|
+
|
|
158
|
+
### `sui-table`
|
|
159
|
+
|
|
160
|
+
| input | tipo | default |
|
|
161
|
+
|---|---|---|
|
|
162
|
+
| `columns` | `SuiTableColumn<T>[]` | — (requerido) |
|
|
163
|
+
| `rows` | `T[]` | — (requerido) |
|
|
164
|
+
| `size` | `'small' \| 'medium' \| 'large' \| 'xlarge'` | `'medium'` |
|
|
165
|
+
| `loading` | `boolean` | `false` |
|
|
166
|
+
| `emptyMessage` | `string` | `'No hay datos'` |
|
|
167
|
+
| `striped` | `boolean` | `false` |
|
|
168
|
+
| `selectable` | `boolean` | `false` |
|
|
169
|
+
| `rowKey` | `keyof T \| ((row: T) => any)` | `undefined` |
|
|
170
|
+
| `selectedRows` · model, `[(selectedRows)]` | `Set<any>` | `new Set()` |
|
|
171
|
+
| `sortKey` · model, `[(sortKey)]` | `string \| null` | `null` |
|
|
172
|
+
| `sortDir` · model, `[(sortDir)]` | `'asc' \| 'desc' \| null` | `null` |
|
|
173
|
+
|
|
174
|
+
| output | payload |
|
|
175
|
+
|---|---|
|
|
176
|
+
| `rowClicked` | `T` |
|
|
177
|
+
| `sortChanged` | `{ key: string; dir: 'asc' \| 'desc' \| null }` |
|
|
178
|
+
|
|
179
|
+
### `[suiTableCell]`
|
|
180
|
+
|
|
181
|
+
| input | tipo | default |
|
|
182
|
+
|---|---|---|
|
|
183
|
+
| `suiTableCell` | `string` | — (requerido) |
|
|
184
|
+
|
|
185
|
+
Outputs: ninguno.
|
|
186
|
+
<!-- api:fin -->
|
|
187
|
+
|
|
188
|
+
```ts
|
|
189
|
+
interface SuiTableColumn<T = any> {
|
|
190
|
+
key: string; // campo de la fila; único
|
|
191
|
+
label: string; // '' para la columna de acciones
|
|
192
|
+
width?: string; // ancho fijo ('100px', '20%')
|
|
193
|
+
minWidth?: string; // piso (manda en el scroll de mobile)
|
|
194
|
+
maxWidth?: string;
|
|
195
|
+
align?: 'left' | 'center' | 'right';
|
|
196
|
+
sortable?: boolean;
|
|
197
|
+
disabled?: boolean; // cabecera apagada, sin orden
|
|
198
|
+
priority?: 'regular' | 'leading' | 'passive' | 'none';
|
|
199
|
+
descriptionKey?: string; // segunda línea (solo texto plano)
|
|
200
|
+
truncate?: boolean; // «…» + tooltip (solo texto plano)
|
|
201
|
+
misc?: SuiTableCellMisc; // documental: qué componente va en la plantilla
|
|
202
|
+
sticky?: boolean; // fija la columna y activa el scroll lateral en cualquier ancho
|
|
203
|
+
}
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
`SuiTableCellDirective` se importa aparte (`<ng-template suiTableCell="key" let-row>`).
|
|
207
|
+
El orden cicla `asc → desc → sin orden` y emite `sortChanged` en cada paso; ordenar las filas es
|
|
208
|
+
trabajo de la página.
|
|
209
|
+
|
|
210
|
+
## Trampas
|
|
211
|
+
|
|
212
|
+
- **Por encima de 767 px la tabla recorta, no scrollea.** Sin una columna `sticky`, el contenedor
|
|
213
|
+
es `overflow: hidden` en desktop: lo que no entra **desaparece** a la derecha (monto, estado,
|
|
214
|
+
acciones). Las columnas tienen que entrar en el ancho real, que con el sidebar abierto es
|
|
215
|
+
~483 px en iPad y ~1015 px en una pantalla de 1351. Lo comentan tres pantallas:
|
|
216
|
+
`pages/drivers/drivers.html:210`, `pages/super-admin/master-gastos/master-gastos.html:38`,
|
|
217
|
+
`pages/central/central-gastos/central-gastos.ts:76`. El wrapper `drivers__table-wrap` es un
|
|
218
|
+
respaldo de eso; no se copia.
|
|
219
|
+
- `sticky` en **cualquier** columna activa el scroll lateral en todos los anchos (no solo en mobile)
|
|
220
|
+
y quita el recorte redondeado de las filas.
|
|
221
|
+
- `descriptionKey` y `truncate` **se ignoran** si la columna tiene plantilla `suiTableCell`.
|
|
222
|
+
- Sin `rowKey`, la fila se identifica por su índice: la selección se mezcla al reordenar o al cargar
|
|
223
|
+
más. Si usas `selectable` o la lista cambia en vivo, pasa `rowKey="id"`.
|
|
224
|
+
- `rowClicked` dispara en **toda** la fila. Un botón dentro de una plantilla necesita
|
|
225
|
+
`$event.stopPropagation()` o abre el detalle además de hacer lo suyo.
|
|
226
|
+
- `toggleAll` selecciona **lo cargado**, no la colección: con cursor, «todas» son las de la página.
|
|
227
|
+
- El hover de fila solo existe con mouse (`@media (hover: hover)`); en táctil no hay feedback de
|
|
228
|
+
toque: si la fila abre algo, que se note por el contenido (una pista «Toca un gasto para…», como
|
|
229
|
+
`central-gastos.html:46`).
|
|
230
|
+
- La fila esqueleto son siempre 5, sin importar el tamaño de página.
|
|
231
|
+
- No le pongas `touch-action` ni `overflow-x` desde la página: el componente ya maneja el gesto en
|
|
232
|
+
Android y lo romperías.
|
|
233
|
+
|
|
234
|
+
## Ejemplo
|
|
235
|
+
|
|
236
|
+
```html
|
|
237
|
+
<sui-card>
|
|
238
|
+
<sui-table
|
|
239
|
+
[columns]="columnas"
|
|
240
|
+
[rows]="filas()"
|
|
241
|
+
rowKey="id"
|
|
242
|
+
[loading]="cargando()"
|
|
243
|
+
emptyMessage="Sin pedidos en este estado."
|
|
244
|
+
(rowClicked)="abrirDetalle($event)">
|
|
245
|
+
<ng-template suiTableCell="estado" let-row>
|
|
246
|
+
<sui-badge [color]="row.color" variant="lighter" size="small">{{ row.estadoLabel }}</sui-badge>
|
|
247
|
+
</ng-template>
|
|
248
|
+
</sui-table>
|
|
249
|
+
|
|
250
|
+
@if (hayMas()) {
|
|
251
|
+
<sui-button variant="stroke" color="neutral" [size]="bp.isMobile() ? 'large' : 'small'"
|
|
252
|
+
[disabled]="cargandoMas()" (click)="cargarMas()">Cargar más</sui-button>
|
|
253
|
+
}
|
|
254
|
+
</sui-card>
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
```ts
|
|
258
|
+
readonly columnas: SuiTableColumn[] = [
|
|
259
|
+
{ key: 'numero', label: 'Pedido', priority: 'leading', descriptionKey: 'desdeHace', minWidth: '130px' },
|
|
260
|
+
{ key: 'cliente', label: 'Cliente', minWidth: '160px', maxWidth: '220px', truncate: true },
|
|
261
|
+
{ key: 'total', label: 'Total', align: 'right', width: '100px' },
|
|
262
|
+
{ key: 'estado', label: 'Estado', width: '130px' },
|
|
263
|
+
];
|
|
264
|
+
```
|
|
@@ -52,6 +52,9 @@ Publicado (0.19.0): `xsmall` (32), `small` (36), `medium` (40). **En el repo del
|
|
|
52
52
|
0.19.0 queda en 14). Los chips de abajo son `sui-tag` de tamaño fijo: **la ✕ para quitar un chip
|
|
53
53
|
no crece** con el campo.
|
|
54
54
|
|
|
55
|
+
En large y xlarge el texto sube a 16 px (regla del 03-10-2026): lo que se escribe va en 16/24 también
|
|
56
|
+
en web; el alto sigue en 48/52. Los chips de abajo no cambian.
|
|
57
|
+
|
|
55
58
|
| uso | mobile | web | fuente |
|
|
56
59
|
|---|---|---|---|
|
|
57
60
|
| campo de formulario | `large` (48) **cuando se publique**; hasta entonces `medium` (40) | `medium` (40) | propuesta, falta aprobación |
|
|
@@ -87,6 +87,9 @@ evita el zoom de iOS al enfocar y el textarea deja de verse más chico que los c
|
|
|
87
87
|
eso cada fila mide 24 px en el teléfono y 20 en web (3 filas ≈ 72 + padding en mobile, 60 + padding
|
|
88
88
|
en web): el área que se toca siempre pasa los 44 px.
|
|
89
89
|
|
|
90
|
+
En large y xlarge el texto sube a 16 px (regla del 03-10-2026): en esos dos tamaños va en 16/24
|
|
91
|
+
también en web, así que cada fila mide 24 en las dos plataformas.
|
|
92
|
+
|
|
90
93
|
| uso | mobile | web | fuente |
|
|
91
94
|
|---|---|---|---|
|
|
92
95
|
| motivo, nota | el `size` del formulario (`large` si los inputs van en `large`), `rows=3`, `[resizable]="false"` | `medium`, `rows=3`, manija | propuesta, falta aprobación |
|
|
@@ -106,6 +106,9 @@ el panel también crece: **filas de 44** y **Cancelar / Aplicar en `large` (48)*
|
|
|
106
106
|
| fila de la columna | 36 | 44 | 44 | 36: Figma · 44: canon (aprobado por el dueño, 03-10-2026), extensión SUI |
|
|
107
107
|
| Cancelar / Aplicar | 36 | 48 | el del `size` | canon (aprobado por el dueño, 03-10-2026), extensión SUI |
|
|
108
108
|
|
|
109
|
+
En large y xlarge el texto sube a 16 px (regla del 03-10-2026): con `large`, la hora del campo y la
|
|
110
|
+
de las filas van en 16/24; la fila sigue en 44 (el padding bajó de 12 a 10).
|
|
111
|
+
|
|
109
112
|
| uso | mobile | web | fuente |
|
|
110
113
|
|---|---|---|---|
|
|
111
114
|
| horario en un formulario | `large` | `medium`, o `small` en filas densas | propuesta, falta aprobación |
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: sui-topbar
|
|
3
|
+
selector: sui-topbar
|
|
4
|
+
resumen: Barra de navegación horizontal de escritorio — logo, secciones, buscador, íconos de acción y el chip de la cuenta
|
|
5
|
+
alternativas: [sui-sidebar (la navegación de los roles de la app, con cajón en mobile), sui-page-header (el título de UNA pantalla, sin navegación), sui-topbar-item / sui-topbar-button / sui-topbar-user (las piezas sueltas, para una cabecera armada a mano)]
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# sui-topbar
|
|
9
|
+
|
|
10
|
+
Story: [Organisms/Topbar](https://sui-design-system.web.app/?path=/docs/organisms-topbar--docs)
|
|
11
|
+
|
|
12
|
+
## Cuándo usarlo / cuándo no
|
|
13
|
+
|
|
14
|
+
**Úsalo** para una **web de escritorio** que navega por arriba en vez de por una columna:
|
|
15
|
+
una landing con secciones, un panel interno con pocas secciones y mucho ancho para datos.
|
|
16
|
+
Compone las tres piezas de la familia (`sui-topbar-item`, `sui-topbar-button`,
|
|
17
|
+
`sui-topbar-user`) y el atajo con `sui-kbd`.
|
|
18
|
+
|
|
19
|
+
**No lo uses** para:
|
|
20
|
+
|
|
21
|
+
- La navegación de los roles de la app (empresa, cliente, repartidor, super admin): es
|
|
22
|
+
`sui-sidebar`, y en el teléfono la barra inferior. Hoy la topbar tiene **0 usos** en la app.
|
|
23
|
+
- El título de una pantalla con sus acciones: `sui-page-header`.
|
|
24
|
+
- Nada que se vea en un teléfono: el componente no tiene versión mobile (ver «Tamaño»).
|
|
25
|
+
|
|
26
|
+
Regla corta: **navegación de la app → sidebar · título de pantalla → page header · web de escritorio
|
|
27
|
+
navegada por arriba → topbar.**
|
|
28
|
+
|
|
29
|
+
## Qué variante usar
|
|
30
|
+
|
|
31
|
+
> **La guía del DS no tiene página de la topbar.** El componente sale del Figma de SUI (Topbar
|
|
32
|
+
> [Navigation], frame 3814:25274, cuatro ejemplos: con y sin íconos, con buscador abierto o en
|
|
33
|
+
> botón). Sin uso en la app, **todo lo de abajo es propuesta, falta aprobación**, salvo lo que el
|
|
34
|
+
> componente ya fija.
|
|
35
|
+
>
|
|
36
|
+
> Uso medido el 03-10-2026 en `master-pedidos/src/app`: `sui-topbar`, `sui-topbar-item` y
|
|
37
|
+
> `sui-topbar-user` tienen 0 usos; `sui-topbar-button`, 1 en la vitrina de variantes.
|
|
38
|
+
|
|
39
|
+
| decisión | opción | cuándo | fuente |
|
|
40
|
+
|---|---|---|---|
|
|
41
|
+
| items | sin `icon` | El caso normal: 3-6 secciones con nombre corto. | propuesta, falta aprobación |
|
|
42
|
+
| items | con `icon` | Si **todos** llevan ícono. Mezclar con y sin se lee desordenado. | propuesta, falta aprobación |
|
|
43
|
+
| item con `rightIcon: 'arrow-down-s-line'` | — | Un «Más ⌄» que abre un menú. El menú lo pones tú (`sui-dropdown-menu`) al escuchar `(itemClicked)`. | propuesta, falta aprobación |
|
|
44
|
+
| `search` | objeto con `placeholder` | Buscador abierto de 232 px cuando buscar es la acción principal. | Figma (Type=Default) |
|
|
45
|
+
| `search` | `{ compact: true }` | Ícono de lupa en la zona de acciones; tú abres el buscador real (`sui-modal` o una paleta de comandos) en `(searchClicked)`. | Figma (Type=With Icon) |
|
|
46
|
+
| `actions` | 1-3 íconos | Avisos, ayuda, acciones rápidas. `dot: true` = hay algo nuevo. | propuesta, falta aprobación |
|
|
47
|
+
| `user` | config | El chip abre el menú de la cuenta: pásale `[userOpen]` mientras el menú está abierto. | Figma |
|
|
48
|
+
| `accent` | `brand` (default) | Siempre. `information` es el azul del Figma original. | canon del DS (accent = marca) |
|
|
49
|
+
|
|
50
|
+
## Tamaño en mobile y en web
|
|
51
|
+
|
|
52
|
+
La topbar **no tiene `size`** ni ningún breakpoint. Mide 80 de alto (20 + 40 + 20), con
|
|
53
|
+
`padding: 20px 44px` fijo, el buscador abierto en 232 fijos y la navegación con scroll lateral
|
|
54
|
+
oculto si no entra.
|
|
55
|
+
|
|
56
|
+
| uso | mobile | web | fuente |
|
|
57
|
+
|---|---|---|---|
|
|
58
|
+
| navegación de una web de escritorio | **no usar** | `sui-topbar` | propuesta, falta aprobación |
|
|
59
|
+
|
|
60
|
+
**Qué pasa en mobile:** nada se adapta. Los 44 px laterales se comen el ancho, los items se
|
|
61
|
+
esconden detrás de un scroll lateral sin pista visual, el buscador no se achica y no hay
|
|
62
|
+
`safe-area-inset-top` (en la app nativa queda debajo del notch). En mobile se usa el patrón de la
|
|
63
|
+
app: barra inferior + cajón `sui-sidebar`. Si algún día hace falta topbar en el teléfono, primero
|
|
64
|
+
hay que agregarle al componente un modo mobile (menú hamburguesa, buscador en botón, safe area).
|
|
65
|
+
|
|
66
|
+
## «No usar»: por qué no hoy y cuándo sí
|
|
67
|
+
|
|
68
|
+
| qué | por qué no hoy | cuándo sí, en un flujo nuevo |
|
|
69
|
+
|---|---|---|
|
|
70
|
+
| `sui-topbar` entero | la app navega con sidebar + barra inferior | una landing o un panel solo de escritorio (un tablero para pantalla grande en el local) |
|
|
71
|
+
| `accent="information"` | el activo es naranja de marca | nunca en esta app |
|
|
72
|
+
| `badge` «NEW» en un item | un «nuevo» que nunca se apaga se vuelve ruido | anunciar una sección recién lanzada, y se quita a las dos semanas |
|
|
73
|
+
|
|
74
|
+
## API
|
|
75
|
+
|
|
76
|
+
<!-- api:inicio -->
|
|
77
|
+
<!-- generada: no editar a mano — `npm run docs` -->
|
|
78
|
+
|
|
79
|
+
| input | tipo | default |
|
|
80
|
+
|---|---|---|
|
|
81
|
+
| `items` | `SuiTopbarEntry[]` | `[]` |
|
|
82
|
+
| `activeValue` | `string \| null` | `null` |
|
|
83
|
+
| `accent` | `'brand' \| 'information'` | `'brand'` |
|
|
84
|
+
| `search` | `SuiTopbarSearchConfig \| boolean \| null` | `false` |
|
|
85
|
+
| `searchValue` · model, `[(searchValue)]` | `string` | `''` |
|
|
86
|
+
| `actions` | `SuiTopbarAction[]` | `[]` |
|
|
87
|
+
| `user` | `SuiTopbarUserConfig \| string \| null` | `null` |
|
|
88
|
+
| `userOpen` | `boolean` | `false` |
|
|
89
|
+
|
|
90
|
+
| output | payload |
|
|
91
|
+
|---|---|
|
|
92
|
+
| `itemClicked` | `SuiTopbarEntry` |
|
|
93
|
+
| `actionClicked` | `SuiTopbarAction` |
|
|
94
|
+
| `userClicked` | `void` |
|
|
95
|
+
| `searchClicked` | `void` |
|
|
96
|
+
| `searchSubmitted` | `string` |
|
|
97
|
+
<!-- api:fin -->
|
|
98
|
+
|
|
99
|
+
```ts
|
|
100
|
+
interface SuiTopbarEntry {
|
|
101
|
+
value: string; // lo emite (itemClicked) y se compara con activeValue
|
|
102
|
+
label: string;
|
|
103
|
+
icon?: string; // RemixIcon izquierdo
|
|
104
|
+
rightIcon?: string; // típico 'arrow-down-s-line'
|
|
105
|
+
badge?: SuiBadgeConfig | string; // «NEW»
|
|
106
|
+
count?: number; // número rojo
|
|
107
|
+
href?: string; // con href se dibuja <a>; sin href, <button>
|
|
108
|
+
target?: string;
|
|
109
|
+
}
|
|
110
|
+
interface SuiTopbarAction { value: string; icon: string; ariaLabel?: string; dot?: boolean; }
|
|
111
|
+
interface SuiTopbarSearchConfig { placeholder?: string; shortcut?: string; compact?: boolean; }
|
|
112
|
+
interface SuiTopbarUserConfig { name?: string; avatar?: SuiAvatarConfig | string; verified?: boolean; }
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Slot: `<ng-content select="[topbar-logo]">` — el logo (una `<img>` directa se normaliza a 40×40 redonda).
|
|
116
|
+
|
|
117
|
+
## Trampas
|
|
118
|
+
|
|
119
|
+
- **No navega sola.** Los items no usan `routerLink`: el activo lo dice `activeValue` y tú navegas
|
|
120
|
+
en `(itemClicked)`. Excepción: con `href` el item es un `<a>` que, si la ruta es interna, navega
|
|
121
|
+
por el router (SPA) con el clic principal. Es una diferencia deliberada con `sui-sidebar`, que sí
|
|
122
|
+
usa `routerLink`.
|
|
123
|
+
- `activeValue` es **una igualdad exacta** con `value`, no un prefijo de ruta: en `/pedidos/123`
|
|
124
|
+
tienes que calcular tú que el activo es `'pedidos'`.
|
|
125
|
+
- Si `actions[].ariaLabel` falta, el lector de pantalla lee el `value` (`'notifications'`): pásalo
|
|
126
|
+
siempre en español.
|
|
127
|
+
- El buscador no busca: expone `[(searchValue)]` y `(searchSubmitted)` con Enter. El placeholder
|
|
128
|
+
por defecto es «Buscar...» (en `sui-sidebar` es «Search...»).
|
|
129
|
+
- El chip de usuario no abre ningún menú: emite `(userClicked)` y solo cambia de aspecto con
|
|
130
|
+
`userOpen`.
|
|
131
|
+
- El host lleva `role="banner"`: una sola por página.
|
|
132
|
+
|
|
133
|
+
## Ejemplo
|
|
134
|
+
|
|
135
|
+
```html
|
|
136
|
+
<sui-topbar
|
|
137
|
+
[items]="[
|
|
138
|
+
{ value: 'tablero', label: 'Tablero' },
|
|
139
|
+
{ value: 'pedidos', label: 'Pedidos', count: pendientes() },
|
|
140
|
+
{ value: 'mas', label: 'Más', rightIcon: 'arrow-down-s-line' }
|
|
141
|
+
]"
|
|
142
|
+
[activeValue]="seccion()"
|
|
143
|
+
[search]="{ placeholder: 'Buscar pedidos', shortcut: '⌘K' }"
|
|
144
|
+
[(searchValue)]="busqueda"
|
|
145
|
+
[actions]="[{ value: 'avisos', icon: 'notification-3-line', ariaLabel: 'Avisos', dot: hayAvisos() }]"
|
|
146
|
+
[user]="{ name: usuario().nombre, avatar: usuario().avatarUrl }"
|
|
147
|
+
[userOpen]="menuCuenta()"
|
|
148
|
+
(itemClicked)="ir($event.value)"
|
|
149
|
+
(actionClicked)="abrirAvisos()"
|
|
150
|
+
(userClicked)="menuCuenta.set(!menuCuenta())">
|
|
151
|
+
<img topbar-logo src="assets/app-icon.png" alt="Master Pedidos" />
|
|
152
|
+
</sui-topbar>
|
|
153
|
+
```
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: sui-topbar-button
|
|
3
|
+
selector: sui-topbar-button
|
|
4
|
+
resumen: Botón de solo ícono de 40×40 para la barra superior, con punto rojo de «hay algo nuevo»
|
|
5
|
+
alternativas: [sui-button con onlyIcon (un botón de ícono en cualquier otro lugar), sui-compact-button (ícono chico de 20-28 en filas y barras apretadas), sui-topbar (la barra completa, que ya lo compone)]
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# sui-topbar-button
|
|
9
|
+
|
|
10
|
+
Story: [Organisms/Topbar](https://sui-design-system.web.app/?path=/docs/organisms-topbar--docs) —
|
|
11
|
+
no tiene story propia: se ve en la página de la topbar, en la story «Icon Button — estados».
|
|
12
|
+
|
|
13
|
+
## Cuándo usarlo / cuándo no
|
|
14
|
+
|
|
15
|
+
**Úsalo** para los íconos de acción **de una barra superior**: avisos, ayuda, acciones rápidas.
|
|
16
|
+
Dentro de `sui-topbar` no se escribe a mano: sale de `[actions]`. Suelto sirve para una cabecera
|
|
17
|
+
armada a mano que quiera verse como la topbar.
|
|
18
|
+
|
|
19
|
+
**No lo uses** para:
|
|
20
|
+
|
|
21
|
+
- Un botón de ícono en una card, una fila o un formulario: `sui-button` con `onlyIcon`, o
|
|
22
|
+
`sui-compact-button` si el espacio es chico.
|
|
23
|
+
- Una acción con texto: no lo tiene.
|
|
24
|
+
|
|
25
|
+
## Qué variante usar
|
|
26
|
+
|
|
27
|
+
> **La guía del DS no tiene página de este botón.** Sale del Figma de SUI (Topbar Item Button
|
|
28
|
+
> [Topbar], set 3814:25156: Default, Hover, Active). Uso medido el 03-10-2026: **0 usos** en la
|
|
29
|
+
> app, 1 en la vitrina de variantes (`master-preview/_guia-variantes`). Lo de abajo es
|
|
30
|
+
> **propuesta, falta aprobación**.
|
|
31
|
+
|
|
32
|
+
| prop | cuándo | fuente |
|
|
33
|
+
|---|---|---|
|
|
34
|
+
| `dot` | Hay algo nuevo detrás del ícono (avisos sin leer). Se apaga cuando la persona lo abre. Si el número importa, no alcanza: va un contador en otro lado. | propuesta, falta aprobación |
|
|
35
|
+
| `active` | Mientras el panel que abre el botón está abierto (pinta el ícono naranja y `aria-pressed`). | Figma (State=Active) |
|
|
36
|
+
| `accent` | `brand` (default). `information` es el azul del Figma original: no usar. | canon del DS (accent = marca) |
|
|
37
|
+
|
|
38
|
+
## Tamaño en mobile y en web
|
|
39
|
+
|
|
40
|
+
**No tiene `size`**: mide siempre 40×40 (padding 10 + ícono de 20), radio 10. En mobile 40 es el
|
|
41
|
+
mínimo táctil aceptable, pero el botón vive en la topbar, que hoy es solo de escritorio (ver
|
|
42
|
+
`sui-topbar`).
|
|
43
|
+
|
|
44
|
+
| uso | mobile | web | fuente |
|
|
45
|
+
|---|---|---|---|
|
|
46
|
+
| ícono de la barra superior | no usar (no hay topbar en mobile) | 40×40 | propuesta, falta aprobación |
|
|
47
|
+
|
|
48
|
+
## «No usar»: por qué no hoy y cuándo sí
|
|
49
|
+
|
|
50
|
+
| qué | por qué no hoy | cuándo sí, en un flujo nuevo |
|
|
51
|
+
|---|---|---|
|
|
52
|
+
| `sui-topbar-button` (0 usos) | las barras de la app tienen sus íconos propios | si se unifica la barra superior del admin con la del DS |
|
|
53
|
+
| `accent="information"` | el activo es naranja de marca | nunca en esta app |
|
|
54
|
+
|
|
55
|
+
## API
|
|
56
|
+
|
|
57
|
+
<!-- api:inicio -->
|
|
58
|
+
<!-- generada: no editar a mano — `npm run docs` -->
|
|
59
|
+
|
|
60
|
+
| input | tipo | default |
|
|
61
|
+
|---|---|---|
|
|
62
|
+
| `icon` | `string` | — (requerido) |
|
|
63
|
+
| `ariaLabel` | `string` | — (requerido) |
|
|
64
|
+
| `dot` | `boolean` | `false` |
|
|
65
|
+
| `active` | `boolean` | `false` |
|
|
66
|
+
| `accent` | `'brand' \| 'information'` | `'brand'` |
|
|
67
|
+
|
|
68
|
+
| output | payload |
|
|
69
|
+
|---|---|
|
|
70
|
+
| `clicked` | `void` |
|
|
71
|
+
<!-- api:fin -->
|
|
72
|
+
|
|
73
|
+
`icon` es el nombre RemixIcon sin `ri-`.
|
|
74
|
+
|
|
75
|
+
## Trampas
|
|
76
|
+
|
|
77
|
+
- **`ariaLabel` es obligatorio** (a diferencia de `sui-button`, que no tiene ese input). En
|
|
78
|
+
español: «Avisos», no `notifications`.
|
|
79
|
+
- El evento es `(clicked)`. Un `(click)` en el host también llega, pero no es la API.
|
|
80
|
+
- No es un `sui-compact-button`: mide 40 (no 24) y su radio es 10 (no 6). No los mezcles en la
|
|
81
|
+
misma barra.
|
|
82
|
+
- El punto rojo (4×4, con aro blanco) va arriba a la derecha y es solo visual: no lo lee el lector
|
|
83
|
+
de pantalla. Si importa, dilo en `ariaLabel` («Avisos, hay nuevos»).
|
|
84
|
+
- Ya trae el arreglo de iOS para el `:active` pegado.
|
|
85
|
+
|
|
86
|
+
## Ejemplo
|
|
87
|
+
|
|
88
|
+
```html
|
|
89
|
+
<sui-topbar-button
|
|
90
|
+
icon="notification-3-line"
|
|
91
|
+
ariaLabel="Avisos"
|
|
92
|
+
[dot]="hayAvisos()"
|
|
93
|
+
[active]="panelAvisos()"
|
|
94
|
+
(clicked)="panelAvisos.set(!panelAvisos())" />
|
|
95
|
+
```
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: sui-topbar-item
|
|
3
|
+
selector: sui-topbar-item
|
|
4
|
+
resumen: Una sección de la navegación horizontal — texto, ícono opcional, badge o contador — con estado activo
|
|
5
|
+
alternativas: [sui-topbar (la barra completa: lo compone desde [items]), sui-tab-menu-horizontal (pestañas dentro de UNA pantalla), sui-tab-chips (filtros), sui-link-button (un link suelto en un texto)]
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# sui-topbar-item
|
|
9
|
+
|
|
10
|
+
Story: [Organisms/Topbar](https://sui-design-system.web.app/?path=/docs/organisms-topbar--docs) —
|
|
11
|
+
no tiene story propia: se ve en la página de la topbar, en la story «Topbar Item — estados».
|
|
12
|
+
|
|
13
|
+
## Cuándo usarlo / cuándo no
|
|
14
|
+
|
|
15
|
+
**Úsalo** como cada sección de una navegación horizontal de escritorio. Dentro de `sui-topbar`
|
|
16
|
+
no se escribe a mano: sale de `[items]`. Suelto sirve para armar una barra propia que se vea
|
|
17
|
+
igual.
|
|
18
|
+
|
|
19
|
+
**No lo uses** para:
|
|
20
|
+
|
|
21
|
+
- Pestañas que cambian el contenido de la misma pantalla: `sui-tab-menu-horizontal`.
|
|
22
|
+
- Filtros que se prenden y apagan: `sui-tab-chips`.
|
|
23
|
+
- Navegación de los roles de la app: `sui-sidebar`.
|
|
24
|
+
|
|
25
|
+
## Qué variante usar
|
|
26
|
+
|
|
27
|
+
> **La guía del DS no tiene página de este item.** Sale del Figma de SUI (Topbar Items [Topbar],
|
|
28
|
+
> set 3802:24588: Default, Hover, Active). Uso medido el 03-10-2026: **0 usos** en la app. Lo de
|
|
29
|
+
> abajo es **propuesta, falta aprobación**.
|
|
30
|
+
|
|
31
|
+
| prop | cuándo | fuente |
|
|
32
|
+
|---|---|---|
|
|
33
|
+
| solo `label` | El caso normal. Una o dos palabras, sentence case. | propuesta, falta aprobación |
|
|
34
|
+
| `icon` | Si **todos** los items de la barra lo llevan. | propuesta, falta aprobación |
|
|
35
|
+
| `rightIcon: 'arrow-down-s-line'` | El item abre un menú («Más ⌄»). El menú lo pones tú. | Figma |
|
|
36
|
+
| `count` | Pendientes que piden acción («3» pedidos por aceptar). Número rojo. | Figma (notification=true) |
|
|
37
|
+
| `badge` | Un «Nuevo» temporal en una sección recién lanzada. String = badge naranja `light` `small`. | Figma (badge=true) |
|
|
38
|
+
| `href` | El item es un link: con ruta interna navega por el router; con `target="_blank"` abre otra pestaña con `rel` seguro. | propuesta, falta aprobación |
|
|
39
|
+
| sin `href` | Es un `<button>`: navegas tú en `(clicked)`. | propuesta, falta aprobación |
|
|
40
|
+
| `active` | La sección actual (fondo gris, texto oscuro, ícono naranja y `aria-current="page"`). Uno solo por barra. | Figma (State=Active) |
|
|
41
|
+
|
|
42
|
+
## Tamaño en mobile y en web
|
|
43
|
+
|
|
44
|
+
**No tiene `size`**: alto 36 (padding 8 + línea de 20), texto 14/500, íconos de 20. Vive en la
|
|
45
|
+
topbar, que hoy es solo de escritorio.
|
|
46
|
+
|
|
47
|
+
| uso | mobile | web | fuente |
|
|
48
|
+
|---|---|---|---|
|
|
49
|
+
| sección de la barra superior | no usar (no hay topbar en mobile) | tamaño único | propuesta, falta aprobación |
|
|
50
|
+
|
|
51
|
+
En mobile, 36 de alto queda por debajo del área táctil cómoda (44): si algún día se usa ahí, la
|
|
52
|
+
barra tendría que darle más aire.
|
|
53
|
+
|
|
54
|
+
## API
|
|
55
|
+
|
|
56
|
+
<!-- api:inicio -->
|
|
57
|
+
<!-- generada: no editar a mano — `npm run docs` -->
|
|
58
|
+
|
|
59
|
+
| input | tipo | default |
|
|
60
|
+
|---|---|---|
|
|
61
|
+
| `label` | `string` | — (requerido) |
|
|
62
|
+
| `icon` | `string \| null` | `null` |
|
|
63
|
+
| `rightIcon` | `string \| null` | `null` |
|
|
64
|
+
| `badge` | `SuiBadgeConfig \| string \| null` | `null` |
|
|
65
|
+
| `count` | `number \| null` | `null` |
|
|
66
|
+
| `active` | `boolean` | `false` |
|
|
67
|
+
| `accent` | `'brand' \| 'information'` | `'brand'` |
|
|
68
|
+
| `href` | `string \| null` | `null` |
|
|
69
|
+
| `target` | `string \| null` | `null` |
|
|
70
|
+
|
|
71
|
+
| output | payload |
|
|
72
|
+
|---|---|
|
|
73
|
+
| `clicked` | `void` |
|
|
74
|
+
<!-- api:fin -->
|
|
75
|
+
|
|
76
|
+
`SuiTopbarAccent` (`'brand' | 'information'`) se exporta desde este archivo y lo usan también
|
|
77
|
+
`sui-topbar` y `sui-topbar-button`.
|
|
78
|
+
|
|
79
|
+
## Trampas
|
|
80
|
+
|
|
81
|
+
- `count` en `0` **se muestra** («0» rojo): solo `null` lo oculta. Pasa `pendientes() || null`.
|
|
82
|
+
- `badge` en string toma naranja `light` `small`; para otro color, el objeto `SuiBadgeConfig`.
|
|
83
|
+
- `active` no se calcula solo: ni por ruta ni por `href`. Lo decides tú.
|
|
84
|
+
- Con `href`, `(clicked)` igual se emite: no navegues dos veces.
|
|
85
|
+
- `accent="information"` es el azul del Figma original: en esta app no se usa.
|
|
86
|
+
- Ya trae el arreglo de iOS para el `:active` pegado.
|
|
87
|
+
|
|
88
|
+
## Ejemplo
|
|
89
|
+
|
|
90
|
+
```html
|
|
91
|
+
<nav class="mi-barra">
|
|
92
|
+
<sui-topbar-item label="Tablero" [active]="seccion() === 'tablero'" (clicked)="ir('tablero')" />
|
|
93
|
+
<sui-topbar-item label="Pedidos" [count]="pendientes() || null"
|
|
94
|
+
[active]="seccion() === 'pedidos'" (clicked)="ir('pedidos')" />
|
|
95
|
+
<sui-topbar-item label="Más" rightIcon="arrow-down-s-line" (clicked)="abrirMenu()" />
|
|
96
|
+
</nav>
|
|
97
|
+
```
|