@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.
Files changed (59) hide show
  1. package/docs/INDEX.md +51 -51
  2. package/docs/sui-alert/README.md +13 -0
  3. package/docs/sui-badge/README.md +17 -0
  4. package/docs/sui-banner/README.md +190 -0
  5. package/docs/sui-breadcrumb-item/README.md +96 -0
  6. package/docs/sui-breadcrumbs/README.md +122 -0
  7. package/docs/sui-button/README.md +17 -0
  8. package/docs/sui-card/README.md +168 -0
  9. package/docs/sui-chart-legend/README.md +140 -0
  10. package/docs/sui-chart-legend-dot/README.md +118 -0
  11. package/docs/sui-checkbox-card/README.md +150 -0
  12. package/docs/sui-compact-select/README.md +127 -0
  13. package/docs/sui-compact-select-for-input/README.md +117 -0
  14. package/docs/sui-content-card/README.md +147 -0
  15. package/docs/sui-content-label/README.md +148 -0
  16. package/docs/sui-counter-input/README.md +145 -0
  17. package/docs/sui-date-selector/README.md +98 -0
  18. package/docs/sui-datepicker/README.md +193 -0
  19. package/docs/sui-day-cell/README.md +118 -0
  20. package/docs/sui-day-label/README.md +81 -0
  21. package/docs/sui-drawer-footer/README.md +127 -0
  22. package/docs/sui-drawer-header/README.md +140 -0
  23. package/docs/sui-empty-state/README.md +145 -0
  24. package/docs/sui-file-upload/README.md +154 -0
  25. package/docs/sui-file-upload-card/README.md +129 -0
  26. package/docs/sui-image-upload/README.md +200 -0
  27. package/docs/sui-image-upload-profile/README.md +145 -0
  28. package/docs/sui-inline-input/README.md +104 -0
  29. package/docs/sui-inline-select/README.md +101 -0
  30. package/docs/sui-input/README.md +244 -0
  31. package/docs/sui-integration-switch/README.md +142 -0
  32. package/docs/sui-notification/README.md +179 -0
  33. package/docs/sui-notification-footer/README.md +98 -0
  34. package/docs/sui-notification-tab-menu/README.md +112 -0
  35. package/docs/sui-otp-input/README.md +116 -0
  36. package/docs/sui-pagination/README.md +146 -0
  37. package/docs/sui-password-strength/README.md +99 -0
  38. package/docs/sui-period-range/README.md +93 -0
  39. package/docs/sui-popover/README.md +178 -0
  40. package/docs/sui-product-card/README.md +173 -0
  41. package/docs/sui-radio-card/README.md +160 -0
  42. package/docs/sui-rating/README.md +7 -6
  43. package/docs/sui-rich-editor/README.md +114 -0
  44. package/docs/sui-select/README.md +180 -0
  45. package/docs/sui-stepper/README.md +166 -0
  46. package/docs/sui-store-card/README.md +147 -0
  47. package/docs/sui-switch-card/README.md +149 -0
  48. package/docs/sui-tab-chips/README.md +185 -0
  49. package/docs/sui-tab-menu-horizontal/README.md +142 -0
  50. package/docs/sui-tab-menu-vertical/README.md +136 -0
  51. package/docs/sui-tag-input/README.md +120 -0
  52. package/docs/sui-textarea/README.md +157 -0
  53. package/docs/sui-time-picker/README.md +237 -0
  54. package/docs/sui-toast/README.md +190 -0
  55. package/docs/sui-tooltip/README.md +201 -0
  56. package/fesm2022/ajuarezso-sui-design-system.mjs +273 -231
  57. package/fesm2022/ajuarezso-sui-design-system.mjs.map +1 -1
  58. package/package.json +1 -1
  59. package/types/ajuarezso-sui-design-system.d.ts +208 -52
@@ -0,0 +1,160 @@
1
+ ---
2
+ name: sui-radio-card
3
+ selector: sui-radio-card
4
+ resumen: Opción con tarjeta (ícono o foto, título, descripción y el radio) para elegir UNA de una lista corta
5
+ alternativas: [sui-radio-label (la misma elección sin tarjeta, en un formulario denso), sui-select (lista larga o que no entra en pantalla), sui-segmented-control (2–4 vistas de la misma pantalla), sui-checkbox-card (se pueden elegir varias), sui-switch-card (se prende o se apaga un ajuste)]
6
+ ---
7
+
8
+ # sui-radio-card
9
+
10
+ Story: [Molecules/Card/Radio Card](https://sui-design-system.web.app/?path=/docs/molecules-card-radio-card--docs)
11
+
12
+ ## Cuándo usarlo / cuándo no
13
+
14
+ **Úsalo** para elegir una sola opción de una lista corta cuando cada opción merece explicarse:
15
+ «Delivery / Recojo en tienda», cómo cobrar («A mi saldo / Por Yape»), el medio de pago, el motivo
16
+ de una cancelación, el modo de asignación de repartidores.
17
+
18
+ **No lo uses** para:
19
+
20
+ - Varias opciones que se suman: `sui-checkbox-card`.
21
+ - Un ajuste que se prende o se apaga: `sui-switch-card`.
22
+ - Una lista larga (más de 6–7 opciones) o que crece con los datos: `sui-select`.
23
+ - Cambiar de vista dentro de la misma pantalla: `sui-segmented-control` o tabs.
24
+
25
+ Regla corta: **una de pocas, con explicación → radio-card · una de muchas → select · varias →
26
+ checkbox-card.**
27
+
28
+ ## Qué variante usar
29
+
30
+ > **La guía del DS no tiene página de la radio card.** De la guía sale solo lo del radio que lleva
31
+ > adentro: **«para elegir una sola opción de una lista corta»**. El resto es práctica de la app
32
+ > («propuesta») o regla ya aprobada («canon»).
33
+ >
34
+ > Uso medido el 03-10-2026 en `master-pedidos/src/app` (misma exclusión que `sui-card`): **31
35
+ > radio-cards en 14 archivos**. Tipos: 23 `left-icon` (3 de ellos con emoji animado por
36
+ > `iconSrc`), 6 `basic`, 1 `avatar`, 1 `company`. Tamaños: 24 `bp.controlSize()`, 4 `medium`, 1
37
+ > `xlarge` fijo, 1 dinámico, 1 sin `size`. 6 con `sublabel`, 3 con `disabled`, 1 con `badge`.
38
+
39
+ ### `type` (el leading)
40
+
41
+ | type | cuándo | fuente |
42
+ |---|---|---|
43
+ | `left-icon` con `icon` | Lo normal: un ícono Remix que dice de qué va la opción (`truck-line` Delivery, `store-2-line` Recojo). | propuesta (práctica de la app) |
44
+ | `left-icon` con `iconSrc` | Emoji animado cuando la elección es de las grandes del rol (el vehículo del repartidor, el rol al registrarse, el tipo de mandadito). Los emojis van de `assets/emojis/` o `FLUENT_EMOJI_ANIM`. | propuesta |
45
+ | `left-icon` con `emoji` | Lo mismo con un nombre de `SuiEmoji` en vez de una URL. Hoy 0 usos; vale igual. | propuesta |
46
+ | `basic` | Opciones de texto puro: motivos de cancelación, quién paga el envío, los premios de una meta. | propuesta |
47
+ | `avatar` (`imageUrl`) | El logo redondo de un medio de pago (Yape, Plin, efectivo en el checkout). | propuesta |
48
+ | `company` (`imageUrl`) | Elegir entre tus locales (cambiar de negocio en mi-negocio). | propuesta |
49
+ | `brand`, `card-provider` | Ver «No usar». | propuesta |
50
+
51
+ ### Las piezas
52
+
53
+ | prop | cuándo | fuente |
54
+ |---|---|---|
55
+ | `value` (obligatorio) | Siempre, aunque no haya grupo. Es lo que emite `selected`. | propuesta |
56
+ | `label` | Siempre. El nombre de la opción, corto: «Delivery», «Lo antes posible». | propuesta |
57
+ | `description` | Casi siempre: la consecuencia de elegirla («Lo revisamos y te transferimos. Puede tardar unas horas.»). | propuesta |
58
+ | `sublabel` | Una precisión corta entre paréntesis («(canal estable)», «(sin OTA)»). Nunca la explicación: eso es `description`. | propuesta |
59
+ | `badge` | Marca una opción frente a las otras: «Por defecto». Con string sale azul `light`; pasa el objeto con el color que corresponda según el badge (un «Por defecto» es `gray`). | propuesta |
60
+ | `disabled` | La opción existe pero hoy no se puede: di por qué en la `description` («El local está cerrado ahora»). | propuesta |
61
+ | `checked` / `[(ngModel)]` / `sui-radio-group` | El estado: `[checked]` + `(selected)` sueltos (lo normal en la app), o `ngModel` con `name` (checkout), o dentro de un `sui-radio-group`. | propuesta |
62
+
63
+ ### `size` (el radio de adentro)
64
+
65
+ | size | cuándo | fuente |
66
+ |---|---|---|
67
+ | `xlarge` (28) | Mobile, vía `bp.controlSize()`. | canon (aprobado por el dueño, 28-09-2026: «componentes grandes») |
68
+ | `large` (24) | Desktop, vía `bp.controlSize()`. | canon (aprobado por el dueño, 28-09-2026) |
69
+ | `medium` (20, default) | No usar en pantallas nuevas. | canon (aprobado por el dueño, 28-09-2026) |
70
+
71
+ **Usos de hoy que rompen las reglas:**
72
+
73
+ - **5 sin el size del breakpoint**: `components/por-cobrar-card/por-cobrar-card.html:38` y `:48`,
74
+ `pages/driver/driver-dashboard/driver-dashboard.html:581`,
75
+ `pages/super-admin/master-orders/master-orders.html:720` (los cuatro en `medium`) y
76
+ `pages/mi-negocio/mi-negocio.html:22` (sin `size`). Además `pages/customer/mandadito/mandadito.html:30`
77
+ va en `xlarge` fijo (en web debería ser `large`).
78
+ - **A revisar:** `pages/super-admin/master-orders/master-orders.html:720` lista a los repartidores
79
+ candidatos, una lista que crece con la flota (con muchos, `sui-select` o una lista con búsqueda).
80
+ `pages/role-selector/role-selector.html:24` usa la radio como botón: elegir ya avanza, sin
81
+ `[checked]`.
82
+
83
+ ## Tamaño en mobile y en web
84
+
85
+ La card entera es el área táctil (≥ 72 de alto con descripción, 16 de padding): llega al piso de
86
+ 44 sola. El `size` cambia solo el radio.
87
+
88
+ | uso | mobile | web |
89
+ |---|---|---|
90
+ | toda radio-card | `xlarge` (radio 28) | `large` (radio 24) |
91
+
92
+ ```html
93
+ <sui-radio-card [size]="bp.controlSize()" … /> <!-- isMobile() ? 'xlarge' : 'large' -->
94
+ ```
95
+
96
+ ## «No usar»: por qué no hoy y cuándo sí
97
+
98
+ | qué | por qué no hoy | cuándo sí, en un flujo nuevo |
99
+ |---|---|---|
100
+ | `type="brand"` (0 usos) | no hay servicios de terceros que elegir | elegir el canal por el que te contactamos (WhatsApp, correo) con su logo (`brand`) |
101
+ | `type="card-provider"` (0 usos) | no hay pago con tarjeta guardada | elegir una tarjeta guardada en el checkout, cuando entre Culqi / Niubiz |
102
+ | `size="medium"` | el radio de 20 se pierde en el teléfono | una tabla densa solo de desktop |
103
+
104
+ ## API
105
+
106
+ <!-- api:inicio -->
107
+ <!-- generada: no editar a mano — `npm run docs` -->
108
+
109
+ | input | tipo | default |
110
+ |---|---|---|
111
+ | `type` | `'basic' \| 'left-icon' \| 'avatar' \| 'card-provider' \| 'brand' \| 'company'` | `'basic'` |
112
+ | `size` | `'medium' \| 'large' \| 'xlarge'` | `'medium'` |
113
+ | `value` | `string` | — (requerido) |
114
+ | `label` | `string` | `''` |
115
+ | `sublabel` | `string \| null` | `null` |
116
+ | `description` | `string \| null` | `null` |
117
+ | `icon` | `string \| null` | `null` |
118
+ | `emoji` | `SuiEmojiName \| null` | `null` |
119
+ | `iconSrc` | `string \| null` | `null` |
120
+ | `imageUrl` | `string \| null` | `null` |
121
+ | `brand` | `SuiBrandLogoCompany \| null` | `null` |
122
+ | `badge` | `SuiBadgeConfig \| string \| null` | `null` |
123
+ | `disabled` | `boolean` | `false` |
124
+ | `checked` · model, `[(checked)]` | `boolean` | `false` |
125
+
126
+ | output | payload |
127
+ |---|---|
128
+ | `selected` | `string` |
129
+ <!-- api:fin -->
130
+
131
+ Implementa `ControlValueAccessor` (el valor del form es el `value` elegido). Dentro de un
132
+ `sui-radio-group`, el grupo decide cuál está marcada.
133
+
134
+ ## Trampas
135
+
136
+ - **`value` es obligatorio** aunque la uses suelta: sin él Angular tira error de input requerido.
137
+ - **Precedencia del leading en `left-icon`: `icon` > `emoji` > `iconSrc`.** Si pasas `icon` y
138
+ `iconSrc`, gana el ícono.
139
+ - Con `iconSrc` el círculo pasa a modo «relleno» (sin padding): el emoji ocupa los 40 × 40.
140
+ - `avatar`, `company` y `card-provider` leen la imagen de **`imageUrl`**; `brand` lee `brand` (o
141
+ `imageUrl` si la marca no está en el catálogo). No hay slot para proyectar el leading (a
142
+ diferencia de `sui-checkbox-card`).
143
+ - Suelta (sin grupo), elegirla la marca pero **no desmarca a las otras**: el padre tiene que
144
+ bindear `[checked]` de todas a la misma señal.
145
+ - `badge` con string sale **azul `light` `small`** (en `sui-content-label` sale naranja).
146
+ - `size` cambia solo el radio, no el padding ni el alto de la card.
147
+
148
+ ## Ejemplo
149
+
150
+ ```html
151
+ <sui-radio-card
152
+ [size]="bp.controlSize()"
153
+ type="left-icon"
154
+ value="pickup"
155
+ icon="store-2-line"
156
+ label="Recojo en tienda"
157
+ description="Lo recoges en el local"
158
+ [checked]="modo() === 'pickup'"
159
+ (selected)="modo.set('pickup')" />
160
+ ```
@@ -90,11 +90,11 @@ lista cargada, que viene con tope. La fórmula depende de `n`: otro denominador
90
90
  | `reviewCount` | número | **No usar** (ver abajo). | propuesta, falta aprobación |
91
91
  | `emojis` | lista | Dejar el default (cinco caras, de triste a feliz). Cambiarlo rompe la lectura de la escala. | propuesta, falta aprobación |
92
92
  | `ariaLabel` | texto | Decir qué se califica: «Califica al repartidor», «Nota del local». El default es «Calificación». | propuesta, falta aprobación |
93
- | `reason` / `reasonPlaceholder` / `reasonRows` | — | Solo en `bar-area`. **El placeholder va siempre en español**: el default está en inglés. | propuesta, falta aprobación |
93
+ | `reason` / `reasonPlaceholder` / `reasonRows` | — | Solo en `bar-area`. El placeholder por defecto es «Cuéntanos por qué» (03-10-2026). | propuesta, falta aprobación |
94
94
 
95
95
  **Usos de hoy que rompen la regla:**
96
96
 
97
- - **1 `reviewCount`** (pinta «Ratings» en inglés):
97
+ - **1 `reviewCount`** (hasta el 03-10-2026 pintaba «Ratings» en inglés; ahora «calificaciones»):
98
98
  `pages/super-admin/master-users/master-user-sheet.html:142`.
99
99
  - **1 rating usado como ícono** (`type="heart"` con `max=1` para los favoritos):
100
100
  `components/ratings-detail/ratings-detail.html:45`. Va `sui-icon name="heart-3-fill"`.
@@ -110,7 +110,7 @@ lista cargada, que viene con tope. La fórmula depende de `n`: otro denominador
110
110
  | `type="heart"` | La app califica con estrellas; el corazón es favoritos. | «¿Cuánto te gustó?» de una campaña, donde una estrella se leería como la nota del local. |
111
111
  | `type="number"` | No hay encuestas de 1 a 10. | «¿Qué tan probable es que nos recomiendes?» con `max=10` (ocupa 640 px de ancho). |
112
112
  | `showValue` | Escribe «4.7» con punto; la app escribe «4,7». | Si el DS formatea en `es-PE`. |
113
- | `reviewCount` | Agrega la palabra «Ratings» en inglés y abrevia «1.2K». | Si el DS traduce la etiqueta. |
113
+ | `reviewCount` | Abrevia «1.2K calificaciones» (la etiqueta está en español desde 03-10-2026). | Una lista de locales donde el conteo exacto no importa. |
114
114
  | `alignment="vertical"` | Solo ordena `showValue` y `reviewCount`, que no se usan. | Junto con esos dos, si se arreglan. |
115
115
 
116
116
  ## Tamaño en mobile y en web
@@ -160,7 +160,7 @@ plataforma solo se elige en `inline`.
160
160
  | `emojis` | `string[]` | `[ 'pensive-face', 'confused-face', 'neutral-face', 'slightly-smiling-face', 'grinning-face-smiling-eyes', ]` |
161
161
  | `ariaLabel` | `string` | `'Calificación'` |
162
162
  | `reason` · model, `[(reason)]` | `string` | `''` |
163
- | `reasonPlaceholder` | `string` | `'Tell us why!'` |
163
+ | `reasonPlaceholder` | `string` | `'Cuéntanos por qué'` |
164
164
  | `reasonRows` | `number` | `3` |
165
165
 
166
166
  | output | payload |
@@ -175,8 +175,9 @@ Implementa `ControlValueAccessor` sobre `value` (sirve con `formControlName`). `
175
175
 
176
176
  - **`showValue`, `reviewCount` y `reviewLink` solo se ven con `alignment="horizontal"` o
177
177
  `"vertical"`.** Con el default `inline` no aparecen.
178
- - **`reviewCount` agrega «Ratings» en inglés** y `showValue` formatea con punto.
179
- - **`reasonPlaceholder` viene en inglés** («Tell us why!»).
178
+ - **`reviewCount` agrega «calificaciones»** (en singular con 1; antes «Ratings») y `showValue`
179
+ formatea con punto.
180
+ - **`reasonPlaceholder` por defecto dice «Cuéntanos por qué»** (hasta el 03-10-2026, «Tell us why!»).
180
181
  - **`halfStep` solo funciona en `inline` + `readonly`.** En un input no hay medias.
181
182
  - **En `bar` el `size` no hace nada** (íconos de 20, celdas de 64); en `cell` los íconos miden 32.
182
183
  - **En `bar` y `bar-area` se pinta solo la celda elegida**, no las anteriores: no es una fila de
@@ -0,0 +1,114 @@
1
+ ---
2
+ name: sui-rich-editor
3
+ selector: sui-rich-editor
4
+ resumen: Barra de formato (negrita, cursiva, alineación, enlace) con un área de texto editable opcional
5
+ alternativas: [sui-textarea (todo texto libre de la app hoy, sin formato)]
6
+ ---
7
+
8
+ # sui-rich-editor
9
+
10
+ Story: [Molecules/Rich Editor](https://sui-design-system.web.app/?path=/docs/molecules-rich-editor--docs)
11
+
12
+ ## Cuándo usarlo / cuándo no
13
+
14
+ **Úsalo** solo si un texto **necesita formato** y se va a mostrar con ese formato: negritas,
15
+ listas o enlaces en un texto largo que se publica en la web.
16
+
17
+ **No lo uses** para:
18
+
19
+ - Notas, motivos, descripciones de productos, mensajes y avisos: `sui-textarea`. Todo eso se
20
+ guarda y se muestra como texto plano.
21
+ - Un push o un aviso del celular: no muestran formato.
22
+
23
+ Regla corta: **hoy, siempre `sui-textarea`.**
24
+
25
+ ## Qué variante usar
26
+
27
+ > **La guía del DS no tiene página para este componente.** Viene del Figma («Rich Editor»), donde
28
+ > solo está la barra de formato. Todo lo de abajo es **propuesta, falta aprobación**.
29
+ >
30
+ > Uso medido el 03-10-2026 en `master-pedidos/src/app`: **0 usos**.
31
+
32
+ | prop / evento | cuándo | fuente |
33
+ |---|---|---|
34
+ | `layout="full"` (default) | Título, tamaño, B I U S, alineación, comentario, enlace, mención. | API |
35
+ | `layout="formatting"` | Solo B I U S y alineación: lo único que el editor aplica solo. | propuesta, falta aprobación |
36
+ | `layout="compact"` | Solo título y tamaño (los dos son avisos a la pantalla, no formato real). | — |
37
+ | `layout="social"` | Comentario, enlace, mención (también avisos). | — |
38
+ | `showMore` | El botón ⋮ al final. Apagarlo si no hay más acciones. | API |
39
+ | `editable` | `true` para tener el área donde se escribe; `false` deja solo la barra. | API |
40
+ | `placeholder` | «Escribe algo…» (default) o algo del contexto. | API |
41
+ | `value` | El contenido, **en HTML**. | API |
42
+ | `headingLabel` · `fontSizeLabel` | Lo que dicen los botones de título y tamaño («Header», «14px» por default). | API |
43
+ | `(action)` | Cada botón de la barra: la pantalla tiene que resolver título, tamaño, enlace, comentario y mención. | API |
44
+
45
+ ## Tamaño en mobile y en web
46
+
47
+ **No tiene `size`.** Los botones de la barra son de 28 px: **no tiene tamaño suficiente para
48
+ mobile**. Si alguna vez se usa, que sea en el panel web.
49
+
50
+ ## «No usar»: por qué no hoy y cuándo sí
51
+
52
+ | qué | por qué no hoy | cuándo sí, en un flujo nuevo |
53
+ |---|---|---|
54
+ | el componente entero (0 usos) | ningún texto de la app lleva formato | una página de ayuda o de términos que se escribe desde el super admin y se muestra en la web |
55
+ | `layout` `full`, `compact`, `social` | título, tamaño, enlace, comentario y mención no los hace el editor: solo avisa | si se monta un editor completo (Tiptap) detrás |
56
+
57
+ ## API
58
+
59
+ <!-- api:inicio -->
60
+ <!-- generada: no editar a mano — `npm run docs` -->
61
+
62
+ ### `sui-rich-editor`
63
+
64
+ | input | tipo | default |
65
+ |---|---|---|
66
+ | `layout` | `'full' \| 'compact' \| 'formatting' \| 'social'` | `'full'` |
67
+ | `showMore` | `boolean` | `true` |
68
+ | `editable` | `boolean` | `false` |
69
+ | `placeholder` | `string` | `'Escribe algo…'` |
70
+ | `value` · model, `[(value)]` | `string` | `''` |
71
+ | `headingLabel` | `string` | `'Header'` |
72
+ | `fontSizeLabel` | `string` | `'14px'` |
73
+
74
+ | output | payload |
75
+ |---|---|
76
+ | `action` | `SuiRichEditorAction` |
77
+ | `valueChange` | `string` |
78
+
79
+ ### `sui-rich-editor-item`
80
+
81
+ | input | tipo | default |
82
+ |---|---|---|
83
+ | `type` | `'text' \| 'dropdown' \| 'icon' \| 'color'` | `'icon'` |
84
+ | `state` | `'default' \| 'hover' \| 'active'` | `'default'` |
85
+ | `label` | `string` | `''` |
86
+ | `icon` | `string` | `''` |
87
+ | `color` | `'gray' \| 'blue' \| 'orange' \| 'red' \| 'green' \| 'yellow' \| 'purple' \| 'sky' \| 'pink' \| 'teal'` | `'gray'` |
88
+ | `colorHex` | `string \| null` | `null` |
89
+ | `ariaLabel` | `string` | `''` |
90
+ | `disabled` | `boolean` | `false` |
91
+
92
+ | output | payload |
93
+ |---|---|
94
+ | `clicked` | `void` |
95
+ <!-- api:fin -->
96
+
97
+ Sub-componente: `sui-rich-editor-item` (cada botón de la barra).
98
+
99
+ ## Trampas
100
+
101
+ - **`value` es HTML.** Mostrarlo con `[innerHTML]` sin limpiarlo abre la puerta a código ajeno.
102
+ Limpiarlo en el servidor antes de guardar.
103
+ - **Solo B I U S y alineación funcionan solos** (usa `document.execCommand`, que está en desuso).
104
+ Título, tamaño, enlace, comentario y mención solo emiten `(action)`: la pantalla tiene que hacer
105
+ el resto.
106
+ - Por default muestra solo la barra: sin `[editable]="true"` no hay dónde escribir.
107
+ - Labels por default en inglés o técnicos («Header», «14px»).
108
+
109
+ ## Ejemplo
110
+
111
+ ```html
112
+ <sui-rich-editor layout="formatting" [showMore]="false" [editable]="true"
113
+ placeholder="Escribe la respuesta…" [(value)]="html" />
114
+ ```
@@ -0,0 +1,180 @@
1
+ ---
2
+ name: sui-select
3
+ selector: sui-select
4
+ resumen: Campo que despliega una lista para elegir UNA opción (distrito, repartidor, categoría, motivo)
5
+ alternativas: [sui-radio-label / sui-radio-card (2 a 6 opciones fijas a la vista), sui-segmented-control (2 a 4 modos que se aplican al instante), sui-compact-select (filtro chico que se ajusta al texto), sui-compact-select-for-input (elegir moneda o país dentro de un campo), sui-tag-input (varios valores)]
6
+ ---
7
+
8
+ # sui-select
9
+
10
+ Story: [Molecules/Select/Select](https://sui-design-system.web.app/?path=/docs/molecules-select-select--docs)
11
+
12
+ ## Cuándo usarlo / cuándo no
13
+
14
+ **Úsalo** para elegir **una** opción de una lista que **sale de datos** (departamento, provincia,
15
+ distrito, repartidor, categoría, plan) o que tiene **más de 6 opciones fijas**.
16
+
17
+ **No lo uses** para:
18
+
19
+ - 2 a 6 opciones fijas dentro de un formulario: se ven todas de una con `sui-radio-label` (web) o
20
+ `sui-radio-card` (mobile). Abrir un menú para elegir entre «Casa» y «Trabajo» es un toque de más.
21
+ - 2 a 4 modos de la vista que se aplican al tocar (Hoy · Semana · Mes): `sui-segmented-control`.
22
+ - **Buscar** dentro de la lista: `sui-select` **no tiene buscador**. Con 40 distritos se scrollea.
23
+ - Elegir **varias**: no es múltiple. Varias opciones fijas → casillas; valores libres → `sui-tag-input`.
24
+ - Una lista con foto o bandera por opción: las opciones solo muestran texto (ver «Trampas»).
25
+
26
+ Regla corta: **sale de datos o son más de 6 → select · 2–6 fijas → radio · modos de la vista → segmented.**
27
+
28
+ ## Qué variante usar
29
+
30
+ > **La guía del DS lo define como el control para elegir una sola opción de un menú** y muestra
31
+ > label y hint, íconos, tamaños, país, método de pago, usuario y deshabilitado. Trae además tres
32
+ > variantes que en SUI son componentes aparte: `compact` (`sui-compact-select`), `inline`
33
+ > (`sui-inline-select`) y `compactForInput` (`sui-compact-select-for-input`). No dice cuándo va cada una.
34
+ >
35
+ > Uso medido el 03-10-2026 en `master-pedidos/src/app` (misma exclusión que `sui-badge`, más
36
+ > `master-ejercicios`): **57 usos en 26 archivos**. Todos `type="basic"` y sin ícono. Tamaños:
37
+ > 39 sin `size` (`medium`), 11 `large`, 3 `bp.isMobile() ? 'large' : 'small'`, 2 `medium`,
38
+ > 1 `small`, 1 `bp.controlSize()`. 29 pasan `placeholder`.
39
+
40
+ ### Qué elegir según las opciones
41
+
42
+ | caso | componente | fuente |
43
+ |---|---|---|
44
+ | La lista sale de datos (ubigeo, repartidores, categorías, planes) | `sui-select` | según la guía del DS (elegir una opción de un menú) |
45
+ | Más de ~6 opciones fijas | `sui-select` | canon (README de `sui-radio`, aprobado 03-10-2026) |
46
+ | 2 a 6 opciones fijas en un formulario | `sui-radio-label` / `sui-radio-card` | propuesta, falta aprobación (sale del umbral de `sui-radio`) |
47
+ | 2 a 4 modos que se aplican al instante | `sui-segmented-control` | canon (README de `sui-segmented-control`, aprobado 03-10-2026) |
48
+ | Filtro de una barra con 5 o más opciones | `sui-select` sin label (o `sui-compact-select` en web) | propuesta, falta aprobación |
49
+
50
+ **Candidatos de hoy** (no rompen nada; se verían mejor con radios o segmented):
51
+
52
+ - **6 selects con 2 opciones fijas**: `components/add-product-modal/add-product-modal.html:246`,
53
+ `pages/drivers/drivers.html:373` y `pages/drivers/add-driver/add-driver.html:111` («Tipo de pago»),
54
+ `pages/super-admin/master-gastos/master-gastos.html:185` y `:200`,
55
+ `pages/super-admin/master-sonidos-push/master-sonidos-push.html:85`.
56
+ - **15 con 3 a 6 opciones fijas en un formulario**: `components/address-form-modal/address-form-modal.html:11`
57
+ («Etiqueta»), `pages/customer/profile/profile.html:249` («Género»), `pages/drivers/drivers.html:359`
58
+ («Tipo de vehículo»), `pages/discounts/discounts.html:139`.
59
+ - **2 filtros de período de 3 opciones** → segmented: `pages/overview/overview.html:46`,
60
+ `pages/discounts/discounts.html:48`.
61
+
62
+ ### `type`, `leadingIcon`, `imageUrl`, `flag`, `badge`
63
+
64
+ | prop | cuándo | fuente |
65
+ |---|---|---|
66
+ | `type="basic"` (default) sin ícono | Todo select de la app hoy. | según la guía del DS |
67
+ | `type="avatar"` + `imageUrl` | Elegir un **repartidor**: la foto de quien quedó elegido en el campo. Hoy `pages/orders/orders.html:256` muestra solo el nombre. | según la guía del DS (ejemplo «User»); el caso es propuesta |
68
+ | `type="provider"` + `imageUrl` | Método de pago con logo (Yape, Plin). | según la guía del DS (ejemplo «Payment Method»); el caso es propuesta |
69
+ | `leadingIcon` (`true` o nombre RemixIcon) | Un ícono que ayuda a reconocer el campo en un formulario largo. Hoy sin caso. | según la guía del DS (ejemplo «Icons») |
70
+ | `type="country"` + `flag` | No usar hoy: todo es Perú. | según la guía del DS (ejemplo «Country») |
71
+ | `type="brand"` / `"company"` | No usar hoy. | — |
72
+ | `badge` | No usar hoy. | — |
73
+
74
+ ### Las piezas
75
+
76
+ | prop | cuándo | fuente |
77
+ |---|---|---|
78
+ | `label` | Siempre en formularios. Sin label solo en un filtro de barra donde el valor se explica solo («Todos los roles»). | según la guía del DS (ejemplo con label y hint) |
79
+ | `placeholder` | **Siempre**, en imperativo con tuteo: «Elige el motivo», «Elige tu distrito». El default es «Seleccionar...». | canon (CANON-SUI §5.3) |
80
+ | `required` · `sublabel` · `tooltip` · `hint` | Igual que `sui-input`: asterisco, «(Opcional)» con paréntesis, aclaración, ayuda de una línea. Hoy 1 sin paréntesis: `pages/customer/profile/profile.html:249`. | según la guía del DS |
81
+ | `error` + `errorMessage` | No eligió en un campo obligatorio: «Elige tu distrito». | según la guía del DS |
82
+ | `disabled` | Selects en cascada: provincia hasta elegir departamento, distrito hasta elegir provincia. | según la guía del DS (ejemplo deshabilitado); el caso ya es práctica (`components/address-form-modal/address-form-modal.html:87`) |
83
+ | `options` | `SuiSelectOption<T>[]`: `{ value, label, disabled? }`. `disabled` en la opción para lo que existe pero hoy no se puede elegir. | API |
84
+
85
+ **Usos de hoy que rompen la regla:**
86
+
87
+ - **28 sin `placeholder`** muestran «Seleccionar...» si arrancan vacíos.
88
+ - **16 placeholders «Seleccionar…» o «Selecciona…»** (y 4 que ya dicen «Elige…») → «Elige…»: «Seleccionar departamento»
89
+ (`components/address-form-modal/address-form-modal.html:77`), «Seleccionar tipo»,
90
+ «Selecciona una categoría».
91
+
92
+ ## Tamaño en mobile y en web
93
+
94
+ El campo sigue la escala del input y del botón (`large` 48 y `xlarge` 52 son extensión de SUI;
95
+ la guía tiene `medium` 40, `small` 36 y `xsmall` 32). **La lista acompaña al campo**: las opciones
96
+ miden 36 hasta `medium` (las de la guía), 44 en `large` y 48 en `xlarge`, y **en mobile (≤ 767 px)
97
+ nunca bajan de 44**, sea cual sea el `size`. El texto de la opción queda en 14/20, el mismo del
98
+ valor del campo.
99
+
100
+ | size del campo | opción en web | opción en mobile | fuente |
101
+ |---|---|---|---|
102
+ | `xsmall` · `small` · `medium` | 36 | 44 | 36: según la guía del DS · 44 en mobile: canon (aprobado por el dueño, 03-10-2026), extensión SUI |
103
+ | `large` | 44 | 44 | canon (aprobado por el dueño, 03-10-2026), extensión SUI |
104
+ | `xlarge` | 48 | 48 | canon (aprobado por el dueño, 03-10-2026), extensión SUI |
105
+
106
+ | uso | mobile | web | fuente |
107
+ |---|---|---|---|
108
+ | campo de formulario | `large` (48) | `medium` (40) | propuesta, falta aprobación (igual que `sui-input`) |
109
+ | filtro de una barra | `large` (48) | `small` (36) | propuesta (ya es práctica en `pages/orders/orders.html:256`) |
110
+ | dentro de una tabla densa | no aplica | `xsmall` (32) | según la guía del DS |
111
+ | `xlarge` (52) | no usar | no usar | propuesta: queda más alto que el botón `large` del footer |
112
+
113
+ ```html
114
+ <sui-select [size]="bp.isMobile() ? 'large' : 'medium'" label="Distrito" … /> <!-- bp = BreakpointsService -->
115
+ ```
116
+
117
+ ## «No usar»: por qué no hoy y cuándo sí
118
+
119
+ | qué | por qué no hoy | cuándo sí, en un flujo nuevo |
120
+ |---|---|---|
121
+ | `type="country"` + `flag` | todo es Perú | si se abren repartidores o locales en otro país |
122
+ | `type="brand"` / `"company"` | no hay listas de marcas o empresas | elegir la marca de un producto envasado o la empresa de una flota |
123
+ | `leadingIcon` | ningún formulario lo necesita para reconocerse | un formulario largo del panel con varios selects seguidos |
124
+ | `badge` | no hay valores que marcar | marcar el plan elegido como «Recomendado» |
125
+ | `size="xsmall"` | no hay selects dentro de tablas | cambiar el estado de una fila sin abrir el detalle |
126
+ | `size="xlarge"` | queda más alto que el botón del footer | un select solo, como acción principal de la pantalla |
127
+
128
+ ## API
129
+
130
+ <!-- api:inicio -->
131
+ <!-- generada: no editar a mano — `npm run docs` -->
132
+
133
+ | input | tipo | default |
134
+ |---|---|---|
135
+ | `size` | `'xsmall' \| 'small' \| 'medium' \| 'large' \| 'xlarge'` | `'medium'` |
136
+ | `placeholder` | `string` | `'Seleccionar...'` |
137
+ | `options` | `SuiSelectOption<T>[]` | `[]` |
138
+ | `disabled` | `boolean` | `false` |
139
+ | `error` | `boolean` | `false` |
140
+ | `errorMessage` | `string \| null` | `null` |
141
+ | `label` | `string \| null` | `null` |
142
+ | `hint` | `string \| null` | `null` |
143
+ | `type` | `'basic' \| 'country' \| 'avatar' \| 'provider' \| 'brand' \| 'company'` | `'basic'` |
144
+ | `leadingIcon` | `string \| boolean` | `false` |
145
+ | `flag` | `SuiFlagName \| null` | `null` |
146
+ | `imageUrl` | `string \| null` | `null` |
147
+ | `badge` | `SuiBadgeConfig \| string \| null` | `null` |
148
+ | `sublabel` | `string \| null` | `null` |
149
+ | `required` | `boolean` | `false` |
150
+ | `tooltip` | `string \| null` | `null` |
151
+ | `value` · model, `[(value)]` | `T \| null` | `null` |
152
+
153
+ Outputs: ninguno.
154
+ <!-- api:fin -->
155
+
156
+ `value` es `model<T | null>`. Implementa `ControlValueAccessor`. Slot `[slot=leading]` para una
157
+ decoración propia del campo (gana sobre ícono, imagen y bandera).
158
+
159
+ ## Trampas
160
+
161
+ - **No busca y no es múltiple.** Con 40 opciones la lista se scrollea; con varias a elegir no sirve.
162
+ - **Las opciones solo llevan texto**: `SuiSelectOption` no tiene ícono, foto ni bandera. El
163
+ `type="avatar"` o `"country"` decora **el campo**, no la lista.
164
+ - **El default del placeholder es «Seleccionar...»**: genérico y con `...`. Pásalo siempre.
165
+ - El `valueChange` puede traer `null`: los usos de hoy hacen `$event ?? ''`.
166
+ - `T` arranca en `any`: tipa las opciones (`SuiSelectOption<string>[]`) para no arrastrar `any`
167
+ a la pantalla.
168
+ - Con 44 px por opción en mobile el panel muestra unas 4 opciones antes de scrollear (el alto
169
+ máximo del panel no cambió).
170
+ - El label también abre la lista al tocarlo.
171
+
172
+ ## Ejemplo
173
+
174
+ ```html
175
+ <sui-select label="Distrito" [required]="true" placeholder="Elige tu distrito"
176
+ [options]="distritos()" [disabled]="!provinciaId()"
177
+ [error]="intentado() && !distritoId()" errorMessage="Elige tu distrito"
178
+ [size]="bp.isMobile() ? 'large' : 'medium'"
179
+ [value]="distritoId()" (valueChange)="distritoId.set($event ?? '')" />
180
+ ```
@@ -0,0 +1,166 @@
1
+ ---
2
+ name: sui-stepper
3
+ selector: sui-stepper
4
+ resumen: Indica en qué paso de un flujo con orden está la persona, cuánto hizo y cuánto le falta
5
+ alternativas: [sui-progress-bar (importa el porcentaje, no los pasos), sui-pagination (páginas de una lista), sui-tab-menu-horizontal (secciones sin orden)]
6
+ ---
7
+
8
+ # sui-stepper
9
+
10
+ Story: [Molecules/Stepper](https://sui-design-system.web.app/?path=/docs/molecules-stepper--docs)
11
+
12
+ Ojo: es el **indicador de pasos** de un proceso. El «− 1 +» de cantidad es otra cosa
13
+ (`sui-counter-input` o los botones del producto).
14
+
15
+ ## Cuándo usarlo / cuándo no
16
+
17
+ **Úsalo** cuando un flujo tiene **pasos con nombre y orden** y ayuda saber cuántos faltan: el alta
18
+ del local («Tu local → Producto»), del cliente («Ubicación → Teléfono»), del repartidor («Datos →
19
+ Vehículo → Listo»).
20
+
21
+ **No lo uses** para:
22
+
23
+ - Un avance que es porcentaje (subida de un archivo, perfil completo al 70 %): `sui-progress-bar`.
24
+ - Un pedido en curso (preparando, en camino, entregado): ese seguimiento tiene su propia línea de
25
+ tiempo y estados que no son pasos que la persona completa.
26
+ - Secciones que se visitan en cualquier orden: `sui-tab-menu-horizontal`.
27
+ - Un solo paso: no hay nada que indicar.
28
+
29
+ Regla corta: **pasos con nombre y orden → stepper · porcentaje → progress-bar · secciones sin orden → tab menu.**
30
+
31
+ ## Qué variante usar
32
+
33
+ > **Lo que dice la guía del DS**: tiene tres piezas. El **de puntos**, «muy mínimo, usado a menudo
34
+ > como puntos de carrusel», con tamaños `small` y `xsmall`. El **horizontal**, «una guía visual de
35
+ > procesos secuenciales». El **vertical**, el mismo indicador «para layouts diversos», con una
36
+ > flecha en el paso activo. Estados de cada paso: `default`, `active`, `completed`. No trae do/don't.
37
+ >
38
+ > Uso medido el 03-10-2026 en `master-pedidos/src/app` (misma exclusión que `sui-badge`):
39
+ > **7 usos en 7 archivos**, los 7 en los onboardings: todos `variant="horizontal"`, sin `size`
40
+ > (`small`), sin `interactive`, de 2 o 3 pasos.
41
+
42
+ ### `variant`
43
+
44
+ | variant | cuándo | ejemplo real de la app | fuente |
45
+ |---|---|---|---|
46
+ | `horizontal` (default) | Flujo de **2 a 4 pasos** con nombre, arriba del contenido del paso. Mobile y web. | `pages/driver-onboarding/step-info/step-info.html:3` («Datos → Vehículo → Listo») | según la guía del DS (procesos secuenciales); el límite de pasos es propuesta |
47
+ | `vertical` | Flujo de **5+ pasos** en web, en una columna al costado del formulario. | (sin uso) | según la guía del DS (la pieza existe); el cuándo es propuesta |
48
+ | `dot` | Pantallas que se pasan de a una sin nombre: carrusel de bienvenida, fotos. | (sin uso) | según la guía del DS (puntos de carrusel) |
49
+
50
+ ### `size`
51
+
52
+ | size | qué cambia | cuándo | fuente |
53
+ |---|---|---|---|
54
+ | `small` (default) | punto de 8 · indicador de 20 · texto 14 | Web. | según la guía del DS (`small` es su default) |
55
+ | `xsmall` | solo el punto: 4 px. Horizontal y vertical quedan igual que `small`. | Puntos sobre una foto o un banner chico, donde 8 px tapan. | según la guía del DS (el tamaño existe); el cuándo es propuesta |
56
+ | `medium` | punto de 10 · indicador de 24 · texto 16 · card vertical de 44 | Mobile. **Está en el repo del DS (03-10-2026), no en la versión publicada 0.19.0.** | canon (dueño: tamaño por plataforma, 03-10-2026) |
57
+
58
+ ### Estado de cada paso (`currentStep`, `errorStep`)
59
+
60
+ | estado | cómo se logra | cuándo | fuente |
61
+ |---|---|---|---|
62
+ | `completed` | índice menor que `currentStep` | pasos ya hechos (check verde) | según la guía del DS |
63
+ | `active` | índice igual a `currentStep` | el paso en pantalla | según la guía del DS |
64
+ | `default` | índice mayor que `currentStep` | lo que falta | según la guía del DS |
65
+ | todos `completed` | `currentStep` = cantidad de pasos | la pantalla final («Listo») | propuesta, falta aprobación |
66
+ | `error` | `errorStep` = índice | un flujo que se cortó en ese paso (pago rechazado, documento no aprobado). Extensión de SUI. | propuesta, falta aprobación |
67
+
68
+ ### `interactive`
69
+
70
+ | valor | cuándo | fuente |
71
+ |---|---|---|
72
+ | `false` (default) | Los onboardings: se avanza con el botón «Continuar», no tocando el paso. | propuesta, falta aprobación |
73
+ | `true` | Solo si los pasos hechos se pueden **volver a editar** y en web (el área tocable es chica, ver Tamaño). | propuesta, falta aprobación |
74
+
75
+ ### `steps`, `count`, `ariaLabel`
76
+
77
+ | input | cuándo | fuente |
78
+ |---|---|---|
79
+ | `steps` | Siempre en `horizontal` y `vertical`, con `label` en cada uno. | propuesta, falta aprobación |
80
+ | `count` | Solo en `dot`, cuando los pasos no tienen nombre. Si pasas `steps`, `count` se ignora. | según el código |
81
+ | `ariaLabel` | Default «Progreso». Cámbialo si hay más de un stepper en la pantalla («Pasos del registro»). | propuesta, falta aprobación |
82
+
83
+ **Usos de hoy que rompen las reglas:**
84
+
85
+ - **0 de variante o estado**: los 7 son horizontales de 2 o 3 pasos, y `step-complete` usa
86
+ `currentStep = stepLabels.length` para marcar todo hecho (`pages/driver-onboarding/step-complete/step-complete.html:3`).
87
+ - **7 sin tamaño por plataforma** (el `medium` todavía no está publicado): los onboardings se hacen
88
+ en el teléfono. Cuando se publique, `[size]="bp.isMobile() ? 'medium' : 'small'"`. Ejemplos:
89
+ `pages/customer-onboarding/step-phone/step-phone.html:3`, `pages/business-onboarding/step-info/step-info.html:3`.
90
+
91
+ ## Tamaño en mobile y en web
92
+
93
+ | uso | mobile | web | fuente |
94
+ |---|---|---|---|
95
+ | horizontal arriba de un paso | `medium` (indicador 24, texto 16) | `small` (indicador 20, texto 14) | canon (dueño: tamaño por plataforma, 03-10-2026) |
96
+ | vertical al costado | no se usa (no entra al lado del formulario) | `small` | propuesta, falta aprobación |
97
+ | puntos de carrusel | `medium` (10) | `small` (8) | propuesta, falta aprobación |
98
+
99
+ ```html
100
+ <sui-stepper [steps]="pasos" [currentStep]="paso - 1" [size]="bp.isMobile() ? 'medium' : 'small'" />
101
+ ```
102
+
103
+ Sin `interactive` el tamaño solo afecta lo que se lee. Con `interactive`, **ningún tamaño llega a
104
+ 44 px tocables** en horizontal (24 de alto con `medium`) ni en puntos (10 px): por eso
105
+ `interactive` queda para web. La card vertical `medium` sí llega a 44.
106
+
107
+ ## «No usar»: por qué no hoy y cuándo sí
108
+
109
+ | qué | por qué no hoy | cuándo sí, en un flujo nuevo |
110
+ |---|---|---|
111
+ | `vertical` | ningún flujo tiene 5+ pasos | un alta de local completa en web (datos, carta, horario, pagos, repartidores) |
112
+ | `dot` | ningún carrusel usa el componente | un carrusel de bienvenida o de fotos del producto |
113
+ | `xsmall` | no hay puntos sobre fotos | puntos sobre el banner del carrusel del home |
114
+ | `errorStep` | ningún flujo muestra dónde se cortó | el estado de una solicitud de repartidor rechazada en el paso «Documentos» |
115
+ | `interactive` | en los onboardings se avanza con el botón | un formulario largo en web donde se vuelve a corregir un paso hecho |
116
+
117
+ ## API
118
+
119
+ <!-- api:inicio -->
120
+ <!-- generada: no editar a mano — `npm run docs` -->
121
+
122
+ | input | tipo | default |
123
+ |---|---|---|
124
+ | `variant` | `'dot' \| 'horizontal' \| 'vertical'` | `'horizontal'` |
125
+ | `steps` | `SuiStepperItem[]` | `[]` |
126
+ | `count` | `number` | `0` |
127
+ | `currentStep` | `number` | `0` |
128
+ | `errorStep` | `number \| null` | `null` |
129
+ | `size` | `'small' \| 'xsmall' \| 'medium'` | `'small'` |
130
+ | `interactive` | `boolean` | `false` |
131
+ | `ariaLabel` | `string` | `'Progreso'` |
132
+
133
+ | output | payload |
134
+ |---|---|
135
+ | `stepClick` | `number` |
136
+ <!-- api:fin -->
137
+
138
+ ```ts
139
+ interface SuiStepperItem {
140
+ label?: string; // sin label sale «Paso N»
141
+ }
142
+ type SuiStepperVariant = 'dot' | 'horizontal' | 'vertical';
143
+ type SuiStepperSize = 'small' | 'xsmall' | 'medium'; // medium: repo del DS, no en 0.19.0
144
+ ```
145
+
146
+ ## Trampas
147
+
148
+ - **`currentStep` arranca en 0.** La app numera los pasos desde 1: por eso los onboardings pasan
149
+ `currentStep - 1`.
150
+ - **Un paso sin `label` dice «Paso 2»** (hasta el 03-10-2026 decía «Step 2»).
151
+ - **`xsmall` solo achica los puntos**: en horizontal y vertical se ve igual que `small`.
152
+ - **El horizontal hace `flex-wrap`**: con muchos pasos o nombres largos baja a otra línea en vez de
153
+ cortarse. Con 4+ pasos en mobile, revisa a 390 px.
154
+ - **`stepClick` solo sale con `interactive`**; sin él los pasos son `div` y no responden.
155
+ - `errorStep` gana sobre `currentStep`: los anteriores quedan hechos y los siguientes por hacer.
156
+ - El activo usa `--sui-primary-base`, que en la app es naranja.
157
+
158
+ ## Ejemplo
159
+
160
+ ```html
161
+ <sui-stepper
162
+ variant="horizontal"
163
+ [steps]="[{ label: 'Datos' }, { label: 'Vehículo' }, { label: 'Listo' }]"
164
+ [currentStep]="1"
165
+ [size]="bp.isMobile() ? 'medium' : 'small'" />
166
+ ```