@ajuarezso/sui-design-system 0.24.1 → 0.25.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 (120) hide show
  1. package/docs/sui-accordion/README.md +85 -11
  2. package/docs/sui-activity-feed/README.md +65 -11
  3. package/docs/sui-activity-filter/README.md +54 -5
  4. package/docs/sui-alert/README.md +54 -0
  5. package/docs/sui-app-store-badge/README.md +64 -10
  6. package/docs/sui-avatar/README.md +92 -29
  7. package/docs/sui-avatar-group/README.md +75 -9
  8. package/docs/sui-badge/README.md +85 -17
  9. package/docs/sui-banner/README.md +85 -20
  10. package/docs/sui-brand-logo/README.md +95 -31
  11. package/docs/sui-breadcrumb-item/README.md +54 -3
  12. package/docs/sui-breadcrumbs/README.md +54 -6
  13. package/docs/sui-button/README.md +76 -12
  14. package/docs/sui-button-group/README.md +91 -23
  15. package/docs/sui-button-group-item/README.md +81 -14
  16. package/docs/sui-card/README.md +105 -18
  17. package/docs/sui-chart-legend/README.md +63 -10
  18. package/docs/sui-chart-legend-dot/README.md +59 -10
  19. package/docs/sui-checkbox/README.md +109 -29
  20. package/docs/sui-checkbox-card/README.md +70 -14
  21. package/docs/sui-checkbox-label/README.md +92 -26
  22. package/docs/sui-circular-progress-bar/README.md +80 -19
  23. package/docs/sui-color-dot/README.md +72 -12
  24. package/docs/sui-color-picker/README.md +71 -13
  25. package/docs/sui-command-menu-footer/README.md +50 -1
  26. package/docs/sui-command-menu-item/README.md +74 -14
  27. package/docs/sui-command-menu-search/README.md +58 -3
  28. package/docs/sui-compact-avatar-group/README.md +73 -13
  29. package/docs/sui-compact-button/README.md +123 -34
  30. package/docs/sui-compact-select/README.md +61 -7
  31. package/docs/sui-compact-select-for-input/README.md +70 -6
  32. package/docs/sui-content-card/README.md +75 -14
  33. package/docs/sui-content-divider/README.md +67 -16
  34. package/docs/sui-content-label/README.md +99 -20
  35. package/docs/sui-counter-input/README.md +102 -18
  36. package/docs/sui-date-selector/README.md +69 -11
  37. package/docs/sui-datepicker/README.md +85 -18
  38. package/docs/sui-day-cell/README.md +75 -17
  39. package/docs/sui-day-label/README.md +56 -7
  40. package/docs/sui-divider/README.md +64 -9
  41. package/docs/sui-drawer-footer/README.md +63 -2
  42. package/docs/sui-drawer-header/README.md +69 -12
  43. package/docs/sui-dropdown-caption/README.md +58 -6
  44. package/docs/sui-dropdown-item/README.md +75 -9
  45. package/docs/sui-dropdown-menu/README.md +83 -14
  46. package/docs/sui-dropdown-search/README.md +60 -4
  47. package/docs/sui-emoji/README.md +94 -30
  48. package/docs/sui-empty-state/README.md +71 -7
  49. package/docs/sui-fancy-button/README.md +74 -14
  50. package/docs/sui-file-icon/README.md +70 -12
  51. package/docs/sui-file-upload/README.md +77 -17
  52. package/docs/sui-file-upload-card/README.md +64 -12
  53. package/docs/sui-filter/README.md +83 -14
  54. package/docs/sui-flag/README.md +73 -8
  55. package/docs/sui-form-hint/README.md +56 -7
  56. package/docs/sui-form-label/README.md +57 -5
  57. package/docs/sui-href/README.md +47 -0
  58. package/docs/sui-icon/README.md +86 -18
  59. package/docs/sui-image-upload/README.md +90 -22
  60. package/docs/sui-image-upload-profile/README.md +70 -11
  61. package/docs/sui-img-retry/README.md +50 -1
  62. package/docs/sui-inline-input/README.md +67 -9
  63. package/docs/sui-inline-select/README.md +62 -2
  64. package/docs/sui-input/README.md +90 -27
  65. package/docs/sui-integration-switch/README.md +84 -17
  66. package/docs/sui-kbd/README.md +73 -9
  67. package/docs/sui-key-icon/README.md +85 -23
  68. package/docs/sui-link-button/README.md +96 -27
  69. package/docs/sui-logo/README.md +93 -22
  70. package/docs/sui-modal/README.md +72 -13
  71. package/docs/sui-modal-footer/README.md +86 -12
  72. package/docs/sui-modal-header/README.md +57 -1
  73. package/docs/sui-modal-sheet/README.md +74 -12
  74. package/docs/sui-notification/README.md +81 -11
  75. package/docs/sui-notification-footer/README.md +55 -5
  76. package/docs/sui-notification-tab-menu/README.md +61 -5
  77. package/docs/sui-otp-input/README.md +70 -9
  78. package/docs/sui-page-header/README.md +89 -19
  79. package/docs/sui-pagination/README.md +73 -13
  80. package/docs/sui-password-strength/README.md +50 -1
  81. package/docs/sui-payment-icon/README.md +80 -18
  82. package/docs/sui-period-range/README.md +70 -11
  83. package/docs/sui-popover/README.md +81 -15
  84. package/docs/sui-product-card/README.md +89 -21
  85. package/docs/sui-progress-bar/README.md +82 -15
  86. package/docs/sui-progress-bar-label/README.md +79 -18
  87. package/docs/sui-radio/README.md +84 -7
  88. package/docs/sui-radio-card/README.md +70 -16
  89. package/docs/sui-radio-label/README.md +89 -22
  90. package/docs/sui-rating/README.md +101 -31
  91. package/docs/sui-rich-editor/README.md +47 -2
  92. package/docs/sui-segmented-control/README.md +90 -21
  93. package/docs/sui-select/README.md +80 -11
  94. package/docs/sui-sidebar/README.md +71 -16
  95. package/docs/sui-slider/README.md +75 -8
  96. package/docs/sui-social-button/README.md +71 -11
  97. package/docs/sui-status-badge/README.md +75 -14
  98. package/docs/sui-stepper/README.md +75 -18
  99. package/docs/sui-store-card/README.md +85 -22
  100. package/docs/sui-switch/README.md +82 -11
  101. package/docs/sui-switch-card/README.md +80 -16
  102. package/docs/sui-switch-label/README.md +91 -14
  103. package/docs/sui-tab-chips/README.md +93 -21
  104. package/docs/sui-tab-menu-horizontal/README.md +68 -7
  105. package/docs/sui-tab-menu-vertical/README.md +64 -11
  106. package/docs/sui-table/README.md +77 -16
  107. package/docs/sui-tag/README.md +86 -12
  108. package/docs/sui-tag-input/README.md +77 -13
  109. package/docs/sui-textarea/README.md +84 -17
  110. package/docs/sui-time-picker/README.md +96 -33
  111. package/docs/sui-toast/README.md +81 -20
  112. package/docs/sui-tooltip/README.md +80 -22
  113. package/docs/sui-topbar/README.md +64 -10
  114. package/docs/sui-topbar-button/README.md +61 -7
  115. package/docs/sui-topbar-item/README.md +68 -7
  116. package/docs/sui-topbar-user/README.md +61 -5
  117. package/fesm2022/ajuarezso-sui-design-system.mjs +15 -10
  118. package/fesm2022/ajuarezso-sui-design-system.mjs.map +1 -1
  119. package/package.json +1 -1
  120. package/types/ajuarezso-sui-design-system.d.ts +7 -3
@@ -34,40 +34,46 @@ tab-chips · secciones → tab menu.**
34
34
  >
35
35
  > Uso medido el 03-10-2026 en `master-pedidos/src/app` (misma exclusión que `sui-badge`):
36
36
  > **5 usos en 4 archivos**. Tamaños: 3 `small`, 1 `medium`, 1 sin `size` (`medium`). 1 con solo
37
- > íconos (vista cuadrícula / lista del catálogo).
37
+ > íconos (vista cuadrícula / lista del catálogo). El 06-10-2026 ya eran **9 usos en 7 archivos**
38
+ > (ver «Usos de hoy» abajo).
38
39
 
39
40
  ### `size`
40
41
 
41
42
  | size | cuándo | fuente |
42
43
  |---|---|---|
43
- | `xlarge` | Mobile: es el único que se acerca a los 44 px de área táctil (segmento de 40 px). | canon (dueño: «componentes grandes», 28-09-2026, y tamaño por plataforma, 03-10-2026) |
44
- | `large` | No aporta: 32 px, chico para el dedo y grande para web. | propuesta, falta aprobación |
45
- | `medium` (default) | Web, junto a títulos o filtros. | canon (dueño: tamaño por plataforma, 03-10-2026); el valor exacto es propuesta |
46
- | `small` | Web, solo íconos en una barra de herramientas (cuadrícula / lista). | propuesta, falta aprobación |
44
+ | `2xlarge` | Celular y tablet táctil: el único que llega a 44 px por segmento. | canon (dueño, 04-10-2026: piso táctil 44 en el teléfono) y D16, dueño 05-10-2026 |
45
+ | `xlarge` | No se usa: 40 px no llega a 44 en el teléfono y sobra en la computadora. Ninguna pantalla de la app lo usa (medido el 06-10-2026; solo aparece en la vitrina `master-preview`). | D16, dueño 05-10-2026 (antes «mobile», 28-09-2026) |
46
+ | `large` | No aporta: 32 px, chico para el dedo y grande para web. | canon (aprobado por el dueño, 05-10-2026, bloque B6) |
47
+ | `medium` (default) | Computadora: junto a títulos o filtros, también solo íconos en una barra. | canon (dueño, 05-10-2026, D16); el valor exacto, canon (aprobado por el dueño, 05-10-2026, bloque B1) |
48
+ | `small` | No usar: es chico. Los íconos de una barra (cuadrícula / lista) van en `medium`. | canon (dueño, 05-10-2026, D16) |
47
49
 
48
50
  ### Ítems (`tabs`)
49
51
 
50
52
  | qué | cuándo | fuente |
51
53
  |---|---|---|
52
54
  | texto | Lo normal. Una o dos palabras por segmento («Por distancia», «Precio único»). | según la guía del DS (ejemplos con texto) |
53
- | `icon` + texto | Cuando el ícono ayuda a reconocer el modo rápido. | propuesta, falta aprobación |
54
- | `iconOnly` | Solo para modos universales (cuadrícula / lista). El `label` pasa a ser el nombre accesible: escríbelo igual. | propuesta, falta aprobación |
55
- | `disabled` (por ítem) | Un modo que existe pero no aplica todavía. | propuesta, falta aprobación |
55
+ | `icon` + texto | Cuando el ícono ayuda a reconocer el modo rápido. | canon (aprobado por el dueño, 05-10-2026, bloque B9) |
56
+ | `iconOnly` | Solo para modos universales (cuadrícula / lista). El `label` pasa a ser el nombre accesible: escríbelo igual. | canon (aprobado por el dueño, 05-10-2026, bloque B9) |
57
+ | `disabled` (por ítem) | Un modo que existe pero no aplica todavía. | canon (aprobado por el dueño, 05-10-2026, bloque B8) |
56
58
 
57
59
  **Usos de hoy que rompen las reglas:**
58
60
 
59
61
  - **2 dentro de un borrador que se guarda después (a discutir):**
60
- `pages/super-admin/master-settings/master-settings.html:303` (modo de envío: «Por distancia» /
61
- «Precio único») y `:336` («Por calle» / «En línea recta»). La guía dice que se aplica de
62
+ `pages/super-admin/master-settings/master-settings.html:281` (modo de envío: «Por distancia» /
63
+ «Precio único») y `:314` («Por calle» / «En línea recta»). La guía dice que se aplica de
62
64
  inmediato; aquí la elección espera al «Guardar». Es trabajo de `sui-radio-card`.
63
- - **1 con textos largos, a verificar en mobile:** `pages/super-admin/master-roles/master-roles.html:47`
65
+ - **1 con textos largos, a verificar en mobile:** `pages/super-admin/master-roles/master-roles.html:48`
64
66
  («Administrador de ciudad» / «Jefe de operaciones»). Por ancho de texto quedan apretados cerca
65
67
  del borde a 390 px; no se midió en la pantalla real.
66
- - **2 en `small` con texto** (la propuesta deja `small` solo para íconos): `master-settings.html:303`
67
- y `:336`. El tercero en `small`, `pages/products/products.html:81`, está bien: solo íconos.
68
- - **5 sin tamaño por plataforma** (todos fijos): ninguno cambia a `xlarge` en mobile. Ejemplo:
69
- `pages/driver/driver-schedule/driver-schedule.html:30` (`size="medium"` en una pantalla del
70
- repartidor, que se usa en el teléfono).
68
+ - **2 en `small` con texto** (D16: `small` no se usa): `master-settings.html:281` y `:314`. El
69
+ tercero, `pages/products/products.html:83`, va en `small` en la computadora con solo íconos: con
70
+ D16 también pasa a `medium`.
71
+ - **Sin tamaño por dispositivo** (revisado el 06-10-2026): `master-roles.html:48` (sin `size`) y
72
+ `pages/super-admin/master-categorias/master-categorias.html:124` (`medium` fijo) se quedan en 28
73
+ en el teléfono; `master-settings.html:224` usa `tallaServicio()` (`master-settings.ts:452`), que
74
+ da `large` (32) en el teléfono. Los que cortan con `bp.isMobile()`
75
+ (`pages/driver/driver-schedule/driver-schedule.html:31`, `pages/overview/overview.html:45`,
76
+ `pages/driver/driver-dashboard/driver-dashboard.html:865`) dejan la tablet táctil en `medium`.
71
77
 
72
78
  ## Tamaño en mobile y en web
73
79
 
@@ -80,18 +86,36 @@ En large, xlarge y 2xlarge el texto sube a 16 px (regla del 03-10-2026): Label/M
80
86
  `large` el padding del segmento con texto bajó de 6 a 4 para que siga midiendo 32.
81
87
 
82
88
  **`2xlarge` es el size del teléfono**: 44 px por segmento, con texto o solo ícono (canon (dueño,
83
- 04-10-2026): piso táctil 44 en el teléfono). `xlarge` (40) no cambia y queda para las pantallas que
84
- ya lo usan.
89
+ 04-10-2026): piso táctil 44 en el teléfono). `xlarge` (40) no se usa: no llega a 44 y ninguna
90
+ pantalla de la app lo tiene.
85
91
 
86
92
  | uso | mobile | web | fuente |
87
93
  |---|---|---|---|
88
94
  | modos con texto (local del horario, rol) | `2xlarge` (segmento de 44 px) | `medium` | canon (dueño, 04-10-2026): piso táctil 44 en el teléfono |
89
- | solo íconos en una barra (cuadrícula / lista) | `2xlarge` (44) | `small` | canon (dueño, 04-10-2026): piso táctil 44 en el teléfono |
95
+ | solo íconos en una barra (cuadrícula / lista) | `2xlarge` (44) | `medium` | mobile: canon (dueño, 04-10-2026): piso táctil 44 en el teléfono · web: canon (dueño, 05-10-2026, D16), antes `small` |
90
96
 
91
97
  ```html
92
- <sui-segmented-control [size]="bp.isMobile() ? '2xlarge' : 'medium'" … />
98
+ <sui-segmented-control [size]="bp.tactil() ? '2xlarge' : 'medium'" … />
93
99
  ```
94
100
 
101
+ ### Por dispositivo (D16)
102
+
103
+ Fila de `segmented-control` en la tabla de D16 (dueño, 05-10-2026): se toca, y el size que llega a
104
+ 44 es `2xlarge`.
105
+
106
+ | dispositivo | size | nota |
107
+ |---|---|---|
108
+ | celular chico (< 380 px) | `2xlarge` (44) | D16 pide `medium` con área de 44, pero el DS todavía no estira el área de los `medium` (nota ¹ de D16): hasta entonces se queda el grande |
109
+ | celular (380–767 px) | `2xlarge` (44) | con texto o solo íconos |
110
+ | tablet táctil (`pointer: coarse`) | `2xlarge` (44) | Apple pide 44 también en el iPad |
111
+ | computadora (`pointer: fine`) | `medium` (28) | también solo íconos en una barra; nunca `small` |
112
+
113
+ Ultrawide (≥ 1920 px): igual que la computadora, `medium`; el espacio extra va al `max-width`, no a
114
+ segmentos más altos.
115
+
116
+ En master-pedidos: `[size]="bp.tactil() ? '2xlarge' : 'medium'"`. No hay helper: `bp.sizeChips()`
117
+ llega a `xlarge` (40) y `bp.sizeControl()` a `large` (32), y ninguno de los dos da 44 aquí.
118
+
95
119
  ## «No usar»: por qué no hoy y cuándo sí
96
120
 
97
121
  | qué | por qué no hoy | cuándo sí, en un flujo nuevo |
@@ -145,12 +169,57 @@ interface SuiSegmentedControlItem<T = string> {
145
169
  - Los tamaños son extensión de SUI: la guía tiene uno solo. Su versión redondeada (`Rounded`)
146
170
  no existe en SUI.
147
171
 
172
+ ## Bien y mal
173
+
174
+ Vista cuadrícula / lista
175
+
176
+ ```html
177
+ <!-- ❌ mal: `small` en la computadora; D16 no usa `small` (pages/products/products.html:83) -->
178
+ <sui-segmented-control [size]="bp.isMobile() ? '2xlarge' : 'small'"
179
+ [tabs]="viewToggleItems" [(active)]="viewMode" />
180
+ ```
181
+
182
+ ```html
183
+ <!-- ✅ bien -->
184
+ <sui-segmented-control [size]="bp.tactil() ? '2xlarge' : 'medium'"
185
+ [tabs]="viewToggleItems" [(active)]="viewMode" />
186
+ ```
187
+
188
+ Modo del servicio en el panel
189
+
190
+ ```html
191
+ <!-- ❌ mal: `large` (32) en el teléfono no llega a 44 (master-settings.html:224, tallaServicio en master-settings.ts:452) -->
192
+ <sui-segmented-control [size]="bp.isMobile() ? 'large' : 'medium'"
193
+ ariaLabel="Cómo se cobra la tarifa de servicio"
194
+ [tabs]="MODOS_SERVICIO" [active]="borrador().servicioModo" (tabChange)="setModoServicio($event)" />
195
+ ```
196
+
197
+ ```html
198
+ <!-- ✅ bien -->
199
+ <sui-segmented-control [size]="bp.tactil() ? '2xlarge' : 'medium'"
200
+ ariaLabel="Cómo se cobra la tarifa de servicio"
201
+ [tabs]="MODOS_SERVICIO" [active]="borrador().servicioModo" (tabChange)="setModoServicio($event)" />
202
+ ```
203
+
204
+ Rol a invitar
205
+
206
+ ```html
207
+ <!-- ❌ mal: sin `size` ni `ariaLabel`: 28 px también en el teléfono y el grupo sin nombre (pages/super-admin/master-roles/master-roles.html:48) -->
208
+ <sui-segmented-control [tabs]="rolesCiudad" [active]="rolStaff()" (activeChange)="rolStaff.set($any($event))" />
209
+ ```
210
+
211
+ ```html
212
+ <!-- ✅ bien -->
213
+ <sui-segmented-control [size]="bp.tactil() ? '2xlarge' : 'medium'" ariaLabel="Rol"
214
+ [tabs]="rolesCiudad" [active]="rolStaff()" (activeChange)="rolStaff.set($any($event))" />
215
+ ```
216
+
148
217
  ## Ejemplo
149
218
 
150
219
  ```html
151
220
  <div style="max-width: 320px">
152
221
  <sui-segmented-control
153
- [size]="bp.isMobile() ? 'xlarge' : 'small'"
222
+ [size]="bp.tactil() ? '2xlarge' : 'medium'"
154
223
  [tabs]="[{ value: 'grid', label: 'Vista cuadrícula', icon: 'layout-grid-line', iconOnly: true },
155
224
  { value: 'list', label: 'Vista lista', icon: 'list-unordered', iconOnly: true }]"
156
225
  [(active)]="vista" />
@@ -46,7 +46,7 @@ Regla corta: **sale de datos o son más de 6 → select · 2–6 fijas → radio
46
46
  | La lista sale de datos (ubigeo, repartidores, categorías, planes) | `sui-select` | según la guía del DS (elegir una opción de un menú) |
47
47
  | Más de ~6 opciones fijas | `sui-select` | derivado del README de `sui-radio` («más de ~6 → select»), falta confirmación |
48
48
  | 2 a 6 opciones fijas en un formulario | `sui-radio-label` / `sui-radio-card` | propuesta, falta aprobación (sale del umbral de `sui-radio`) |
49
- | 2 a 4 modos que se aplican al instante | `sui-segmented-control` | según la guía del DS («aplicarla de inmediato», ver README de `sui-segmented-control`); el tope de 4 es propuesta |
49
+ | 2 a 4 modos que se aplican al instante | `sui-segmented-control` | según la guía del DS («aplicarla de inmediato», ver README de `sui-segmented-control`); el tope de 4: canon (decisión del dueño 04-10-2026: 2 a 4 opciones excluyentes → segmented, 5 o más → tab-chips) |
50
50
  | Filtro de una barra con 5 o más opciones | `sui-select` sin label (o `sui-compact-select` en web) | propuesta, falta aprobación |
51
51
 
52
52
  **Candidatos de hoy** (no rompen nada; se verían mejor con radios o segmented):
@@ -69,11 +69,11 @@ Regla corta: **sale de datos o son más de 6 → select · 2–6 fijas → radio
69
69
  |---|---|---|
70
70
  | `type="basic"` (default) sin ícono | Todo select de la app hoy. | según la guía del DS |
71
71
  | `type="avatar"` + `imageUrl` | Elegir un **repartidor**: la foto de quien quedó elegido en el campo. Hoy `pages/orders/orders.html:257` muestra solo el nombre. | según la guía del DS (ejemplo «User»); el caso es propuesta |
72
- | `type="provider"` + `imageUrl` | Método de pago con logo (Yape, Plin). | según la guía del DS (ejemplo «Payment Method»); el caso es propuesta |
72
+ | `type="provider"` + `imageUrl` | Método de pago con logo (Yape, Plin). | según la guía del DS (ejemplo «Payment Method»); el caso, canon (aprobado por el dueño, 05-10-2026, bloque B2) |
73
73
  | `leadingIcon` (`true` o nombre RemixIcon) | Un ícono que ayuda a reconocer el campo en un formulario largo. Hoy sin caso. | según la guía del DS (ejemplo «Icons») |
74
74
  | `type="country"` + `flag` | No usar hoy: todo es Perú. | según la guía del DS (ejemplo «Country») |
75
- | `type="brand"` / `"company"` | No usar hoy. | propuesta, falta aprobación |
76
- | `badge` | No usar hoy. | propuesta, falta aprobación |
75
+ | `type="brand"` / `"company"` | No usar hoy. | canon (aprobado por el dueño, 05-10-2026, bloque B6) |
76
+ | `badge` | No usar hoy. | canon (aprobado por el dueño, 05-10-2026, bloque B6) |
77
77
 
78
78
  ### Las piezas
79
79
 
@@ -109,15 +109,37 @@ y las opciones de la lista; el alto no cambia (las opciones bajan 2 de padding p
109
109
 
110
110
  | uso | mobile | web | fuente |
111
111
  |---|---|---|---|
112
- | campo de formulario | `large` (48) | `medium` (40) | propuesta, falta aprobación (igual que `sui-input`) |
113
- | filtro de una barra | `large` (48) | `small` (36) | propuesta (ya es práctica en `pages/orders/orders.html:257`) |
114
- | dentro de una tabla densa | no aplica | `xsmall` (32) | según la guía del DS |
115
- | `xlarge` (52) | no usar | no usar | propuesta: queda más alto que el botón `large` del footer |
112
+ | campo de formulario | `large` (48) | `medium` (40) | mobile `large`: canon (decisión del dueño 04-10-2026, piso táctil 44: `medium` 40 no llega y `large` 48 es el primer size que sí) · web `medium`: canon (aprobado por el dueño, 05-10-2026, bloque B1) |
113
+ | filtro de una barra | `large` (48) | `medium` (40) | mobile `large`: canon (decisión del dueño 04-10-2026, piso táctil 44: `large` 48 es el primer size que llega) · web `medium`: canon (dueño, 05-10-2026, D16) (el `small` de `pages/orders/orders.html:257` ya se migró a `bp.sizeControl()`) |
114
+ | dentro de una tabla | no aplica | `medium` (40) | canon (dueño, 05-10-2026, D16): nada en `xsmall` (la guía del DS lo usa en tablas densas) |
115
+ | `xlarge` (52) | no usar | no usar | canon (aprobado por el dueño, 05-10-2026, bloque B6): queda más alto que el botón `large` del footer |
116
116
 
117
117
  ```html
118
- <sui-select [size]="bp.isMobile() ? 'large' : 'medium'" label="Distrito" … /> <!-- bp = BreakpointsService -->
118
+ <sui-select [size]="bp.sizeControl()" label="Distrito" … /> <!-- bp = BreakpointsService · D16, dueño 05-10-2026 -->
119
119
  ```
120
120
 
121
+ ### Por dispositivo (D16)
122
+
123
+ Fila `select` de la tabla D16 (dueño, 05-10-2026): se decide por el tipo de puntero además del ancho.
124
+
125
+ | dispositivo | size | nota |
126
+ |---|---|---|
127
+ | celular chico (< 380 px) | `large` (48) | interino: D16 pide `medium` con área tocable de 44; hasta que el DS la estire, se queda el grande (nota ¹ de D16) |
128
+ | celular (380–767 px) | `large` (48) | el primer size que llega al piso táctil de 44 |
129
+ | tablet táctil (`pointer: coarse`) | `large` (48) | Apple pide 44 pt también en iPad; con `bp.isMobile()` el iPad quedaba en `medium` 40 |
130
+ | computadora (`pointer: fine`) | `medium` (40) | también en filtros de barra y dentro de tablas; nunca `small` ni `xsmall` |
131
+
132
+ Ultrawide (≥ 1920 px): igual que la computadora, `medium`. El espacio extra va a ancho máximo y columnas, no a un campo más alto.
133
+
134
+ En master-pedidos: `[size]="bp.sizeControl()"`. Re-medido el 06-10-2026: 52 de 56 `<sui-select>` ya lo usan. Faltan 4:
135
+
136
+ - `pages/driver/driver-dashboard/driver-dashboard.html:1507`: `size="large"` fijo por pedido del dueño (22-09-2026),
137
+ pendiente de confirmar si D16 lo reemplaza.
138
+ - `pages/super-admin/master-preview/master-preview.html:807` y `:813`: sin `size`, salen en `medium` (el default) en
139
+ todos los dispositivos. Es la vitrina del super admin.
140
+ - `pages/super-admin/master-preview/_ruta-pedido/ruta-pedido.html:12`: sin `size`, sale en `medium`. Es la pantalla de
141
+ diagnóstico `/dx/ruta-pedido` (auditor de rutas del super admin), no una vitrina.
142
+
121
143
  ## «No usar»: por qué no hoy y cuándo sí
122
144
 
123
145
  | qué | por qué no hoy | cuándo sí, en un flujo nuevo |
@@ -126,7 +148,7 @@ y las opciones de la lista; el alto no cambia (las opciones bajan 2 de padding p
126
148
  | `type="brand"` / `"company"` | no hay listas de marcas o empresas | elegir la marca de un producto envasado o la empresa de una flota |
127
149
  | `leadingIcon` | ningún formulario lo necesita para reconocerse | un formulario largo del panel con varios selects seguidos |
128
150
  | `badge` | no hay valores que marcar | marcar el plan elegido como «Recomendado» |
129
- | `size="xsmall"` | no hay selects dentro de tablas | cambiar el estado de una fila sin abrir el detalle |
151
+ | `size="xsmall"` | es chico (D16, 05-10-2026) | nunca: cambiar el estado de una fila va con un select `medium` |
130
152
  | `size="xlarge"` | queda más alto que el botón del footer | un select solo, como acción principal de la pantalla |
131
153
 
132
154
  ## API
@@ -176,12 +198,59 @@ decoración propia del campo (gana sobre ícono, imagen y bandera).
176
198
  label, con el placeholder), apunta al listbox abierto (`aria-controls`) y anuncia la opción
177
199
  resaltada con las flechas (`aria-activedescendant`). Hint y error van en `aria-describedby`.
178
200
 
201
+ ## Bien y mal
202
+
203
+ **Filtro de período con 3 opciones**
204
+
205
+ ```html
206
+ <!-- ❌ mal: 3 opciones excluyentes que se aplican al tocar, escondidas en un menú (pages/discounts/discounts.html:49) -->
207
+ <sui-select [size]="bp.sizeControl()" placeholder="Período"
208
+ [options]="periodOptions" [value]="selectedPeriod()"
209
+ (valueChange)="selectedPeriod.set($event ?? '7days')" />
210
+ ```
211
+
212
+ ```html
213
+ <!-- ✅ bien: 2 a 4 opciones excluyentes → sui-segmented-control (canon, dueño 04-10-2026) -->
214
+ <sui-segmented-control [size]="bp.tactil() ? '2xlarge' : 'medium'"
215
+ [tabs]="periodos" [(active)]="periodo" />
216
+ ```
217
+
218
+ **El valor que vuelve del select**
219
+
220
+ ```html
221
+ <!-- ❌ mal: `$any` es un `any` disfrazado y además deja pasar el `null` (pages/super-admin/super-admin.html:317) -->
222
+ <sui-select [size]="bp.sizeControl()" label="Plan" placeholder="Elige…"
223
+ [options]="planSelectOptions()" [value]="subPlan()"
224
+ (valueChange)="subPlan.set($any($event))" />
225
+ ```
226
+
227
+ ```html
228
+ <!-- ✅ bien: opciones tipadas (SuiSelectOption<string>[]) y el null resuelto en el template -->
229
+ <sui-select [size]="bp.sizeControl()" label="Plan" placeholder="Elige…"
230
+ [options]="planSelectOptions()" [value]="subPlan()"
231
+ (valueChange)="subPlan.set($event ?? 'crecimiento')" />
232
+ ```
233
+
234
+ **El size por dispositivo**
235
+
236
+ ```html
237
+ <!-- ❌ mal: solo mira el ancho; el iPad (≥ 768, táctil) recibe `medium` 40, bajo el piso de 44 -->
238
+ <sui-select [size]="bp.isMobile() ? 'large' : 'medium'" label="Distrito"
239
+ placeholder="Elige el distrito" [options]="distritos()" />
240
+ ```
241
+
242
+ ```html
243
+ <!-- ✅ bien: el helper de D16 (`large` en celular y tablet táctil, `medium` en la computadora) -->
244
+ <sui-select [size]="bp.sizeControl()" label="Distrito"
245
+ placeholder="Elige el distrito" [options]="distritos()" />
246
+ ```
247
+
179
248
  ## Ejemplo
180
249
 
181
250
  ```html
182
251
  <sui-select label="Distrito" [required]="true" placeholder="Elige tu distrito"
183
252
  [options]="distritos()" [disabled]="!provinciaId()"
184
253
  [error]="intentado() && !distritoId()" errorMessage="Elige tu distrito"
185
- [size]="bp.isMobile() ? 'large' : 'medium'"
254
+ [size]="bp.sizeControl()"
186
255
  [value]="distritoId()" (valueChange)="distritoId.set($event ?? '')" />
187
256
  ```
@@ -31,8 +31,8 @@ Regla corta: **navegación del rol → sidebar · secciones de una pantalla →
31
31
  > **La guía del DS no tiene página del sidebar.** El componente sale del Figma de SUI (Sidebar
32
32
  > [Navigation], node 3802:11759) y el cajón de mobile no existe en ese Figma: se portó del layout
33
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`.
34
+ > 25-07-2026) o **propuesta, falta aprobación**; lo marcado «canon» sale de `docs/CANON-SUI.md`,
35
+ > de `master-pedidos/CLAUDE.md` o de la aprobación del dueño del 05-10-2026.
36
36
  >
37
37
  > Uso medido el 03-10-2026 en `master-pedidos/src/app`: **4 sidebars**, sin contar vitrinas
38
38
  > (`master-preview` tiene el quinto).
@@ -44,11 +44,11 @@ Regla corta: **navegación del rol → sidebar · secciones de una pantalla →
44
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
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
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) |
47
+ | `activeRoute` | No hace falta si los items de navegación llevan `route`: el `<a>` usa `routerLinkActive` y marca por prefijo (`/cliente/pedidos/123` deja «Mis pedidos» activo). `activeRoute` solo marca items **sin** `route`, y por `value` exacto (`activeRoute="pedidos"`), para demos sin router (`sui-sidebar.ts:369-412`). Los 4 layouts pasan `[activeRoute]="currentUrl()"`, pero no cambia nada: todos sus items de navegación tienen `route` y la URL nunca es igual al `value` de un item-acción. | comportamiento del `.ts` · práctica de la app (4 de 4 lo pasan, sin efecto) |
48
48
  | `profile` | Nombre + `avatarUrl` (nunca `photoURL`) + correo. | canon (CLAUDE.md, «Fotos de otra persona»: el campo correcto es `avatarUrl`) |
49
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) |
50
+ | `[(mobileOpen)]` + `closeOnItemClick` | Siempre los dos (`closeOnItemClick` ya es `true` por defecto; los 4 layouts lo pasan explícito). Más `cerrarAlNavegar(...)` en el constructor del layout (ver Trampas). | canon (CANON-SUI §1.1) |
51
+ | `search` | `{ shortcut: '⌘K' }` (el placeholder por defecto ya es «Buscar…», con elipsis) y el layout **filtra** los items con `searchValue` (el componente no filtra). | buscador: práctica de la app (4 de 4) · `shortcut: '⌘K'`: práctica de la app (3 de 4; el cliente no lo pasa, `layouts/customer/customer-layout.html:12`) · la elipsis «…»: canon (CANON-SUI, copy); los 4 layouts todavía pasan «Buscar...» (ver «Bien y mal») |
52
52
  | `indicatorColor` | Default `brand` (naranja). No se cambia. | canon del DS (accent = marca) |
53
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
54
 
@@ -56,12 +56,12 @@ Regla corta: **navegación del rol → sidebar · secciones de una pantalla →
56
56
 
57
57
  | prop | cuándo | fuente |
58
58
  |---|---|---|
59
- | `icon` | Siempre, RemixIcon `-line`. Sin ícono, el modo colapsado queda vacío. | propuesta, falta aprobación |
59
+ | `icon` | Siempre, RemixIcon `-line`. Sin ícono, el modo colapsado queda vacío. | canon (aprobado por el dueño, 05-10-2026, bloque B9) |
60
60
  | `route` | Navegación normal (usa `routerLink`). | práctica de la app |
61
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 |
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»: canon (aprobado por el dueño, 05-10-2026, bloque B9) |
63
+ | `variant: 'danger'` | Solo «Cerrar sesión» o salidas destructivas. | «Cerrar sesión» en rojo: canon (decisión del dueño 04-10-2026, salida destructiva en `color error` aunque sea un link; `danger` pinta `--sui-state-error-base`) · el «solo» (ningún otro item en rojo): canon (aprobado por el dueño, 05-10-2026, bloque B3) |
64
+ | `shortcut`, `colorDot` | No usar (ver «No usar»). | canon (aprobado por el dueño, 05-10-2026, bloque B6) |
65
65
 
66
66
  ## Tamaño en mobile y en web
67
67
 
@@ -78,7 +78,7 @@ El sidebar **no tiene `size`**. El ancho lo decide el viewport:
78
78
  |---|---|---|---|
79
79
  | navegación del rol | cajón `drawer`, cerrado por defecto | columna fija de 272 | práctica de la app (4 de 4) |
80
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 |
81
+ | `sheet` | no usar (0 usos) | — | canon (aprobado por el dueño, 05-10-2026, bloque B6) |
82
82
 
83
83
  **Qué pasa en mobile (≤ 767 px):** el sidebar sale del flujo y queda `position: fixed` fuera de la
84
84
  pantalla. Lo abre la acción `toggle-sidebar` de la **barra inferior** («Más»), que el layout
@@ -87,6 +87,16 @@ con el fondo, con Escape, al tocar un item (`closeOnItemClick`) y —por el help
87
87
  al terminar cualquier navegación. Cerrado queda `inert` y `aria-hidden`: el foco no se mete.
88
88
  Respeta las safe areas de arriba, izquierda y abajo.
89
89
 
90
+ ### Por dispositivo (D16)
91
+
92
+ El sidebar **no tiene `size`**: D16 (dueño, 05-10-2026) no le da un tamaño que pasar. El alto de los items lo pone el DS por
93
+ ancho: 52 en el cajón (≤ 767 px, `padding: 14px` + ícono 24) y 36 en la columna (> 767 px). Hueco conocido: una tablet táctil
94
+ (iPad, ≥ 768 px y `pointer: coarse`) recibe la columna con items de 36, bajo el piso de 44 que D16 pide para lo que se toca.
95
+ Queda **pendiente del DS** (el mixin `sui-tactil` de la propuesta de D16, que todavía espera el sí del dueño); desde la app no
96
+ se corrige.
97
+
98
+ En master-pedidos: no se pasa `size`; lo único que depende del dispositivo es `[collapsed]="colapsado() && !bp.isMobile()"`.
99
+
90
100
  ## «No usar»: por qué no hoy y cuándo sí
91
101
 
92
102
  | qué | por qué no hoy | cuándo sí, en un flujo nuevo |
@@ -170,16 +180,62 @@ Slots: `[header-panel]` (debajo del header: el switcher), `[feature-card]` (al f
170
180
  filtra los items (`master-layout.ts:125`). Su placeholder por defecto es «Buscar…» (en español desde el 04-10-2026).
171
181
  - **`collapsed` no mira el viewport.** Con `collapsed` en `true`, el cajón de mobile también sale
172
182
  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.
183
+ - Un item con `route` (y sin `action`) queda activo **solo** por `routerLinkActive`, por prefijo:
184
+ `isItemActive()` devuelve `false` para todo item con `route` (`sui-sidebar.ts:411`), así que
185
+ `activeRoute` no lo toca. Un item sin `route` solo por `activeRoute`, y por `value` exacto
186
+ (`sui-sidebar.ts:379`): pasarle la URL actual no lo marca nunca.
187
+ - Cualquier `action` (no solo `'logout'`) anula el `route`: el item se pinta como `<button>`, no navega y
188
+ tampoco se marca activo (tiene `route`, así que `isItemActive()` da `false`, y no hay `routerLinkActive`).
177
189
  - El `title` nativo del host se borra (sin tooltip gris); en colapsado el tooltip va en cada item.
178
190
  - El cajón tiene `z-index: 300` sobre la barra inferior (200). Mientras está abierto el layout
179
191
  esconde la barra (`customer-layout.ts:66`); si armas un layout nuevo, haz lo mismo.
180
192
  - El comentario de cabecera del `.ts` todavía dice 240 px; el ancho real es 272 (`sui-sidebar.scss:50`).
181
193
  - Los items ya traen el arreglo de iOS del `:active` pegado: no lo agregues.
182
194
 
195
+ ## Bien y mal
196
+
197
+ **El buscador**
198
+
199
+ ```html
200
+ <!-- ❌ mal: tres puntos sueltos en vez de elipsis. Así en components/sidebar/sidebar.html:48, layouts/driver/driver-layout.html:9 y layouts/master/master-layout.html:10; layouts/customer/customer-layout.html:12 pasa el mismo «Buscar...» sin `shortcut` -->
201
+ <sui-sidebar [search]="{ placeholder: 'Buscar...', shortcut: '⌘K' }"
202
+ [(searchValue)]="busqueda" [items]="items()" />
203
+ ```
204
+
205
+ ```html
206
+ <!-- ✅ bien: sin placeholder sale «Buscar…»; el layout filtra `items()` con `busqueda` -->
207
+ <sui-sidebar [search]="{ shortcut: '⌘K' }"
208
+ [(searchValue)]="busqueda" [items]="items()" />
209
+ ```
210
+
211
+ **Colapsar**
212
+
213
+ ```html
214
+ <!-- ❌ mal: `collapsed` no mira el viewport; el cajón de mobile también sale de 80 px, solo íconos -->
215
+ <sui-sidebar [collapsed]="colapsado()" [items]="items()" [(mobileOpen)]="menuAbierto" />
216
+ ```
217
+
218
+ ```html
219
+ <!-- ✅ bien: se colapsa solo en web (layouts/customer/customer-layout.html:7) -->
220
+ <sui-sidebar [collapsed]="colapsado() && !bp.isMobile()" [items]="items()" [(mobileOpen)]="menuAbierto" />
221
+ ```
222
+
223
+ **El item activo**
224
+
225
+ ```ts
226
+ // ❌ mal: navegar con `action` + `(itemClicked)` y `router.navigate`. El item se pinta como `<button>`,
227
+ // no como `<a routerLink>`, y nunca queda activo: sin `route`, `activeRoute` solo lo marca si es igual
228
+ // a su `value` (`sui-sidebar.ts:379`), y `[activeRoute]="currentUrl()"` nunca lo es
229
+ { value: 'pedidos', label: 'Mis pedidos', icon: 'time-line', action: 'ir-a-pedidos' }
230
+ ```
231
+
232
+ ```ts
233
+ // ✅ bien: con `route` (y sin `action`) el item es un `<a routerLink>` y `routerLinkActive` lo marca por
234
+ // prefijo: `/cliente/pedidos/123` deja «Mis pedidos» activo sin pasar `activeRoute`
235
+ // (layouts/customer/customer-layout.ts:287)
236
+ { value: 'pedidos', label: 'Mis pedidos', icon: 'time-line', route: '/cliente/pedidos' }
237
+ ```
238
+
183
239
  ## Ejemplo
184
240
 
185
241
  ```html
@@ -188,12 +244,11 @@ Slots: `[header-panel]` (debajo del header: el switcher), `[feature-card]` (al f
188
244
  [showHeaderButton]="true"
189
245
  [headerButtonActive]="switcherOpen()"
190
246
  (headerButtonClicked)="switcherOpen.set(!switcherOpen())"
191
- [search]="{ placeholder: 'Buscar...', shortcut: '⌘K' }"
247
+ [search]="{ shortcut: '⌘K' }"
192
248
  [(searchValue)]="busqueda"
193
249
  itemsLabel="Operación" [items]="items()"
194
250
  secondaryItemsLabel="Dinero" [secondaryItems]="itemsDinero()"
195
251
  supportingItemsLabel="Cuenta" [supportingItems]="itemsCuenta()"
196
- [activeRoute]="currentUrl()"
197
252
  [profile]="perfil()"
198
253
  [(mobileOpen)]="menuAbierto"
199
254
  [closeOnItemClick]="true"
@@ -38,19 +38,19 @@ Regla corta: **escala con tope y la posición importa → slider · número exac
38
38
  | type | cuándo | fuente |
39
39
  |---|---|---|
40
40
  | `single` (default) | Un valor: radio de cobertura, porcentaje. | según la guía del DS |
41
- | `range` | Un mínimo y un máximo en la misma escala: rango de precios de un filtro. Una sola barra con dos manijas, nunca dos sliders. | según la guía del DS (existe); el «cuándo» es propuesta |
41
+ | `range` | Un mínimo y un máximo en la misma escala: rango de precios de un filtro. Una sola barra con dos manijas, nunca dos sliders. | según la guía del DS (existe); el «cuándo», canon (aprobado por el dueño, 05-10-2026, bloque B2) |
42
42
 
43
43
  ### Las piezas
44
44
 
45
45
  | prop | cuándo | fuente |
46
46
  |---|---|---|
47
- | `label` | Siempre que el slider no esté dentro de un campo que ya lo titula. Sin `label` desaparece toda la fila de arriba, `amount` incluido. | propuesta, falta aprobación |
48
- | `amount` | El valor con su unidad, a la derecha del label: «12 km», «S/ 10 – S/ 40». Sin `amount` escribe el número pelado. | propuesta, falta aprobación |
49
- | `sublabel` | Una precisión corta junto al label: «(máximo 15)». | propuesta, falta aprobación |
50
- | `tooltip` | Solo **sin** `amount`: el número flota sobre la manija mientras se arrastra. Con `amount` repite el valor y sin unidad. | según la guía del DS (existe); el «cuándo» es propuesta |
51
- | `tooltipAlways` | No usar (ver abajo). | propuesta, falta aprobación |
47
+ | `label` | Siempre que el slider no esté dentro de un campo que ya lo titula. Sin `label` desaparece toda la fila de arriba, `amount` incluido. | canon (aprobado por el dueño, 05-10-2026, bloque B4) |
48
+ | `amount` | El valor con su unidad, a la derecha del label: «12 km», «S/ 10 – S/ 40». Sin `amount` escribe el número pelado. | canon (aprobado por el dueño, 05-10-2026, bloque B4) |
49
+ | `sublabel` | Una precisión corta junto al label: «(máximo 15)». | canon (aprobado por el dueño, 05-10-2026, bloque B4) |
50
+ | `tooltip` | Solo **sin** `amount`: el número flota sobre la manija mientras se arrastra. Con `amount` repite el valor y sin unidad. | según la guía del DS (existe); el «cuándo», canon (aprobado por el dueño, 05-10-2026, bloque B9) |
51
+ | `tooltipAlways` | No usar (ver abajo). | canon (aprobado por el dueño, 05-10-2026, bloque B6) |
52
52
  | `min` / `max` / `step` | La escala real del negocio (1–15 km, paso 1). | API |
53
- | `disabled` | La escala existe pero hoy no se puede mover (falta un dato antes). | propuesta, falta aprobación |
53
+ | `disabled` | La escala existe pero hoy no se puede mover (falta un dato antes). | canon (aprobado por el dueño, 05-10-2026, bloque B8) |
54
54
  | `size` | `medium` (default, Figma): manija 16, riel 6, label 12/16. `large`: manija 24, riel 8, punto interno 8, label 14/20 — para mobile. | `medium`: según la guía del DS · `large`: canon (aprobado por el dueño, 03-10-2026), extensión SUI |
55
55
 
56
56
  **Usos de hoy que rompen la propuesta:**
@@ -73,7 +73,8 @@ va un tamaño más chico. La app ya lo resuelve con `BreakpointsService`
73
73
  | slider con label (radio de cobertura, filtro de precio) | `large` (manija 24, riel 8) | `medium` (manija 16, riel 6) | canon (aprobado por el dueño, 03-10-2026) |
74
74
 
75
75
  ```html
76
- <sui-slider [size]="bp.isMobile() ? 'large' : 'medium'" label="Radio de cobertura" amount="12 km"
76
+ <!-- D16, dueño 05-10-2026: `large` en todo lo táctil, `medium` con mouse -->
77
+ <sui-slider [size]="(bp.isMobile() || bp.toque()) ? 'large' : 'medium'" label="Radio de cobertura" amount="12 km"
77
78
  [min]="1" [max]="15" [(value)]="radioKm" />
78
79
  ```
79
80
 
@@ -82,6 +83,24 @@ manija. Igual la barra mide menos de 44: el slider necesita aire arriba y abajo
82
83
  manija en 0 o en 100 sobresale media manija (12 px en `large`) del borde de la barra: el
83
84
  contenedor tiene que tener margen lateral.
84
85
 
86
+ ### Por dispositivo (D16)
87
+
88
+ Fila `slider` de la tabla D16 (dueño, 05-10-2026). A diferencia del botón o el campo, el slider **no** tiene la excepción
89
+ «`medium` + área 44» en el celular chico: va `large` en todo lo que se toca.
90
+
91
+ | dispositivo | size | nota |
92
+ |---|---|---|
93
+ | celular chico (< 380 px) | `large` | manija 24, riel 8; con `medium` la manija de 16 es difícil de agarrar |
94
+ | celular (380–767 px) | `large` | |
95
+ | tablet táctil (`pointer: coarse`) | `large` | también se arrastra con el dedo |
96
+ | computadora (`pointer: fine`) | `medium` | manija 16, riel 6 (el de la guía del DS) |
97
+
98
+ Ultrawide (≥ 1920 px): igual que la computadora, `medium`.
99
+
100
+ En master-pedidos: `[size]="(bp.isMobile() || bp.toque()) ? 'large' : 'medium'"`. No hay helper propio. Hoy da lo mismo que
101
+ `bp.tactil()`, pero el servicio anuncia que `tactil` dejará fuera al celular chico cuando el DS estire el área de los
102
+ `medium`, y el slider tiene que seguir en `large` ahí.
103
+
85
104
  ## «No usar»: por qué no hoy y cuándo sí
86
105
 
87
106
  | qué | por qué no hoy | cuándo sí, en un flujo nuevo |
@@ -138,10 +157,58 @@ Implementa `ControlValueAccessor` **solo para `single`**.
138
157
  El lector lee el valor con su unidad: en single, el texto de `amount` («12 km»); en range (o sin
139
158
  `amount`), el número + `unit`. En range cada manija se anuncia «<label>, mínimo» / «…, máximo».
140
159
 
160
+ ## Bien y mal
161
+
162
+ **El valor arriba y flotando a la vez**
163
+
164
+ ```html
165
+ <!-- ❌ mal: `amount` muestra «12 km» y el tooltip repite «12» sin unidad (components/driver-coverage-modal/driver-coverage-modal.html:83) -->
166
+ <sui-slider label="Radio de cobertura" [amount]="radiusKm() + ' km'"
167
+ [min]="minKm" [max]="maxKm" [tooltip]="true"
168
+ [value]="radiusKm()" (valueChange)="onRadiusChange($event)" />
169
+ ```
170
+
171
+ ```html
172
+ <!-- ✅ bien: con `amount`, sin tooltip -->
173
+ <sui-slider [size]="(bp.isMobile() || bp.toque()) ? 'large' : 'medium'"
174
+ label="Radio de cobertura" [amount]="radiusKm() + ' km'" [min]="minKm" [max]="maxKm"
175
+ [value]="radiusKm()" (valueChange)="onRadiusChange($event)" />
176
+ ```
177
+
178
+ **El size en una pantalla del repartidor**
179
+
180
+ ```html
181
+ <!-- ❌ mal: sin `size` sale `medium` (manija 16) en el teléfono (components/driver-coverage-modal/driver-coverage-modal.html:83) -->
182
+ <sui-slider label="Radio de cobertura" [amount]="radiusKm() + ' km'" [min]="minKm" [max]="maxKm"
183
+ [value]="radiusKm()" (valueChange)="onRadiusChange($event)" />
184
+ ```
185
+
186
+ ```html
187
+ <!-- ✅ bien: D16, `large` en todo lo táctil -->
188
+ <sui-slider [size]="(bp.isMobile() || bp.toque()) ? 'large' : 'medium'"
189
+ label="Radio de cobertura" [amount]="radiusKm() + ' km'" [min]="minKm" [max]="maxKm"
190
+ [value]="radiusKm()" (valueChange)="onRadiusChange($event)" />
191
+ ```
192
+
193
+ **Un mínimo y un máximo**
194
+
195
+ ```html
196
+ <!-- ❌ mal: dos sliders sueltos para un rango; nada impide que el mínimo pase al máximo -->
197
+ <sui-slider label="Precio mínimo" [min]="0" [max]="100" [(value)]="precioMin" />
198
+ <sui-slider label="Precio máximo" [min]="0" [max]="100" [(value)]="precioMax" />
199
+ ```
200
+
201
+ ```html
202
+ <!-- ✅ bien: una barra con dos manijas -->
203
+ <sui-slider type="range" label="Precio" [amount]="'S/ ' + precioMin() + ' – S/ ' + precioMax()"
204
+ [min]="0" [max]="100" [(minValue)]="precioMin" [(maxValue)]="precioMax" />
205
+ ```
206
+
141
207
  ## Ejemplo
142
208
 
143
209
  ```html
144
210
  <sui-slider
211
+ [size]="(bp.isMobile() || bp.toque()) ? 'large' : 'medium'"
145
212
  label="Radio de cobertura"
146
213
  [amount]="radioKm() + ' km'"
147
214
  [min]="1" [max]="15" [step]="1"