@ajuarezso/sui-design-system 0.22.0 → 0.23.1

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 (99) hide show
  1. package/docs/INDEX.md +8 -8
  2. package/docs/sui-accordion/README.md +2 -2
  3. package/docs/sui-activity-feed/README.md +1 -2
  4. package/docs/sui-alert/README.md +28 -19
  5. package/docs/sui-app-store-badge/README.md +5 -4
  6. package/docs/sui-avatar/README.md +16 -16
  7. package/docs/sui-avatar-group/README.md +4 -4
  8. package/docs/sui-badge/README.md +27 -9
  9. package/docs/sui-banner/README.md +10 -9
  10. package/docs/sui-brand-logo/README.md +3 -3
  11. package/docs/sui-breadcrumbs/README.md +1 -1
  12. package/docs/sui-button/README.md +48 -24
  13. package/docs/sui-button-group/README.md +6 -4
  14. package/docs/sui-button-group-item/README.md +3 -3
  15. package/docs/sui-card/README.md +17 -19
  16. package/docs/sui-chart-legend/README.md +8 -7
  17. package/docs/sui-checkbox/README.md +11 -6
  18. package/docs/sui-checkbox-card/README.md +24 -19
  19. package/docs/sui-checkbox-label/README.md +32 -10
  20. package/docs/sui-circular-progress-bar/README.md +2 -0
  21. package/docs/sui-color-dot/README.md +1 -1
  22. package/docs/sui-color-picker/README.md +22 -7
  23. package/docs/sui-command-menu-footer/README.md +8 -8
  24. package/docs/sui-command-menu-search/README.md +2 -2
  25. package/docs/sui-compact-avatar-group/README.md +4 -3
  26. package/docs/sui-compact-button/README.md +41 -44
  27. package/docs/sui-compact-select/README.md +9 -5
  28. package/docs/sui-compact-select-for-input/README.md +2 -2
  29. package/docs/sui-content-card/README.md +6 -5
  30. package/docs/sui-content-divider/README.md +4 -4
  31. package/docs/sui-content-label/README.md +11 -6
  32. package/docs/sui-counter-input/README.md +19 -18
  33. package/docs/sui-date-selector/README.md +16 -12
  34. package/docs/sui-datepicker/README.md +46 -32
  35. package/docs/sui-day-cell/README.md +17 -8
  36. package/docs/sui-day-label/README.md +2 -2
  37. package/docs/sui-divider/README.md +5 -5
  38. package/docs/sui-drawer-footer/README.md +19 -5
  39. package/docs/sui-dropdown-search/README.md +3 -3
  40. package/docs/sui-emoji/README.md +6 -6
  41. package/docs/sui-empty-state/README.md +13 -23
  42. package/docs/sui-fancy-button/README.md +24 -18
  43. package/docs/sui-file-icon/README.md +1 -1
  44. package/docs/sui-file-upload/README.md +3 -0
  45. package/docs/sui-file-upload-card/README.md +8 -7
  46. package/docs/sui-filter/README.md +5 -5
  47. package/docs/sui-flag/README.md +3 -2
  48. package/docs/sui-form-hint/README.md +12 -8
  49. package/docs/sui-form-label/README.md +11 -16
  50. package/docs/sui-icon/README.md +4 -3
  51. package/docs/sui-image-upload/README.md +28 -16
  52. package/docs/sui-inline-input/README.md +7 -6
  53. package/docs/sui-inline-select/README.md +8 -5
  54. package/docs/sui-input/README.md +26 -35
  55. package/docs/sui-integration-switch/README.md +14 -7
  56. package/docs/sui-kbd/README.md +4 -4
  57. package/docs/sui-key-icon/README.md +6 -2
  58. package/docs/sui-link-button/README.md +21 -17
  59. package/docs/sui-modal-footer/README.md +1 -1
  60. package/docs/sui-notification/README.md +8 -6
  61. package/docs/sui-notification-footer/README.md +2 -2
  62. package/docs/sui-notification-tab-menu/README.md +5 -3
  63. package/docs/sui-pagination/README.md +8 -5
  64. package/docs/sui-password-strength/README.md +1 -1
  65. package/docs/sui-period-range/README.md +18 -14
  66. package/docs/sui-popover/README.md +13 -7
  67. package/docs/sui-product-card/README.md +14 -10
  68. package/docs/sui-progress-bar/README.md +4 -2
  69. package/docs/sui-progress-bar-label/README.md +2 -0
  70. package/docs/sui-radio/README.md +14 -7
  71. package/docs/sui-radio-card/README.md +12 -12
  72. package/docs/sui-radio-label/README.md +36 -11
  73. package/docs/sui-rating/README.md +28 -9
  74. package/docs/sui-rich-editor/README.md +3 -3
  75. package/docs/sui-segmented-control/README.md +32 -21
  76. package/docs/sui-select/README.md +35 -31
  77. package/docs/sui-sidebar/README.md +1 -2
  78. package/docs/sui-slider/README.md +7 -0
  79. package/docs/sui-social-button/README.md +24 -11
  80. package/docs/sui-status-badge/README.md +7 -3
  81. package/docs/sui-stepper/README.md +30 -17
  82. package/docs/sui-store-card/README.md +9 -4
  83. package/docs/sui-switch/README.md +16 -11
  84. package/docs/sui-switch-card/README.md +18 -16
  85. package/docs/sui-switch-label/README.md +22 -11
  86. package/docs/sui-tab-chips/README.md +55 -41
  87. package/docs/sui-tab-menu-horizontal/README.md +19 -11
  88. package/docs/sui-tab-menu-vertical/README.md +10 -5
  89. package/docs/sui-tag/README.md +25 -11
  90. package/docs/sui-tag-input/README.md +24 -14
  91. package/docs/sui-textarea/README.md +21 -21
  92. package/docs/sui-time-picker/README.md +38 -32
  93. package/docs/sui-toast/README.md +27 -22
  94. package/docs/sui-tooltip/README.md +14 -17
  95. package/docs/sui-topbar-button/README.md +2 -2
  96. package/fesm2022/ajuarezso-sui-design-system.mjs +1071 -240
  97. package/fesm2022/ajuarezso-sui-design-system.mjs.map +1 -1
  98. package/package.json +1 -1
  99. package/types/ajuarezso-sui-design-system.d.ts +601 -267
@@ -30,7 +30,7 @@ Es el reemplazo del `sui-button` `ghost` `primary`.
30
30
  > los dos tamaños, el subrayado, los íconos y el deshabilitado, sin do/don't. Las reglas de
31
31
  > abajo son **canon (aprobado por el dueño, 03-10-2026)** salvo donde dice otra fuente.
32
32
  >
33
- > Uso medido el 03-10-2026 en `master-pedidos/src/app`: 22 link-buttons en 17 archivos, sin
33
+ > Uso medido el 03-10-2026 en `master-pedidos/src/app` (el 04-10-2026 ya son 23): 22 link-buttons en 17 archivos, sin
34
34
  > contar prototipos ni vitrinas (`master-preview`, `master-prototipos`, `mockup-sheets-*`,
35
35
  > `dx/*`, `master-rutina`, `master-medico`, `dev-index`) ni la copia local del componente en
36
36
  > `components/sui/sui-link-button/`. Variantes: 10 `gray` (1 por default), 7 `primary`,
@@ -44,24 +44,26 @@ Es el reemplazo del `sui-button` `ghost` `primary`.
44
44
  - **`modifiable` no tiene color propio**: hereda el del contenedor, para que lo pinte quien lo usa.
45
45
  - **Subrayado**: aparece al pasar el mouse; con `underline` queda fijo.
46
46
  - **Deshabilitado**: el texto pasa a `text-disabled-300` y se va el subrayado.
47
- - **Tamaños**: `large` (24 px, texto `label-md`, ícono 20; extensión SUI para mobile), `medium` (20 px, `label-sm`, ícono 20) y `small` (16 px, `label-xs`, ícono 16).
47
+ - **Tamaños**: `medium` (20 px, `label-sm`, ícono 20) y `small` (16 px, `label-xs`, ícono 16).
48
+ `large` (24 px, `label-md`, ícono 20) **no está en la guía**: es extensión de SUI para mobile.
48
49
 
49
50
  ### `variant`
50
51
 
51
52
  | variant | cuándo | ejemplo real de la app | fuente |
52
53
  |---|---|---|---|
53
54
  | `primary` | El link principal de una sección: «Ver todas», «Cambiar horario», «Descargar la app». Reemplaza al `sui-button` `ghost` `primary`. | `pages/customer/checkout/checkout.html:165` («Cambiar horario») · `pages/public/landing-business/landing-business.html:208` («Descargar la app») | canon (aprobado por el dueño, 03-10-2026) |
54
- | `gray` (default) | Salida de baja jerarquía: «Omitir», «Ahora no», «Cerrar sesión», «Más información». | `pages/account-suspended/account-suspended.html:70` («Cerrar sesión») · `pages/super-admin/master-approvals/master-approvals.html:90` («Más información») | canon (aprobado por el dueño, 03-10-2026) |
55
+ | `gray` (default) | Salida de baja jerarquía: «Omitir», «Ahora no», «Cerrar sesión», «Más información». | `pages/account-suspended/account-suspended.html:70` («Cerrar sesión») · `pages/super-admin/master-approvals/master-approvals.html:89` («Más información») | canon (aprobado por el dueño, 03-10-2026) |
55
56
  | `black` | Un link dentro de un texto, con `underline`: «Términos y condiciones», «Ver política». | (sin uso hoy) | canon (aprobado por el dueño, 03-10-2026) |
56
57
  | `error` | Quitar algo menor, en texto: «Quitar», «Borrar foto». Nunca para abrir una destructiva grande. | (sin uso correcto hoy) | canon (aprobado por el dueño, 03-10-2026) |
57
58
  | `modifiable` | Toma el color del contenedor: las acciones del alert, del banner y del toast. | `components/sui/sui-toast/sui-toast-outlet.html:36` (acción del toast) · `components/subscription-banner/subscription-banner.html:10` («Renovar plan») | hereda el color: según la guía del DS · dónde va: canon (aprobado por el dueño, 03-10-2026) |
58
59
 
59
60
  **Usos de hoy que rompen la regla:**
60
61
 
61
- - **3 `error` que abren una destructiva grande → `sui-button` `stroke` `error`:**
62
+ - **4 `error` que abren una destructiva grande → `sui-button` `stroke` `error`:**
62
63
  `pages/super-admin/master-orders/master-orders.html:425` («Cancelar pedido»),
63
- `pages/orders/orders.html:232` («Rechazar pedido»), `pages/central/central-gastos/central-gastos.html:101`
64
- («Anular gasto»).
64
+ `pages/orders/orders.html:233` («Rechazar pedido»), `pages/central/central-gastos/central-gastos.html:101`
65
+ («Anular gasto») y `pages/driver/driver-order-detail/driver-order-detail.html:745` («Cancelar» el
66
+ pedido, en `large`; nuevo, medido el 04-10-2026).
65
67
  - A discutir: `pages/super-admin/master-orders/master-orders.html:430` («Liberar» en `gray`): es una
66
68
  acción de operación, no una salida de baja jerarquía.
67
69
 
@@ -96,8 +98,8 @@ Los íconos son nombres RemixIcon sin el prefijo `ri-`. Miden 20 px en `large` y
96
98
  |---|---|---|
97
99
  | `true` | La acción existe pero ahora no se puede: mientras se guarda, mientras se procesa otra acción. Mejor que esconderla si la persona la espera en ese lugar. | cómo se ve: según la guía del DS · cuándo: propuesta |
98
100
 
99
- Ejemplos: `components/add-product-modal/add-product-modal.html:330` («Vista previa» mientras guarda),
100
- `pages/orders/orders.html:232`.
101
+ Ejemplos: `components/add-product-modal/add-product-modal.html:339` («Vista previa» mientras guarda),
102
+ `pages/orders/orders.html:233`.
101
103
 
102
104
  ### `href`, `target`, `rel`, `type`, `ariaLabel`
103
105
 
@@ -113,8 +115,8 @@ Ejemplos: `components/add-product-modal/add-product-modal.html:330` («Vista pre
113
115
  En mobile se toca con el dedo: el área táctil tiene que medir **44 px o más**. En web, con mouse,
114
116
  va un tamaño más chico. La app ya lo resuelve con `BreakpointsService`
115
117
  (`src/app/services/breakpoints.service.ts`, mobile = hasta 767 px):
116
- `[size]="bp.isMobile() ? 'large' : 'small'"`, 27 usos hoy en `master-pedidos` (16 `large`/`small`,
117
- 9 `large`/`medium`, 2 `medium`/`xsmall`). Regla del dueño, 03-10-2026.
118
+ `[size]="bp.isMobile() ? 'large' : 'small'"`. Medido el 04-10-2026 en `master-pedidos`: 166 `[size]`
119
+ con `bp` (142 `large`/`medium`, 22 `large`/`small`, 2 `medium`/`xsmall`). Regla del dueño, 03-10-2026.
118
120
 
119
121
  | size | alto | texto | ícono |
120
122
  |---|---|---|---|
@@ -138,11 +140,13 @@ va un tamaño más chico. La app ya lo resuelve con `BreakpointsService`
138
140
 
139
141
  **Ningún tamaño llega a 44 px**: el link mide 16–24 de alto y no tiene padding. En mobile el área
140
142
  táctil la pone el contenedor: la fila o el bloque donde vive tiene que medir 44 px o más de alto, o
141
- dejar aire alrededor del link. `small` (16) no va en mobile: hoy hay 6 links `small` fijos
142
- (`pages/driver/driver-profile/driver-profile.html:258`, `:264`, `pages/driver/driver-dashboard/driver-dashboard.html:1089`,
143
- `pages/mi-negocio/mi-negocio.html:472`, `pages/customer/order-history/order-history.html:413`,
144
- `components/add-product-modal/add-product-modal.html:330`); los 4 de repartidor y cliente se usan
145
- sí o sí en el teléfono → `[size]="bp.isMobile() ? 'medium' : 'small'"`.
143
+ dejar aire alrededor del link. `small` (16) no va en mobile. Medido el 04-10-2026: los 4 de
144
+ repartidor y cliente ya usan `[size]="bp.isMobile() ? 'medium' : 'small'"`
145
+ (`pages/driver/driver-profile/driver-profile.html:258` y `:264`,
146
+ `pages/driver/driver-dashboard/driver-dashboard.html:1092`,
147
+ `pages/customer/order-history/order-history.html:412`). Quedan 2 `small` fijos, los dos del panel
148
+ de la empresa: `pages/mi-negocio/mi-negocio.html:474` y
149
+ `components/add-product-modal/add-product-modal.html:339`.
146
150
 
147
151
  ## «No usar»: por qué no hoy y cuándo sí
148
152
 
@@ -180,8 +184,8 @@ Slots: `<ng-content>` (el texto).
180
184
 
181
185
  - **El output es `(clicked)`**, no `(click)` como en `sui-button`. `(click)` sobre el host igual
182
186
  funciona porque el clic burbujea, pero hoy hay 6 usos así (`components/subscription-banner/subscription-banner.html:10`,
183
- `pages/super-admin/master-approvals/master-approvals.html:90`, `pages/central/central-gastos/central-gastos.html:101`,
184
- `pages/account-suspended/account-suspended.html:66` y `:70`, `pages/customer/viaje/viaje.html:215`).
187
+ `pages/super-admin/master-approvals/master-approvals.html:89`, `pages/central/central-gastos/central-gastos.html:101`,
188
+ `pages/account-suspended/account-suspended.html:66` y `:70`, `pages/customer/viaje/viaje.html:216`).
185
189
  Usa `(clicked)`, que ya respeta `disabled`.
186
190
  - **`rel` arranca en `null`**, a diferencia de compact, fancy y social, que traen
187
191
  `'noopener noreferrer'`. Con `target="_blank"` hay que ponerlo a mano.
@@ -2,7 +2,7 @@
2
2
  name: sui-modal-footer
3
3
  selector: sui-modal-footer
4
4
  resumen: Pie de modal con la acción principal a la derecha, la secundaria a su izquierda y un slot izquierdo para un checkbox, un link o un texto
5
- alternativas: [sui-button (botones sueltos fuera de un modal o una hoja), sui-drawer-footer (pie de un panel lateral), sui-notification-footer (acciones de una notificación)]
5
+ alternativas: [sui-button (botones sueltos fuera de un modal o una hoja), sui-drawer-footer (pie de un panel lateral), sui-notification-footer (pie del panel de notificaciones: ayuda de teclado y link a ajustes)]
6
6
  ---
7
7
 
8
8
  # sui-modal-footer
@@ -101,8 +101,8 @@ La fila **no tiene `size`**: foto de 40 px, 12 px de relleno, texto de 14.
101
101
  | uso | mobile | web | fuente |
102
102
  |---|---|---|---|
103
103
  | la fila | toda la fila se toca para abrirla: mide 64 px o más | igual | según el componente |
104
- | ⋮ (`showMore`) | no aplica: aparece con el mouse | 24 px | según el componente |
105
- | la X (`dismissible`) | se ve de 20 px; **se toca en 40 × 40** | igual | canon (aprobado por el dueño, 03-10-2026): área táctil invisible, extensión SUI |
104
+ | ⋮ (`showMore`) | se ve de 24 y se toca en 44 × 44 cuando está visible (foco o fila activa); oculto no recibe toques | 24 px | canon (dueño, 04-10-2026): piso táctil 44 en el teléfono |
105
+ | la X (`dismissible`) | se ve de 20 px; **se toca en 44 × 44** | se ve de 20; se toca en 40 × 40 | canon (dueño, 04-10-2026): piso táctil 44 en el teléfono (antes 40, pedido del dueño 03-10-2026): área táctil invisible, extensión SUI |
106
106
  | botones de `type="button"` | los pone quien la usa: `[size]="bp.isMobile() ? 'large' : 'xsmall'"` | `xsmall` | propuesta |
107
107
 
108
108
  ## «No usar»: por qué no hoy y cuándo sí
@@ -147,9 +147,9 @@ Slots: `[slot=company-logo]`, `[slot=file]`, `[slot=message]`, el contenido libr
147
147
 
148
148
  ## Trampas
149
149
 
150
- - **La X se toca en 40 × 40** aunque se vea de 20 (un `::before` invisible sobre su `<button>`,
151
- desde 03-10-2026): en una fila que se toca entera, el toque a 10 px de la X la cierra en vez de
152
- abrirla.
150
+ - **La X se toca en 44 × 44 en el teléfono** (40 × 40 en web) aunque se vea de 20 (un `::before`
151
+ invisible sobre su `<button>`; 44 desde el 04-10-2026): en una fila que se toca entera, el toque a
152
+ 12 px de la X la cierra en vez de abrirla. La X y el ⋮ comparten la esquina: no se usan juntos.
153
153
  - **Es el avatar el que decide el modelo**: con `avatar` es una fila plana (`role="article"`); sin
154
154
  `avatar` es un alert con borde y sombra (`role="status"`, que el lector de pantalla anuncia).
155
155
  - **El avatar no es `sui-avatar`**: lo dibuja la fila, en un círculo **negro** con iniciales.
@@ -161,7 +161,9 @@ Slots: `[slot=company-logo]`, `[slot=file]`, `[slot=message]`, el contenido libr
161
161
  - `feature` usa `sparkling-fill` aquí y en el alert, y `magic-fill` en el banner.
162
162
  - `dismissible` solo emite `(dismissed)`: la fila **no se esconde sola** (a diferencia de alert y
163
163
  banner). La saca quien la usa.
164
- - El ⋮ de `showMore` se ve solo con el mouse encima o con `active`: en mobile no aparece.
164
+ - El ⋮ de `showMore` se ve solo con el mouse encima, con `active` o cuando le llega el foco de
165
+ teclado: en mobile no aparece. **Mientras está oculto no recibe toques** (desde el 04-10-2026;
166
+ antes un toque en la esquina disparaba `moreClicked` sin que se viera nada).
165
167
  - **`showMore` y `dismissible` juntos se pisan**: el ⋮ y la X van los dos arriba a la derecha.
166
168
  - Con avatar (o con `type` distinto de `basic`) y **sin `description`**, queda un «∙» colgando
167
169
  después de la hora («Hace 8 min ∙»).
@@ -44,7 +44,7 @@ la barra superior, con filas `sui-notification` y la cabecera `sui-notification-
44
44
 
45
45
  | uso | mobile | web | fuente |
46
46
  |---|---|---|---|
47
- | el pie entero | no aplica: es ayuda de teclado; en mobile no se muestra | unos 48 px de alto | propuesta |
47
+ | el pie entero | no aplica: es ayuda de teclado; en mobile no se muestra (el componente no se oculta solo: lo esconde quien lo usa) | 48 px de alto (14 + 20 de la tecla + 14) | alto: según el componente · ocultarlo en mobile: propuesta |
48
48
  | el link de ajustes | si hiciera falta, un `sui-link-button` `large` suelto | `small` (16 px) | propuesta |
49
49
 
50
50
  ```html
@@ -59,7 +59,7 @@ la barra superior, con filas `sui-notification` y la cabecera `sui-notification-
59
59
  | qué | por qué no hoy | cuándo sí, en un flujo nuevo |
60
60
  |---|---|---|
61
61
  | el componente | no hay panel de campana | si el panel del local o el super admin suman una campana con la bandeja desplegable en la barra superior (web) |
62
- | `manage` con el texto por defecto | está en inglés | nunca: siempre un texto propio |
62
+ | `manage` con el texto por defecto | ya está en español («Administrar notificaciones», 03-10-2026), pero el link debe nombrar la pantalla a la que lleva | nunca: siempre un texto propio |
63
63
 
64
64
  ## API
65
65
 
@@ -44,8 +44,8 @@ texto) y el filtro es un compact-button de 24 px.
44
44
 
45
45
  | uso | mobile | web | fuente |
46
46
  |---|---|---|---|
47
- | las pestañas | **no alcanza**: 20 px de alto para el dedo. Usar `sui-tab-chips` | 20 px de alto, en una fila de 48 | sin tamaño suficiente (no se cambia aquí) |
48
- | el filtro | 24 px, **bajo el mínimo de 32 px** en mobile | 24 px | sin tamaño suficiente |
47
+ | las pestañas | **no alcanza**: 20 px de alto (el `line-height` del texto; el botón no tiene relleno), lejos de los 44 del dedo. Usar `sui-tab-chips` | 20 px de alto, en una fila de 48 | según el componente |
48
+ | el filtro | 24 px (compact-button `large`), **bajo los 44 px del dedo** | 24 px | según el componente |
49
49
 
50
50
  ```html
51
51
  @if (bp.isMobile()) {
@@ -97,7 +97,9 @@ interface SuiNotificationTab<T = string> {
97
97
  - La raya de la pestaña activa usa el primario de la app (naranja), no el azul del Figma.
98
98
  - El badge no tiene tope: 120 sale «120». Si hace falta, el texto lo recorta quien lo usa («99+» va
99
99
  en `label`, no en `badge`, porque `badge` es un número).
100
- - El host lleva `role="tablist"` y cada pestaña `role="tab"` con `aria-selected`; no hay panel `tabpanel` asociado: lo arma quien lo usa.
100
+ - Las pestañas van en su propio `role="tablist"` (el botón de filtro queda afuera, desde el
101
+ 04-10-2026) y cada una es `role="tab"` con `aria-selected`. Un solo tab stop: ← → mueven y
102
+ activan con vuelta al inicio, Home/End a los extremos. No hay `tabpanel` asociado: lo arma quien lo usa.
101
103
 
102
104
  ## Ejemplo
103
105
 
@@ -18,7 +18,8 @@ página.
18
18
  **No lo uses** para:
19
19
 
20
20
  - **Mobile**: las listas se recorren con el dedo. Va scroll infinito (la directiva
21
- `appInfiniteScroll` que ya usan productos, clientes y equipo).
21
+ `appInfiniteScroll` que ya usan productos, clientes, el historial del repartidor y del cliente,
22
+ usuarios del super admin y las listas de la central).
22
23
  - **Listas que se leen de Firestore por cursor** (`getCollectionPage`): con cursores solo se puede
23
24
  pedir la página siguiente. Saltar a la página 7 obliga a leer las 6 anteriores, y Firestore las
24
25
  cobra igual. El canon de la app para esas listas es scroll infinito (CLAUDE.md, «Performance —
@@ -36,8 +37,10 @@ Regla corta: **tabla con todo cargado en web → pagination · lista de Firestor
36
37
  > cuándo cada forma.
37
38
  >
38
39
  > Uso medido el 03-10-2026 en `master-pedidos/src/app` (misma exclusión que `sui-badge`): **0 usos**.
39
- > Las 3 listas largas de la app (`pages/products/products.html:242`, `pages/customers/customers.html:161`,
40
- > `pages/settings/team/team.ts:347`) usan scroll infinito.
40
+ > Las listas largas de la app usan scroll infinito con `appInfiniteScroll` (por ejemplo
41
+ > `pages/products/products.html:242` y `pages/customers/customers.html:161`). Equipo
42
+ > (`pages/settings/team/team.ts:339`) pagina por cursor con `loadMore()`, pero hoy nada lo llama
43
+ > (medido el 04-10-2026).
41
44
 
42
45
  ### `type`
43
46
 
@@ -63,7 +66,7 @@ Regla corta: **tabla con todo cargado en web → pagination · lista de Firestor
63
66
  | `firstLast` | `true` | Más de 20 páginas, donde ir al final es un caso de uso (la última semana de un export). | según la guía del DS (los botones existen); el cuándo es propuesta |
64
67
  | `siblingCount` | `1` (default) | Siempre. Más números a cada lado ensanchan sin ayudar. | propuesta, falta aprobación |
65
68
  | `showInfo` | `true` (default) | Con `infoFormat="items"`: «Mostrando 11-20 de 134». | propuesta, falta aprobación |
66
- | `infoFormat` | `'items'` (default) | El único en español. | según el código |
69
+ | `infoFormat` | `'items'` (default) | «Mostrando 11-20 de 134». | según el código |
67
70
  | `infoFormat` | `'pages'` | Imprime «Página 2 de 14» (en español desde 03-10-2026). Cuando no se sabe el total de ítems o no importa. | propuesta, falta aprobación |
68
71
  | `pageSizeOptions` | `[]` (default) | Lo normal: sin selector de filas por página. | propuesta, falta aprobación |
69
72
  | `pageSizeOptions` | `[10, 25, 50]` | Las opciones dicen «10 / página» (en español desde 03-10-2026). | propuesta, falta aprobación |
@@ -92,7 +95,7 @@ mobile no se usa.
92
95
  |---|---|---|
93
96
  | el componente entero | las listas de la app leen de Firestore por cursor y usan scroll infinito | una tabla de web con todos los datos ya cargados (un reporte de 300 filas filtrado en el navegador) |
94
97
  | `full-radius` | no combina con las esquinas del resto de la app | nunca, salvo que la app pase a botones redondos |
95
- | `infoFormat="pages"` | sale en inglés | cuando el DS lo traduzca («Página 2 de 14») |
98
+ | `infoFormat="pages"` | la razón original (salía en inglés) ya no aplica: desde el 03-10-2026 dice «Página 2 de 14» | cuando no se sabe el total de ítems o no importa |
96
99
  | `firstLast` | ninguna tabla tiene 20+ páginas | un export largo donde ir al final es habitual |
97
100
 
98
101
  ## API
@@ -18,7 +18,7 @@ la barra se llena (rojo, naranja, verde) y cada condición se marca a medida que
18
18
 
19
19
  - El login: la contraseña ya existe, no se evalúa.
20
20
  - Una sola regla («Mínimo 6 caracteres»): alcanza el `hint` del `sui-input`, como hoy en
21
- `pages/auth/register/register.html:121`.
21
+ `pages/auth/register/register.html:124`.
22
22
 
23
23
  Regla corta: **contraseña nueva con 2+ reglas → este · una regla → hint.**
24
24
 
@@ -2,7 +2,7 @@
2
2
  name: sui-period-range
3
3
  selector: sui-period-range
4
4
  resumen: Un período predefinido (Hoy, Últimos 7 días) en la columna de presets del calendario de rango
5
- alternativas: [sui-datepicker mode="range" (ya los trae), sui-tab-chips (períodos fijos a la vista: super admin, ganancias del repartidor), sui-select (períodos fijos en poco espacio: resumen del local)]
5
+ alternativas: [sui-datepicker mode="range" (ya los trae), sui-segmented-control (2 a 4 períodos fijos a la vista), sui-tab-chips (5 o más períodos fijos o que deslizan)]
6
6
  ---
7
7
 
8
8
  # sui-period-range
@@ -18,9 +18,10 @@ costado del calendario.
18
18
 
19
19
  - El rango normal: `sui-datepicker mode="range"` ya pinta los presets con este componente y los
20
20
  cambia por `[presets]`.
21
- - **Cambiar de período en un resumen** («Hoy · 7 días · 30 días»): `sui-tab-chips`, como hoy en
22
- el super admin (`master-overview.html:13`) y en las ganancias del repartidor; o `sui-select`,
23
- como el resumen del local (`overview.html:46`).
21
+ - **Cambiar de período en un resumen** («Hoy · 7 días · 30 días»): `sui-segmented-control` si son 2
22
+ a 4 opciones, `sui-tab-chips` si son 5 o más o se deslizan (canon, dueño 04-10-2026). Hoy la app
23
+ los tiene en `sui-tab-chips` (super admin `master-overview.html:13`, ganancias del repartidor) y
24
+ en `sui-select` (resumen del local, `overview.html:44`): con 3 opciones pasan a segmented.
24
25
 
25
26
  ## Qué variante usar
26
27
 
@@ -40,26 +41,28 @@ Usos de hoy que rompen la regla: **0**.
40
41
 
41
42
  ## Tamaño en mobile y en web
42
43
 
43
- **No tiene `size`.** Mide 168 × 36: en mobile **no llega** a los 44 px. En el datepicker, en
44
- mobile, los presets pasan a una fila que se desplaza de costado.
44
+ Tiene `size`: **`medium`** (default, 168 × 36, Figma) y **`large`** (168 × 44, texto 16/24). El
45
+ `sui-datepicker` `xlarge` pinta sus rangos predefinidos en `large`; en mobile pasan a una fila que
46
+ se desplaza de costado.
45
47
 
46
- | uso | mobile | web | fuente |
47
- |---|---|---|---|
48
- | preset de un rango | 36 px de alto — **no llega** | 168 × 36 | medido |
48
+ | size | alto | texto | uso | fuente |
49
+ |---|---|---|---|---|
50
+ | `large` | **44** (10 + 24 + 10) | 16/24 | mobile | canon (dueño, 04-10-2026): piso táctil 44 en el teléfono |
51
+ | `medium` (default) | 36 | 14/20 | web, columna de presets | medido (Figma 443:341) |
49
52
 
50
53
  ```html
51
- <!-- Web: columna de presets -->
52
- <sui-period-range label="Últimos 7 días" [active]="preset() === '7d'" (clicked)="aplicar('7d')" />
54
+ <sui-period-range [size]="bp.isMobile() ? 'large' : 'medium'" label="Últimos 7 días"
55
+ [active]="preset() === '7d'" (clicked)="aplicar('7d')" />
53
56
  ```
54
57
 
55
- **Sin tamaño suficiente para mobile.** En el celular, los períodos fijos van en `sui-tab-chips`,
56
- como ya hacen el super admin y las ganancias del repartidor.
58
+ Fuera del datepicker, en el celular los períodos fijos de 2 a 4 opciones van en
59
+ `sui-segmented-control` y los de más opciones en `sui-tab-chips` (canon del dueño, 04-10-2026).
57
60
 
58
61
  ## «No usar»: por qué no hoy y cuándo sí
59
62
 
60
63
  | qué | por qué no hoy | cuándo sí, en un flujo nuevo |
61
64
  |---|---|---|
62
- | todo el componente suelto (0 usos) | los períodos de la app son fijos y van en tab-chips o select | una columna de atajos al lado de un calendario propio, en web |
65
+ | todo el componente suelto (0 usos) | los períodos de la app son fijos y van en segmented-control (2-4) o tab-chips (5+) | una columna de atajos al lado de un calendario propio, en web |
63
66
  | `disabled` | ningún período queda sin datos hoy | presets de un local nuevo («Últimos 12 meses» con 2 semanas de vida) |
64
67
 
65
68
  ## API
@@ -72,6 +75,7 @@ como ya hacen el super admin y las ganancias del repartidor.
72
75
  | `label` | `string` | — (requerido) |
73
76
  | `active` | `boolean` | `false` |
74
77
  | `disabled` | `boolean` | `false` |
78
+ | `size` | `'medium' \| 'large'` | `'medium'` |
75
79
 
76
80
  | output | payload |
77
81
  |---|---|
@@ -57,8 +57,8 @@ una función nueva que conviene mostrar donde está («Aquí programas tus pedid
57
57
  |---|---|---|---|
58
58
  | `doubleButton` | `true` (default) | Desde el segundo paso de un recorrido («Atrás» / «Siguiente»), o un aviso suelto con «Ahora no» / «Probar». | propuesta |
59
59
  | `doubleButton` | `false` | El primer paso de un recorrido o un aviso suelto con una sola salida («Entendido»). | propuesta |
60
- | `backLabel` · `nextLabel` | texto en español | Los defaults ya son «Atrás» y «Siguiente» (03-10-2026); el último paso pasa `nextLabel="Listo"`. | canon (copy de la app: tuteo, sentence case) |
61
- | orden | secundario a la izquierda, primario a la derecha | Ya lo hace el componente (stroke neutral + filled primary), igual que `sui-modal-footer`. | canon (orden de botones de la app) |
60
+ | `backLabel` · `nextLabel` | texto en español | Los defaults ya son «Atrás» y «Siguiente» (03-10-2026); el último paso pasa `nextLabel="Listo"`. | canon (CANON-SUI §5.1 y §5.3: sentence case, tuteo) |
61
+ | orden | secundario a la izquierda, primario a la derecha | Ya lo hace el componente (stroke neutral + filled primary), igual que `sui-modal-footer`. | canon (CLAUDE.md, «Botones — composición y orden») |
62
62
  | `step` | `{ current, total }` | Con `stepper`. Sin `step`, el componente asume **1 de 4**. | propuesta |
63
63
 
64
64
  ### Flecha, ícono, texto y cierre
@@ -73,7 +73,7 @@ una función nueva que conviene mostrar donde está («Aquí programas tus pedid
73
73
  | `position` | `*-left` · `*-center` · `*-right` | Alinea la flecha con el elemento cuando el popover no puede centrarse sobre él (está cerca de un borde). | propuesta |
74
74
  | `icon` | el de lo que se explica | Siempre uno que diga el tema (`calendar-schedule-line` para programar). El default es un ícono de persona. | propuesta |
75
75
  | `icon` | `null` | Cuando el texto ya basta y el ícono sería decoración. | propuesta |
76
- | `title` | frase corta | Qué es, en sentence case y sin punto final. | canon (copy de la app) |
76
+ | `title` | frase corta | Qué es, en sentence case y sin punto final. | canon (CANON-SUI §5.1 y §5.2) |
77
77
  | `description` | una o dos frases | Qué hace o por qué importa. | propuesta |
78
78
  | `dismissIcon` | `true` (default) | Siempre: un recorrido se puede saltar. | propuesta |
79
79
  | `dismissIcon` | `false` | No usar hoy. **Cuándo sí:** un paso que no se puede saltar porque sin él no funciona lo siguiente. | propuesta |
@@ -88,20 +88,24 @@ cada lado; en uno más angosto se sale. El `size` cambia **los botones del pie**
88
88
  |---|---|---|
89
89
  | `small` (default) | 36 px (`sui-button` `small`) | Figma |
90
90
  | `medium` | 40 px (`sui-button` `medium`) | canon (aprobado por el dueño, 03-10-2026): extensión SUI |
91
+ | `large` | 48 px (`sui-button` `large`) | canon (dueño, 04-10-2026): piso táctil 44 en el teléfono. Size nuevo del 04-10-2026 |
91
92
 
92
- La X se ve de 24 y **se toca en 40 × 40** en los dos (un `::before` invisible sobre su botón,
93
+ La X se ve de 24 y **se toca en 40 × 40** en todos (un `::before` invisible sobre su botón,
93
94
  extensión SUI 03-10-2026).
94
95
 
95
96
  | uso | mobile | web | fuente |
96
97
  |---|---|---|---|
97
98
  | el panel | 320 px (cabe desde 352 px de pantalla) | 320 px | según el componente |
98
- | botones del pie | `medium` (40) | `small` (36) | propuesta: el tamaño es extensión SUI aprobada (03-10-2026); el «cuándo» falta aprobarlo |
99
+ | botones del pie | `large` (48) | `small` (36) | canon (dueño, 04-10-2026): piso táctil 44 en el teléfono |
99
100
  | la X | se ve de 24, se toca en 40 | igual | canon (aprobado por el dueño, 03-10-2026) |
100
101
 
101
102
  ```html
102
- <sui-popover footer="stretch" [size]="bp.isMobile() ? 'medium' : 'small'" … />
103
+ <sui-popover footer="stretch" [size]="bp.isMobile() ? 'large' : 'small'" … />
103
104
  ```
104
105
 
106
+ `large` es el siguiente de la escala del `sui-button` (48, el del footer de los modales). `medium`
107
+ (40) queda para quien ya lo usa: no llega al piso de 44.
108
+
105
109
  En mobile, si el recorrido es la bienvenida de la app, conviene una pantalla o un
106
110
  `sui-modal-sheet` por paso en vez del popover (propuesta, falta aprobación).
107
111
 
@@ -135,7 +139,7 @@ Hoy el popover entero tiene **0 usos**; esto es lo que no se usaría aunque lleg
135
139
  | `nextLabel` | `string` | `'Siguiente'` |
136
140
  | `doubleButton` | `boolean` | `true` |
137
141
  | `step` | `{ current: number; total: number } \| null` | `null` |
138
- | `size` | `'small' \| 'medium'` | `'small'` |
142
+ | `size` | `'small' \| 'medium' \| 'large'` | `'small'` |
139
143
 
140
144
  | output | payload |
141
145
  |---|---|
@@ -152,6 +156,8 @@ Slot: `[data-slot=body]` reemplaza título y descripción.
152
156
  «Paso X de N» (este último no se puede cambiar).
153
157
  - **El ícono por defecto es una persona** (`user-6-line`). Si no quieres ícono, `[icon]="null"`.
154
158
  - **`step` vacío = 1 de 4**: con `stepper` o `text-stepper`, pásalo siempre.
159
+ - Con `stepper`, los puntos se leen como «Paso X de N» (`role="img"` con `aria-label`, desde el
160
+ 04-10-2026; antes eran `aria-hidden` y el lector no sabía en qué paso iba).
155
161
  - **No se posiciona solo**: `position` cambia dónde sale la flecha, no dónde aparece el panel.
156
162
  Tampoco se cierra al tocar afuera ni con Escape; cierra quien escucha `(dismissed)`.
157
163
  - `position` se lee «borde de la flecha, luego su lugar»: `top-left` es flecha **arriba a la
@@ -32,7 +32,7 @@ Regla corta: **producto en la grilla de la carta → product-card · producto en
32
32
  >
33
33
  > Uso medido el 03-10-2026 en `master-pedidos/src/app` (misma exclusión que `sui-card`): **3
34
34
  > product-cards en 2 archivos**: la carta del cliente
35
- > (`pages/customer/restaurant-menu/restaurant-menu.html:324` y `:387`) y la grilla del local
35
+ > (`pages/customer/restaurant-menu/restaurant-menu.html:323` y `:386`) y la grilla del local
36
36
  > (`pages/products/products.html:145`, con `action="edit"`).
37
37
 
38
38
  ### Las piezas
@@ -54,9 +54,10 @@ Regla corta: **producto en la grilla de la carta → product-card · producto en
54
54
 
55
55
  Outputs: `openDetail` (toque en la card), `add`, `increment`, `decrement`, `edit`.
56
56
 
57
- **Usos de hoy que rompen las reglas:** 0. **Falta en el DS:** el precio tachado y la chapa de
58
- descuento. La carta los dibuja afuera (`pages/customer/restaurant-menu/restaurant-menu.scss:426`,
59
- deuda anotada): cuando se pueda publicar, va un input `precioLista`.
57
+ **Usos de hoy que rompen las reglas:** 0. **Pendiente de migrar:** el precio tachado y la chapa de
58
+ descuento ya existen en el DS (`precioLista`, ver «Precio con descuento»), pero la carta los sigue
59
+ dibujando afuera (`pages/customer/restaurant-menu/restaurant-menu.scss:426`, deuda anotada) y
60
+ ninguna de las 3 cards pasa `precioLista` ni `size`.
60
61
 
61
62
  ## Tamaño en mobile y en web
62
63
 
@@ -67,20 +68,23 @@ El ancho lo da la grilla y la card llena su celda. El `size` cambia **los botone
67
68
  |---|---|---|---|---|
68
69
  | `small` (default) | 36 × 36 | 34 × 36 | 18 / 16 | lo que había en el DS |
69
70
  | `medium` | 40 × 40 | 40 × 40 (pill de 104) | 20 | canon (aprobado por el dueño, 03-10-2026): extensión SUI |
71
+ | `large` | 44 × 44 | 44 × 44 (pill de 112) | 20 | canon (dueño, 04-10-2026): piso táctil 44 en el teléfono. Size nuevo del 04-10-2026 |
70
72
 
71
- En `medium` el stepper (104 px) no entra al lado del precio en la grilla de 2 columnas de mobile:
72
- el pie envuelve y el stepper baja a su propia línea, a la derecha. El «+» y el lápiz sí siguen al
73
- lado del precio.
73
+ En `medium` y `large` el stepper (104 / 112 px) no entra al lado del precio en la grilla de 2
74
+ columnas de mobile: el pie envuelve y el stepper baja a su propia línea, a la derecha. El «+» y el
75
+ lápiz sí siguen al lado del precio.
74
76
 
75
77
  | uso | mobile | web | fuente |
76
78
  |---|---|---|---|
77
79
  | grilla de la carta | 2 columnas (`1fr 1fr`, gap 12) | `repeat(auto-fill, minmax(220px, 1fr))` desde 600 px y `minmax(180px, 1fr)` en desktop | lo que hay en la app |
78
- | botón «+», lápiz, stepper | `medium` (40) | `small` (36) | propuesta: el tamaño es extensión SUI aprobada (03-10-2026); el «cuándo» falta aprobarlo |
80
+ | botón «+», lápiz, stepper | `large` (44) | `small` (36) | canon (dueño, 04-10-2026): piso táctil 44 en el teléfono |
79
81
 
80
82
  ```html
81
- <sui-product-card [size]="bp.isMobile() ? 'medium' : 'small'" … />
83
+ <sui-product-card [size]="bp.isMobile() ? 'large' : 'small'" … />
82
84
  ```
83
85
 
86
+ `medium` (40) queda para quien ya lo usa: no llega al piso de 44 del teléfono.
87
+
84
88
  ## Precio con descuento
85
89
 
86
90
  `precioLista` es el precio de referencia. Si es **mayor** que `price`, la card pinta el precio en
@@ -116,7 +120,7 @@ por `::after` y chapa por `::before` sobre `.product__price`), que se borra al m
116
120
  | `unavailableLabel` | `string` | `'Agotado'` |
117
121
  | `action` | `'add' \| 'edit'` | `'add'` |
118
122
  | `precioLista` | `number \| null` | `null` |
119
- | `size` | `'small' \| 'medium'` | `'small'` |
123
+ | `size` | `'small' \| 'medium' \| 'large'` | `'small'` |
120
124
 
121
125
  | output | payload |
122
126
  |---|---|
@@ -96,7 +96,7 @@ readonly bp = inject(BreakpointsService); // master-pedidos: src/app/services/br
96
96
  ```
97
97
 
98
98
  ```html
99
- <sui-progress-bar [value]="progreso()" [size]="bp.isMobile() ? 'medium' : 'small'" ariaLabel="Subiendo la foto" />
99
+ <sui-progress-bar [value]="progreso()" [size]="bp.isMobile() ? 'large' : 'medium'" ariaLabel="Subiendo la foto" />
100
100
  ```
101
101
 
102
102
  ## API
@@ -110,6 +110,7 @@ readonly bp = inject(BreakpointsService); // master-pedidos: src/app/services/br
110
110
  | `color` | `'blue' \| 'green' \| 'orange' \| 'red' \| 'purple'` | `'blue'` |
111
111
  | `size` | `'small' \| 'medium' \| 'large' \| 'xlarge'` | `'medium'` |
112
112
  | `ariaLabel` | `string \| null` | `null` |
113
+ | `ariaLabelledby` | `string \| null` | `null` |
113
114
 
114
115
  Outputs: ninguno.
115
116
  <!-- api:fin -->
@@ -122,7 +123,8 @@ Outputs: ninguno.
122
123
  este proyecto es naranja).
123
124
  - El ancho es el 100 % del padre: dentro de un flex, dale `flex: 1` o un ancho.
124
125
  - Lleva `role="progressbar"` con `aria-valuenow`; la animación se apaga con
125
- `prefers-reduced-motion`.
126
+ `prefers-reduced-motion`. Nombre: `ariaLabel`, o `ariaLabelledby` (id de un texto visible), y si
127
+ no hay ninguno se llama «Progreso» (04-10-2026: antes quedaba sin nombre).
126
128
 
127
129
  ## Ejemplo
128
130
 
@@ -123,6 +123,8 @@ Output: `(linkClick)`. Con `link` de texto el `<a>` no navega y solo emite; con
123
123
  - El link se pinta en el azul de información, no en el naranja de la marca.
124
124
  - Si no hay `title` y `percentage` es `false`, no se dibuja la fila de arriba.
125
125
  - Tiene el strip del `title` nativo: no aparece el tooltip gris del navegador.
126
+ - El `title` visible nombra la barra (`aria-labelledby`, 04-10-2026); sin título (`on-right`) y sin
127
+ `ariaLabel` se anuncia «Progreso».
126
128
 
127
129
  ## Ejemplo
128
130
 
@@ -19,8 +19,8 @@ Va dentro de un `sui-radio-group`, que es el que hace que elegir una desmarque l
19
19
 
20
20
  - Un círculo con su texto en una lista densa (franjas horarias): `sui-radio-label`.
21
21
  - Opciones con peso (ícono, descripción, borde) o que se tocan en el teléfono: `sui-radio-card`
22
- (método de pago, tipo de entrega, motivos de cancelación). Crece con `bp.controlSize()`; el
23
- radio-label no tiene `size`.
22
+ (método de pago, tipo de entrega, motivos de cancelación). La tarjeta entera es el área táctil
23
+ (54 px o más); un radio-label sin descripción mide lo que su círculo.
24
24
  - Más de ~6 opciones: `sui-select`.
25
25
  - 2-4 modos de la misma vista que se aplican al instante: `sui-segmented-control`.
26
26
  - Varias a la vez: `sui-checkbox`.
@@ -57,10 +57,10 @@ Regla corta: **lista densa de texto → radio-label · con peso o en el teléfon
57
57
  **Usos de hoy que rompen la regla:**
58
58
 
59
59
  - **1 radio nativo → `sui-radio-card type="basic"`:**
60
- `pages/driver/driver-order-detail/driver-order-detail.html:812` (motivos de cancelación del
60
+ `pages/driver/driver-order-detail/driver-order-detail.html:844` (motivos de cancelación del
61
61
  repartidor, el mismo caso del ejemplo de la guía). La pantalla hermana del local ya lo resolvió
62
- así: `pages/orders/orders.html:566`.
63
- - **1 suelto que se puede desincronizar:** `pages/super-admin/master-settings/master-settings.html:105`
62
+ así: `pages/orders/orders.html:567`.
63
+ - **1 suelto que se puede desincronizar:** `pages/super-admin/master-settings/master-settings.html:107`
64
64
  (categoría por defecto). Usa `[standaloneChecked]` + `$event && …`: al tocar el que ya está
65
65
  elegido, el círculo se apaga por dentro pero el padre sigue diciendo que es el elegido. Va en
66
66
  un `sui-radio-group` con `[ngModel]`.
@@ -96,6 +96,7 @@ El más grande mide 28 px: el área táctil de 44 px la tiene que dar la fila.
96
96
  | `size` | `'medium' \| 'large' \| 'xlarge'` | `'medium'` |
97
97
  | `value` | `SuiRadioValue` | `null` |
98
98
  | `disabled` | `boolean` | `false` |
99
+ | `focusable` | `boolean` | `true` |
99
100
  | `standaloneChecked` · model, `[(standaloneChecked)]` | `boolean` | `false` |
100
101
 
101
102
  Outputs: ninguno.
@@ -117,8 +118,14 @@ y proyecta los radios (`sui-radio`, `sui-radio-label`, `sui-radio-card`).
117
118
  - **`sui-radio-group` no tiene `value`**: se maneja con `[(ngModel)]` o un form control.
118
119
  - **`sui-radio-group` es `inline-flex` en fila con gap 16.** Para lista vertical hay que darle
119
120
  `flex-direction: column; align-items: flex-start` desde afuera.
120
- - **Deshabilitar el control del grupo no deshabilita los radios** (`setDisabledState` no hace
121
- nada): pasa `[disabled]` a cada uno.
121
+ - **Teclado en `sui-radio-group`** (revisión 04-10-2026): un solo tab stop —la opción marcada, o la
122
+ primera habilitada— y las flechas ↑ ↓ ← → mueven el foco y eligen la vecina, saltando las
123
+ deshabilitadas y dando la vuelta. Vale igual con `sui-radio-label` y `sui-radio-card` adentro.
124
+ Antes cada radio era una parada de Tab y no había flechas.
125
+ - **Deshabilitar el control del grupo deshabilita todas las opciones** (`setDisabledState`;
126
+ hasta el 04-10-2026 no hacía nada y había que pasar `[disabled]` a cada una).
127
+ - **`[focusable]="false"`** saca al radio del Tab y del grupo de flechas: es para cuando un padre
128
+ ya es el radio enfocable (`sui-radio-label`).
122
129
  - No hay `small`: el más chico es `medium` (20 px).
123
130
  - Sin marcar, en foco, el círculo se pinta del color de marca: viene del Figma, no es un error.
124
131
  - No dibuja texto ni `aria-label`: pelado, pon el texto en un `<label>` o usa `sui-radio-label`.
@@ -31,10 +31,11 @@ checkbox-card.**
31
31
  > adentro: **«para elegir una sola opción de una lista corta»**. El resto es práctica de la app
32
32
  > («propuesta») o regla ya aprobada («canon»).
33
33
  >
34
- > Uso medido el 03-10-2026 en `master-pedidos/src/app` (misma exclusión que `sui-card`): **31
34
+ > Uso medido el 04-10-2026 en `master-pedidos/src/app` (misma exclusión que `sui-card`): **31
35
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`.
36
+ > `iconSrc`), 6 `basic`, 1 `avatar`, 1 `company`. Tamaños: 30 `bp.controlSize()` y 1 con el
37
+ > `size()` del padre (`components/address-picker-modal/address-picker-modal.html:41`). 6 con
38
+ > `sublabel`, 6 con `disabled`, 1 con `badge`.
38
39
 
39
40
  ### `type` (el leading)
40
41
 
@@ -68,13 +69,10 @@ checkbox-card.**
68
69
  | `large` (24) | Desktop, vía `bp.controlSize()`. | canon (aprobado por el dueño, 28-09-2026) |
69
70
  | `medium` (20, default) | No usar en pantallas nuevas. | canon (aprobado por el dueño, 28-09-2026) |
70
71
 
71
- **Usos de hoy que rompen las reglas:**
72
+ **Usos de hoy que rompen las reglas: 0.** Los 5 que iban sin el size del breakpoint y el
73
+ `xlarge` fijo de `pages/customer/mandadito/mandadito.html:30` pasaron a `bp.controlSize()` el
74
+ 03-10-2026.
72
75
 
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
76
  - **A revisar:** `pages/super-admin/master-orders/master-orders.html:720` lista a los repartidores
79
77
  candidatos, una lista que crece con la flota (con muchos, `sui-select` o una lista con búsqueda).
80
78
  `pages/role-selector/role-selector.html:24` usa la radio como botón: elegir ya avanza, sin
@@ -82,8 +80,9 @@ checkbox-card.**
82
80
 
83
81
  ## Tamaño en mobile y en web
84
82
 
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.
83
+ La card entera es el área táctil: 74 px con descripción (16 + 40 + 16 de padding y contenido,
84
+ más 2 de borde) y 54 px la más chica (`basic`, sin descripción, `medium`). Llega al piso de 44
85
+ sola. El `size` cambia solo el radio.
87
86
 
88
87
  | uso | mobile | web |
89
88
  |---|---|---|
@@ -141,7 +140,8 @@ Implementa `ControlValueAccessor` (el valor del form es el `value` elegido). Den
141
140
  `imageUrl` si la marca no está en el catálogo). No hay slot para proyectar el leading (a
142
141
  diferencia de `sui-checkbox-card`).
143
142
  - 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.
143
+ bindear `[checked]` de todas a la misma señal. Suelta, además, **cada card es una parada de Tab
144
+ y no hay flechas**; dentro de `sui-radio-group` sí hay un solo tab stop y flechas (revisión 04-10-2026).
145
145
  - `badge` con string sale **azul `light` `small`** (en `sui-content-label` sale naranja).
146
146
  - `size` cambia solo el radio, no el padding ni el alto de la card.
147
147