@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
@@ -53,7 +53,7 @@ dropdown, select y command menu en el README de `sui-dropdown-menu`.
53
53
 
54
54
  | size | alto | cuándo | fuente |
55
55
  |---|---|---|---|
56
- | `small` (default) | 36 | Menú de acciones en web, una línea (label + `sublabel` en la misma línea). | según la guía del DS (Figma: Small 36) |
56
+ | `small` (default) | 36 | Fila de una línea (label + `sublabel` en la misma línea). En lo táctil no va (36 < 44); en la computadora está **pendiente** (D16, nota ⁵). | según la guía del DS (Figma: Small 36) · táctil y computadora: D16, dueño 05-10-2026 |
57
57
  | `large` | 56 | Toda fila en mobile; en web, cuando hay segunda línea (`description`) o el ícono va enmarcado. | según la guía del DS (Figma: Large 56) · toda fila en mobile: canon (decisión del dueño 04-10-2026, piso táctil 44); es el primer size ≥ 44, no hay 44 · el cuándo en web: propuesta |
58
58
  | `xlarge` | 76 | Extensión SUI. Sin uso hoy. | — |
59
59
 
@@ -90,18 +90,41 @@ celular: queda debajo de los 44 del dedo.
90
90
 
91
91
  | uso | mobile | web | fuente |
92
92
  |---|---|---|---|
93
- | menú de acciones (⋮) | `large` (56) | `small` (36) | mobile: canon (decisión del dueño 04-10-2026, piso táctil 44); `large` es el primer size ≥ 44, no hay 44 · web: propuesta, falta aprobación |
94
- | switcher con segunda línea (negocio + dirección) | `large` (56) | `large` (56) | mobile: canon (decisión del dueño 04-10-2026, piso táctil 44) · web: propuesta (ya es práctica en el sidebar) |
93
+ | menú de acciones (⋮) | `large` (56), también en la tablet táctil | **pendiente** (ver D16 abajo); hoy la app va en `large` en los 10 usos | mobile: canon (decisión del dueño 04-10-2026, piso táctil 44); `large` es el primer size ≥ 44, no hay 44 · tablet y web: D16, dueño 05-10-2026 (antes decía `small` como propuesta) |
94
+ | switcher con segunda línea (negocio + dirección) | `large` (56), también en la tablet táctil | `large` (56) mientras lleve `description`: en `small` no se ve | mobile: canon (decisión del dueño 04-10-2026, piso táctil 44) · tablet: D16, dueño 05-10-2026 · web: según el código (`description` solo en `large`) |
95
95
  | opciones de un select | las pone el select (44) | las pone el select (36–48) | canon (README de `sui-select`, aprobado 03-10-2026) |
96
96
 
97
97
  ```html
98
- <sui-dropdown-item label="Editar" [size]="bp.isMobile() ? 'large' : 'small'" … /> <!-- bp = BreakpointsService -->
98
+ <!-- `large` fijo mientras la computadora siga pendiente (D16, nota ⁵): es lo que ya hace la app en los 10 usos -->
99
+ <sui-dropdown-item label="Editar" size="large" … />
99
100
  ```
100
101
 
101
102
  En large y xlarge el texto sube a 16 px (regla del 03-10-2026). El label va en Label/Medium 16/24
102
103
  (el nodo de Figma del large lo dibuja en 14); la description no cambia en large (12) y el alto
103
104
  sigue en 56: el padding-y bajó de 8 a 6.
104
105
 
106
+ ### Por dispositivo (D16)
107
+
108
+ Está en la tabla por componente de D16 (dueño, 05-10-2026). Se toca, así que la tablet va con el
109
+ celular. En la computadora D16 lo deja **pendiente** (nota ⁵): no hay `medium`, y `small` (36) y
110
+ `large` (56) no son la misma fila más chica o más grande, porque la `description` solo se ve en
111
+ `large`; elegir uno cambia qué se lee.
112
+
113
+ | dispositivo | size | nota |
114
+ |---|---|---|
115
+ | celular chico (< 380) | `large` (56) | D16 deja la celda vacía; `large` es el único size ≥ 44 y es lo que ya da `bp.tactil()` |
116
+ | celular (380–767) | `large` (56) | el primer size ≥ 44 |
117
+ | tablet táctil (`pointer: coarse`) | `large` (56) | Apple pide 44 pt también en el iPad |
118
+ | computadora (`pointer: fine`) | **pendiente** | falta decidir (D16, nota ⁵) entre `small` (36, sin `description`) y `large` (56); hoy la app va en `large` en los 10 usos, y con `description` o `leadingFramed` solo sirve `large` |
119
+
120
+ Ultrawide: igual que la computadora.
121
+
122
+ En master-pedidos: no hay helper. Mientras la computadora siga pendiente, `size="large"` fijo en todo
123
+ dispositivo (lo que ya hace la app en los 10 usos); no es la decisión de la celda pendiente, es no bajar
124
+ de 44 en lo táctil sin elegir por la computadora. Cuando se decida, si la computadora queda en otro
125
+ size: `[size]="bp.tactil() ? 'large' : '<ese size>'"`. Con `description` o `leadingFramed`:
126
+ `size="large"` siempre.
127
+
105
128
  ## API
106
129
 
107
130
  <!-- api:inicio -->
@@ -146,11 +169,54 @@ está `disabled`.
146
169
  - El label corta con `…` en una línea: no hace salto de línea.
147
170
  - Ya trae los listeners `touchstart`/`touchend` para el `:active` pegado de iOS.
148
171
 
172
+ ## Bien y mal
173
+
174
+ **Segunda línea en `large`**
175
+
176
+ ```html
177
+ <!-- ❌ mal: en `large` el sublabel cae abajo en gris claro (sidebar.html:71; igual en customer-layout.html:27, driver-layout.html:25 y master-layout.html:27) -->
178
+ <sui-dropdown-item [label]="t.name" [sublabel]="t.address ?? ''" mode="option" size="large" />
179
+ ```
180
+
181
+ ```html
182
+ <!-- ✅ bien -->
183
+ <sui-dropdown-item [label]="t.name" [description]="t.address ?? null" mode="option" size="large" />
184
+ ```
185
+
186
+ **Ícono enmarcado**
187
+
188
+ ```html
189
+ <!-- ❌ mal: el círculo está medido para 20; con 18 queda de 38 (option-sections-manager.html:41, :44, :47) -->
190
+ <sui-dropdown-item label="Editar" size="large" [leadingFramed]="true" (clicked)="menu.close(); openEdit(s)">
191
+ <sui-icon slot="leading" name="pencil-line" [size]="18" />
192
+ </sui-dropdown-item>
193
+ ```
194
+
195
+ ```html
196
+ <!-- ✅ bien -->
197
+ <sui-dropdown-item label="Editar" size="large" [leadingFramed]="true" (clicked)="menu.close(); openEdit(s)">
198
+ <sui-icon slot="leading" name="pencil-line" [size]="20" />
199
+ </sui-dropdown-item>
200
+ ```
201
+
202
+ **Cerrar el menú**
203
+
204
+ ```html
205
+ <!-- ❌ mal: el item no cierra el menú; el panel queda abierto después de archivar -->
206
+ <sui-dropdown-item label="Archivar" size="large" (clicked)="archivar()" />
207
+ ```
208
+
209
+ ```html
210
+ <!-- ✅ bien -->
211
+ <sui-dropdown-item label="Archivar" size="large"
212
+ (clicked)="menu.close(); archivar()" />
213
+ ```
214
+
149
215
  ## Ejemplo
150
216
 
151
217
  ```html
152
- <!-- Acción en un menú -->
153
- <sui-dropdown-item label="Archivar" [size]="bp.isMobile() ? 'large' : 'small'"
218
+ <!-- Acción en un menú (`large` fijo mientras la computadora siga pendiente) -->
219
+ <sui-dropdown-item label="Archivar" size="large"
154
220
  (clicked)="menu.close(); archivar()">
155
221
  <sui-icon slot="leading" name="archive-line" [size]="20" />
156
222
  </sui-dropdown-item>
@@ -103,14 +103,34 @@ El menú **no tiene `size`**: el alto lo ponen los items. El panel mide lo que s
103
103
 
104
104
  | uso | mobile | web | fuente |
105
105
  |---|---|---|---|
106
- | items de un menú de acciones | `sui-dropdown-item size="large"` (56) | `size="small"` (36) | mobile: canon (decisión del dueño 04-10-2026, piso táctil 44); `large` es el primer size ≥ 44, no hay 44 · web: propuesta; hoy los 3 items del ⋮ van en `large` en las dos |
106
+ | items de un menú de acciones | `sui-dropdown-item size="large"` (56) | **pendiente** (D16, nota ⁵); hoy queda `small` (36), el default | mobile: canon (decisión del dueño 04-10-2026, piso táctil 44); `large` es el primer size ≥ 44, no hay 44 · web: pendiente (D16, dueño 05-10-2026): el item no tiene `medium` y `description` solo se ve en `large` y `xlarge`; hoy los 3 items del ⋮ van en `large` en las dos |
107
107
  | trigger ⋮ | `sui-compact-button` `5xlarge` (44) | `sui-compact-button` `large` | canon (aprobado por el dueño, 05-10-2026, bloque B13) (ver README de `sui-compact-button`) |
108
108
  | más de 5 acciones, o alguna destructiva que pide confirmar | `sui-modal-sheet` | `sui-dropdown-menu` | propuesta, falta aprobación |
109
109
 
110
110
  ```html
111
- <sui-dropdown-item [size]="bp.isMobile() ? 'large' : 'small'" … /> <!-- bp = BreakpointsService -->
111
+ <sui-dropdown-item [size]="bp.tactil() ? 'large' : 'small'" … /> <!-- bp = BreakpointsService -->
112
112
  ```
113
113
 
114
+ ### Por dispositivo (D16)
115
+
116
+ El menú no tiene `size`, así que D16 se aplica a lo que va adentro y al trigger, que se tocan: la
117
+ tablet va con el celular. Para los items manda la fila `dropdown-item` de D16; para el ⋮, la de
118
+ `compact-button`.
119
+
120
+ | dispositivo | size | nota |
121
+ |---|---|---|
122
+ | celular chico (< 380) | items `large` · ⋮ `5xlarge` | D16 no fija los items aquí; `large` (56) es el primer size ≥ 44 (`small` mide 36 y el item no tiene `medium` con área de 44). El ⋮ va con su escala propia |
123
+ | celular (380–767) | items `large` · ⋮ `5xlarge` (44) | `large` (56) es el primer size ≥ 44 |
124
+ | tablet táctil (`pointer: coarse`) | items `large` · ⋮ `5xlarge` | Apple pide 44 también en iPad |
125
+ | computadora (`pointer: fine`) | items **pendiente** · ⋮ `large` | items: falta decidir (D16, nota ⁵): `small` (36) y `large` (56) no son el mismo item más chico o más grande, porque la descripción solo se ve en `large` y `xlarge`. Hoy queda el default `small` |
126
+
127
+ Ultrawide: igual que la computadora. Fuente: D16, dueño 05-10-2026.
128
+
129
+ En master-pedidos: items `[size]="bp.tactil() ? 'large' : 'small'"` y trigger
130
+ `[size]="bp.tactil() ? '5xlarge' : 'large'"` (no hay helper; el `'small'` es el default de hoy
131
+ mientras la computadora sigue pendiente). Con `bp.isMobile()` la tablet táctil se queda con el
132
+ tamaño de la computadora.
133
+
114
134
  ## API
115
135
 
116
136
  <!-- api:inicio -->
@@ -176,18 +196,67 @@ panel va en un `<ng-template suiDropdownPanel>` (hay que importar `SuiDropdownPa
176
196
  app, pero es lo primero que hay que mirar si un menú «no abre» dentro de un modal.
177
197
  - El host es `display: contents`: no ocupa caja. Para alinearlo, se alinea el trigger.
178
198
 
199
+ ## Bien y mal
200
+
201
+ El ⋮ en la tablet
202
+
203
+ ```html
204
+ <!-- ❌ mal: con isMobile la tablet táctil se queda con el ⋮ de la computadora, sin 44 (components/option-sections-manager/option-sections-manager.html:38) -->
205
+ <sui-compact-button trigger icon="more-2-line" variantStyle="ghost"
206
+ [size]="bp.isMobile() ? '5xlarge' : 'large'" ariaLabel="Opciones de la sección" />
207
+ ```
208
+
209
+ ```html
210
+ <!-- ✅ bien -->
211
+ <sui-compact-button trigger icon="more-2-line" variantStyle="ghost"
212
+ [size]="bp.tactil() ? '5xlarge' : 'large'" ariaLabel="Opciones de la sección" />
213
+ ```
214
+
215
+ Items sin `ng-template`
216
+
217
+ ```html
218
+ <!-- ❌ mal: los items no se proyectan en ningún lado y el menú no abre -->
219
+ <sui-dropdown-menu #menu="suiDropdownMenu">
220
+ <sui-compact-button trigger icon="more-2-line" variantStyle="ghost" ariaLabel="Opciones" />
221
+ <sui-dropdown-item label="Editar" (clicked)="editar()" />
222
+ </sui-dropdown-menu>
223
+ ```
224
+
225
+ ```html
226
+ <!-- ✅ bien -->
227
+ <sui-dropdown-menu #menu="suiDropdownMenu">
228
+ <sui-compact-button trigger icon="more-2-line" variantStyle="ghost" ariaLabel="Opciones" />
229
+ <ng-template suiDropdownPanel>
230
+ <sui-dropdown-item label="Editar" (clicked)="menu.close(); editar()" />
231
+ </ng-template>
232
+ </sui-dropdown-menu>
233
+ ```
234
+
235
+ Cerrar al elegir
236
+
237
+ ```html
238
+ <!-- ❌ mal: el item no cierra el menú; queda abierto encima del modal de edición -->
239
+ <sui-dropdown-item label="Editar" (clicked)="editar()" />
240
+ ```
241
+
242
+ ```html
243
+ <!-- ✅ bien -->
244
+ <sui-dropdown-item label="Editar" (clicked)="menu.close(); editar()" />
245
+ ```
246
+
179
247
  ## Ejemplo
180
248
 
181
249
  ```html
182
250
  <sui-dropdown-menu #menu="suiDropdownMenu">
183
- <sui-compact-button trigger icon="more-2-line" variantStyle="ghost" size="large"
251
+ <sui-compact-button trigger icon="more-2-line" variantStyle="ghost"
252
+ [size]="bp.tactil() ? '5xlarge' : 'large'"
184
253
  ariaLabel="Opciones de la sección" />
185
254
  <ng-template suiDropdownPanel>
186
- <sui-dropdown-item label="Editar" [size]="bp.isMobile() ? 'large' : 'small'"
255
+ <sui-dropdown-item label="Editar" [size]="bp.tactil() ? 'large' : 'small'"
187
256
  (clicked)="menu.close(); editar()">
188
257
  <sui-icon slot="leading" name="pencil-line" [size]="20" />
189
258
  </sui-dropdown-item>
190
- <sui-dropdown-item label="Archivar" [size]="bp.isMobile() ? 'large' : 'small'"
259
+ <sui-dropdown-item label="Archivar" [size]="bp.tactil() ? 'large' : 'small'"
191
260
  (clicked)="menu.close(); archivar()">
192
261
  <sui-icon slot="leading" name="archive-line" [size]="20" />
193
262
  </sui-dropdown-item>
@@ -57,12 +57,23 @@ No tiene tamaños: 36 px de alto (8 + 20 + 8), texto 14/20, en los dos.
57
57
 
58
58
  | uso | mobile | web | fuente |
59
59
  |---|---|---|---|
60
- | buscador del menú | igual (36) | igual (36) | propuesta |
60
+ | buscador del menú | no se usa: `sui-modal-sheet` con `sui-input type="search"` arriba | 36, fijo | mobile: canon (aprobado por el dueño, 05-10-2026, bloque B7) y D16 (dueño 05-10-2026: lo que se toca llega a 44, y este campo mide 36) · web: lo que hay en el DS |
61
61
 
62
62
  En mobile tiene dos problemas que el componente no resuelve (ver «Trampas»): el texto de 14 px hace
63
63
  que iOS haga zoom al enfocarlo, y el teclado no muestra la lupa. Para buscar en una lista larga en
64
64
  mobile, mejor un `sui-modal-sheet` con `sui-input type="search"` arriba. Canon (aprobado por el dueño, 05-10-2026, bloque B7).
65
65
 
66
+ ### Por dispositivo (D16)
67
+
68
+ No aplica como tabla: **no tiene `size`** (36 px fijo, del celular chico al ultrawide), así que D16
69
+ no lo agranda; lo único que cambia por dispositivo es **si se usa**. Se toca, y 36 no llega a 44:
70
+ en el celular (también el chico) y en la tablet táctil va el sheet con `sui-input type="search"`
71
+ (que sí tiene `size`); en la computadora y el ultrawide, este buscador dentro del menú. La tablet
72
+ entra con el celular porque D16 pone la tablet táctil con el celular en todo lo que se toca.
73
+
74
+ En master-pedidos: `@if (bp.tactil())` → sheet con `<sui-input type="search" [size]="bp.sizeControl()">`;
75
+ `@else` → `sui-dropdown-search` en el menú, sin `[size]`.
76
+
66
77
  ## API
67
78
 
68
79
  <!-- api:inicio -->
@@ -96,6 +107,51 @@ que además deja `value` en `''`.
96
107
  a mano.
97
108
  - El `<input>` no tiene `(keydown)`: Enter no hace nada salvo que quien lo usa lo escuche.
98
109
 
110
+ ## Bien y mal
111
+
112
+ Hoy no hay usos en la app (0, medido el 03-10-2026): los pares salen de «Trampas» y de la regla B7.
113
+
114
+ Qué se busca
115
+
116
+ ```html
117
+ <!-- ❌ mal: sin placeholder sale el genérico «Buscar…» y no dice qué se busca -->
118
+ <sui-dropdown-search [(value)]="busqueda" />
119
+ ```
120
+
121
+ ```html
122
+ <!-- ✅ bien -->
123
+ <sui-dropdown-search [(value)]="busqueda" placeholder="Buscar repartidor…" />
124
+ ```
125
+
126
+ Filtrar la lista
127
+
128
+ ```html
129
+ <!-- ❌ mal: el buscador no filtra; la lista sigue entera aunque se escriba -->
130
+ <sui-dropdown-search [(value)]="busqueda" placeholder="Buscar repartidor…" />
131
+ @for (r of repartidores(); track r.uid) { <sui-dropdown-item [label]="r.nombre" /> }
132
+ ```
133
+
134
+ ```html
135
+ <!-- ✅ bien: repartidoresFiltrados() es un computed sobre busqueda() -->
136
+ <sui-dropdown-search [(value)]="busqueda" placeholder="Buscar repartidor…" />
137
+ @for (r of repartidoresFiltrados(); track r.uid) { <sui-dropdown-item [label]="r.nombre" /> }
138
+ ```
139
+
140
+ Buscar en el celular
141
+
142
+ ```html
143
+ <!-- ❌ mal: 36 px sin lupa en el teclado, y iOS hace zoom al enfocarlo -->
144
+ <sui-dropdown-search [(value)]="busqueda" placeholder="Buscar repartidor…" />
145
+ ```
146
+
147
+ ```html
148
+ <!-- ✅ bien: en el celular y la tablet táctil, sheet con el input de búsqueda (B7) -->
149
+ <sui-modal-sheet [(open)]="buscando">
150
+ <sui-input type="search" [size]="bp.sizeControl()" placeholder="Buscar repartidor…"
151
+ [(value)]="busqueda" />
152
+ </sui-modal-sheet>
153
+ ```
154
+
99
155
  ## Ejemplo
100
156
 
101
157
  ```html
@@ -32,7 +32,7 @@ confirmado», los pasos de una landing, la barra de calificación.
32
32
 
33
33
  | caso | cómo | fuente |
34
34
  |---|---|---|
35
- | Estados vacíos y celebraciones | Emoji animado, uno solo, en `xl`. Nada de íconos genéricos en un estado vacío. | canon (CANON-SUI §5.6) para los estados vacíos · propuesta, falta aprobación para celebraciones y el `xl` |
35
+ | Estados vacíos y celebraciones | Emoji animado, uno solo. Nada de íconos genéricos en un estado vacío. El del vacío lo pone `sui-empty-state` en `full` (caja de 120); el `size` de la celebración está **pendiente** (P38). | canon (CANON-SUI §5.6) para los estados vacíos · `full` en el vacío: según el código (`sui-empty-state.html`) · celebración: pendiente (P38) |
36
36
  | Pasos de una landing | `lg`, uno por paso. | canon (aprobado por el dueño, 05-10-2026, bloque B1) |
37
37
  | Junto a un título o dentro de un texto | `md` o `sm`, como acento. | canon (aprobado por el dueño, 05-10-2026, bloque B1) |
38
38
  | Como ícono de un botón | No: el botón lleva `leftIcon`. | canon (CANON-SUI §5.7: emojis solo en contenido escrito por un usuario; en un botón, `leftIcon` con `sui-icon`) |
@@ -41,12 +41,12 @@ confirmado», los pasos de una landing, la barra de calificación.
41
41
 
42
42
  | valor | px | cuándo | fuente |
43
43
  |---|---|---|---|
44
- | `xl` | 48 | Estado vacío, celebración. | propuesta |
44
+ | `xl` | 48 | El más grande con nombre. Para la celebración, **pendiente** (P38): todavía no se decidió su `size`. El estado vacío no lo usa: va en `full`. | pendiente (P38) |
45
45
  | `lg` | 32 | Pasos de una landing, la barra de calificación. | canon (aprobado por el dueño, 05-10-2026, bloque B1) |
46
46
  | `md` (default) | 24 | Acompaña un título. | canon (aprobado por el dueño, 05-10-2026, bloque B1) |
47
47
  | `sm` | 20 | Dentro de una línea de texto. | canon (aprobado por el dueño, 05-10-2026, bloque B1) |
48
48
  | `xs` | 16 | No usar hoy. | canon (aprobado por el dueño, 05-10-2026, bloque B6) |
49
- | `full` | 100 % | Llena su caja: lo usa `sui-empty-state`. | según el código |
49
+ | `full` | 100 % | Llena su caja: es el del estado vacío (`sui-empty-state` lo pone en una caja de 120). | según el código |
50
50
 
51
51
  ### `animated`, `src`, `name`, `ariaLabel`
52
52
 
@@ -75,24 +75,45 @@ confirmado», los pasos de una landing, la barra de calificación.
75
75
 
76
76
  ## Tamaño en mobile y en web
77
77
 
78
- En mobile se lee y se toca con el dedo, así que va más grande; en web, más chico. En las
79
- pantallas que se usan en los dos (panel del local, super admin) se elige con el servicio de
80
- breakpoints de la app (`bp`, en `services/breakpoints.service.ts`); en las que solo existen en
81
- el celular (cliente, repartidor) va directo el valor de mobile. Todo es **propuesta**.
78
+ El emoji no se toca: en el celular va **un paso más grande** que en la computadora (D16, P1 b),
79
+ porque ahí se lee más de cerca y en una columna sola. Se elige con el servicio de breakpoints de
80
+ la app (`bp`, en `services/breakpoints.service.ts`), también en las pantallas del cliente y del
81
+ repartidor: el celular chico y la tablet llevan el valor de web.
82
82
 
83
- | uso | mobile | web |
84
- |---|---|---|
85
- | estado vacío, celebración | `xl` (48) | `xl` (48) |
86
- | pasos de una landing | `lg` (32) | `xl` (48) |
87
- | dentro de un texto | `md` (24) | `sm` (20) |
83
+ | uso | mobile | web | fuente |
84
+ |---|---|---|---|
85
+ | estado vacío | `full` (caja de 120) | `full` (caja de 120) | según el código: lo pone `sui-empty-state` y no cambia por dispositivo |
86
+ | celebración | **pendiente** (P38) | **pendiente** (P38) | P38 sigue abierta: no se decidió el `size` |
87
+ | pasos de una landing | `xl` (48) | `lg` (32) | web: canon (aprobado por el dueño, 05-10-2026, bloque B1) · mobile: D16, dueño 05-10-2026 (antes decía `lg` en mobile y `xl` en web, al revés de P1 b) |
88
+ | dentro de un texto | `md` (24) | `sm` (20) | propuesta; cuadra con D16 (un paso más en el celular) |
88
89
 
89
90
  ```html
90
- <sui-emoji name="hamburger" [size]="bp.isMobile() ? 'lg' : 'xl'" />
91
+ <sui-emoji name="hamburger" [size]="bp.celular() ? 'xl' : 'lg'" />
91
92
  ```
92
93
 
93
- El emoji no se toca, así que la regla del dedo no aplica: en los casos de ilustración va igual o
94
- más grande en web, donde sobra espacio. El tamaño con nombre más grande es `xl` (48); para uno más
95
- grande, `size="full"` dentro de una caja con el alto que se quiera.
94
+ El tamaño con nombre más grande es `xl` (48); para uno más grande, `size="full"` dentro de una
95
+ caja con el alto que se quiera.
96
+
97
+ ### Por dispositivo (D16)
98
+
99
+ No está en la tabla por componente de D16; como no se toca, sigue la columna «lo que no se toca»:
100
+ valor «web» en todos salvo el celular de 380 o más. Dos casos quedan fuera: el estado vacío no
101
+ cambia por dispositivo (lo pone `sui-empty-state` en `full`) y la celebración espera P38 («Lo que
102
+ esta hoja no cierra» de D16).
103
+
104
+ | dispositivo | size | nota |
105
+ |---|---|---|
106
+ | celular chico (< 380) | valor «web»: landing `lg` · texto `sm` · vacío `full` · celebración pendiente (P38) | lo que no se toca no sube en el celular chico |
107
+ | celular (380–767) | valor «mobile»: landing `xl` · texto `md` · vacío `full` · celebración pendiente (P38) | un paso más que en la computadora (P1 b); el vacío no cambia, lo pone `sui-empty-state` |
108
+ | tablet táctil (`pointer: coarse`) | valor «web»: landing `lg` · texto `sm` · vacío `full` · celebración pendiente (P38) | |
109
+ | computadora (`pointer: fine`) | valor «web»: landing `lg` · texto `sm` · vacío `full` · celebración pendiente (P38) | `sm` (20) aquí es el alto de una línea de texto 14/20, no el `small` de los controles que D16 saca |
110
+
111
+ Ultrawide: igual que la computadora. Fuente: D16, dueño 05-10-2026.
112
+
113
+ En master-pedidos: no hay helper (`bp.sizeAvatar()` es solo del avatar, con otra escala). Landing:
114
+ `[size]="bp.celular() ? 'xl' : 'lg'"` · dentro de un texto: `[size]="bp.celular() ? 'md' : 'sm'"` ·
115
+ estado vacío: no se usa `sui-emoji` suelto, va `sui-empty-state` (que lo pone en `full`) ·
116
+ celebración: pendiente (P38).
96
117
 
97
118
  ## «No usar»: por qué no hoy y cuándo sí
98
119
 
@@ -127,11 +148,54 @@ Outputs: ninguno.
127
148
  - Sin `ariaLabel` es decorativo: el lector de pantalla no lo dice.
128
149
  - `loading="lazy"`: fuera de la pantalla, no carga hasta que se acerca.
129
150
 
151
+ ## Bien y mal
152
+
153
+ El emoji de un botón
154
+
155
+ ```html
156
+ <!-- ❌ mal: un emoji no es un ícono (pages/orders/orders.html:323 y :354) -->
157
+ <sui-button variant="stroke" color="neutral" [size]="bp.sizeControl()" (click)="handleMyself(order)">
158
+ <sui-emoji data-slot="start" name="shop" size="sm" />
159
+ Encargarme yo
160
+ </sui-button>
161
+ ```
162
+
163
+ ```html
164
+ <!-- ✅ bien -->
165
+ <sui-button variant="stroke" color="neutral" [size]="bp.sizeControl()" leftIcon="store-2-line"
166
+ (click)="handleMyself(order)">Encargarme yo</sui-button>
167
+ ```
168
+
169
+ Pasos de una landing
170
+
171
+ ```html
172
+ <!-- ❌ mal: lg fijo; en el celular no sube el paso que pide D16 (pages/public/landing-customers/landing-customers.html:160) -->
173
+ <sui-emoji name="pushpin" size="lg" class="landing-customers__flow-icon"></sui-emoji>
174
+ ```
175
+
176
+ ```html
177
+ <!-- ✅ bien -->
178
+ <sui-emoji name="pushpin" [size]="bp.celular() ? 'xl' : 'lg'" class="landing-customers__flow-icon" />
179
+ ```
180
+
181
+ Un emoji del catálogo con `<img>`
182
+
183
+ ```html
184
+ <!-- ❌ mal: la URL del paquete escrita a mano, fuera del componente (pages/products/add-product/add-product.html:122) -->
185
+ <img src="https://raw.githubusercontent.com/Tarikul-Islam-Anik/Animated-Fluent-Emojis/master/Emojis/Objects/Package.png"
186
+ alt="Producto" width="48" height="48" />
187
+ ```
188
+
189
+ ```html
190
+ <!-- ✅ bien: decorativo, el título de al lado ya lo dice -->
191
+ <sui-emoji name="package" size="xl" />
192
+ ```
193
+
130
194
  ## Ejemplo
131
195
 
132
196
  ```html
133
- <!-- Celebración -->
134
- <sui-emoji name="party-popper" size="xl" />
197
+ <!-- Junto a un texto: un paso más en el celular (D16) -->
198
+ <p>Pedido confirmado <sui-emoji name="party-popper" [size]="bp.celular() ? 'md' : 'sm'" /></p>
135
199
 
136
200
  <!-- La barra de calificación: cinco juntos, estáticos -->
137
201
  <sui-emoji name="neutral-face" size="lg" [animated]="false" ariaLabel="Regular" />
@@ -31,8 +31,8 @@ algo que avisar → alert.**
31
31
  > propósito con Fluent Emoji animados en vez de ilustraciones: es una decisión del proyecto, escrita
32
32
  > en CANON-SUI §5.6 (ilustración = Fluent Emoji animado, default el zorro).
33
33
  >
34
- > Uso medido el 04-10-2026 en `master-pedidos/src/app` (misma exclusión que `sui-card`): **66
35
- > empty-states en 40 archivos**. 29 con `action` (10 con `route`). 8 con `emoji` propio y 58 sin
34
+ > Uso medido el 06-10-2026 en `master-pedidos/src/app` (misma exclusión que `sui-card`): **70
35
+ > empty-states en 42 archivos**. 31 con `action` (10 con `route`). 8 con `emoji` propio y 62 sin
36
36
  > `emoji` (sale el zorro). 0 con `icon`, 0 con la URL del zorro pegada, 0 con `size`.
37
37
 
38
38
  ### Las piezas
@@ -66,15 +66,32 @@ abajo (media query `bp.medium` del componente). El `size` solo cambia **el botó
66
66
  | uso | mobile | web | fuente |
67
67
  |---|---|---|---|
68
68
  | ilustración + texto | lo resuelve el componente | lo resuelve el componente | lo que hay en el DS |
69
- | botón de la acción | `large` (48) | `medium` (40) | el tamaño es extensión SUI aprobada (03-10-2026) · mobile: canon (decisión del dueño 04-10-2026, piso táctil 44) · web: propuesta, falta aprobación |
69
+ | botón de la acción | `large` (48) | `medium` (40) | el tamaño es extensión SUI aprobada (03-10-2026) · mobile: canon (decisión del dueño 04-10-2026, piso táctil 44) · web: D16, dueño 05-10-2026 (fila `button`) |
70
70
 
71
71
  ```html
72
72
  <sui-empty-state
73
73
  title="Tu carrito está vacío"
74
74
  [action]="{ label: 'Ver negocios', route: '/cliente/inicio' }"
75
- [size]="bp.isMobile() ? 'large' : 'medium'" />
75
+ [size]="bp.sizeControl()" />
76
76
  ```
77
77
 
78
+ ### Por dispositivo (D16)
79
+
80
+ El `size` es el del botón de la acción, que se toca: sigue la fila `button` de D16. Sin `action`,
81
+ `size` no cambia nada y no hace falta pasarlo.
82
+
83
+ | dispositivo | size | nota |
84
+ |---|---|---|
85
+ | celular chico (< 380) | `large` | D16 pide `medium` con área de 44, pero el DS todavía no la estira: hasta entonces, `large` |
86
+ | celular (380–767) | `large` (48) | |
87
+ | tablet táctil (`pointer: coarse`) | `large` | Apple pide 44 también en iPad |
88
+ | computadora (`pointer: fine`) | `medium` (40) | el default |
89
+
90
+ Ultrawide: igual que la computadora. Fuente: D16, dueño 05-10-2026.
91
+
92
+ En master-pedidos: `[size]="bp.sizeControl()"` en todo empty-state con `action`. Medido el
93
+ 06-10-2026: 0 de los 31 con `action` lo pasan, así que en el celular y la tablet todos salen en 40.
94
+
78
95
  ## «No usar»: por qué no hoy y cuándo sí
79
96
 
80
97
  | qué | por qué no hoy | cuándo sí, en un flujo nuevo |
@@ -116,6 +133,53 @@ interface SuiEmptyStateAction { label: string; route?: string; }
116
133
  - El botón es `sui-button` `filled` `primary`: el color no se cambia; el tamaño sí, con `size` (`medium` 40 · `large` 48).
117
134
  - El emoji carga con `loading="lazy"`: en una captura de pantalla completa puede salir vacío.
118
135
 
136
+ ## Bien y mal
137
+
138
+ La acción en el celular
139
+
140
+ ```html
141
+ <!-- ❌ mal: sin size el botón sale en 40 también en el celular (pages/customer/cart/cart.html:18) -->
142
+ <sui-empty-state
143
+ title="Tu carrito está vacío"
144
+ [action]="{ label: 'Explorar negocios', route: '/cliente/inicio' }" />
145
+ ```
146
+
147
+ ```html
148
+ <!-- ✅ bien -->
149
+ <sui-empty-state
150
+ title="Tu carrito está vacío"
151
+ [action]="{ label: 'Explorar negocios', route: '/cliente/inicio' }"
152
+ [size]="bp.sizeControl()" />
153
+ ```
154
+
155
+ Un emoji propio
156
+
157
+ ```html
158
+ <!-- ❌ mal: emoji es una URL, no un nombre de sui-emoji; 'hourglass' no carga nada -->
159
+ <sui-empty-state emoji="hourglass" title="Aún no tienes facturas" />
160
+ ```
161
+
162
+ ```html
163
+ <!-- ✅ bien: la URL de FLUENT_EMOJI_ANIM, como pages/invoices/invoices.ts:50 -->
164
+ <sui-empty-state [emoji]="emptyEmoji" title="Aún no tienes facturas" />
165
+ <!-- emptyEmoji = FLUENT_EMOJI_ANIM.hourglass -->
166
+ ```
167
+
168
+ Mientras carga
169
+
170
+ ```html
171
+ <!-- ❌ mal: mientras llega la lista se lee «no hay nada» por un segundo -->
172
+ @if (pedidos().length === 0) {
173
+ <sui-empty-state title="Sin pedidos aún" />
174
+ }
175
+ ```
176
+
177
+ ```html
178
+ <!-- ✅ bien: skeleton hasta que cargue; el vacío solo con la lista ya cargada (el guard `hasLoaded()` es el de pages/locations/locations.html:15; esa pantalla, mientras carga, muestra un texto y no un skeleton) -->
179
+ @if (isLoading()) { <!-- skeleton de la lista --> }
180
+ @else if (hasLoaded() && pedidos().length === 0) { <sui-empty-state title="Sin pedidos aún" /> }
181
+ ```
182
+
119
183
  ## Ejemplo
120
184
 
121
185
  ```html
@@ -95,11 +95,29 @@ que va al lado. El texto sube a 16 (regla de tamaños del 03-10-2026); los ícon
95
95
  | CTA dentro de la card de un plan | `large` (48) | `medium` (40) | mobile: canon (decisión del dueño 04-10-2026, piso táctil 44) · web: canon (dueño, 05-10-2026, D16) |
96
96
 
97
97
  ```html
98
- <sui-fancy-button type="primary" [size]="bp.isMobile() ? 'large' : 'medium'">Empieza gratis</sui-fancy-button>
98
+ <sui-fancy-button type="primary" [size]="bp.sizeControl()">Empieza gratis</sui-fancy-button>
99
99
  ```
100
100
 
101
101
  Hoy no hay usos (todo el componente está en «no usar»).
102
102
 
103
+ ### Por dispositivo (D16)
104
+
105
+ Se toca, así que va como «lo que se toca»; la fila de `fancy-button` de la tabla D16 manda
106
+ (canon, dueño, 05-10-2026, D16).
107
+
108
+ | dispositivo | size | nota |
109
+ |---|---|---|
110
+ | celular chico (< 380 px) | `medium` + área de 44 ¹ | ¹ el DS todavía no estira a 44 el área del `medium` (40): hasta que lo haga, va `large`, que es lo que ya da el helper |
111
+ | celular (380–767 px) | `large` (48) | del mismo alto que el `large` de `sui-button` que va al lado |
112
+ | tablet táctil (`pointer: coarse`) | `large` (48) | Apple pide 44 pt también en el iPad; `bp.isMobile()` sola la deja en `medium` |
113
+ | computadora (`pointer: fine`) | `medium` (40) | también dentro de la card de un plan; `small` y `xsmall` no se usan |
114
+
115
+ Ultrawide (≥ 1920 px): igual que la computadora, `medium`. El espacio extra va al ancho de la
116
+ sección, no a un CTA más grande.
117
+
118
+ En master-pedidos: `[size]="bp.sizeControl()"` (`large` en el celular y en toda pantalla táctil,
119
+ `medium` en la computadora).
120
+
103
121
  ## «No usar»: por qué no hoy y cuándo sí
104
122
 
105
123
  Nada se borra del DS. Lo marcado «no usar» no tiene caso en la app de hoy; si un flujo nuevo cae
@@ -146,6 +164,46 @@ El clic se escucha con `(clicked)`. Slots: `<ng-content>` (el texto).
146
164
  - El anillo del `neutral` es un hex crudo (`#242628`): no hay token para ese gris.
147
165
  - Ya trae el arreglo de iOS para el `:active` pegado: no lo agregues.
148
166
 
167
+ ## Bien y mal
168
+
169
+ **El CTA en el teléfono y en la computadora**
170
+
171
+ ```html
172
+ <!-- ❌ mal: dos componentes para el mismo CTA. La vitrina (master-preview/_guia-atomos/botones.ts:138)
173
+ todavía pone sui-button large en mobile «porque el fancy mide 40»; desde el 04-10 tiene large (48) -->
174
+ <sui-button size="large">Empieza gratis</sui-button>
175
+ <sui-fancy-button type="primary" size="medium">Empieza gratis</sui-fancy-button>
176
+ ```
177
+
178
+ ```html
179
+ <!-- ✅ bien -->
180
+ <sui-fancy-button type="primary" [size]="bp.sizeControl()">Empieza gratis</sui-fancy-button>
181
+ ```
182
+
183
+ **Un formulario que se envía**
184
+
185
+ ```html
186
+ <!-- ❌ mal: `type` es el relleno, no el type HTML; no compila y no hace submit (Trampas) -->
187
+ <sui-fancy-button type="submit">Crear cuenta</sui-fancy-button>
188
+ ```
189
+
190
+ ```html
191
+ <!-- ✅ bien -->
192
+ <sui-fancy-button type="primary" htmlType="submit" [size]="bp.sizeControl()">Crear cuenta</sui-fancy-button>
193
+ ```
194
+
195
+ **Una acción destructiva**
196
+
197
+ ```html
198
+ <!-- ❌ mal: una destructiva no es marketing («No usar»), y el brillo la vuelve llamativa -->
199
+ <sui-fancy-button type="destructive">Eliminar cuenta</sui-fancy-button>
200
+ ```
201
+
202
+ ```html
203
+ <!-- ✅ bien -->
204
+ <sui-button variant="filled" color="error" [size]="bp.sizeControl()">Eliminar cuenta</sui-button>
205
+ ```
206
+
149
207
  ## Ejemplo
150
208
 
151
209
  ```html