@ajuarezso/sui-design-system 0.25.1 → 0.26.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 (68) hide show
  1. package/docs/INDEX.md +3 -3
  2. package/docs/TEXTOS.md +85 -0
  3. package/docs/sui-activity-feed/README.md +19 -4
  4. package/docs/sui-alert/README.md +10 -0
  5. package/docs/sui-avatar-group/README.md +10 -0
  6. package/docs/sui-banner/README.md +10 -0
  7. package/docs/sui-brand-logo/README.md +10 -0
  8. package/docs/sui-breadcrumbs/README.md +10 -0
  9. package/docs/sui-checkbox-card/README.md +2 -1
  10. package/docs/sui-circular-progress-bar/README.md +10 -0
  11. package/docs/sui-color-dot/README.md +20 -0
  12. package/docs/sui-color-picker/README.md +20 -3
  13. package/docs/sui-command-menu-footer/README.md +17 -4
  14. package/docs/sui-command-menu-item/README.md +18 -10
  15. package/docs/sui-command-menu-search/README.md +18 -8
  16. package/docs/sui-compact-select/README.md +2 -0
  17. package/docs/sui-content-card/README.md +11 -1
  18. package/docs/sui-content-divider/README.md +11 -0
  19. package/docs/sui-counter-input/README.md +13 -2
  20. package/docs/sui-date-selector/README.md +11 -0
  21. package/docs/sui-datepicker/README.md +17 -0
  22. package/docs/sui-day-cell/README.md +10 -0
  23. package/docs/sui-drawer-footer/README.md +17 -2
  24. package/docs/sui-drawer-header/README.md +11 -1
  25. package/docs/sui-dropdown-menu/README.md +9 -1
  26. package/docs/sui-dropdown-search/README.md +21 -10
  27. package/docs/sui-file-icon/README.md +11 -0
  28. package/docs/sui-file-upload/README.md +14 -1
  29. package/docs/sui-file-upload-card/README.md +20 -4
  30. package/docs/sui-filter/README.md +27 -15
  31. package/docs/sui-image-upload/README.md +19 -0
  32. package/docs/sui-image-upload-profile/README.md +16 -2
  33. package/docs/sui-inline-input/README.md +15 -2
  34. package/docs/sui-input/README.md +12 -0
  35. package/docs/sui-integration-switch/README.md +10 -0
  36. package/docs/sui-modal/README.md +51 -3
  37. package/docs/sui-modal-header/README.md +10 -0
  38. package/docs/sui-modal-sheet/README.md +24 -12
  39. package/docs/sui-notification/README.md +12 -0
  40. package/docs/sui-notification-footer/README.md +14 -2
  41. package/docs/sui-notification-tab-menu/README.md +11 -1
  42. package/docs/sui-otp-input/README.md +12 -1
  43. package/docs/sui-pagination/README.md +16 -0
  44. package/docs/sui-password-strength/README.md +21 -3
  45. package/docs/sui-popover/README.md +15 -2
  46. package/docs/sui-progress-bar/README.md +10 -0
  47. package/docs/sui-radio/README.md +4 -1
  48. package/docs/sui-radio-label/README.md +5 -2
  49. package/docs/sui-rating/README.md +16 -2
  50. package/docs/sui-rich-editor/README.md +25 -2
  51. package/docs/sui-select/README.md +11 -1
  52. package/docs/sui-sidebar/README.md +18 -1
  53. package/docs/sui-slider/README.md +11 -0
  54. package/docs/sui-social-button/README.md +10 -0
  55. package/docs/sui-stepper/README.md +12 -1
  56. package/docs/sui-tab-chips/README.md +11 -0
  57. package/docs/sui-table/README.md +15 -1
  58. package/docs/sui-tag/README.md +11 -1
  59. package/docs/sui-tag-input/README.md +12 -1
  60. package/docs/sui-time-picker/README.md +19 -1
  61. package/docs/sui-toast/README.md +11 -0
  62. package/docs/sui-tooltip/README.md +10 -0
  63. package/docs/sui-topbar/README.md +15 -2
  64. package/docs/sui-topbar-user/README.md +10 -0
  65. package/fesm2022/ajuarezso-sui-design-system.mjs +1030 -462
  66. package/fesm2022/ajuarezso-sui-design-system.mjs.map +1 -1
  67. package/package.json +1 -1
  68. package/types/ajuarezso-sui-design-system.d.ts +703 -138
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: sui-modal-sheet
3
3
  selector: sui-modal-sheet
4
- resumen: Hoja que sube desde abajo, se arrastra entre alturas fijas y puede dejar usable lo de atrás (un mapa)
4
+ resumen: Hoja del celular que sube desde abajo, se arrastra entre alturas fijas y puede dejar usable lo de atrás (un mapa); en tablet y computadora se usa sui-modal
5
5
  alternativas: [sui-modal (pide terminar algo antes de seguir, sin fondo usable), sui-popover (contenido chico anclado a un botón), sui-dropdown-menu (lista de acciones)]
6
6
  ---
7
7
 
@@ -22,8 +22,11 @@ Story: [Organisms/Modal/Modal Sheet](https://sui-design-system.web.app/?path=/do
22
22
 
23
23
  - Un formulario o una confirmación que hay que terminar: `sui-modal`. El sheet se cierra con un
24
24
  deslizón y se pierde lo escrito.
25
- - Desktop como superficie principal: en una pantalla de 1440 px un sheet a todo el ancho se lee
26
- como un error (ver tamaño). Si en desktop hay sitio, un panel lateral sirve mejor.
25
+ - **Tablet y computadora (> 768 px): nunca.** Canon (decisión del dueño, 08-10-2026): en
26
+ pantalla ancha el mismo contenido va en un `sui-modal` centrado, con el ancho según cuánto
27
+ contenido hay (mucho → `xlarge`). La receta para abrir lo mismo en los dos está en el README de
28
+ `sui-modal` («Celular, tablet y computadora»). Si la pantalla tiene sitio para mostrarlo al
29
+ lado, un panel lateral también sirve (`pages/customer/viaje/viaje.html:25`).
27
30
 
28
31
  ## Qué variante usar
29
32
 
@@ -84,22 +87,25 @@ El sheet **no tiene `size`**. Mide lo que mide su contenido, con tope en el brea
84
87
  | ancho | toda la pantalla menos 8 px a cada lado | **igual: todo el ancho menos 8 px** | componente |
85
88
  | esquinas | iOS 36 arriba / 54 abajo · Android 20 | igual | canon (CLAUDE.md, 2026-07-22) |
86
89
  | padding del body | `0 20px 20px` | igual | canon (CLAUDE.md, 2026-07-21) |
87
- | ancho en desktop | — | acotarlo a una columna centrada de 560 px | propuesta (hoy lo hace cada pantalla a mano) |
90
+ | en tablet y computadora | — | **no se usa**: va `sui-modal` centrado | canon (dueño, 08-10-2026) |
88
91
 
89
- **El sheet no se acota en desktop.** La app lo arregla con CSS propio, cinco reglas en cuatro archivos:
90
- `components/store-ratings-modal/store-ratings-modal.scss:81`,
91
- `components/movimientos-saldo/movimientos-saldo-sheet.scss:25`,
92
- `pages/driver/driver-order-detail/driver-order-detail.scss:1096` (las tres a 560 px) y
93
- `pages/customer/order-tracking/order-tracking.scss:1175` y `:1238` (a 480 px). Propuesta:
94
- que el DS traiga ese tope (`max-width` desde 768 px, centrado) y se borren esos parches.
92
+ **Migrados el 09-10-2026** (master-pedidos `fix(ui): reseñas, movimientos y métodos de pago abren un modal…`):
93
+ la ficha del local (`components/store-ratings-modal`), los movimientos de la billetera
94
+ (`components/movimientos-saldo`), las calificaciones del cliente en `driver-order-detail` y las
95
+ reseñas y los métodos de pago del repartidor en `order-tracking`. Hoja en el celular, `sui-modal` en
96
+ tablet y computadora (listas en `xlarge`, métodos de pago en `medium`); los parches de CSS se borraron.
97
+
98
+ Los dos «sobre un mapa» del seguimiento (`order-tracking.html:139`, `driver-order-detail.html:60`)
99
+ no son un modal: en pantalla ancha van mejor como panel lateral, como ya hace
100
+ `pages/customer/viaje/viaje.html:25`.
95
101
 
96
102
  ### Por dispositivo (D16)
97
103
 
98
104
  No aplica: el sheet **no tiene `size`**; mide lo que mide su contenido y se configura con alturas
99
105
  (`breakpoints`), no con un tamaño. Es igual en el celular chico, el celular, la tablet táctil, la
100
106
  computadora y el ultrawide. El tamaño de lo que va adentro (botones, campos) sigue su propia
101
- fila de D16. Lo único que cambia por dispositivo es el ancho desde 768 px, y eso es P21
102
- (**pendiente**: acotarlo a 560 en el DS o dejar los parches) y no se decide aquí.
107
+ fila de D16. Desde 768 px no se usa (P21 resuelto por el dueño el 08-10-2026: en tablet y
108
+ computadora va `sui-modal`).
103
109
 
104
110
  En master-pedidos: sin `[size]`; en desktop, cuando hay sitio, la pantalla puede mostrar el
105
111
  contenido en un panel en vez de la hoja (`pages/customer/viaje/viaje.html:25`, con `@if (escritorio())`).
@@ -149,6 +155,12 @@ Slot: un solo `<ng-content>`, el body. No hay header ni footer.
149
155
  carrusel o un slider dentro puede pelear con el gesto. Los campos (`input`, `textarea`,
150
156
  `select`) no arrancan arrastre; para otro control que necesita el dedo, ponle el atributo
151
157
  `data-sui-no-sheet-drag` (o a un ancestro).
158
+ - **Una lista con scroll propio adentro** (`overflow-y: auto` con tope de alto) cuenta igual que el
159
+ body desde 0.26.0: en la altura máxima, si la lista está a medio scroll el dedo la scrollea a ella,
160
+ y la hoja solo baja cuando la lista y el body están arriba del todo. Antes la hoja se llevaba el
161
+ gesto porque solo miraba el body (el checkout lo esquivó sacando el scroll anidado). En alturas
162
+ intermedias la lista no scrollea: el dedo sube la hoja, como en iOS. Probado con specs; **falta
163
+ probarlo en un iPhone** antes de anidar listas en pantallas reales.
152
164
  - **Sin `0` en `breakpoints` no se cierra deslizando.** Si quieres que se cierre y no lo hace, es
153
165
  eso.
154
166
  - **`closeOnBackdrop` solo actúa cuando hay backdrop** (altura actual por encima de
@@ -159,6 +159,18 @@ En master-pedidos: `[size]="bp.sizeControl()"` en los `sui-button` de `slot="act
159
159
  | `moreClicked` | `MouseEvent` |
160
160
  <!-- api:fin -->
161
161
 
162
+ <!-- textos:inicio -->
163
+ ### Textos
164
+
165
+ Lo que el componente escribe solo sale de `provideSuiTextos` (español por defecto, se cambia en vivo; ver `docs/TEXTOS.md`). El input de la última columna le gana al texto global.
166
+
167
+ | clave | por defecto | se pisa con |
168
+ |---|---|---|
169
+ | `notificacion.noLeido` | No leído | — |
170
+ | `comun.masOpciones` | Más opciones | — |
171
+ | `comun.cerrar` | Cerrar | — |
172
+ <!-- textos:fin -->
173
+
162
174
  Slots: `[slot=company-logo]`, `[slot=file]`, `[slot=message]`, el contenido libre, `[slot=actions]`.
163
175
 
164
176
  ## Trampas
@@ -77,8 +77,8 @@ En master-pedidos: sin helper; `@if (!bp.isMobile())` alrededor.
77
77
 
78
78
  | input | tipo | default |
79
79
  |---|---|---|
80
- | `usePrefix` | `string` | `'Usa'` |
81
- | `useSuffix` | `string` | `'para moverte'` |
80
+ | `usePrefix` | `string \| null` | `null` |
81
+ | `useSuffix` | `string \| null` | `null` |
82
82
  | `manage` | `SuiLinkConfig \| string \| boolean \| null` | `true` |
83
83
 
84
84
  | output | payload |
@@ -86,6 +86,18 @@ En master-pedidos: sin helper; `@if (!bp.isMobile())` alrededor.
86
86
  | `manageClick` | `MouseEvent` |
87
87
  <!-- api:fin -->
88
88
 
89
+ <!-- textos:inicio -->
90
+ ### Textos
91
+
92
+ Lo que el componente escribe solo sale de `provideSuiTextos` (español por defecto, se cambia en vivo; ver `docs/TEXTOS.md`). El input de la última columna le gana al texto global.
93
+
94
+ | clave | por defecto | se pisa con |
95
+ |---|---|---|
96
+ | `notificacion.usa` | Usa | `usePrefix` |
97
+ | `notificacion.paraMoverte` | para moverte | `useSuffix` |
98
+ | `notificacion.administrar` | Administrar notificaciones | `manage` |
99
+ <!-- textos:fin -->
100
+
89
101
  ```ts
90
102
  interface SuiLinkConfig { label: string; href?: string; target?: string; rel?: string; }
91
103
  ```
@@ -90,7 +90,7 @@ En master-pedidos: sin helper; `@if (bp.isMobile())` elige `sui-tab-chips` con
90
90
  | `tabs` | `SuiNotificationTab<T>[]` | — (requerido) |
91
91
  | `active` · model, `[(active)]` | `T` | `undefined` |
92
92
  | `showFilter` | `boolean` | `true` |
93
- | `filterLabel` | `string` | `'Filtrar'` |
93
+ | `filterLabel` | `string \| null` | `null` |
94
94
 
95
95
  | output | payload |
96
96
  |---|---|
@@ -98,6 +98,16 @@ En master-pedidos: sin helper; `@if (bp.isMobile())` elige `sui-tab-chips` con
98
98
  | `filterClick` | `MouseEvent` |
99
99
  <!-- api:fin -->
100
100
 
101
+ <!-- textos:inicio -->
102
+ ### Textos
103
+
104
+ Lo que el componente escribe solo sale de `provideSuiTextos` (español por defecto, se cambia en vivo; ver `docs/TEXTOS.md`). El input de la última columna le gana al texto global.
105
+
106
+ | clave | por defecto | se pisa con |
107
+ |---|---|---|
108
+ | `notificacion.filtrar` | Filtrar | `filterLabel` |
109
+ <!-- textos:fin -->
110
+
101
111
  ```ts
102
112
  interface SuiNotificationTab<T = string> {
103
113
  value: T;
@@ -111,7 +111,7 @@ pendiente. No hay helper: `bp.sizeControl()` da `large` en el celular, y 6 celda
111
111
  | `type` | `'number' \| 'text'` | `'number'` |
112
112
  | `disabled` · model, `[(disabled)]` | `boolean` | `false` |
113
113
  | `error` | `boolean` | `false` |
114
- | `ariaLabel` | `string` | `'Código de verificación'` |
114
+ | `ariaLabel` | `string \| null` | `null` |
115
115
  | `value` · model, `[(value)]` | `string` | `''` |
116
116
 
117
117
  | output | payload |
@@ -119,6 +119,17 @@ pendiente. No hay helper: `bp.sizeControl()` da `large` en el celular, y 6 celda
119
119
  | `completed` | `string` |
120
120
  <!-- api:fin -->
121
121
 
122
+ <!-- textos:inicio -->
123
+ ### Textos
124
+
125
+ Lo que el componente escribe solo sale de `provideSuiTextos` (español por defecto, se cambia en vivo; ver `docs/TEXTOS.md`). El input de la última columna le gana al texto global.
126
+
127
+ | clave | por defecto | se pisa con |
128
+ |---|---|---|
129
+ | `otp.digito` | Dígito {n} | — |
130
+ | `otp.nombre` | Código de verificación | `ariaLabel` |
131
+ <!-- textos:fin -->
132
+
122
133
  `value` y `disabled` son `model`. Implementa `ControlValueAccessor`.
123
134
 
124
135
  ## Trampas
@@ -143,6 +143,22 @@ decida.
143
143
  | `pageSizeChange` | `number` |
144
144
  <!-- api:fin -->
145
145
 
146
+ <!-- textos:inicio -->
147
+ ### Textos
148
+
149
+ Lo que el componente escribe solo sale de `provideSuiTextos` (español por defecto, se cambia en vivo; ver `docs/TEXTOS.md`). El input de la última columna le gana al texto global.
150
+
151
+ | clave | por defecto | se pisa con |
152
+ |---|---|---|
153
+ | `paginacion.nombre` | Paginación | — |
154
+ | `paginacion.primera` | Primera página | — |
155
+ | `paginacion.anterior` | Página anterior | — |
156
+ | `paginacion.pagina` | Página {n} | — |
157
+ | `paginacion.siguiente` | Página siguiente | — |
158
+ | `paginacion.ultima` | Última página | — |
159
+ | `paginacion.porPagina` | {n} / página | — |
160
+ <!-- textos:fin -->
161
+
146
162
  ```ts
147
163
  type SuiPaginationType = 'basic' | 'full-radius' | 'group';
148
164
  type SuiPaginationSize = 'small' | 'medium';
@@ -66,16 +66,34 @@ la computadora y el ultrawide. Lo que sí cambia por dispositivo es el campo de
66
66
  |---|---|---|
67
67
  | `value` | `string` | `''` |
68
68
  | `strength` | `'empty' \| 'weak' \| 'moderate' \| 'strong' \| null` | `null` |
69
- | `caption` | `string` | `'Debe contener al menos:'` |
70
- | `conditions` | `SuiPasswordStrengthCondition[]` | `SUI_PASSWORD_STRENGTH_DEFAULT_CONDITIONS` |
69
+ | `caption` | `string \| null` | `null` |
70
+ | `conditions` | `SuiPasswordStrengthCondition[] \| null` | `null` |
71
71
  | `levelLabels` | `Partial<Record<SuiPasswordStrengthLevel, string>>` | `{}` |
72
- | `ariaLabel` | `string` | `'Seguridad de la contraseña'` |
72
+ | `ariaLabel` | `string \| null` | `null` |
73
73
 
74
74
  | output | payload |
75
75
  |---|---|
76
76
  | `strengthChange` | `'empty' \| 'weak' \| 'moderate' \| 'strong'` |
77
77
  <!-- api:fin -->
78
78
 
79
+ <!-- textos:inicio -->
80
+ ### Textos
81
+
82
+ Lo que el componente escribe solo sale de `provideSuiTextos` (español por defecto, se cambia en vivo; ver `docs/TEXTOS.md`). El input de la última columna le gana al texto global.
83
+
84
+ | clave | por defecto | se pisa con |
85
+ |---|---|---|
86
+ | `contrasena.titulo` | Debe contener al menos: | `caption` |
87
+ | `contrasena.nombre` | Seguridad de la contraseña | `ariaLabel` |
88
+ | `contrasena.vacia` | Sin contraseña | `levelLabels.empty` |
89
+ | `contrasena.debil` | Contraseña débil | `levelLabels.weak` |
90
+ | `contrasena.moderada` | Contraseña moderada | `levelLabels.moderate` |
91
+ | `contrasena.fuerte` | Contraseña fuerte | `levelLabels.strong` |
92
+ | `contrasena.mayuscula` | Al menos 1 mayúscula | `conditions` |
93
+ | `contrasena.numero` | Al menos 1 número | `conditions` |
94
+ | `contrasena.ochoCaracteres` | Al menos 8 caracteres | `conditions` |
95
+ <!-- textos:fin -->
96
+
79
97
  Exporta `SUI_PASSWORD_STRENGTH_DEFAULT_CONDITIONS` y `SUI_PASSWORD_STRENGTH_DEFAULT_LEVEL_LABELS`.
80
98
 
81
99
  ```ts
@@ -154,8 +154,8 @@ Hoy el popover entero tiene **0 usos**; esto es lo que no se usaría aunque lleg
154
154
  | `description` | `string \| null` | `null` |
155
155
  | `dismissIcon` | `boolean` | `true` |
156
156
  | `footer` | `'none' \| 'stretch' \| 'text-stepper' \| 'stepper'` | `'stretch'` |
157
- | `backLabel` | `string` | `'Atrás'` |
158
- | `nextLabel` | `string` | `'Siguiente'` |
157
+ | `backLabel` | `string \| null` | `null` |
158
+ | `nextLabel` | `string \| null` | `null` |
159
159
  | `doubleButton` | `boolean` | `true` |
160
160
  | `step` | `{ current: number; total: number } \| null` | `null` |
161
161
  | `size` | `'small' \| 'medium' \| 'large'` | `'small'` |
@@ -167,6 +167,19 @@ Hoy el popover entero tiene **0 usos**; esto es lo que no se usaría aunque lleg
167
167
  | `next` | `void` |
168
168
  <!-- api:fin -->
169
169
 
170
+ <!-- textos:inicio -->
171
+ ### Textos
172
+
173
+ Lo que el componente escribe solo sale de `provideSuiTextos` (español por defecto, se cambia en vivo; ver `docs/TEXTOS.md`). El input de la última columna le gana al texto global.
174
+
175
+ | clave | por defecto | se pisa con |
176
+ |---|---|---|
177
+ | `comun.cerrar` | Cerrar | — |
178
+ | `popover.atras` | Atrás | `backLabel` |
179
+ | `popover.siguiente` | Siguiente | `nextLabel` |
180
+ | `comun.pasoDe` | Paso {actual} de {total} | — |
181
+ <!-- textos:fin -->
182
+
170
183
  Slot: `[data-slot=body]` reemplaza título y descripción.
171
184
 
172
185
  ## Trampas
@@ -143,6 +143,16 @@ En master-pedidos: no hay helper. Si P10 confirma `large` en el celular,
143
143
  Outputs: ninguno.
144
144
  <!-- api:fin -->
145
145
 
146
+ <!-- textos:inicio -->
147
+ ### Textos
148
+
149
+ Lo que el componente escribe solo sale de `provideSuiTextos` (español por defecto, se cambia en vivo; ver `docs/TEXTOS.md`). El input de la última columna le gana al texto global.
150
+
151
+ | clave | por defecto | se pisa con |
152
+ |---|---|---|
153
+ | `comun.progreso` | Progreso | `ariaLabel` |
154
+ <!-- textos:fin -->
155
+
146
156
  ## Trampas
147
157
 
148
158
  - **No hay `max`** (la guía sí lo tiene): `value` es un porcentaje de 0 a 100, con tope.
@@ -148,7 +148,10 @@ y proyecta los radios (`sui-radio`, `sui-radio-label`, `sui-radio-card`).
148
148
  ya es el radio enfocable (`sui-radio-label`).
149
149
  - No hay `small`: el más chico es `medium` (20 px).
150
150
  - Sin marcar, en foco, el círculo se pinta del color de marca: viene del Figma, no es un error.
151
- - No dibuja texto ni `aria-label`: pelado, pon el texto en un `<label>` o usa `sui-radio-label`.
151
+ - No dibuja texto ni `aria-label`: pelado, ponle `aria-label="…"` (o `aria-labelledby` apuntando
152
+ al texto de al lado) o usa `sui-radio-label`. Un `<label>` que lo envuelve **no** le da nombre:
153
+ `sui-radio` no es un control nativo y el lector solo dice «botón de opción» (axe:
154
+ `aria-toggle-field-name`, corregido en las stories el 09-10-2026).
152
155
 
153
156
  ## Bien y mal
154
157
 
@@ -170,8 +170,11 @@ dueño decida si en este componente el celular y la tablet pasan a `2xlarge` (y
170
170
  - **Tocar una opción ya elegida no la desmarca** (bien, es un radio). Tocar el link tampoco la elige.
171
171
  - **`link` solo se dibuja con `description`.**
172
172
  - El `sui-radio` de adentro no recibe clics (`pointer-events: none`): no le pongas handlers.
173
- Tampoco foco ni lector: va con `[focusable]="false"` y `aria-hidden`, y el radio es el host,
174
- con nombre = `label` y descripción = `description`. Hasta el 04-10-2026 cada opción eran dos
173
+ Tampoco foco ni lector: va con `[focusable]="false"`, `aria-hidden` e `inert` (sin `inert`, axe
174
+ marca nested-interactive por su `tabindex="-1"`), y el radio es el contenedor
175
+ interno `.sui-radio-label__control` (círculo + textos), con nombre = `label` y descripción =
176
+ `description`. El link va fuera de él, como hermano (un botón dentro de un radio también es
177
+ nested-interactive, 09-10-2026); se ve igual, debajo del texto. Hasta el 04-10-2026 cada opción eran dos
175
178
  paradas de Tab y dos radios anidados.
176
179
  - En `sui-radio-group`, un solo tab stop y flechas ↑ ↓ ← → (revisión 04-10-2026).
177
180
  - El badge con string sale naranja; en `sui-radio-card` el default es azul.
@@ -199,9 +199,9 @@ En master-pedidos, sin helper propio:
199
199
  | `reviewLink` | `SuiRatingReviewLink \| null` | `null` |
200
200
  | `alignment` | `'inline' \| 'vertical' \| 'horizontal'` | `'inline'` |
201
201
  | `emojis` | `string[]` | `[ 'pensive-face', 'confused-face', 'neutral-face', 'slightly-smiling-face', 'grinning-face-smiling-eyes', ]` |
202
- | `ariaLabel` | `string` | `'Calificación'` |
202
+ | `ariaLabel` | `string \| null` | `null` |
203
203
  | `reason` · model, `[(reason)]` | `string` | `''` |
204
- | `reasonPlaceholder` | `string` | `'Cuéntanos por qué'` |
204
+ | `reasonPlaceholder` | `string \| null` | `null` |
205
205
  | `reasonRows` | `number` | `3` |
206
206
 
207
207
  | output | payload |
@@ -209,6 +209,20 @@ En master-pedidos, sin helper propio:
209
209
  | `valueChange` | `number` |
210
210
  <!-- api:fin -->
211
211
 
212
+ <!-- textos:inicio -->
213
+ ### Textos
214
+
215
+ Lo que el componente escribe solo sale de `provideSuiTextos` (español por defecto, se cambia en vivo; ver `docs/TEXTOS.md`). El input de la última columna le gana al texto global.
216
+
217
+ | clave | por defecto | se pisa con |
218
+ |---|---|---|
219
+ | `calificacion.una` | calificación | — |
220
+ | `calificacion.varias` | calificaciones | — |
221
+ | `calificacion.nombre` | Calificación | `ariaLabel` |
222
+ | `calificacion.motivo` | Cuéntanos por qué | `reasonPlaceholder` |
223
+ | `calificacion.nota` | {nombre}: {valor} de {max} | — |
224
+ <!-- textos:fin -->
225
+
212
226
  Implementa `ControlValueAccessor` sobre `value` (sirve con `formControlName`). `reason` es un
213
227
  `model` aparte: no entra al `FormControl`.
214
228
 
@@ -72,9 +72,9 @@ los 44 de D16 (dueño, 05-10-2026) en el celular ni en la tablet táctil. Solo e
72
72
  | `layout` | `'full' \| 'compact' \| 'formatting' \| 'social'` | `'full'` |
73
73
  | `showMore` | `boolean` | `true` |
74
74
  | `editable` | `boolean` | `false` |
75
- | `placeholder` | `string` | `'Escribe algo…'` |
75
+ | `placeholder` | `string \| null` | `null` |
76
76
  | `value` · model, `[(value)]` | `string` | `''` |
77
- | `headingLabel` | `string` | `'Título'` |
77
+ | `headingLabel` | `string \| null` | `null` |
78
78
  | `fontSizeLabel` | `string` | `'14px'` |
79
79
 
80
80
  | output | payload |
@@ -100,6 +100,29 @@ los 44 de D16 (dueño, 05-10-2026) en el celular ni en la tablet táctil. Solo e
100
100
  | `clicked` | `void` |
101
101
  <!-- api:fin -->
102
102
 
103
+ <!-- textos:inicio -->
104
+ ### Textos
105
+
106
+ Lo que el componente escribe solo sale de `provideSuiTextos` (español por defecto, se cambia en vivo; ver `docs/TEXTOS.md`). El input de la última columna le gana al texto global.
107
+
108
+ | clave | por defecto | se pisa con |
109
+ |---|---|---|
110
+ | `editorTexto.barra` | Formato de texto | — |
111
+ | `editorTexto.encabezado` | Estilo de encabezado | — |
112
+ | `editorTexto.tamano` | Tamaño de fuente | — |
113
+ | `editorTexto.negrita` | Negrita | — |
114
+ | `editorTexto.cursiva` | Cursiva | — |
115
+ | `editorTexto.subrayado` | Subrayado | — |
116
+ | `editorTexto.tachado` | Tachado | — |
117
+ | `editorTexto.alineacion` | Alineación | — |
118
+ | `editorTexto.comentario` | Comentario | — |
119
+ | `editorTexto.enlace` | Insertar enlace | — |
120
+ | `editorTexto.mencionar` | Mencionar | — |
121
+ | `comun.masOpciones` | Más opciones | — |
122
+ | `editorTexto.placeholder` | Escribe algo… | `placeholder` |
123
+ | `editorTexto.titulo` | Título | `headingLabel` |
124
+ <!-- textos:fin -->
125
+
103
126
  Sub-componente: `sui-rich-editor-item` (cada botón de la barra).
104
127
 
105
128
  ## Trampas
@@ -159,7 +159,7 @@ En master-pedidos: `[size]="bp.sizeControl()"`. Re-medido el 06-10-2026: 52 de 5
159
159
  | input | tipo | default |
160
160
  |---|---|---|
161
161
  | `size` | `'xsmall' \| 'small' \| 'medium' \| 'large' \| 'xlarge'` | `'medium'` |
162
- | `placeholder` | `string` | `'Elige…'` |
162
+ | `placeholder` | `string \| null` | `null` |
163
163
  | `options` | `SuiSelectOption<T>[]` | `[]` |
164
164
  | `disabled` | `boolean` | `false` |
165
165
  | `error` | `boolean` | `false` |
@@ -179,6 +179,16 @@ En master-pedidos: `[size]="bp.sizeControl()"`. Re-medido el 06-10-2026: 52 de 5
179
179
  Outputs: ninguno.
180
180
  <!-- api:fin -->
181
181
 
182
+ <!-- textos:inicio -->
183
+ ### Textos
184
+
185
+ Lo que el componente escribe solo sale de `provideSuiTextos` (español por defecto, se cambia en vivo; ver `docs/TEXTOS.md`). El input de la última columna le gana al texto global.
186
+
187
+ | clave | por defecto | se pisa con |
188
+ |---|---|---|
189
+ | `comun.elige` | Elige… | `placeholder` |
190
+ <!-- textos:fin -->
191
+
182
192
  `value` es `model<T | null>`. Implementa `ControlValueAccessor`. Slot `[slot=leading]` para una
183
193
  decoración propia del campo (gana sobre ícono, imagen y bandera).
184
194
 
@@ -148,6 +148,20 @@ En master-pedidos: no se pasa `size`; lo único que depende del dispositivo es `
148
148
  | `searchSubmitted` | `string` |
149
149
  <!-- api:fin -->
150
150
 
151
+ <!-- textos:inicio -->
152
+ ### Textos
153
+
154
+ Lo que el componente escribe solo sale de `provideSuiTextos` (español por defecto, se cambia en vivo; ver `docs/TEXTOS.md`). El input de la última columna le gana al texto global.
155
+
156
+ | clave | por defecto | se pisa con |
157
+ |---|---|---|
158
+ | `navegacion.cambiarWorkspace` | Cambiar workspace | — |
159
+ | `comun.limpiarBusqueda` | Limpiar búsqueda | — |
160
+ | `comun.verificado` | Verificado | — |
161
+ | `navegacion.opcionesPerfil` | Opciones de perfil | — |
162
+ | `comun.buscar` | Buscar… | `search.placeholder` |
163
+ <!-- textos:fin -->
164
+
151
165
  ```ts
152
166
  interface SuiSidebarItem {
153
167
  value: string; // lo emite (itemClicked)
@@ -163,7 +177,7 @@ interface SuiSidebarItem {
163
177
  tooltip?: string; // tooltip en colapsado; default = label
164
178
  }
165
179
  interface SuiSidebarBrandConfig { name: string; subtitle?: string; subtitleAsBadge?: boolean; logo?: string; fallback?: string; }
166
- interface SuiSidebarSearchConfig { placeholder?: string; shortcut?: string; }
180
+ interface SuiSidebarSearchConfig { placeholder?: string; ariaLabel?: string; shortcut?: string; }
167
181
  interface SuiSidebarProfile { name: string; avatarUrl?: string; initials?: string; status?: SuiAvatarStatus; email?: string; verified?: boolean; }
168
182
  ```
169
183
 
@@ -178,6 +192,9 @@ Slots: `[header-panel]` (debajo del header: el switcher), `[feature-card]` (al f
178
192
  (`core/services/cerrar-al-navegar.ts`). Canon: CANON-SUI §1.1.
179
193
  - **El buscador no filtra nada.** Solo expone `[(searchValue)]` y `(searchSubmitted)`; el layout
180
194
  filtra los items (`master-layout.ts:125`). Su placeholder por defecto es «Buscar…» (en español desde el 04-10-2026).
195
+ - El campo del buscador lleva `enterkeyhint="search"` (lupa en el teclado), sin `inputmode` (D14), y
196
+ sube a 16 px en ≤ 767 px para que iOS no haga zoom en el cajón; su nombre accesible es
197
+ `ariaLabel` o, si no viene, el placeholder. Las tres cosas desde 0.26.0.
181
198
  - **`collapsed` no mira el viewport.** Con `collapsed` en `true`, el cajón de mobile también sale
182
199
  de 80 px. Condiciónalo: `[collapsed]="colapsado() && !bp.isMobile()"`.
183
200
  - Un item con `route` (y sin `action`) queda activo **solo** por `routerLinkActive`, por prefijo:
@@ -139,6 +139,17 @@ En master-pedidos: `[size]="(bp.isMobile() || bp.toque()) ? 'large' : 'medium'"`
139
139
  | `maxValueChange` | `number` |
140
140
  <!-- api:fin -->
141
141
 
142
+ <!-- textos:inicio -->
143
+ ### Textos
144
+
145
+ Lo que el componente escribe solo sale de `provideSuiTextos` (español por defecto, se cambia en vivo; ver `docs/TEXTOS.md`). El input de la última columna le gana al texto global.
146
+
147
+ | clave | por defecto | se pisa con |
148
+ |---|---|---|
149
+ | `deslizador.minimo` | mínimo | — |
150
+ | `deslizador.maximo` | máximo | — |
151
+ <!-- textos:fin -->
152
+
142
153
  Implementa `ControlValueAccessor` **solo para `single`**.
143
154
 
144
155
  ## Trampas
@@ -163,6 +163,16 @@ en la columna de la derecha, se usa (aprobado por el dueño, 03-10-2026).
163
163
  | `clicked` | `MouseEvent` |
164
164
  <!-- api:fin -->
165
165
 
166
+ <!-- textos:inicio -->
167
+ ### Textos
168
+
169
+ Lo que el componente escribe solo sale de `provideSuiTextos` (español por defecto, se cambia en vivo; ver `docs/TEXTOS.md`). El input de la última columna le gana al texto global.
170
+
171
+ | clave | por defecto | se pisa con |
172
+ |---|---|---|
173
+ | `varios.continuarCon` | Continuar con {marca} | `label` |
174
+ <!-- textos:fin -->
175
+
166
176
  ## Trampas
167
177
 
168
178
  - **`brand` es obligatorio** y **`variantStyle` arranca en `filled`**: `<sui-social-button brand="google" />`
@@ -155,13 +155,24 @@ En master-pedidos: `size="medium"` fijo, sin helper (no depende del dispositivo)
155
155
  | `errorStep` | `number \| null` | `null` |
156
156
  | `size` | `'small' \| 'xsmall' \| 'medium'` | `'small'` |
157
157
  | `interactive` | `boolean` | `false` |
158
- | `ariaLabel` | `string` | `'Progreso'` |
158
+ | `ariaLabel` | `string \| null` | `null` |
159
159
 
160
160
  | output | payload |
161
161
  |---|---|
162
162
  | `stepClick` | `number` |
163
163
  <!-- api:fin -->
164
164
 
165
+ <!-- textos:inicio -->
166
+ ### Textos
167
+
168
+ Lo que el componente escribe solo sale de `provideSuiTextos` (español por defecto, se cambia en vivo; ver `docs/TEXTOS.md`). El input de la última columna le gana al texto global.
169
+
170
+ | clave | por defecto | se pisa con |
171
+ |---|---|---|
172
+ | `comun.progreso` | Progreso | `ariaLabel` |
173
+ | `comun.paso` | Paso {n} | `label` de cada paso |
174
+ <!-- textos:fin -->
175
+
165
176
  ```ts
166
177
  interface SuiStepperItem {
167
178
  label?: string; // sin label sale «Paso N»
@@ -204,6 +204,17 @@ solo:
204
204
  Outputs: ninguno.
205
205
  <!-- api:fin -->
206
206
 
207
+ <!-- textos:inicio -->
208
+ ### Textos
209
+
210
+ Lo que el componente escribe solo sale de `provideSuiTextos` (español por defecto, se cambia en vivo; ver `docs/TEXTOS.md`). El input de la última columna le gana al texto global.
211
+
212
+ | clave | por defecto | se pisa con |
213
+ |---|---|---|
214
+ | `comun.verMasIzquierda` | Ver más a la izquierda | — |
215
+ | `comun.verMasDerecha` | Ver más a la derecha | — |
216
+ <!-- textos:fin -->
217
+
207
218
  ```ts
208
219
  interface SuiTabChipItem {
209
220
  value: string;
@@ -198,7 +198,7 @@ sola, sin nada en la página:
198
198
  | `rows` | `T[]` | — (requerido) |
199
199
  | `size` | `'small' \| 'medium' \| 'large' \| 'xlarge'` | `'medium'` |
200
200
  | `loading` | `boolean` | `false` |
201
- | `emptyMessage` | `string` | `'No hay datos'` |
201
+ | `emptyMessage` | `string \| null` | `null` |
202
202
  | `striped` | `boolean` | `false` |
203
203
  | `selectable` | `boolean` | `false` |
204
204
  | `rowKey` | `keyof T \| ((row: T) => any)` | `undefined` |
@@ -221,6 +221,20 @@ sola, sin nada en la página:
221
221
  Outputs: ninguno.
222
222
  <!-- api:fin -->
223
223
 
224
+ <!-- textos:inicio -->
225
+ ### Textos
226
+
227
+ Lo que el componente escribe solo sale de `provideSuiTextos` (español por defecto, se cambia en vivo; ver `docs/TEXTOS.md`). El input de la última columna le gana al texto global.
228
+
229
+ | clave | por defecto | se pisa con |
230
+ |---|---|---|
231
+ | `tabla.seleccionarTodas` | Seleccionar todas las filas | — |
232
+ | `tabla.seleccionarFila` | Seleccionar fila | — |
233
+ | `tabla.sinDatos` | No hay datos | `emptyMessage` |
234
+ | `comun.verMasIzquierda` | Ver más a la izquierda | — |
235
+ | `comun.verMasDerecha` | Ver más a la derecha | — |
236
+ <!-- textos:fin -->
237
+
224
238
  ```ts
225
239
  interface SuiTableColumn<T = any> {
226
240
  key: string; // campo de la fila; único
@@ -148,13 +148,23 @@ En master-pedidos (no hay helper para el tag):
148
148
  | `dismissible` | `boolean` | `false` |
149
149
  | `interactive` | `boolean` | `false` |
150
150
  | `disabled` | `boolean` | `false` |
151
- | `dismissLabel` | `string` | `'Quitar'` |
151
+ | `dismissLabel` | `string \| null` | `null` |
152
152
 
153
153
  | output | payload |
154
154
  |---|---|
155
155
  | `dismiss` | `void` |
156
156
  <!-- api:fin -->
157
157
 
158
+ <!-- textos:inicio -->
159
+ ### Textos
160
+
161
+ Lo que el componente escribe solo sale de `provideSuiTextos` (español por defecto, se cambia en vivo; ver `docs/TEXTOS.md`). El input de la última columna le gana al texto global.
162
+
163
+ | clave | por defecto | se pisa con |
164
+ |---|---|---|
165
+ | `comun.quitar` | Quitar | `dismissLabel` |
166
+ <!-- textos:fin -->
167
+
158
168
  Slots: `[data-slot=start]` (avatar, logo, bandera o ícono de 16 px) y `<ng-content>` (el texto).
159
169
 
160
170
  ## Trampas
@@ -111,7 +111,7 @@ En master-pedidos: `[size]="bp.sizeControl()"`.
111
111
  | input | tipo | default |
112
112
  |---|---|---|
113
113
  | `size` | `'xsmall' \| 'small' \| 'medium' \| 'large' \| 'xlarge'` | `'medium'` |
114
- | `placeholder` | `string` | `'Agrega una etiqueta…'` |
114
+ | `placeholder` | `string \| null` | `null` |
115
115
  | `disabled` | `boolean` | `false` |
116
116
  | `error` | `boolean` | `false` |
117
117
  | `errorMessage` | `string \| null` | `null` |
@@ -133,6 +133,17 @@ En master-pedidos: `[size]="bp.sizeControl()"`.
133
133
  | `tagRemoved` | `string` |
134
134
  <!-- api:fin -->
135
135
 
136
+ <!-- textos:inicio -->
137
+ ### Textos
138
+
139
+ Lo que el componente escribe solo sale de `provideSuiTextos` (español por defecto, se cambia en vivo; ver `docs/TEXTOS.md`). El input de la última columna le gana al texto global.
140
+
141
+ | clave | por defecto | se pisa con |
142
+ |---|---|---|
143
+ | `comun.quitarNombre` | Quitar {nombre} | — |
144
+ | `comun.agregaEtiqueta` | Agrega una etiqueta… | `placeholder` |
145
+ <!-- textos:fin -->
146
+
136
147
  `value` es `model<string[]>`. Implementa `ControlValueAccessor`: lo que está escrito sin confirmar
137
148
  no es parte del valor. Slot `[slot=right]` para un contenido propio a la derecha.
138
149