@ajuarezso/sui-design-system 0.25.0 → 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 (118) hide show
  1. package/docs/sui-accordion/README.md +83 -9
  2. package/docs/sui-activity-feed/README.md +55 -1
  3. package/docs/sui-activity-filter/README.md +50 -1
  4. package/docs/sui-alert/README.md +54 -0
  5. package/docs/sui-app-store-badge/README.md +57 -3
  6. package/docs/sui-avatar/README.md +66 -6
  7. package/docs/sui-avatar-group/README.md +64 -2
  8. package/docs/sui-badge/README.md +79 -11
  9. package/docs/sui-banner/README.md +70 -5
  10. package/docs/sui-brand-logo/README.md +77 -14
  11. package/docs/sui-breadcrumb-item/README.md +51 -0
  12. package/docs/sui-breadcrumbs/README.md +48 -0
  13. package/docs/sui-button/README.md +68 -6
  14. package/docs/sui-button-group/README.md +70 -5
  15. package/docs/sui-button-group-item/README.md +68 -4
  16. package/docs/sui-card/README.md +97 -10
  17. package/docs/sui-chart-legend/README.md +53 -0
  18. package/docs/sui-chart-legend-dot/README.md +49 -0
  19. package/docs/sui-checkbox/README.md +106 -26
  20. package/docs/sui-checkbox-card/README.md +58 -2
  21. package/docs/sui-checkbox-label/README.md +89 -23
  22. package/docs/sui-circular-progress-bar/README.md +63 -5
  23. package/docs/sui-color-dot/README.md +61 -5
  24. package/docs/sui-color-picker/README.md +62 -4
  25. package/docs/sui-command-menu-footer/README.md +49 -0
  26. package/docs/sui-command-menu-item/README.md +63 -4
  27. package/docs/sui-command-menu-search/README.md +58 -4
  28. package/docs/sui-compact-avatar-group/README.md +61 -4
  29. package/docs/sui-compact-button/README.md +112 -28
  30. package/docs/sui-compact-select/README.md +58 -4
  31. package/docs/sui-compact-select-for-input/README.md +69 -5
  32. package/docs/sui-content-card/README.md +63 -2
  33. package/docs/sui-content-divider/README.md +49 -1
  34. package/docs/sui-content-label/README.md +83 -4
  35. package/docs/sui-counter-input/README.md +91 -7
  36. package/docs/sui-date-selector/README.md +61 -3
  37. package/docs/sui-datepicker/README.md +72 -5
  38. package/docs/sui-day-cell/README.md +60 -3
  39. package/docs/sui-day-label/README.md +52 -3
  40. package/docs/sui-divider/README.md +57 -5
  41. package/docs/sui-drawer-footer/README.md +63 -2
  42. package/docs/sui-drawer-header/README.md +60 -3
  43. package/docs/sui-dropdown-caption/README.md +53 -1
  44. package/docs/sui-dropdown-item/README.md +72 -6
  45. package/docs/sui-dropdown-menu/README.md +74 -5
  46. package/docs/sui-dropdown-search/README.md +57 -1
  47. package/docs/sui-emoji/README.md +82 -18
  48. package/docs/sui-empty-state/README.md +68 -4
  49. package/docs/sui-fancy-button/README.md +59 -1
  50. package/docs/sui-file-icon/README.md +56 -1
  51. package/docs/sui-file-upload/README.md +69 -9
  52. package/docs/sui-file-upload-card/README.md +53 -2
  53. package/docs/sui-filter/README.md +74 -5
  54. package/docs/sui-flag/README.md +62 -1
  55. package/docs/sui-form-hint/README.md +54 -5
  56. package/docs/sui-form-label/README.md +53 -1
  57. package/docs/sui-href/README.md +47 -0
  58. package/docs/sui-icon/README.md +69 -4
  59. package/docs/sui-image-upload/README.md +70 -3
  60. package/docs/sui-image-upload-profile/README.md +58 -0
  61. package/docs/sui-img-retry/README.md +49 -0
  62. package/docs/sui-inline-input/README.md +61 -3
  63. package/docs/sui-inline-select/README.md +60 -0
  64. package/docs/sui-input/README.md +77 -14
  65. package/docs/sui-integration-switch/README.md +69 -2
  66. package/docs/sui-kbd/README.md +71 -7
  67. package/docs/sui-key-icon/README.md +65 -6
  68. package/docs/sui-link-button/README.md +79 -13
  69. package/docs/sui-logo/README.md +74 -4
  70. package/docs/sui-modal/README.md +61 -2
  71. package/docs/sui-modal-footer/README.md +83 -9
  72. package/docs/sui-modal-header/README.md +56 -0
  73. package/docs/sui-modal-sheet/README.md +72 -10
  74. package/docs/sui-notification/README.md +71 -1
  75. package/docs/sui-notification-footer/README.md +51 -1
  76. package/docs/sui-notification-tab-menu/README.md +57 -1
  77. package/docs/sui-otp-input/README.md +67 -6
  78. package/docs/sui-page-header/README.md +83 -15
  79. package/docs/sui-pagination/README.md +60 -0
  80. package/docs/sui-password-strength/README.md +50 -1
  81. package/docs/sui-payment-icon/README.md +66 -7
  82. package/docs/sui-period-range/README.md +65 -6
  83. package/docs/sui-popover/README.md +73 -7
  84. package/docs/sui-product-card/README.md +76 -8
  85. package/docs/sui-progress-bar/README.md +72 -8
  86. package/docs/sui-progress-bar-label/README.md +69 -12
  87. package/docs/sui-radio/README.md +83 -6
  88. package/docs/sui-radio-card/README.md +58 -4
  89. package/docs/sui-radio-label/README.md +86 -19
  90. package/docs/sui-rating/README.md +81 -14
  91. package/docs/sui-rich-editor/README.md +45 -0
  92. package/docs/sui-segmented-control/README.md +83 -14
  93. package/docs/sui-select/README.md +72 -3
  94. package/docs/sui-sidebar/README.md +64 -9
  95. package/docs/sui-slider/README.md +68 -1
  96. package/docs/sui-social-button/README.md +63 -3
  97. package/docs/sui-status-badge/README.md +64 -6
  98. package/docs/sui-stepper/README.md +57 -0
  99. package/docs/sui-store-card/README.md +71 -8
  100. package/docs/sui-switch/README.md +80 -9
  101. package/docs/sui-switch-card/README.md +70 -6
  102. package/docs/sui-switch-label/README.md +90 -13
  103. package/docs/sui-tab-chips/README.md +79 -9
  104. package/docs/sui-tab-menu-horizontal/README.md +62 -1
  105. package/docs/sui-tab-menu-vertical/README.md +56 -3
  106. package/docs/sui-table/README.md +68 -7
  107. package/docs/sui-tag/README.md +75 -4
  108. package/docs/sui-tag-input/README.md +71 -7
  109. package/docs/sui-textarea/README.md +78 -11
  110. package/docs/sui-time-picker/README.md +70 -7
  111. package/docs/sui-toast/README.md +65 -5
  112. package/docs/sui-tooltip/README.md +61 -4
  113. package/docs/sui-topbar/README.md +57 -3
  114. package/docs/sui-topbar-button/README.md +57 -3
  115. package/docs/sui-topbar-item/README.md +61 -0
  116. package/docs/sui-topbar-user/README.md +56 -0
  117. package/package.json +1 -1
  118. package/types/ajuarezso-sui-design-system.d.ts +19 -19
@@ -110,8 +110,8 @@ Hoy: 45 `small`, 63 `medium` (50 explícitos + 13 por default), 5 `large`, 14 `x
110
110
  | `statusAlignment` | quita el header y pone ícono + texto dentro del body (`vertical` centrado, `horizontal` en fila) | pantallas de resultado («Pedido enviado») o confirmaciones con más peso visual. Requiere `iconVariant` o `headerIcon`. 0 usos hoy | según el Figma del DS (Status Modals) |
111
111
 
112
112
  **Usos de hoy que rompen el copy canon** (CANON-SUI: títulos en sentence case):
113
- `pages/super-admin/super-admin.html:353` «Suspender Negocio», `:471` «Evidencia de Pago»,
114
- `:487` «Rechazar Solicitud», `:557` «Rechazar Promoción».
113
+ `pages/super-admin/super-admin.html:364` «Suspender Negocio», `:484` «Evidencia de Pago»,
114
+ `:501` «Rechazar Solicitud», `:572` «Rechazar Promoción» (líneas al 06-10-2026).
115
115
 
116
116
  ### Cerrar
117
117
 
@@ -140,6 +140,17 @@ interno lo pone quien proyecta. Canon (CLAUDE.md, 2026-07-21).
140
140
 
141
141
  El modal **no tiene un size para mobile**: la decisión de mobile es `fullscreen`.
142
142
 
143
+ ### Por dispositivo (D16)
144
+
145
+ No aplica: `size` es el **ancho del modal centrado** y lo elige el contenido (tabla de arriba), no
146
+ el dispositivo; a 768 px o menos ni se usa, porque el modal toma el ancho completo (centrado o
147
+ fullscreen). En la tablet de 820 o 1024 px el modal se ve centrado con su `size`, igual que en la
148
+ computadora y el ultrawide. Lo que se toca adentro lleva su propio D16: el pie va `large` en todos
149
+ los dispositivos (D2) y los campos del body siguen la fila de `input`.
150
+
151
+ En master-pedidos: sin helper para el modal; `<sui-modal-footer>` sin `buttonSize` (ya es
152
+ `large`) y los campos del body con `[size]="bp.sizeControl()"`.
153
+
143
154
  ## API
144
155
 
145
156
  <!-- api:inicio -->
@@ -201,6 +212,54 @@ pinta una sombra sobre el footer).
201
212
  - `(closed)` se emite **después** de cerrar, por cualquier vía (X, backdrop, Escape o
202
213
  `open = false`). Para limpiar estado, escúchalo ahí y no en el botón.
203
214
 
215
+ ## Bien y mal
216
+
217
+ Confirmación de sí o no
218
+
219
+ ```html
220
+ <!-- ❌ mal: sin [fullscreen]="false", el 'auto' lo abre a pantalla completa en la app (components/confirm-dialog/confirm-dialog.html:1) -->
221
+ <sui-modal [(open)]="open" size="small"
222
+ [title]="title()" [description]="description()" [closeOnBackdrop]="false">
223
+ <sui-modal-footer slot="footer" secondaryButton="Cancelar" primaryButton="Confirmar" />
224
+ </sui-modal>
225
+ ```
226
+
227
+ ```html
228
+ <!-- ✅ bien -->
229
+ <sui-modal [(open)]="open" size="small" [fullscreen]="false"
230
+ [title]="title()" [description]="description()" [closeOnBackdrop]="false">
231
+ <sui-modal-footer slot="footer" secondaryButton="Cancelar" primaryButton="Confirmar" />
232
+ </sui-modal>
233
+ ```
234
+
235
+ Pie con los botones
236
+
237
+ ```html
238
+ <!-- ❌ mal: sin slot="footer" el pie cae dentro del body: doble padding y scrollea con el contenido -->
239
+ <sui-modal [(open)]="creando" title="Crear descuento">
240
+ <sui-modal-footer secondaryButton="Cancelar" primaryButton="Crear descuento" />
241
+ </sui-modal>
242
+ ```
243
+
244
+ ```html
245
+ <!-- ✅ bien -->
246
+ <sui-modal [(open)]="creando" title="Crear descuento">
247
+ <sui-modal-footer slot="footer" secondaryButton="Cancelar" primaryButton="Crear descuento" />
248
+ </sui-modal>
249
+ ```
250
+
251
+ Título del modal
252
+
253
+ ```html
254
+ <!-- ❌ mal: título en Title Case; el canon es sentence case (pages/super-admin/super-admin.html:364) -->
255
+ <sui-modal [(open)]="suspendiendo" iconVariant="error" title="Suspender Negocio" />
256
+ ```
257
+
258
+ ```html
259
+ <!-- ✅ bien -->
260
+ <sui-modal [(open)]="suspendiendo" iconVariant="error" title="Suspender negocio" />
261
+ ```
262
+
204
263
  ## Ejemplo
205
264
 
206
265
  ```html
@@ -49,8 +49,8 @@ peso de los botones** de toda la app: no solo de los modales.
49
49
  | acciones | cómo | ejemplo real de la app | fuente |
50
50
  |---|---|---|---|
51
51
  | **1** | solo `primaryButton`. Queda a la derecha, no a todo el ancho (para eso, `[stretch]="true"`) | `pages/super-admin/master-sonidos-push/master-sonidos-push.html:146` («Cerrar») | canon (CLAUDE.md) |
52
- | **2** | `secondaryButton` + `primaryButton`. El componente los pone en orden: secundario a la izquierda | `pages/driver/driver-dashboard/driver-dashboard.html:1574` («Cancelar» / «Enviar») | canon (CLAUDE.md) |
53
- | **3+** | **no hay tercer botón.** La tercera acción va como `sui-link-button` en el slot izquierdo | `components/add-product-modal/add-product-modal.html:332` («Vista previa») | canon (CLAUDE.md) |
52
+ | **2** | `secondaryButton` + `primaryButton`. El componente los pone en orden: secundario a la izquierda | `pages/driver/driver-dashboard/driver-dashboard.html:1691` («Cancelar» / «Enviar») | canon (CLAUDE.md) |
53
+ | **3+** | **no hay tercer botón.** La tercera acción va como `sui-link-button` en el slot izquierdo | `components/add-product-modal/add-product-modal.html:334` («Vista previa») | canon (CLAUDE.md) |
54
54
 
55
55
  ### El slot izquierdo
56
56
 
@@ -58,7 +58,7 @@ peso de los botones** de toda la app: no solo de los modales.
58
58
  |---|---|---|---|
59
59
  | `sui-link-button` | la tercera acción, de menos peso | `pages/central/central-gastos/central-gastos.html:97` | canon (CLAUDE.md) |
60
60
  | `sui-checkbox-label` / `sui-switch-label` | una opción que acompaña la confirmación («No volver a preguntar») | (sin uso hoy) | según el Figma del DS |
61
- | texto | un dato que se lee antes de confirmar («Llega a las 8:30») | `components/add-product-modal/add-product-modal.html:359` | según el Figma del DS |
61
+ | texto | un dato que se lee antes de confirmar («Llega a las 8:30») | `components/add-product-modal/add-product-modal.html:361` | según el Figma del DS |
62
62
  | `sui-counter-input` (stepper) | elegir cantidad junto al botón de agregar | `pages/customer/restaurant-menu/restaurant-menu.html:461` | según el Figma del DS |
63
63
 
64
64
  Con `stretch` y algo en el slot izquierdo, se reparte 50 % slot / 50 % botones.
@@ -84,12 +84,14 @@ aprobación: `[stretch]="bp.isMobile()"` para que desktop vuelva al tipo Basic.
84
84
 
85
85
  **Usos de hoy que rompen el canon:**
86
86
 
87
- - **3 footers con un solo botón en `secondaryButton`** → pasarlo a `primaryButton`:
88
- `pages/driver/driver-dashboard/driver-dashboard.html:1272`, `:1419` y `:1555` (los tres
89
- «Cerrar»). Contraargumento a decidir: en un modal que solo informa, un «Cerrar» relleno de
87
+ - **4 footers con un solo botón en `secondaryButton`** → pasarlo a `primaryButton`:
88
+ `pages/driver/driver-dashboard/driver-dashboard.html:1390`, `:1537` y `:1673` (los tres
89
+ «Cerrar»), y `pages/central/central-gastos/central-gastos.html:97` cuando el gasto está
90
+ anulado (el primario pasa a `null` y queda solo «Cerrar»). Contraargumento a decidir: en un modal que solo informa, un «Cerrar» relleno de
90
91
  naranja grita más que el contenido; si se prefiere así, hay que escribirlo como excepción.
91
92
  - **1 pie hecho a mano** con dos `sui-button` en un `<div slot="footer">` →
92
- `sui-modal-footer`: `components/copy-text-dialog/copy-text-dialog.html:15`.
93
+ `sui-modal-footer`: `components/copy-text-dialog/copy-text-dialog.html:16`. Al migrarlo se
94
+ pierde el ícono del botón «Copiar» (`file-copy-line` → `check-line`): ver «Bien y mal».
93
95
  - Botones `sui-button` proyectados dentro del footer: 0.
94
96
 
95
97
  ## Tamaño en mobile y en web
@@ -102,8 +104,25 @@ aprobación: `[stretch]="bp.isMobile()"` para que desktop vuelva al tipo Basic.
102
104
 
103
105
  `buttonSize` existe para un caso puntual, no para «achicar porque se ve grande». Hoy 0 usos.
104
106
 
105
- `CANON-SUI.md` §6.3 todavía dice «botones `small`»: quedó viejo frente a la decisión del
106
- 2026-07-23 y al default del componente.
107
+ `CANON-SUI.md` §6.3 ya dice lo mismo: footer de modal con botones `large` (48), por encima del
108
+ Figma que dibuja `small`.
109
+
110
+ ### Por dispositivo (D16)
111
+
112
+ D16 lo nombra en la fila de `button`: **footer de modal, `large` siempre** (D2). No baja a
113
+ `medium` en la computadora como los botones sueltos.
114
+
115
+ | dispositivo | size | nota |
116
+ |---|---|---|
117
+ | celular chico (< 380) | `large` | ya llega a 48, no necesita el área de 44 aparte |
118
+ | celular (380–767) | `large` | |
119
+ | tablet táctil | `large` | |
120
+ | computadora | `large` | D2 manda sobre la regla de `medium` en la computadora |
121
+
122
+ Ultrawide: igual, `large`. Fuente: D16, dueño 05-10-2026 (fila `button`) y D2.
123
+
124
+ En master-pedidos: no se pasa `buttonSize`; `null` ya resuelve a `large`. Nunca
125
+ `[buttonSize]="bp.sizeControl()"`: en la computadora bajaría a `medium`.
107
126
 
108
127
  ## API
109
128
 
@@ -154,6 +173,61 @@ Slot: `<ng-content>` sin selector → el bloque **izquierdo**.
154
173
  - Dentro de `sui-modal` el footer recibe una sombra arriba mientras el body tiene más contenido
155
174
  para scrollear (`scrollActive`).
156
175
 
176
+ ## Bien y mal
177
+
178
+ Un modal que solo informa
179
+
180
+ ```html
181
+ <!-- ❌ mal: la única acción va en el secundario (pages/driver/driver-dashboard/driver-dashboard.html:1390) -->
182
+ <sui-modal-footer slot="footer" secondaryButton="Cerrar"
183
+ (secondaryClick)="modalTope.set(false)" />
184
+ ```
185
+
186
+ ```html
187
+ <!-- ✅ bien -->
188
+ <sui-modal-footer slot="footer" primaryButton="Cerrar"
189
+ (primaryClick)="modalTope.set(false)" />
190
+ ```
191
+
192
+ Copiar un texto y cerrar
193
+
194
+ ```html
195
+ <!-- ❌ mal: pie hecho a mano con dos sui-button (components/copy-text-dialog/copy-text-dialog.html:16) -->
196
+ <div slot="footer">
197
+ <sui-button variant="stroke" color="neutral" size="large" (click)="close()">{{ closeLabel() }}</sui-button>
198
+ <sui-button variant="filled" color="primary" size="large" (click)="onCopy()">
199
+ <sui-icon data-slot="start" [name]="copied() ? 'check-line' : 'file-copy-line'" [size]="16" />
200
+ {{ copied() ? copiedLabel() : copyLabel() }}
201
+ </sui-button>
202
+ </div>
203
+ ```
204
+
205
+ ```html
206
+ <!-- ✅ bien: el label sigue al estado copiado -->
207
+ <sui-modal-footer slot="footer" [secondaryButton]="closeLabel()"
208
+ [primaryButton]="copied() ? copiedLabel() : copyLabel()"
209
+ (secondaryClick)="close()" (primaryClick)="onCopy()" />
210
+ ```
211
+
212
+ Lo que se pierde: el ícono. `SuiFooterButtonConfig` solo acepta `label`, `disabled` y `color`, así
213
+ que el footer no dibuja el `sui-icon` que hoy pasa de `file-copy-line` a `check-line`. El aviso de
214
+ «copiado» sigue llegando por el label («Copiar» → «Copiado»). Conservar el ícono pide un `icon` en
215
+ `SuiFooterButtonConfig`, que hoy no existe (**propuesta**, sin decidir); no es razón para volver al
216
+ pie a mano.
217
+
218
+ Botones del footer en la computadora
219
+
220
+ ```html
221
+ <!-- ❌ mal: D16 deja el footer en large siempre (D2); esto lo baja a medium en la computadora -->
222
+ <sui-modal-footer slot="footer" secondaryButton="Cancelar" primaryButton="Guardar"
223
+ [buttonSize]="bp.sizeControl()" />
224
+ ```
225
+
226
+ ```html
227
+ <!-- ✅ bien: sin buttonSize, resuelve a large -->
228
+ <sui-modal-footer slot="footer" secondaryButton="Cancelar" primaryButton="Guardar" />
229
+ ```
230
+
157
231
  ## Ejemplo
158
232
 
159
233
  ```html
@@ -63,6 +63,17 @@ mobile y en web. La X mide 24 px en las dos (`sui-compact-button` `large`).
63
63
  | con descripción | `medium` | `medium` | según el Figma del DS |
64
64
  | solo título | `small` | `small` | según el Figma del DS |
65
65
 
66
+ ### Por dispositivo (D16)
67
+
68
+ No aplica: el `size` lo decide si hay `description` (56 solo título, 80 con descripción), no el
69
+ dispositivo, y D16 deja fuera este `small` porque cambia el layout y no la escala. Es igual en el
70
+ celular chico, el celular, la tablet, la computadora y el ultrawide. La X es un
71
+ `sui-compact-button` interno de 24 a la vista; su área de 44 se prende solo bajo 768 px
72
+ (`sui-modal-header.scss:119`), así que en la tablet táctil todavía no la tiene: eso espera el
73
+ mixin `sui-tactil` de la propuesta de D16, **pendiente** del sí del dueño.
74
+
75
+ En master-pedidos: `[size]="description ? 'medium' : 'small'"`, nunca una señal de `bp`.
76
+
66
77
  ## API
67
78
 
68
79
  <!-- api:inicio -->
@@ -98,6 +109,51 @@ mobile y en web. La X mide 24 px en las dos (`sui-compact-button` `large`).
98
109
  en `aria-labelledby`.
99
110
  - El host borra el atributo `title` nativo (sin tooltip gris del navegador).
100
111
 
112
+ ## Bien y mal
113
+
114
+ La cabecera de un modal
115
+
116
+ ```html
117
+ <!-- ❌ mal: sui-modal ya dibuja su header; quedan dos cabeceras -->
118
+ <sui-modal [(open)]="abierto" [fullscreen]="true">
119
+ <sui-modal-header title="Editar producto" icon="edit-line" (closed)="abierto.set(false)" />
120
+ </sui-modal>
121
+ ```
122
+
123
+ ```html
124
+ <!-- ✅ bien -->
125
+ <sui-modal [(open)]="abierto" [fullscreen]="true" title="Editar producto" headerIcon="edit-line">
126
+ </sui-modal>
127
+ ```
128
+
129
+ Cabecera con descripción
130
+
131
+ ```html
132
+ <!-- ❌ mal: con description va medium; en small el ícono pasa a plano de 24 -->
133
+ <sui-modal-header size="small" title="Filtros" description="Elige qué pedidos ver" icon="filter-line" />
134
+ ```
135
+
136
+ ```html
137
+ <!-- ✅ bien -->
138
+ <sui-modal-header size="medium" title="Filtros" description="Elige qué pedidos ver" icon="filter-line" />
139
+ ```
140
+
141
+ Un panel propio que hace de diálogo
142
+
143
+ ```html
144
+ <!-- ❌ mal: sin titleId el diálogo no tiene nombre accesible -->
145
+ <section class="panel" role="dialog">
146
+ <sui-modal-header size="small" title="Filtros" (closed)="cerrarPanel()" />
147
+ </section>
148
+ ```
149
+
150
+ ```html
151
+ <!-- ✅ bien -->
152
+ <section class="panel" role="dialog" aria-labelledby="filtros-titulo">
153
+ <sui-modal-header size="small" title="Filtros" titleId="filtros-titulo" (closed)="cerrarPanel()" />
154
+ </section>
155
+ ```
156
+
101
157
  ## Ejemplo
102
158
 
103
159
  ```html
@@ -47,12 +47,13 @@ conviene copiar una de las dos en vez de inventar otra.
47
47
 
48
48
  | patrón | `breakpoints` | `initialBreakpoint` | `backdropBreakpoint` | cuándo | ejemplo real de la app | fuente |
49
49
  |---|---|---|---|---|---|---|
50
- | **Sobre un mapa** | `[0.25, 0.5, 0.7, 1]` (sin `0`) | `0.5` | `1` | el seguimiento: el mapa se usa a cualquier altura y la hoja no se puede cerrar | `pages/customer/order-tracking/order-tracking.html:130` · `pages/driver/driver-order-detail/driver-order-detail.html:60` | canon (aprobado por el dueño, 05-10-2026, bloque B9) |
51
- | **Hoja de lectura** | `[0, 0.92]` | `0.92` | `0` | una lista o detalle que se abre y se cierra deslizando, con el fondo apagado | `pages/customer/order-tracking/order-tracking.html:809` (reseñas) · `pages/customer/checkout/checkout.html:448` (hora) | canon (aprobado por el dueño, 05-10-2026, bloque B9) |
50
+ | **Sobre un mapa** | `[0.25, 0.5, 0.7, 1]` (sin `0`) | `0.5` | `1` | el seguimiento: el mapa se usa a cualquier altura y la hoja no se puede cerrar | `pages/customer/order-tracking/order-tracking.html:139` · `pages/driver/driver-order-detail/driver-order-detail.html:60` | canon (aprobado por el dueño, 05-10-2026, bloque B9) |
51
+ | **Hoja de lectura** | `[0, 0.92]` | `0.92` | `0` | una lista o detalle que se abre y se cierra deslizando, con el fondo apagado | `pages/customer/order-tracking/order-tracking.html:836` (reseñas) · `pages/customer/checkout/checkout.html:449` (hora, con tope `0.96`) | canon (aprobado por el dueño, 05-10-2026, bloque B9) |
52
52
 
53
- Hoy: 4 «sobre un mapa» (más 2 variantes con alturas propias: `pages/envios/envios.html:578` y
54
- `pages/customer/viaje/viaje.html:24`), 5 hojas de lectura en `0.92`–`0.96`, 2 en `[0, 1]` y 1 en
55
- `[0, 0.6, 0.95]`.
53
+ Hoy: 3 «sobre un mapa» (`order-tracking.html:139`, `driver-order-detail.html:60` y
54
+ `pages/super-admin/master-map-overview/master-map-overview.html:35`), más 2 variantes con alturas
55
+ propias (`pages/envios/envios.html:584` y `pages/customer/viaje/viaje.html:30`), 5 hojas de
56
+ lectura en `0.92`–`0.96`, 2 en `[0, 1]` y 1 en `[0, 0.6, 0.95]`. Suman los 13.
56
57
 
57
58
  | input | regla | fuente |
58
59
  |---|---|---|
@@ -65,9 +66,10 @@ Hoy: 4 «sobre un mapa» (más 2 variantes con alturas propias: `pages/envios/en
65
66
 
66
67
  **Usos de hoy a revisar:**
67
68
 
68
- - `pages/customer/viaje/viaje.html:24` reabre la hoja en `(closed)` (`hojaAbierta.set(true)`)
69
+ - `pages/customer/viaje/viaje.html:36` reabre la hoja en `(closed)` (`hojaAbierta.set(true)`)
69
70
  para que no se pueda cerrar. Sin `0` en `breakpoints` y con `[closeOnBackdrop]="false"` ya no se
70
- cierra; el reabrir sobra o tapa otro caso.
71
+ cierra con el dedo ni con el fondo; el caso que tapa es Escape (`closeOnEscape` sigue en `true`).
72
+ Con `[closeOnEscape]="false"` el reabrir sobra.
71
73
  - 2 footers de modal metidos en hojas: van sin `slot` (no hay slot de footer). Está bien, pero el
72
74
  botón scrollea con el contenido: `pages/customer/checkout/checkout.html:490`,
73
75
  `pages/super-admin/master-sonidos-push/master-sonidos-push.html:146`.
@@ -86,11 +88,22 @@ El sheet **no tiene `size`**. Mide lo que mide su contenido, con tope en el brea
86
88
 
87
89
  **El sheet no se acota en desktop.** La app lo arregla con CSS propio, cinco reglas en cuatro archivos:
88
90
  `components/store-ratings-modal/store-ratings-modal.scss:81`,
89
- `pages/driver/movimientos/movimientos-sheet.scss:24`,
90
- `pages/driver/driver-order-detail/driver-order-detail.scss:1028` y
91
- `pages/customer/order-tracking/order-tracking.scss:1175` y `:1238`, todos a 560 px. Propuesta:
91
+ `components/movimientos-saldo/movimientos-saldo-sheet.scss:25`,
92
+ `pages/driver/driver-order-detail/driver-order-detail.scss:1096` (las tres a 560 px) y
93
+ `pages/customer/order-tracking/order-tracking.scss:1175` y `:1238` (a 480 px). Propuesta:
92
94
  que el DS traiga ese tope (`max-width` desde 768 px, centrado) y se borren esos parches.
93
95
 
96
+ ### Por dispositivo (D16)
97
+
98
+ No aplica: el sheet **no tiene `size`**; mide lo que mide su contenido y se configura con alturas
99
+ (`breakpoints`), no con un tamaño. Es igual en el celular chico, el celular, la tablet táctil, la
100
+ computadora y el ultrawide. El tamaño de lo que va adentro (botones, campos) sigue su propia
101
+ fila de D16. Lo único que cambia por dispositivo es el ancho desde 768 px, y eso es P21
102
+ (**pendiente**: acotarlo a 560 en el DS o dejar los parches) y no se decide aquí.
103
+
104
+ En master-pedidos: sin `[size]`; en desktop, cuando hay sitio, la pantalla puede mostrar el
105
+ contenido en un panel en vez de la hoja (`pages/customer/viaje/viaje.html:25`, con `@if (escritorio())`).
106
+
94
107
  ## API
95
108
 
96
109
  <!-- api:inicio -->
@@ -145,6 +158,55 @@ Slot: un solo `<ng-content>`, el body. No hay header ni footer.
145
158
  ejemplo para centrarlo en desktop) sin romper el arrastre.
146
159
  - Pide ocultar la barra inferior de la app por `SUI_NAVBAR_VISIBILITY`, igual que `sui-modal`.
147
160
 
161
+ ## Bien y mal
162
+
163
+ Una hoja que no se puede cerrar
164
+
165
+ ```html
166
+ <!-- ❌ mal: la reabre en (closed) para tapar el cierre (pages/customer/viaje/viaje.html:36) -->
167
+ <sui-modal-sheet [(open)]="hojaAbierta" [breakpoints]="[0.35, 0.6, 0.92]"
168
+ [backdropBreakpoint]="1" [closeOnBackdrop]="false"
169
+ (closed)="hojaAbierta.set(true)">
170
+ ```
171
+
172
+ ```html
173
+ <!-- ✅ bien: sin 0 en breakpoints y sin Escape, no hay cierre que tapar -->
174
+ <sui-modal-sheet [(open)]="hojaAbierta" [breakpoints]="[0.35, 0.6, 0.92]"
175
+ [backdropBreakpoint]="1" [closeOnBackdrop]="false" [closeOnEscape]="false">
176
+ ```
177
+
178
+ Un formulario que hay que terminar
179
+
180
+ ```html
181
+ <!-- ❌ mal: un deslizón cierra la hoja y se pierde lo escrito -->
182
+ <sui-modal-sheet [(open)]="editando" [breakpoints]="[0, 0.92]" [initialBreakpoint]="0.92">
183
+ <sui-input label="Nombre del local" [(value)]="nombre" />
184
+ </sui-modal-sheet>
185
+ ```
186
+
187
+ ```html
188
+ <!-- ✅ bien -->
189
+ <sui-modal [(open)]="editando" [fullscreen]="true" title="Editar local">
190
+ <sui-input label="Nombre del local" [(value)]="nombre" />
191
+ </sui-modal>
192
+ ```
193
+
194
+ El margen del contenido
195
+
196
+ ```html
197
+ <!-- ❌ mal: el body ya trae 0 20px 20px; con el padding propio queda doble (el tracking del repartidor) -->
198
+ <sui-modal-sheet [(open)]="abierta" [breakpoints]="[0, 0.92]" [initialBreakpoint]="0.92">
199
+ <section style="padding: 16px 16px 48px">…</section>
200
+ </sui-modal-sheet>
201
+ ```
202
+
203
+ ```html
204
+ <!-- ✅ bien: la sección a 0, el margen lo pone el sheet -->
205
+ <sui-modal-sheet [(open)]="abierta" [breakpoints]="[0, 0.92]" [initialBreakpoint]="0.92">
206
+ <section>…</section>
207
+ </sui-modal-sheet>
208
+ ```
209
+
148
210
  ## Ejemplo
149
211
 
150
212
  ```html
@@ -103,7 +103,23 @@ La fila **no tiene `size`**: foto de 40 px, 12 px de relleno, texto de 14.
103
103
  | la fila | toda la fila se toca para abrirla: mide 64 px o más | igual | según el componente |
104
104
  | ⋮ (`showMore`) | se ve de 24 y se toca en 44 × 44 cuando está visible (foco o fila activa); oculto no recibe toques | 24 px | canon (dueño, 04-10-2026): piso táctil 44 en el teléfono |
105
105
  | la X (`dismissible`) | se ve de 20 px; **se toca en 44 × 44** | se ve de 20; se toca en 40 × 40 | canon (dueño, 04-10-2026): piso táctil 44 en el teléfono (antes 40, pedido del dueño 03-10-2026): área táctil invisible, extensión SUI |
106
- | botones de `type="button"` | los pone quien la usa: `[size]="bp.isMobile() ? 'large' : 'medium'"` | `medium` | mobile `large`: canon (decisión del dueño 04-10-2026, piso táctil 44) · web `medium`: canon (dueño, 05-10-2026, D16), reemplaza el `xsmall` del bloque B1 |
106
+ | botones de `type="button"` | los pone quien la usa: `[size]="bp.sizeControl()"` (`large`, también en la tablet táctil) | `medium` | mobile `large`: canon (decisión del dueño 04-10-2026, piso táctil 44) · web `medium` y tablet táctil `large`: D16, dueño 05-10-2026 (reemplaza el `xsmall` del bloque B1 y el `bp.isMobile()`, que dejaba la tablet en `medium`) |
107
+
108
+ ### Por dispositivo (D16)
109
+
110
+ Fila `notification` (botones) de la tabla D16 (dueño, 05-10-2026). La fila no tiene `size`: lo que
111
+ cambia por dispositivo son los `sui-button` de `slot="actions"` (`type="button"`), que se tocan.
112
+
113
+ | dispositivo | size | nota |
114
+ |---|---|---|
115
+ | celular chico (< 380 px) | `large` (48) | D16 pide `medium` con área tocable de 44; mientras el DS no estire el área de los `medium`, va `large` (interino) |
116
+ | celular (380–767 px) | `large` (48) | la X y el ⋮ se tocan en 44 × 44 |
117
+ | tablet táctil (`pointer: coarse`) | `large` (48) | la X queda en 40 × 40 y el ⋮ en 24: su área de 44 se prende solo con `max-width: 767px`. **Pendiente**: el mixin `sui-tactil` (`pointer: coarse`) espera el sí del dueño |
118
+ | computadora (`pointer: fine`) | `medium` (40) | `small`, `xsmall` y `2xsmall` no se usan |
119
+
120
+ Ultrawide (≥ 1920 px): igual que la computadora, `medium`.
121
+
122
+ En master-pedidos: `[size]="bp.sizeControl()"` en los `sui-button` de `slot="actions"`.
107
123
 
108
124
  ## «No usar»: por qué no hoy y cuándo sí
109
125
 
@@ -169,6 +185,60 @@ Slots: `[slot=company-logo]`, `[slot=file]`, `[slot=message]`, el contenido libr
169
185
  después de la hora («Hace 8 min ∙»).
170
186
  - Borra el `title` nativo del host.
171
187
 
188
+ ## Bien y mal
189
+
190
+ Botones de una solicitud (`type="button"`)
191
+
192
+ ```html
193
+ <!-- ❌ mal: xsmall (32) no llega al dedo y D16 no usa chicos (vitrina: pages/super-admin/master-preview/_guia-moleculas/avisos.ts:242) -->
194
+ <sui-notification [avatar]="{ initials: 'MR' }" type="button" title="Miguel Rojas te invitó a su equipo">
195
+ <span slot="actions">
196
+ <sui-button variant="stroke" color="neutral" size="xsmall">Rechazar</sui-button>
197
+ <sui-button size="xsmall">Aprobar</sui-button>
198
+ </span>
199
+ </sui-notification>
200
+ ```
201
+
202
+ ```html
203
+ <!-- ✅ bien -->
204
+ <sui-notification [avatar]="{ initials: 'MR' }" type="button" title="Miguel Rojas te invitó a su equipo">
205
+ <span slot="actions">
206
+ <sui-button variant="stroke" color="neutral" [size]="bp.sizeControl()">Rechazar</sui-button>
207
+ <sui-button [size]="bp.sizeControl()">Aprobar</sui-button>
208
+ </span>
209
+ </sui-notification>
210
+ ```
211
+
212
+ Aviso del sistema en la bandeja
213
+
214
+ ```html
215
+ <!-- ❌ mal: con tipo y sin foto la fila se vuelve un alert con borde y sombra (vitrina: avisos.ts:253) -->
216
+ <sui-notification variant="success" title="Recarga aprobada"
217
+ description="Ya tienes S/ 20.00 en tu saldo" timestamp="Hace 1 h" />
218
+ ```
219
+
220
+ ```html
221
+ <!-- ✅ bien: el isotipo de la app como foto, sin variant -->
222
+ <sui-notification [avatar]="isotipo" title="Recarga aprobada"
223
+ description="Ya tienes S/ 20.00 en tu saldo" timestamp="Hace 1 h" />
224
+ ```
225
+
226
+ Acciones de la fila
227
+
228
+ ```html
229
+ <!-- ❌ mal: el ⋮ y la X van los dos arriba a la derecha y se pisan -->
230
+ <sui-notification [avatar]="n.foto" title="Nuevo pedido" timestamp="Hace 5 min"
231
+ description="Pollería El Dorado · S/ 42.50"
232
+ [showMore]="true" [dismissible]="true" />
233
+ ```
234
+
235
+ ```html
236
+ <!-- ✅ bien: uno solo (aquí, la X; el ⋮ es solo para web con mouse) -->
237
+ <sui-notification [avatar]="n.foto" title="Nuevo pedido" timestamp="Hace 5 min"
238
+ description="Pollería El Dorado · S/ 42.50"
239
+ [dismissible]="true" (dismissed)="quitar(n)" />
240
+ ```
241
+
172
242
  ## Ejemplo
173
243
 
174
244
  ```html
@@ -45,7 +45,7 @@ la barra superior, con filas `sui-notification` y la cabecera `sui-notification-
45
45
  | uso | mobile | web | fuente |
46
46
  |---|---|---|---|
47
47
  | el pie entero | no aplica: es ayuda de teclado; en mobile no se muestra (el componente no se oculta solo: lo esconde quien lo usa) | 48 px de alto (14 + 20 de la tecla + 14) | alto: según el componente · ocultarlo en mobile: canon (aprobado por el dueño, 05-10-2026, bloque B7) |
48
- | el link de ajustes | si hiciera falta, un `sui-link-button` `large` suelto | `small` (16 px) | propuesta |
48
+ | el link de ajustes | si hiciera falta, un `sui-link-button` suelto: su size en el celular y la tablet sigue **pendiente** (P8 de la tabla D16) | `small` (16 px), fijo dentro del componente | `small` fijo: según el componente · choca con el «nada en `small`» de D16 (el `link-button` va `medium` en la computadora): **pendiente** del componente, quien lo usa no lo puede cambiar |
49
49
 
50
50
  ```html
51
51
  @if (!bp.isMobile()) {
@@ -54,6 +54,15 @@ la barra superior, con filas `sui-notification` y la cabecera `sui-notification-
54
54
  }
55
55
  ```
56
56
 
57
+ ### Por dispositivo (D16)
58
+
59
+ No aplica: no tiene `size` y solo se usa en la computadora (y el ultrawide), porque la mitad del
60
+ pie es una ayuda de **teclado**; en el celular chico y en el celular no se muestra. En la tablet
61
+ táctil de 768 px o más `bp.isMobile()` lo deja visible y el link de 16 px no llega al piso de 44:
62
+ queda **pendiente**, igual que el resto del panel de la campana (`sui-notification-tab-menu`).
63
+
64
+ En master-pedidos: sin helper; `@if (!bp.isMobile())` alrededor.
65
+
57
66
  ## «No usar»: por qué no hoy y cuándo sí
58
67
 
59
68
  | qué | por qué no hoy | cuándo sí, en un flujo nuevo |
@@ -90,6 +99,47 @@ interface SuiLinkConfig { label: string; href?: string; target?: string; rel?: s
90
99
  - Ocupa el 100 % del ancho de su contenedor (el Figma lo dibuja de 540 px).
91
100
  - Borra el `title` nativo del host.
92
101
 
102
+ ## Bien y mal
103
+
104
+ Link a los ajustes
105
+
106
+ ```html
107
+ <!-- ❌ mal: con un texto y sin (manageClick) ni href, el link no lleva a ningún lado (vitrina: pages/super-admin/master-preview/_guia-moleculas/avisos.ts:268) -->
108
+ <sui-notification-footer manage="Ajustes de notificaciones" />
109
+ ```
110
+
111
+ ```html
112
+ <!-- ✅ bien -->
113
+ <sui-notification-footer
114
+ [manage]="{ label: 'Ajustes de notificaciones', href: '/empresa/notificaciones' }" />
115
+ ```
116
+
117
+ Texto del link
118
+
119
+ ```html
120
+ <!-- ❌ mal: sin manage sale «Administrar notificaciones», que no nombra la pantalla a la que lleva -->
121
+ <sui-notification-footer (manageClick)="abrirAjustes()" />
122
+ ```
123
+
124
+ ```html
125
+ <!-- ✅ bien -->
126
+ <sui-notification-footer manage="Ajustes de notificaciones" (manageClick)="abrirAjustes()" />
127
+ ```
128
+
129
+ En el celular
130
+
131
+ ```html
132
+ <!-- ❌ mal: «Usa ↑ ↓ para moverte» en una pantalla sin teclado; el componente no se oculta solo -->
133
+ <sui-notification-footer manage="Ajustes de notificaciones" (manageClick)="abrirAjustes()" />
134
+ ```
135
+
136
+ ```html
137
+ <!-- ✅ bien -->
138
+ @if (!bp.isMobile()) {
139
+ <sui-notification-footer manage="Ajustes de notificaciones" (manageClick)="abrirAjustes()" />
140
+ }
141
+ ```
142
+
93
143
  ## Ejemplo
94
144
 
95
145
  ```html
@@ -49,12 +49,29 @@ texto) y el filtro es un compact-button de 24 px.
49
49
 
50
50
  ```html
51
51
  @if (bp.isMobile()) {
52
- <sui-tab-chips [chips]="pestanas" [value]="activa()" (valueChange)="activa.set($event)" />
52
+ <sui-tab-chips [chips]="pestanas" [size]="bp.sizeChips()"
53
+ [value]="activa()" (valueChange)="activa.set($event)" />
53
54
  } @else {
54
55
  <sui-notification-tab-menu [tabs]="pestanas" [(active)]="activa" [showFilter]="false" />
55
56
  }
56
57
  ```
57
58
 
59
+ ### Por dispositivo (D16)
60
+
61
+ No aplica: no tiene `size` y es solo de la computadora (y el ultrawide). En el celular va
62
+ `sui-tab-chips` con `[size]="bp.sizeChips()"` (`xlarge`, fila `tab-chips` de D16). En el celular
63
+ chico el helper también da `xlarge`, pero es interino: la fila `tab-chips` pide `medium` con área
64
+ tocable de 44, y mientras el DS no estire el área de los `medium` se queda el size grande (nota ¹
65
+ de D16).
66
+ Lo que trae fijo adentro: el filtro es un `sui-compact-button` `large` (24), que cuadra con la
67
+ computadora; el conteo es un `sui-badge` `small`, que choca con el «nada en `small`» de D16 y
68
+ queda **pendiente** del componente (quien lo usa no lo puede cambiar). En la tablet táctil de
69
+ 768 px o más `bp.isMobile()` lo deja visible con pestañas de 20 y filtro de 24, lejos del piso de
70
+ 44: queda **pendiente**, igual que el resto del panel de la campana.
71
+
72
+ En master-pedidos: sin helper; `@if (bp.isMobile())` elige `sui-tab-chips` con
73
+ `[size]="bp.sizeChips()"`, y si no, este componente.
74
+
58
75
  ## «No usar»: por qué no hoy y cuándo sí
59
76
 
60
77
  | qué | por qué no hoy | cuándo sí, en un flujo nuevo |
@@ -101,6 +118,45 @@ interface SuiNotificationTab<T = string> {
101
118
  04-10-2026) y cada una es `role="tab"` con `aria-selected`. Un solo tab stop: ← → mueven y
102
119
  activan con vuelta al inicio, Home/End a los extremos. No hay `tabpanel` asociado: lo arma quien lo usa.
103
120
 
121
+ ## Bien y mal
122
+
123
+ Pestañas en el celular
124
+
125
+ ```html
126
+ <!-- ❌ mal: cada pestaña mide 20 px de alto, lejos de los 44 del dedo -->
127
+ <sui-notification-tab-menu [tabs]="pestanas" [(active)]="activa" [showFilter]="false" />
128
+ ```
129
+
130
+ ```html
131
+ <!-- ✅ bien -->
132
+ <sui-tab-chips [chips]="pestanas" [size]="bp.sizeChips()"
133
+ [value]="activa()" (valueChange)="activa.set($event)" />
134
+ ```
135
+
136
+ Pestaña activa
137
+
138
+ ```html
139
+ <!-- ❌ mal: active fijo; la pestaña cambia adentro pero la página no se entera (vitrina: pages/super-admin/master-preview/_guia-moleculas/avisos.ts:264) -->
140
+ <sui-notification-tab-menu [tabs]="pestanas" active="todas" [showFilter]="false" />
141
+ ```
142
+
143
+ ```html
144
+ <!-- ✅ bien -->
145
+ <sui-notification-tab-menu [tabs]="pestanas" [(active)]="pestana" [showFilter]="false" />
146
+ ```
147
+
148
+ Botón de filtro
149
+
150
+ ```html
151
+ <!-- ❌ mal: showFilter arranca en true; sin filtros de verdad sale un botón que no hace nada -->
152
+ <sui-notification-tab-menu [tabs]="pestanas" [(active)]="pestana" />
153
+ ```
154
+
155
+ ```html
156
+ <!-- ✅ bien -->
157
+ <sui-notification-tab-menu [tabs]="pestanas" [(active)]="pestana" [showFilter]="false" />
158
+ ```
159
+
104
160
  ## Ejemplo
105
161
 
106
162
  ```html