@ajuarezso/sui-design-system 0.21.0 → 0.23.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 (114) hide show
  1. package/docs/INDEX.md +30 -35
  2. package/docs/sui-accordion/README.md +171 -0
  3. package/docs/sui-activity-feed/README.md +154 -0
  4. package/docs/sui-activity-filter/README.md +100 -0
  5. package/docs/sui-alert/README.md +28 -19
  6. package/docs/sui-app-store-badge/README.md +5 -4
  7. package/docs/sui-avatar/README.md +16 -16
  8. package/docs/sui-avatar-group/README.md +4 -4
  9. package/docs/sui-badge/README.md +27 -9
  10. package/docs/sui-banner/README.md +10 -9
  11. package/docs/sui-brand-logo/README.md +3 -3
  12. package/docs/sui-breadcrumbs/README.md +1 -1
  13. package/docs/sui-button/README.md +64 -21
  14. package/docs/sui-button-group/README.md +6 -4
  15. package/docs/sui-button-group-item/README.md +3 -3
  16. package/docs/sui-card/README.md +17 -19
  17. package/docs/sui-chart-legend/README.md +8 -7
  18. package/docs/sui-checkbox/README.md +11 -6
  19. package/docs/sui-checkbox-card/README.md +24 -19
  20. package/docs/sui-checkbox-label/README.md +32 -10
  21. package/docs/sui-circular-progress-bar/README.md +2 -0
  22. package/docs/sui-color-dot/README.md +1 -1
  23. package/docs/sui-color-picker/README.md +22 -7
  24. package/docs/sui-command-menu-footer/README.md +100 -0
  25. package/docs/sui-command-menu-item/README.md +140 -0
  26. package/docs/sui-command-menu-search/README.md +105 -0
  27. package/docs/sui-compact-avatar-group/README.md +4 -3
  28. package/docs/sui-compact-button/README.md +41 -44
  29. package/docs/sui-compact-select/README.md +12 -5
  30. package/docs/sui-compact-select-for-input/README.md +5 -2
  31. package/docs/sui-content-card/README.md +6 -5
  32. package/docs/sui-content-divider/README.md +4 -4
  33. package/docs/sui-content-label/README.md +11 -6
  34. package/docs/sui-counter-input/README.md +21 -17
  35. package/docs/sui-date-selector/README.md +16 -12
  36. package/docs/sui-datepicker/README.md +46 -28
  37. package/docs/sui-day-cell/README.md +17 -8
  38. package/docs/sui-day-label/README.md +2 -2
  39. package/docs/sui-divider/README.md +5 -5
  40. package/docs/sui-drawer-footer/README.md +19 -5
  41. package/docs/sui-dropdown-caption/README.md +92 -0
  42. package/docs/sui-dropdown-item/README.md +163 -0
  43. package/docs/sui-dropdown-menu/README.md +196 -0
  44. package/docs/sui-dropdown-search/README.md +113 -0
  45. package/docs/sui-emoji/README.md +6 -6
  46. package/docs/sui-empty-state/README.md +13 -23
  47. package/docs/sui-fancy-button/README.md +24 -18
  48. package/docs/sui-file-icon/README.md +1 -1
  49. package/docs/sui-file-upload/README.md +3 -0
  50. package/docs/sui-file-upload-card/README.md +8 -7
  51. package/docs/sui-filter/README.md +181 -0
  52. package/docs/sui-flag/README.md +3 -2
  53. package/docs/sui-form-hint/README.md +12 -8
  54. package/docs/sui-form-label/README.md +11 -16
  55. package/docs/sui-href/README.md +85 -0
  56. package/docs/sui-icon/README.md +4 -3
  57. package/docs/sui-image-upload/README.md +28 -16
  58. package/docs/sui-img-retry/README.md +107 -0
  59. package/docs/sui-inline-input/README.md +7 -6
  60. package/docs/sui-inline-select/README.md +8 -5
  61. package/docs/sui-input/README.md +27 -33
  62. package/docs/sui-integration-switch/README.md +14 -7
  63. package/docs/sui-kbd/README.md +4 -4
  64. package/docs/sui-key-icon/README.md +6 -2
  65. package/docs/sui-link-button/README.md +21 -17
  66. package/docs/sui-modal/README.md +238 -0
  67. package/docs/sui-modal-footer/README.md +178 -0
  68. package/docs/sui-modal-header/README.md +115 -0
  69. package/docs/sui-modal-sheet/README.md +170 -0
  70. package/docs/sui-notification/README.md +8 -6
  71. package/docs/sui-notification-footer/README.md +2 -2
  72. package/docs/sui-notification-tab-menu/README.md +5 -3
  73. package/docs/sui-page-header/README.md +123 -0
  74. package/docs/sui-pagination/README.md +8 -5
  75. package/docs/sui-password-strength/README.md +1 -1
  76. package/docs/sui-period-range/README.md +18 -14
  77. package/docs/sui-popover/README.md +13 -7
  78. package/docs/sui-product-card/README.md +14 -10
  79. package/docs/sui-progress-bar/README.md +4 -2
  80. package/docs/sui-progress-bar-label/README.md +2 -0
  81. package/docs/sui-radio/README.md +14 -7
  82. package/docs/sui-radio-card/README.md +12 -12
  83. package/docs/sui-radio-label/README.md +36 -11
  84. package/docs/sui-rating/README.md +28 -9
  85. package/docs/sui-rich-editor/README.md +3 -3
  86. package/docs/sui-segmented-control/README.md +33 -19
  87. package/docs/sui-select/README.md +40 -33
  88. package/docs/sui-sidebar/README.md +216 -0
  89. package/docs/sui-slider/README.md +7 -0
  90. package/docs/sui-social-button/README.md +24 -11
  91. package/docs/sui-status-badge/README.md +7 -3
  92. package/docs/sui-stepper/README.md +30 -17
  93. package/docs/sui-store-card/README.md +9 -4
  94. package/docs/sui-switch/README.md +16 -11
  95. package/docs/sui-switch-card/README.md +18 -16
  96. package/docs/sui-switch-label/README.md +25 -11
  97. package/docs/sui-tab-chips/README.md +56 -39
  98. package/docs/sui-tab-menu-horizontal/README.md +19 -11
  99. package/docs/sui-tab-menu-vertical/README.md +10 -5
  100. package/docs/sui-table/README.md +264 -0
  101. package/docs/sui-tag/README.md +25 -11
  102. package/docs/sui-tag-input/README.md +25 -12
  103. package/docs/sui-textarea/README.md +23 -20
  104. package/docs/sui-time-picker/README.md +39 -30
  105. package/docs/sui-toast/README.md +27 -22
  106. package/docs/sui-tooltip/README.md +14 -17
  107. package/docs/sui-topbar/README.md +153 -0
  108. package/docs/sui-topbar-button/README.md +95 -0
  109. package/docs/sui-topbar-item/README.md +97 -0
  110. package/docs/sui-topbar-user/README.md +83 -0
  111. package/fesm2022/ajuarezso-sui-design-system.mjs +1076 -242
  112. package/fesm2022/ajuarezso-sui-design-system.mjs.map +1 -1
  113. package/package.json +1 -1
  114. package/types/ajuarezso-sui-design-system.d.ts +616 -280
@@ -0,0 +1,216 @@
1
+ ---
2
+ name: sui-sidebar
3
+ selector: sui-sidebar
4
+ resumen: Navegación principal de un rol — columna fija a la izquierda en web y cajón que entra desde la izquierda en mobile
5
+ alternativas: [la barra inferior nativa del layout (las 4-5 secciones más usadas en el teléfono), sui-topbar (navegación arriba, sin columna lateral), sui-tab-menu-vertical (secciones dentro de UNA pantalla, como ajustes), sui-dropdown-menu (acciones de una cuenta o un botón)]
6
+ ---
7
+
8
+ # sui-sidebar
9
+
10
+ Story: [Organisms/Sidebar](https://sui-design-system.web.app/?path=/docs/organisms-sidebar--docs)
11
+
12
+ ## Cuándo usarlo / cuándo no
13
+
14
+ **Úsalo** como **la** navegación de un layout de rol: una por layout, montada en el layout y no
15
+ en las páginas. En la app hay 4 y cubren los roles: empresa (`components/sidebar/sidebar.html:43`,
16
+ dentro del shell), repartidor (`layouts/driver/driver-layout.html:4`), super admin y central
17
+ (`layouts/master/master-layout.html:5`) y cliente (`layouts/customer/customer-layout.html:5`).
18
+
19
+ **No lo uses** para:
20
+
21
+ - Navegar entre secciones **de una sola pantalla** (las pestañas de Ajustes, los pasos de un
22
+ formulario): `sui-tab-menu-vertical` o `sui-tab-chips`.
23
+ - Un menú de acciones (editar, eliminar, cerrar sesión de un item): `sui-dropdown-menu`.
24
+ - Reemplazar la barra inferior en el teléfono. En mobile, las secciones de todos los días van en la
25
+ barra inferior (nativa en iOS) y el sidebar es el cajón de «Más».
26
+
27
+ Regla corta: **navegación del rol → sidebar · secciones de una pantalla → tab menu · acciones → dropdown.**
28
+
29
+ ## Qué variante usar
30
+
31
+ > **La guía del DS no tiene página del sidebar.** El componente sale del Figma de SUI (Sidebar
32
+ > [Navigation], node 3802:11759) y el cajón de mobile no existe en ese Figma: se portó del layout
33
+ > del super admin. Lo de abajo es **práctica de la app** (los 4 usos están homologados desde el
34
+ > 25-07-2026) o **propuesta, falta aprobación**; lo marcado «canon» sale de `docs/CANON-SUI.md`
35
+ > o de `master-pedidos/CLAUDE.md`.
36
+ >
37
+ > Uso medido el 03-10-2026 en `master-pedidos/src/app`: **4 sidebars**, sin contar vitrinas
38
+ > (`master-preview` tiene el quinto).
39
+
40
+ ### La composición (igual en los 4 layouts)
41
+
42
+ | pieza | cómo | fuente |
43
+ |---|---|---|
44
+ | `brand` | `{ name: 'Master Pedidos', subtitle: '<Rol>', logo: 'assets/app-icon.png', fallback: 'M' }`. En empresa, el nombre del local. | práctica de la app (4 de 4) |
45
+ | `showHeaderButton` + `headerButtonActive` + panel `[header-panel]` | El botón del header abre el **cambio de rol** (o de negocio/sucursal en empresa). El panel se proyecta con `<div header-panel>` y adentro van `sui-dropdown-item mode="option" size="large"`. El cliente lo muestra solo en mobile. | práctica de la app (4 de 4) |
46
+ | tres secciones con rótulo | `items` + `itemsLabel` (lo de todos los días), `secondaryItems` + `secondaryItemsLabel` (dinero o crecimiento), `supportingItems` + `supportingItemsLabel` (cuenta, administración: va anclado abajo). Rótulos en sentence case: «Operación», «Dinero», «Cuenta». | práctica de la app (4 de 4) |
47
+ | `activeRoute` | Siempre `[activeRoute]="currentUrl()"`, aunque los items tengan `route`: así el activo se resuelve por prefijo (`/cliente/pedidos/123` deja marcado «Pedidos»). | práctica de la app (4 de 4) |
48
+ | `profile` | Nombre + `avatarUrl` (nunca `photoURL`) + correo. | canon (CLAUDE.md, «Fotos de otra persona»: el campo correcto es `avatarUrl`) |
49
+ | cerrar sesión | Hoy **ningún** item usa `action: 'logout'`: el cierre real vive en el selector de rol y el «salir» del panel solo cambia de rol (`components/sidebar/sidebar.ts:367`). Los 4 layouts dejan `(logoutClicked)` conectado por si se agrega. | práctica de la app |
50
+ | `[(mobileOpen)]` + `closeOnItemClick` | Siempre los dos. Más `cerrarAlNavegar(...)` en el constructor del layout (ver Trampas). | canon (CANON-SUI §1.1) |
51
+ | `search` | `{ placeholder: 'Buscar...', shortcut: '⌘K' }` y el layout **filtra** los items con `searchValue` (el componente no filtra). | práctica de la app (4 de 4) |
52
+ | `indicatorColor` | Default `brand` (naranja). No se cambia. | canon del DS (accent = marca) |
53
+ | `collapsed` | Solo el cliente lo usa, con un item «colapsar», y **solo en web**: `[collapsed]="colapsado() && !bp.isMobile()"`. | práctica de la app (1 uso) |
54
+
55
+ ### El item (`SuiSidebarItem`)
56
+
57
+ | prop | cuándo | fuente |
58
+ |---|---|---|
59
+ | `icon` | Siempre, RemixIcon `-line`. Sin ícono, el modo colapsado queda vacío. | propuesta, falta aprobación |
60
+ | `route` | Navegación normal (usa `routerLink`). | práctica de la app |
61
+ | sin `route` | Acción, no navegación (abrir Configuración, colapsar): `action` o solo `value`, y se escucha `(itemClicked)`. | práctica de la app |
62
+ | `badge` | Un contador que pide acción: notificaciones sin leer, con tope «99+» (`components/sidebar/sidebar.ts:129`). Nunca un «NEW» decorativo. | práctica de la app (el «nunca NEW» es propuesta) |
63
+ | `variant: 'danger'` | Solo «Cerrar sesión» o salidas destructivas. | propuesta, falta aprobación |
64
+ | `shortcut`, `colorDot` | No usar (ver «No usar»). | propuesta, falta aprobación |
65
+
66
+ ## Tamaño en mobile y en web
67
+
68
+ El sidebar **no tiene `size`**. El ancho lo decide el viewport:
69
+
70
+ | estado | ancho | fuente |
71
+ |---|---|---|
72
+ | web (> 767 px) | 272 fijo, alto `100dvh` | Figma |
73
+ | web colapsado (`collapsed`) | 80, solo íconos; los rótulos siguen visibles y cada item tiene tooltip nativo con su label | Figma |
74
+ | mobile `drawer` (default) | `min(86vw, 360px)`, entra desde la izquierda con fondo oscuro | extensión SUI (no está en el Figma) |
75
+ | mobile `sheet` | `100vw - 40px`, se siente casi a pantalla completa | extensión SUI |
76
+
77
+ | uso | mobile | web | fuente |
78
+ |---|---|---|---|
79
+ | navegación del rol | cajón `drawer`, cerrado por defecto | columna fija de 272 | práctica de la app (4 de 4) |
80
+ | colapsar | nunca (`!bp.isMobile()`) | opcional, a pedido de la persona | práctica de la app |
81
+ | `sheet` | no usar (0 usos) | — | propuesta, falta aprobación |
82
+
83
+ **Qué pasa en mobile (≤ 767 px):** el sidebar sale del flujo y queda `position: fixed` fuera de la
84
+ pantalla. Lo abre la acción `toggle-sidebar` de la **barra inferior** («Más»), que el layout
85
+ traduce a `mobileOpen = true` (`layouts/shell/shell.ts:326`, `customer-layout.ts:322`). Se cierra
86
+ con el fondo, con Escape, al tocar un item (`closeOnItemClick`) y —por el helper del proyecto—
87
+ al terminar cualquier navegación. Cerrado queda `inert` y `aria-hidden`: el foco no se mete.
88
+ Respeta las safe areas de arriba, izquierda y abajo.
89
+
90
+ ## «No usar»: por qué no hoy y cuándo sí
91
+
92
+ | qué | por qué no hoy | cuándo sí, en un flujo nuevo |
93
+ |---|---|---|
94
+ | `indicatorColor="information"` | el activo es naranja de marca en toda la app | nunca en esta app (es el azul del Figma original) |
95
+ | `mobileMode="sheet"` | el `drawer` deja ver la página detrás y se entiende que es un cajón | un rol con muchísimos items donde 360 px quedan cortos |
96
+ | `shortcut` en items | no hay atajos de teclado por sección | si se agregan atajos tipo `⌘1` en el panel web |
97
+ | `colorDot` | no hay «favoritos» ni etiquetas de color | proyectos o locales favoritos fijados por la persona |
98
+ | `profileDropdown` | el perfil se abre desde «Cuenta» | si el perfil pasa a tener menú propio (cambiar cuenta, idioma) |
99
+ | feature card (`[feature-card]`) | no hay promo dentro de la navegación | invitar a mejorar el plan en el panel de empresa |
100
+ | `showBackdrop` en `false` | sin fondo, el cajón parece pegado a la página | nunca en mobile |
101
+
102
+ ## API
103
+
104
+ <!-- api:inicio -->
105
+ <!-- generada: no editar a mano — `npm run docs` -->
106
+
107
+ | input | tipo | default |
108
+ |---|---|---|
109
+ | `collapsed` | `boolean` | `false` |
110
+ | `indicatorColor` | `'information' \| 'brand'` | `'brand'` |
111
+ | `brand` | `SuiSidebarBrandConfig \| null` | `null` |
112
+ | `showHeaderButton` | `boolean` | `false` |
113
+ | `headerButtonActive` | `boolean` | `false` |
114
+ | `search` | `SuiSidebarSearchConfig \| boolean \| null` | `false` |
115
+ | `searchValue` · model, `[(searchValue)]` | `string` | `''` |
116
+ | `items` | `SuiSidebarItem[]` | `[]` |
117
+ | `secondaryItems` | `SuiSidebarItem[]` | `[]` |
118
+ | `supportingItems` | `SuiSidebarItem[]` | `[]` |
119
+ | `supportingAnchorBottom` | `boolean` | `true` |
120
+ | `itemsLabel` | `string \| null` | `null` |
121
+ | `secondaryItemsLabel` | `string \| null` | `null` |
122
+ | `supportingItemsLabel` | `string \| null` | `null` |
123
+ | `activeRoute` | `string \| null` | `null` |
124
+ | `profile` | `SuiSidebarProfile \| null` | `null` |
125
+ | `profileDropdown` | `boolean` | `false` |
126
+ | `mobileOpen` · model, `[(mobileOpen)]` | `boolean` | `false` |
127
+ | `closeOnItemClick` | `boolean` | `true` |
128
+ | `showBackdrop` | `boolean` | `true` |
129
+ | `mobileMode` | `'drawer' \| 'sheet'` | `'drawer'` |
130
+
131
+ | output | payload |
132
+ |---|---|
133
+ | `itemClicked` | `SuiSidebarItem` |
134
+ | `logoutClicked` | `void` |
135
+ | `backdropClicked` | `void` |
136
+ | `headerButtonClicked` | `void` |
137
+ | `profileClicked` | `void` |
138
+ | `searchSubmitted` | `string` |
139
+ <!-- api:fin -->
140
+
141
+ ```ts
142
+ interface SuiSidebarItem {
143
+ value: string; // lo emite (itemClicked)
144
+ label: string;
145
+ icon?: string; // RemixIcon sin 'ri-'
146
+ route?: string; // routerLink; sin route solo emite
147
+ external?: boolean;
148
+ variant?: 'default' | 'danger';
149
+ action?: 'logout' | string; // cualquier action anula el route
150
+ badge?: string | number;
151
+ shortcut?: string;
152
+ colorDot?: string; // reemplaza el ícono por un punto de color
153
+ tooltip?: string; // tooltip en colapsado; default = label
154
+ }
155
+ interface SuiSidebarBrandConfig { name: string; subtitle?: string; subtitleAsBadge?: boolean; logo?: string; fallback?: string; }
156
+ interface SuiSidebarSearchConfig { placeholder?: string; shortcut?: string; }
157
+ interface SuiSidebarProfile { name: string; avatarUrl?: string; initials?: string; status?: SuiAvatarStatus; email?: string; verified?: boolean; }
158
+ ```
159
+
160
+ Slots: `[header-panel]` (debajo del header: el switcher), `[feature-card]` (al fondo del contenido).
161
+
162
+ ## Trampas
163
+
164
+ - **El cajón no se cierra solo al navegar desde afuera.** Se cierra con el fondo, Escape y el toque
165
+ en un item; cualquier otra navegación (atrás, un push, `router.navigate`, una ruta cacheada que
166
+ vuelve) lo deja abierto tapando la página siguiente. Mientras el DS no traiga `closeOnNavigate`,
167
+ cada layout llama `cerrarAlNavegar(menuAbierto, switcherAbierto)`
168
+ (`core/services/cerrar-al-navegar.ts`). Canon: CANON-SUI §1.1.
169
+ - **El buscador no filtra nada.** Solo expone `[(searchValue)]` y `(searchSubmitted)`; el layout
170
+ filtra los items (`master-layout.ts:125`). Su placeholder por defecto es «Buscar…» (en español desde el 04-10-2026).
171
+ - **`collapsed` no mira el viewport.** Con `collapsed` en `true`, el cajón de mobile también sale
172
+ de 80 px. Condiciónalo: `[collapsed]="colapsado() && !bp.isMobile()"`.
173
+ - Un item con `route` queda activo por `routerLinkActive` **y** por `activeRoute`; un item sin
174
+ `route` solo por `activeRoute` (por `value` exacto). Si no pasas `activeRoute`, los items-acción
175
+ nunca se marcan.
176
+ - Cualquier `action` (no solo `'logout'`) anula el `route`: el item no navega.
177
+ - El `title` nativo del host se borra (sin tooltip gris); en colapsado el tooltip va en cada item.
178
+ - El cajón tiene `z-index: 300` sobre la barra inferior (200). Mientras está abierto el layout
179
+ esconde la barra (`customer-layout.ts:66`); si armas un layout nuevo, haz lo mismo.
180
+ - El comentario de cabecera del `.ts` todavía dice 240 px; el ancho real es 272 (`sui-sidebar.scss:50`).
181
+ - Los items ya traen el arreglo de iOS del `:active` pegado: no lo agregues.
182
+
183
+ ## Ejemplo
184
+
185
+ ```html
186
+ <sui-sidebar
187
+ [brand]="{ name: 'Master Pedidos', subtitle: 'Repartidor', logo: 'assets/app-icon.png', fallback: 'M' }"
188
+ [showHeaderButton]="true"
189
+ [headerButtonActive]="switcherOpen()"
190
+ (headerButtonClicked)="switcherOpen.set(!switcherOpen())"
191
+ [search]="{ placeholder: 'Buscar...', shortcut: '⌘K' }"
192
+ [(searchValue)]="busqueda"
193
+ itemsLabel="Operación" [items]="items()"
194
+ secondaryItemsLabel="Dinero" [secondaryItems]="itemsDinero()"
195
+ supportingItemsLabel="Cuenta" [supportingItems]="itemsCuenta()"
196
+ [activeRoute]="currentUrl()"
197
+ [profile]="perfil()"
198
+ [(mobileOpen)]="menuAbierto"
199
+ [closeOnItemClick]="true"
200
+ (logoutClicked)="logout()">
201
+ @if (switcherOpen()) {
202
+ <div header-panel role="listbox" aria-label="Cambiar de rol">
203
+ @for (rol of roles; track rol.value) {
204
+ <sui-dropdown-item [label]="rol.label" [sublabel]="rol.sublabel" mode="option" size="large"
205
+ (clicked)="irARol(rol)" />
206
+ }
207
+ </div>
208
+ }
209
+ </sui-sidebar>
210
+ ```
211
+
212
+ ```ts
213
+ constructor() {
214
+ cerrarAlNavegar(this.menuAbierto, this.switcherOpen); // mientras el DS no cierre solo
215
+ }
216
+ ```
@@ -57,6 +57,8 @@ Regla corta: **escala con tope y la posición importa → slider · número exac
57
57
 
58
58
  - **1 con `amount` y `tooltip` a la vez:** `components/driver-coverage-modal/driver-coverage-modal.html:83`
59
59
  muestra «12 km» arriba y «12» flotando al arrastrar.
60
+ - **El mismo uso va sin `size`** (`medium`: manija 16, riel 6) en una pantalla del repartidor, que
61
+ se usa en el teléfono: rompe la tabla de «Tamaño en mobile y en web» (`large` en mobile).
60
62
  - **1 nativo → `sui-slider`:** `components/image-cropper/image-cropper.html:57` (zoom del recorte).
61
63
  A discutir: es un control de herramienta sin label, con botones − y + al lado.
62
64
 
@@ -102,6 +104,8 @@ contenedor tiene que tener margen lateral.
102
104
  | `label` | `string` | `''` |
103
105
  | `sublabel` | `string` | `''` |
104
106
  | `amount` | `string \| null` | `null` |
107
+ | `unit` | `string \| null` | `null` |
108
+ | `ariaLabel` | `string \| null` | `null` |
105
109
  | `tooltip` | `boolean` | `false` |
106
110
  | `tooltipAlways` | `boolean` | `false` |
107
111
  | `disabled` | `boolean` | `false` |
@@ -130,6 +134,9 @@ Implementa `ControlValueAccessor` **solo para `single`**.
130
134
  - Mide el ancho con el DOM: si arranca oculto (`display: none`, una pestaña cerrada) el arrastre
131
135
  calcula mal hasta que se muestra.
132
136
  - Las flechas, Inicio y Fin lo mueven con teclado.
137
+ - **Accesibilidad (04-10-2026)**: el `label` visible nombra la manija; sin label, pasa `ariaLabel`.
138
+ El lector lee el valor con su unidad: en single, el texto de `amount` («12 km»); en range (o sin
139
+ `amount`), el número + `unit`. En range cada manija se anuncia «<label>, mínimo» / «…, máximo».
133
140
 
134
141
  ## Ejemplo
135
142
 
@@ -78,26 +78,38 @@ otra marca: hoy Google y Apple.
78
78
 
79
79
  ## Tamaño en mobile y en web
80
80
 
81
- En mobile se toca con el dedo: el área táctil tiene que medir **44 px o más**. En web, con mouse,
82
- va un tamaño más chico. La app ya lo resuelve con `BreakpointsService`
83
- (`src/app/services/breakpoints.service.ts`, mobile = hasta 767 px):
84
- `[size]="bp.isMobile() ? 'large' : 'small'"`, 27 usos hoy en `master-pedidos` (16 `large`/`small`,
85
- 9 `large`/`medium`, 2 `medium`/`xsmall`). Regla del dueño, 03-10-2026.
81
+ En mobile se toca con el dedo: el área táctil tiene que medir **44 px o más** (canon (dueño, 04-10-2026): piso táctil 44 en el teléfono). En web,
82
+ con mouse, va un tamaño más chico. La app ya lo resuelve con `BreakpointsService`
83
+ (`src/app/services/breakpoints.service.ts`, mobile = hasta 767 px).
84
+
85
+ | size | alto | texto | solo ícono | fuente |
86
+ |---|---|---|---|---|
87
+ | `large` | 48 | 16 (Label/Medium) | 48 × 48 | canon (dueño, 04-10-2026): piso táctil 44 en el teléfono. Size nuevo del 04-10-2026 |
88
+ | `medium` (default) | 40 | 14 | 40 × 40 | Figma |
89
+
90
+ **Por qué `large` = 48 y no 44**: el social-button es «el mismo botón con otro acabado» que
91
+ `sui-button` y su único tamaño (40) es el `medium` de sui-button. El siguiente de esa escala es
92
+ `large`, que mide 48: en el login queda del mismo alto que el CTA de al lado. El texto sube a 16
93
+ (regla de tamaños del 03-10-2026); el logo sigue en 20.
86
94
 
87
95
  | uso | mobile | web | fuente |
88
96
  |---|---|---|---|
89
- | login con Google o Apple | 40 de alto, **ancho completo** (`width: 100%`) | 40 de alto, ancho del formulario | propuesta (es lo que ya hace `pages/auth/login/login.html` con `.auth-page__provider-btn`) |
97
+ | login con Google o Apple | `large` (48), **ancho completo** (`width: 100%`) | `medium` (40), ancho del formulario | canon (dueño, 04-10-2026): piso táctil 44 en el teléfono (alto) · propuesta (ancho, es lo que ya hace `pages/auth/login/login.html` con `.auth-page__provider-btn`) |
98
+
99
+ ```html
100
+ <sui-social-button brand="google" variantStyle="stroke" style="width: 100%"
101
+ [size]="bp.isMobile() ? 'large' : 'medium'" (clicked)="loginGoogle()" />
102
+ ```
90
103
 
91
104
  **Ancho completo**: `width: 100%` en el host estira el botón (arreglado en el DS el 03-10-2026 con
92
105
  `flex: 1 1 auto` en `.sui-social-button__el`; antes el host medía 360 y el botón 193). Sin
93
- `width` sigue midiendo lo que su texto, como siempre. Con `onlyIcon` el cuadrado de 40 no se
106
+ `width` sigue midiendo lo que su texto, como siempre. Con `onlyIcon` el cuadrado (40 o 48) no se
94
107
  estira nunca. El host sigue siendo `inline-flex`: para el ancho completo va `width: 100%`, no
95
108
  `display: block`. El `::ng-deep .sui-social-button__el { width: 100% }` de
96
109
  `pages/auth/auth-shared.scss` queda de más con la versión que trae el arreglo.
97
110
 
98
- No tiene input `size`: mide siempre 40 de alto. En mobile no llega a 44; lo compensa el ancho
99
- completo (el dedo no puede errarle) y 12 px de separación entre los dos botones. Si un día hace
100
- falta más alto, se pide al DS un `size`, no se estira con CSS (el logo y el padding no escalan).
111
+ No se estira el alto con CSS desde afuera: el logo y el padding no escalan. Para el teléfono va
112
+ `size="large"`.
101
113
 
102
114
  ## «No usar»: por qué no hoy y cuándo sí
103
115
 
@@ -119,6 +131,7 @@ en la columna de la derecha, se usa (aprobado por el dueño, 03-10-2026).
119
131
  | `brand` | `'apple' \| 'x-twitter' \| 'google' \| 'facebook' \| 'linkedin' \| 'github' \| 'dropbox'` | — (requerido) |
120
132
  | `variantStyle` | `'filled' \| 'stroke'` | `'filled'` |
121
133
  | `onlyIcon` | `boolean` | `false` |
134
+ | `size` | `'medium' \| 'large'` | `'medium'` |
122
135
  | `label` | `string \| null` | `null` |
123
136
  | `disabled` | `boolean` | `false` |
124
137
  | `loading` | `boolean` | `false` |
@@ -139,7 +152,7 @@ en la columna de la derecha, se usa (aprobado por el dueño, 03-10-2026).
139
152
  sale rojo lleno. Para el login de Google hay que pasar `variantStyle="stroke"`.
140
153
  - **El estilo se llama `variantStyle`** (en la guía, `mode`) y **X se llama `x-twitter`** (en la
141
154
  guía, `twitter`).
142
- - **No tiene `size`**: mide 40 px de alto. Con `width: 100%` en el host el botón se estira al ancho completo (arreglado en el DS el 03-10-2026; antes no estiraba). El de solo ícono queda en 40 × 40.
155
+ - **`size` va de `medium` (40, default) a `large` (48, para el teléfono, 04-10-2026).** Con `width: 100%` en el host el botón se estira al ancho completo (arreglado en el DS el 03-10-2026; antes no estiraba). El de solo ícono queda en 40 × 40 (48 × 48 en `large`).
143
156
  - **`loading` también deshabilita**: no emite `(clicked)` mientras está en `true`.
144
157
  - El logo es una imagen distinta por tema: en modo oscuro, Apple, X y GitHub en `stroke` usan el
145
158
  logo blanco para no perderse. El componente lo resuelve solo leyendo `data-theme`.
@@ -109,8 +109,11 @@ de la app.
109
109
  | `large` | 28 px | `label-sm` 14/20 | 16 (20) | 8 |
110
110
  | `xlarge` | 32 px | `label-md` 16/24 | 20 (24) | 8 |
111
111
 
112
- `medium` es el de Figma; `large` y `xlarge` son extensión SUI (03-10-2026). Siguen la escala del
113
- `sui-button` (28 · 32) y no la del `sui-badge` (24 · 28), porque el status-badge ya parte de 24.
112
+ `medium` es el de Figma; `large` y `xlarge` son extensión SUI (03-10-2026). El **alto** sigue la
113
+ escala del `sui-button` (28 · 32) y no la del `sui-badge` (24 · 28), porque el status-badge ya
114
+ parte de 24. El **texto** sigue al `sui-badge` (14 en `large`, 16 en `xlarge`) y no la regla
115
+ general del 03-10-2026 (16 en los dos): excepción documentada, canon (dueño, 04-10-2026) — la
116
+ escala de badge (12/14/16) se mantiene. No es táctil: no tiene foco ni output.
114
117
 
115
118
  | uso | mobile | web | fuente |
116
119
  |---|---|---|---|
@@ -150,7 +153,8 @@ Slot: `<ng-content>` (el texto).
150
153
  - Tamaños: `medium` 24 (default, Figma), `large` 28 y `xlarge` 32 para mobile (extensión SUI, 03-10-2026). No hay uno más chico que 24.
151
154
  - **No pasa a mayúsculas** (el `sui-badge` small sí).
152
155
  - `icon` no hace nada con `withDot`.
153
- - El punto mide 6 px; el del `sui-badge with-dot`, 4 px. Son distintos a propósito.
156
+ - El punto mide 6 px en `medium` y 8 en `large`/`xlarge`; el del `sui-badge with-dot`, 4 px. Son
157
+ distintos a propósito.
154
158
  - El host lleva `role="status"`: el lector de pantalla anuncia los cambios.
155
159
 
156
160
  ## Ejemplo
@@ -26,7 +26,8 @@ Vehículo → Listo»).
26
26
  - Secciones que se visitan en cualquier orden: `sui-tab-menu-horizontal`.
27
27
  - Un solo paso: no hay nada que indicar.
28
28
 
29
- Regla corta: **pasos con nombre y orden → stepper · porcentaje → progress-bar · secciones sin orden → tab menu.**
29
+ Regla corta (propuesta, falta aprobación): **pasos con nombre y orden → stepper · porcentaje →
30
+ progress-bar · secciones sin orden → tab menu.**
30
31
 
31
32
  ## Qué variante usar
32
33
 
@@ -35,9 +36,11 @@ Regla corta: **pasos con nombre y orden → stepper · porcentaje → progress-b
35
36
  > procesos secuenciales». El **vertical**, el mismo indicador «para layouts diversos», con una
36
37
  > flecha en el paso activo. Estados de cada paso: `default`, `active`, `completed`. No trae do/don't.
37
38
  >
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.
39
+ > Uso medido el 04-10-2026 en `master-pedidos/src/app` (misma exclusión que `sui-badge`):
40
+ > **8 usos en 8 archivos**. 7 en los onboardings: todos `variant="horizontal"`, sin `size`
41
+ > (`small`), sin `interactive`, de 2 o 3 pasos. 1 en el home del cliente:
42
+ > `pages/customer/store-browser/store-browser.html:214`, `variant="dot"`, `size="medium"`,
43
+ > `[interactive]="true"` (paginador de los rubros, desde el 03-10-2026).
41
44
 
42
45
  ### `variant`
43
46
 
@@ -45,7 +48,7 @@ Regla corta: **pasos con nombre y orden → stepper · porcentaje → progress-b
45
48
  |---|---|---|---|
46
49
  | `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
50
  | `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) |
51
+ | `dot` | Pantallas que se pasan de a una sin nombre: carrusel de bienvenida, fotos. | `pages/customer/store-browser/store-browser.html:214` (páginas de rubros del home) | según la guía del DS (puntos de carrusel) |
49
52
 
50
53
  ### `size`
51
54
 
@@ -53,7 +56,7 @@ Regla corta: **pasos con nombre y orden → stepper · porcentaje → progress-b
53
56
  |---|---|---|---|
54
57
  | `small` (default) | punto de 8 · indicador de 20 · texto 14 | Web. | según la guía del DS (`small` es su default) |
55
58
  | `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) |
59
+ | `medium` | punto de 10 · indicador de 24 · texto 16 · card vertical de 44 | Mobile. Publicado desde la 0.20.0 (la app usa la 0.22.0). | canon (dueño: tamaño por plataforma, 03-10-2026) |
57
60
 
58
61
  ### Estado de cada paso (`currentStep`, `errorStep`)
59
62
 
@@ -70,7 +73,7 @@ Regla corta: **pasos con nombre y orden → stepper · porcentaje → progress-b
70
73
  | valor | cuándo | fuente |
71
74
  |---|---|---|
72
75
  | `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 |
76
+ | `true` | Los puntos de un carrusel (en el teléfono se tocan en 44 de alto, ver Tamaño), o pasos hechos que se pueden **volver a editar** en web (el horizontal mide 24 de alto). | propuesta, falta aprobación |
74
77
 
75
78
  ### `steps`, `count`, `ariaLabel`
76
79
 
@@ -82,11 +85,14 @@ Regla corta: **pasos con nombre y orden → stepper · porcentaje → progress-b
82
85
 
83
86
  **Usos de hoy que rompen las reglas:**
84
87
 
85
- - **0 de variante o estado**: los 7 son horizontales de 2 o 3 pasos, y `step-complete` usa
88
+ - **0 de variante o estado** en los onboardings: los 7 son horizontales de 2 o 3 pasos, y `step-complete` usa
86
89
  `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:
90
+ - **7 sin tamaño por plataforma** (`medium` ya está publicado): los onboardings se hacen en el
91
+ teléfono y van con `[size]="bp.isMobile() ? 'medium' : 'small'"`. Ejemplos:
89
92
  `pages/customer-onboarding/step-phone/step-phone.html:3`, `pages/business-onboarding/step-info/step-info.html:3`.
93
+ - **A discutir, 1 `interactive` en mobile:** `pages/customer/store-browser/store-browser.html:214`
94
+ usa los puntos `medium` como paginador tocable en el home del cliente. Desde el 04-10-2026 cada
95
+ punto se toca en 22 × 44 en el teléfono (ver Tamaño); el dibujo sigue de 10 × 10.
90
96
 
91
97
  ## Tamaño en mobile y en web
92
98
 
@@ -94,25 +100,29 @@ Regla corta: **pasos con nombre y orden → stepper · porcentaje → progress-b
94
100
  |---|---|---|---|
95
101
  | 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
102
  | 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 |
103
+ | puntos de carrusel | `medium` (10, se toca en 22 × 44) | `small` (8) | tamaño: propuesta, falta aprobación · área de 44: canon (dueño, 04-10-2026): piso táctil 44 en el teléfono |
98
104
 
99
105
  ```html
100
106
  <sui-stepper [steps]="pasos" [currentStep]="paso - 1" [size]="bp.isMobile() ? 'medium' : 'small'" />
101
107
  ```
102
108
 
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.
109
+ Sin `interactive` el tamaño solo afecta lo que se lee. Con `interactive`, en el teléfono
110
+ (≤ 767 px) **los puntos se tocan en 44 de alto** (canon (dueño, 04-10-2026): piso táctil 44 en el teléfono): un `::before` invisible
111
+ los estira a 44 de alto y, de ancho, hasta la mitad del espacio con el vecino, para que dos áreas
112
+ nunca se pisen: `medium` 22 × 44, `small` 18 × 44, `xsmall` 10 × 44. El dibujo no cambia. No se
113
+ agregó un size que separe los puntos: cambiaría el paginador, y lo que faltaba era alto. El
114
+ horizontal sigue en 24 de alto con `medium`: con `interactive` queda para web. La card vertical `medium` sí llega a 44 (padding 10 + 24 + padding 10).
115
+ Alto de cada pieza: horizontal `small` 20 y `medium` 24 (el indicador; la línea del texto mide lo
116
+ mismo) · puntos 4 / 8 / 10 · card vertical `small` 36 (8 + 20 + 8) y `medium` 44.
106
117
 
107
118
  ## «No usar»: por qué no hoy y cuándo sí
108
119
 
109
120
  | qué | por qué no hoy | cuándo sí, en un flujo nuevo |
110
121
  |---|---|---|
111
122
  | `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
123
  | `xsmall` | no hay puntos sobre fotos | puntos sobre el banner del carrusel del home |
114
124
  | `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 |
125
+ | `interactive` | en los onboardings se avanza con el botón (el único uso, en el home del cliente, está a discutir arriba) | un formulario largo en web donde se vuelve a corregir un paso hecho |
116
126
 
117
127
  ## API
118
128
 
@@ -140,7 +150,7 @@ interface SuiStepperItem {
140
150
  label?: string; // sin label sale «Paso N»
141
151
  }
142
152
  type SuiStepperVariant = 'dot' | 'horizontal' | 'vertical';
143
- type SuiStepperSize = 'small' | 'xsmall' | 'medium'; // medium: repo del DS, no en 0.19.0
153
+ type SuiStepperSize = 'small' | 'xsmall' | 'medium'; // medium: extensión SUI (03-10-2026)
144
154
  ```
145
155
 
146
156
  ## Trampas
@@ -152,6 +162,9 @@ type SuiStepperSize = 'small' | 'xsmall' | 'medium'; // medium: repo del DS, n
152
162
  - **El horizontal hace `flex-wrap`**: con muchos pasos o nombres largos baja a otra línea en vez de
153
163
  cortarse. Con 4+ pasos en mobile, revisa a 390 px.
154
164
  - **`stepClick` solo sale con `interactive`**; sin él los pasos son `div` y no responden.
165
+ - **Rol del host (04-10-2026):** sin `interactive` es `role="list"` con hijos `listitem`; con
166
+ `interactive` los pasos son `<button>` (no pueden ser `listitem`), así que el host pasa a
167
+ `role="group"` con su `ariaLabel`. El paso actual lleva `aria-current="step"` en los dos casos.
155
168
  - `errorStep` gana sobre `currentStep`: los anteriores quedan hechos y los siguientes por hacer.
156
169
  - El activo usa `--sui-primary-base`, que en la app es naranja.
157
170
 
@@ -68,17 +68,22 @@ El ancho lo da el contenedor. El `size` cambia **el corazón de favorito**, en l
68
68
  |---|---|---|---|
69
69
  | `small` (default) | 36 × 36 | 18 | lo que había en el DS |
70
70
  | `medium` | 40 × 40 | 20 | canon (aprobado por el dueño, 03-10-2026): extensión SUI |
71
+ | `large` | 44 × 44 | 20 | canon (dueño, 04-10-2026): piso táctil 44 en el teléfono. Size nuevo del 04-10-2026; además la nota se toca en 44 de alto |
71
72
 
72
73
  | uso | mobile | web | fuente |
73
74
  |---|---|---|---|
74
75
  | tarjeta | ancho completo | celda de una grilla de 2–3 columnas (≥ 300 de ancho) | lo que hay en la app |
75
- | corazón de favorito | `medium` (40) | `small` (36) | propuesta: el tamaño es extensión SUI aprobada (03-10-2026); el «cuándo» falta aprobarlo |
76
- | nota (abre las opiniones) | el alto de su columna (~40) | ~40 | lo que hay en el DS |
76
+ | corazón de favorito | `large` (44) | `small` (36) | canon (dueño, 04-10-2026): piso táctil 44 en el teléfono |
77
+ | nota (abre las opiniones) | `large`: se ve igual (≈ 38) y se toca en 44 de alto con un `::before` invisible que no se estira a los lados (no pisa la columna de al lado) | ≈ 38: padding 4 × 2 + etiqueta de 10 px + gap 2 + valor de 13 px, con el `line-height` heredado | canon (dueño, 04-10-2026): piso táctil 44 en el teléfono (área) · medido del `.scss` (alto visible) |
77
78
 
78
79
  ```html
79
- <sui-store-card [store]="local" [size]="bp.isMobile() ? 'medium' : 'small'" />
80
+ <sui-store-card [store]="local" [size]="bp.isMobile() ? 'large' : 'small'" />
80
81
  ```
81
82
 
83
+ `medium` (40) queda para quien ya lo usa: no llega al piso de 44. **Favoritos no pasa `size`**
84
+ (`pages/customer/favorites/favorites.html`): en el teléfono el corazón queda en 36 hasta que la
85
+ app le pase `[size]="bp.isMobile() ? 'large' : 'small'"` (cambio de la app, no del DS).
86
+
82
87
  ## «No usar»: por qué no hoy y cuándo sí
83
88
 
84
89
  | qué | por qué no hoy | cuándo sí, en un flujo nuevo |
@@ -97,7 +102,7 @@ El ancho lo da el contenedor. El `size` cambia **el corazón de favorito**, en l
97
102
  | `isFavorite` | `boolean` | `false` |
98
103
  | `disableLink` | `boolean` | `false` |
99
104
  | `linkBase` | `string` | `'/cliente/restaurante'` |
100
- | `size` | `'small' \| 'medium'` | `'small'` |
105
+ | `size` | `'small' \| 'medium' \| 'large'` | `'small'` |
101
106
  | `deliveryText` | `string \| null` | `undefined` |
102
107
  | `distanceText` | `string \| null` | `undefined` |
103
108
 
@@ -22,7 +22,7 @@ propio título (día de la semana, tarjeta de la oferta).
22
22
  descripción y el toque en toda la fila.
23
23
  - Un valor de formulario que se confirma con «Guardar»: `sui-checkbox`. (Excepción aceptada hoy:
24
24
  los formularios de producto y de planes usan switch para «disponible»/«activo» aunque se guarden
25
- después; es el patrón que la persona reconoce.)
25
+ después; es el patrón que la persona reconoce. Propuesta, falta aprobación.)
26
26
  - Algo destructivo o que no se deshace: el switch promete que se puede volver atrás al toque.
27
27
  - Elegir entre dos modos con nombre: `sui-segmented-control` si se aplica al instante (cuadrícula /
28
28
  lista); `sui-radio-card` si se guarda después («Por distancia» / «Precio único» en ajustes).
@@ -64,24 +64,24 @@ Regla corta: **se aplica ya → switch · se confirma después → checkbox · d
64
64
  **Usos de hoy que rompen las reglas:**
65
65
 
66
66
  - **19 switches con su texto armado a mano → `sui-switch-label`.** Ejemplos:
67
- `pages/discounts/discounts.html:198` («Un uso por cliente», con `sui-form-label` + `<span>`),
67
+ `pages/discounts/discounts.html:207` («Un uso por cliente», con `sui-form-label` + `<span>`),
68
68
  `pages/drivers/drivers.html:58` («Aceptar pedidos automáticamente»),
69
- `pages/super-admin/master-plans/master-plans.html:90` («Plan activo», y 8 más en ese archivo).
70
- El resto: `discounts.html:302`, `pages/super-admin/master-map-overview/master-map-overview.html:67`,
71
- `pages/schedule/schedule.html:46`, `components/add-product-modal/add-product-modal.html:196`, `:255`, `:280`,
72
- `components/option-sections-manager/option-sections-manager.html:107`, `:123`.
69
+ `pages/super-admin/master-plans/master-plans.html:92` («Plan activo», y 8 más en ese archivo).
70
+ El resto: `discounts.html:319`, `pages/super-admin/master-map-overview/master-map-overview.html:67`,
71
+ `pages/schedule/schedule.html:46`, `components/add-product-modal/add-product-modal.html:205`, `:264`, `:289`,
72
+ `components/option-sections-manager/option-sections-manager.html:107`, `:125`.
73
73
  - **3 con la etiqueta que repite el estado** («Disponible» / «No disponible», «Activo»):
74
- `components/option-sections-manager/option-sections-manager.html:143`,
75
- `components/add-product-modal/add-product-modal.html:303`, `pages/employees/employees.html:99`.
74
+ `components/option-sections-manager/option-sections-manager.html:145`,
75
+ `components/add-product-modal/add-product-modal.html:312`, `pages/employees/employees.html:99`.
76
76
  - **2 en `medium` (sin `size`):** `pages/drivers/drivers.html:58`,
77
77
  `pages/super-admin/master-map-overview/master-map-overview.html:67`.
78
78
  - **1 nativo dibujado como switch:** `components/settings-panel/settings-panel.html:97`
79
79
  («Notificaciones Push») → `sui-switch-label`.
80
80
 
81
- Bien pelados (el texto vive en la fila o la tabla): `pages/discounts/discounts.html:96` (columna
82
- de la tabla), `pages/super-admin/master-settings/master-settings.html:103`, los días de
81
+ Bien pelados (el texto vive en la fila o la tabla): `pages/discounts/discounts.html:98` (columna
82
+ de la tabla), `pages/super-admin/master-settings/master-settings.html:105`, los días de
83
83
  `components/weekly-schedule-editor/weekly-schedule-editor.html:5` y
84
- `pages/driver/driver-schedule/driver-schedule.html:108`, `pages/central/central-ofertas/central-ofertas.html:19`.
84
+ `pages/driver/driver-schedule/driver-schedule.html:106`, `pages/central/central-ofertas/central-ofertas.html:19`.
85
85
 
86
86
  ## Tamaño en mobile y en web
87
87
 
@@ -114,6 +114,7 @@ va `sui-switch-label`, que hace tocable todo el bloque.
114
114
  | `size` | `'medium' \| 'large' \| 'xlarge'` | `'medium'` |
115
115
  | `checked` | `boolean` | `false` |
116
116
  | `disabled` | `boolean` | `false` |
117
+ | `focusable` | `boolean` | `true` |
117
118
 
118
119
  | output | payload |
119
120
  |---|---|
@@ -131,6 +132,10 @@ Implementa `ControlValueAccessor` (`[(ngModel)]`, `formControlName`).
131
132
  mezcles las dos formas.
132
133
  - `disabled` no baja la opacidad: cambia el color y achica el círculo. Un `opacity` encima lo duplica.
133
134
  - No tiene `aria-label`: pelado, pásalo con `[attr.aria-label]` (como en `central-ofertas`).
135
+ Dentro de `sui-switch-label`, `sui-switch-card`, `sui-integration-switch` y el toggle de
136
+ `sui-content-label` ya toma el nombre del texto con `aria-labelledby` (revisión 04-10-2026).
137
+ - **`[focusable]="false"` lo saca del Tab** (tabindex -1), para cuando un padre es el control
138
+ enfocable. `tabindex="-1"` en el host no sirve: el binding del componente lo pisa.
134
139
  - Ya trae el arreglo de iOS para el `:active` pegado.
135
140
 
136
141
  ## Ejemplo
@@ -17,7 +17,8 @@ su propia tarjeta: «Notificaciones», «Ubicación siempre», «Recibir pedidos
17
17
 
18
18
  **No lo uses** para:
19
19
 
20
- - Algo que se confirma después con «Guardar»: `sui-checkbox-card` (canon del switch-label).
20
+ - Algo que se confirma después con «Guardar»: `sui-checkbox-card` (según la guía del DS: el switch
21
+ es «para prender o apagar un ajuste de forma inmediata»).
21
22
  - Una lista larga de ajustes parecidos: `sui-switch-label` con `flip`, uno por fila.
22
23
  - Una integración con otro servicio (logo + «Administrar»): `sui-integration-switch`.
23
24
  - Algo destructivo o que no se deshace: un botón con confirmación.
@@ -30,16 +31,16 @@ Regla corta: **ajuste con peso, al toque → switch-card · lista de ajustes →
30
31
  > **La guía del DS no tiene página de la switch card.** De la guía sale lo del switch que lleva
31
32
  > adentro: **«para prender o apagar un ajuste de forma inmediata»**.
32
33
  >
33
- > Uso medido el 03-10-2026 en `master-pedidos/src/app` (misma exclusión que `sui-card`): **26
34
- > switch-cards en 8 archivos**. Tipos: 19 `left-icon` (los 19 con el ícono proyectado), 7 `basic`
35
- > (5 de ellos sin `type`). Tamaños: 20 `bp.controlSize()`, 6 sin `size`. 10 viven en formularios
36
- > que se guardan con un botón.
34
+ > Uso medido el 04-10-2026 en `master-pedidos/src/app` (misma exclusión que `sui-card`): **16
35
+ > switch-cards en 8 archivos**. Tipos: 14 `left-icon` (los 14 con el ícono proyectado), 2 `basic`.
36
+ > Tamaños: los 16 con `bp.controlSize()`. Ninguna vive ya en un formulario que se guarda con un
37
+ > botón: las 10 que lo hacían pasaron a `sui-checkbox-card` el 03-10-2026.
37
38
 
38
39
  ### `type` (el leading)
39
40
 
40
41
  | type | cuándo | fuente |
41
42
  |---|---|---|
42
- | `left-icon` + ícono proyectado | Lo normal: `<sui-icon sui-switch-card-leading name="…" [size]="20" />`. | propuesta (19 de 26) |
43
+ | `left-icon` + ícono proyectado | Lo normal: `<sui-icon sui-switch-card-leading name="…" [size]="20" />`. | propuesta (14 de 16) |
43
44
  | `left-icon` + `emoji` | Ver «No usar». | propuesta |
44
45
  | `basic` | El ajuste es EL tema de la pantalla y no necesita ícono («Disponible» en el inicio del repartidor, «Disponibilidad automática»). | propuesta |
45
46
  | `avatar` (`imageUrl`) | Ver «No usar». | propuesta |
@@ -64,19 +65,16 @@ Regla corta: **ajuste con peso, al toque → switch-card · lista de ajustes →
64
65
  | `large` (40 × 24) | Desktop, vía `bp.controlSize()`. | canon (aprobado por el dueño, 28-09-2026) |
65
66
  | `medium` (default) | No usar en pantallas nuevas. | canon (aprobado por el dueño, 28-09-2026) |
66
67
 
67
- **Usos de hoy que rompen las reglas:**
68
-
69
- - **10 switch-cards en formularios que se guardan con un botón** (van `sui-checkbox-card`): los 5
70
- métodos de pago de `pages/mi-negocio/mi-negocio.html:1181`–`:1217` («Guardar cambios») y 5 de
71
- `pages/super-admin/master-settings/master-settings.html` (`:36` «Pausar los pedidos», `:179`,
72
- `:336`, `:342`, `:349`, cada uno con su «Guardar…» abajo).
73
- - **6 sin `size`**: los 5 de `master-settings` de arriba y `pages/notifications/notifications.html:59`
74
- («Sonidos de la app»).
68
+ **Usos de hoy que rompen las reglas: 0.** Los 10 que se guardaban con un botón (métodos de pago
69
+ de mi-negocio y 5 ajustes de master-settings) pasaron a `sui-checkbox-card`, y el de
70
+ `pages/notifications/notifications.html:59` («Sonidos de la app») ya lleva `bp.controlSize()`,
71
+ los dos el 03-10-2026.
75
72
 
76
73
  ## Tamaño en mobile y en web
77
74
 
78
- La card entera se toca (≥ 72 con descripción): llega al piso de 44 sola. El `size` cambia solo el
79
- interruptor.
75
+ La card entera se toca: 74 px con descripción (16 + 40 + 16 de padding y contenido, más 2 de
76
+ borde) y 54 px la más chica (`basic`, sin descripción, `medium`). Llega al piso de 44 sola. El
77
+ `size` cambia solo el interruptor.
80
78
 
81
79
  | uso | mobile | web |
82
80
  |---|---|---|
@@ -130,6 +128,10 @@ Slot: `[sui-switch-card-leading]` (el ícono o el logo). Implementa `ControlValu
130
128
  - `avatar` siempre dibuja un `sui-avatar` con `imageUrl` (si falla, las iniciales del `label`): no usa lo
131
129
  proyectado. `card-provider`, `brand` y `company` leen `imageUrl` y, sin ella, usan lo proyectado.
132
130
  - Toda la card togglea; el toque sobre el propio switch no cuenta doble.
131
+ - **Teclado**: el único tab stop es el switch de la derecha, con nombre = `label` y descripción =
132
+ `description` (`aria-labelledby` / `aria-describedby`). Espacio y Enter emiten
133
+ `checkedChange` **una vez** (revisión 04-10-2026); antes emitían dos (el switch y, por burbujeo, la card),
134
+ y en formulario el valor se revertía.
133
135
  - El interruptor siempre va a la derecha (no hay `flip`).
134
136
  - `badge` con string sale **azul `light` `small`** (en `sui-switch-label` sale naranja).
135
137