@ajuarezso/sui-design-system 0.21.0 → 0.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (114) hide show
  1. package/docs/INDEX.md +30 -35
  2. package/docs/sui-accordion/README.md +171 -0
  3. package/docs/sui-activity-feed/README.md +154 -0
  4. package/docs/sui-activity-filter/README.md +100 -0
  5. package/docs/sui-alert/README.md +28 -19
  6. package/docs/sui-app-store-badge/README.md +5 -4
  7. package/docs/sui-avatar/README.md +16 -16
  8. package/docs/sui-avatar-group/README.md +4 -4
  9. package/docs/sui-badge/README.md +27 -9
  10. package/docs/sui-banner/README.md +10 -9
  11. package/docs/sui-brand-logo/README.md +3 -3
  12. package/docs/sui-breadcrumbs/README.md +1 -1
  13. package/docs/sui-button/README.md +64 -21
  14. package/docs/sui-button-group/README.md +6 -4
  15. package/docs/sui-button-group-item/README.md +3 -3
  16. package/docs/sui-card/README.md +17 -19
  17. package/docs/sui-chart-legend/README.md +8 -7
  18. package/docs/sui-checkbox/README.md +11 -6
  19. package/docs/sui-checkbox-card/README.md +24 -19
  20. package/docs/sui-checkbox-label/README.md +32 -10
  21. package/docs/sui-circular-progress-bar/README.md +2 -0
  22. package/docs/sui-color-dot/README.md +1 -1
  23. package/docs/sui-color-picker/README.md +22 -7
  24. package/docs/sui-command-menu-footer/README.md +100 -0
  25. package/docs/sui-command-menu-item/README.md +140 -0
  26. package/docs/sui-command-menu-search/README.md +105 -0
  27. package/docs/sui-compact-avatar-group/README.md +4 -3
  28. package/docs/sui-compact-button/README.md +41 -44
  29. package/docs/sui-compact-select/README.md +12 -5
  30. package/docs/sui-compact-select-for-input/README.md +5 -2
  31. package/docs/sui-content-card/README.md +6 -5
  32. package/docs/sui-content-divider/README.md +4 -4
  33. package/docs/sui-content-label/README.md +11 -6
  34. package/docs/sui-counter-input/README.md +21 -17
  35. package/docs/sui-date-selector/README.md +16 -12
  36. package/docs/sui-datepicker/README.md +46 -28
  37. package/docs/sui-day-cell/README.md +17 -8
  38. package/docs/sui-day-label/README.md +2 -2
  39. package/docs/sui-divider/README.md +5 -5
  40. package/docs/sui-drawer-footer/README.md +19 -5
  41. package/docs/sui-dropdown-caption/README.md +92 -0
  42. package/docs/sui-dropdown-item/README.md +163 -0
  43. package/docs/sui-dropdown-menu/README.md +196 -0
  44. package/docs/sui-dropdown-search/README.md +113 -0
  45. package/docs/sui-emoji/README.md +6 -6
  46. package/docs/sui-empty-state/README.md +13 -23
  47. package/docs/sui-fancy-button/README.md +24 -18
  48. package/docs/sui-file-icon/README.md +1 -1
  49. package/docs/sui-file-upload/README.md +3 -0
  50. package/docs/sui-file-upload-card/README.md +8 -7
  51. package/docs/sui-filter/README.md +181 -0
  52. package/docs/sui-flag/README.md +3 -2
  53. package/docs/sui-form-hint/README.md +12 -8
  54. package/docs/sui-form-label/README.md +11 -16
  55. package/docs/sui-href/README.md +85 -0
  56. package/docs/sui-icon/README.md +4 -3
  57. package/docs/sui-image-upload/README.md +28 -16
  58. package/docs/sui-img-retry/README.md +107 -0
  59. package/docs/sui-inline-input/README.md +7 -6
  60. package/docs/sui-inline-select/README.md +8 -5
  61. package/docs/sui-input/README.md +27 -33
  62. package/docs/sui-integration-switch/README.md +14 -7
  63. package/docs/sui-kbd/README.md +4 -4
  64. package/docs/sui-key-icon/README.md +6 -2
  65. package/docs/sui-link-button/README.md +21 -17
  66. package/docs/sui-modal/README.md +238 -0
  67. package/docs/sui-modal-footer/README.md +178 -0
  68. package/docs/sui-modal-header/README.md +115 -0
  69. package/docs/sui-modal-sheet/README.md +170 -0
  70. package/docs/sui-notification/README.md +8 -6
  71. package/docs/sui-notification-footer/README.md +2 -2
  72. package/docs/sui-notification-tab-menu/README.md +5 -3
  73. package/docs/sui-page-header/README.md +123 -0
  74. package/docs/sui-pagination/README.md +8 -5
  75. package/docs/sui-password-strength/README.md +1 -1
  76. package/docs/sui-period-range/README.md +18 -14
  77. package/docs/sui-popover/README.md +13 -7
  78. package/docs/sui-product-card/README.md +14 -10
  79. package/docs/sui-progress-bar/README.md +4 -2
  80. package/docs/sui-progress-bar-label/README.md +2 -0
  81. package/docs/sui-radio/README.md +14 -7
  82. package/docs/sui-radio-card/README.md +12 -12
  83. package/docs/sui-radio-label/README.md +36 -11
  84. package/docs/sui-rating/README.md +28 -9
  85. package/docs/sui-rich-editor/README.md +3 -3
  86. package/docs/sui-segmented-control/README.md +33 -19
  87. package/docs/sui-select/README.md +40 -33
  88. package/docs/sui-sidebar/README.md +216 -0
  89. package/docs/sui-slider/README.md +7 -0
  90. package/docs/sui-social-button/README.md +24 -11
  91. package/docs/sui-status-badge/README.md +7 -3
  92. package/docs/sui-stepper/README.md +30 -17
  93. package/docs/sui-store-card/README.md +9 -4
  94. package/docs/sui-switch/README.md +16 -11
  95. package/docs/sui-switch-card/README.md +18 -16
  96. package/docs/sui-switch-label/README.md +25 -11
  97. package/docs/sui-tab-chips/README.md +56 -39
  98. package/docs/sui-tab-menu-horizontal/README.md +19 -11
  99. package/docs/sui-tab-menu-vertical/README.md +10 -5
  100. package/docs/sui-table/README.md +264 -0
  101. package/docs/sui-tag/README.md +25 -11
  102. package/docs/sui-tag-input/README.md +25 -12
  103. package/docs/sui-textarea/README.md +23 -20
  104. package/docs/sui-time-picker/README.md +39 -30
  105. package/docs/sui-toast/README.md +27 -22
  106. package/docs/sui-tooltip/README.md +14 -17
  107. package/docs/sui-topbar/README.md +153 -0
  108. package/docs/sui-topbar-button/README.md +95 -0
  109. package/docs/sui-topbar-item/README.md +97 -0
  110. package/docs/sui-topbar-user/README.md +83 -0
  111. package/fesm2022/ajuarezso-sui-design-system.mjs +1076 -242
  112. package/fesm2022/ajuarezso-sui-design-system.mjs.map +1 -1
  113. package/package.json +1 -1
  114. package/types/ajuarezso-sui-design-system.d.ts +616 -280
@@ -63,7 +63,7 @@ El archivo que entrega **no se sube tal cual**: pasa por `ImageCompressorService
63
63
  | input | cuándo | fuente |
64
64
  |---|---|---|
65
65
  | `title` | Verbo + qué: «Subir logo», «Subir comprobante», «Subir captura del pago». | propuesta |
66
- | `subtitle` | Formatos y tamaño, **solo los que el componente acepta** (JPG, PNG o WebP), o el encuadre que se va a aplicar («se recorta a 16:9»). Mientras procesa: «Procesando…». | propuesta |
66
+ | `subtitle` | Formatos y tamaño, **solo los que el componente acepta** (JPG, PNG, WebP, GIF o HEIC), o el encuadre que se va a aplicar («se recorta a 16:9»). Mientras procesa: «Procesando…». | propuesta |
67
67
 
68
68
  ### `maxSize`, `disabled`, `src`
69
69
 
@@ -75,19 +75,20 @@ El archivo que entrega **no se sube tal cual**: pasa por `ImageCompressorService
75
75
 
76
76
  ### Usos de hoy que rompen la propuesta
77
77
 
78
- - **5 subtítulos prometen HEIC**: hasta el 03-10-2026 el componente lo rechazaba; con la versión
79
- nueva del DS ya pasa (ver Trampas por la vista previa en Chrome):
80
- `components/plan-change-modal/plan-change-modal.html:150`, `pages/driver/driver-wallet/driver-wallet.html:243`,
81
- `pages/promociones/promociones.html:185` y `:269`, `pages/customer/order-tracking/order-tracking.html:985`.
78
+ - **5 subtítulos prometen HEIC**: hasta el 03-10-2026 el componente lo rechazaba; desde la 0.22.0
79
+ (la que usa la app) ya lo acepta, así que **ya no rompen nada**. Lo que queda es la vista previa en
80
+ blanco en Chrome hasta que la pantalla ponga el JPG comprimido (ver Trampas):
81
+ `components/plan-change-modal/plan-change-modal.html:157`, `pages/driver/driver-wallet/driver-wallet.html:252`,
82
+ `pages/promociones/promociones.html:194` y `:279`, `pages/customer/order-tracking/order-tracking.html:985`.
82
83
  - **1 logo en círculo** → `rect`: `pages/business-onboarding/step-info/step-info.html:42` (en
83
- `mi-negocio.html:518` el mismo logo es `rect`, y en el home del cliente se ve cuadrado).
84
+ `mi-negocio.html:520` el mismo logo es `rect`, y en el home del cliente se ve cuadrado).
84
85
  - **3 imágenes en cuadrado que deberían ir `fluid`**: comprobantes en
85
86
  `components/plan-change-modal/plan-change-modal.html:150` y `pages/central/central-gastos/central-gastos.html:118`;
86
- la portada 16:9 en `pages/mi-negocio/mi-negocio.html:572` (en el onboarding ya va `fluid`).
87
+ la portada 16:9 en `pages/mi-negocio/mi-negocio.html:574` (en el onboarding ya va `fluid`).
87
88
  - **8 sin `editable`**: `components/avatar-editor/avatar-editor.ts:33` (pone `false` aunque tiene
88
- recortador), `pages/customer/order-tracking/order-tracking.html:985` (cliente, solo celular),
89
+ recortador), `pages/customer/order-tracking/order-tracking.html:978` (cliente, solo celular),
89
90
  `components/plan-change-modal/plan-change-modal.html:150`, `pages/central/central-gastos/central-gastos.html:118`,
90
- `pages/promociones/promociones.html:185` y `:269`, y `pages/business-onboarding/step-info/step-info.html:42` y `:56`.
91
+ `pages/promociones/promociones.html:186` y `:271`, y `pages/business-onboarding/step-info/step-info.html:42` y `:56`.
91
92
  - **2 áreas de subida armadas a mano** que van con este componente (`rect`, `fluid`, `editable`):
92
93
  `components/renewal-modal/renewal-modal.html:64` (comprobante, con SVG propio) y
93
94
  `pages/products/add-product/add-product.html:223` (foto del producto, con dropzone propia).
@@ -95,16 +96,22 @@ El archivo que entrega **no se sube tal cual**: pasa por `ImageCompressorService
95
96
 
96
97
  ## Tamaño en mobile y en web
97
98
 
98
- En mobile se toca con el dedo: lo que se toca mide **44 px o más**. El área vacía se toca entera
99
- (80 a 200 px), así que pasa; los botones con imagen, no. En pantallas de los dos se elige con el
100
- servicio de breakpoints de la app (`bp`, en `services/breakpoints.service.ts`).
99
+ En mobile se toca con el dedo: lo que se toca mide **44 px o más** (canon (dueño, 04-10-2026): piso táctil 44 en el teléfono). El área vacía se
100
+ toca entera (80 a 200 px), así que pasa. Los botones con imagen se **ven** de 40 (lápiz y tacho) y
101
+ 32 («Quitar»), pero en el teléfono (≤ 767 px) **se tocan en 44 de alto** con un `::before`
102
+ invisible (04-10-2026). En pantallas de los dos se elige con el servicio de breakpoints de la app
103
+ (`bp`, en `services/breakpoints.service.ts`).
104
+
105
+ **Por qué no hay un size nuevo**: aquí `size` (`sm`/`md`/`lg`/`xl`) es el tamaño de la **foto**, no
106
+ el de los botones. Un `2xl` agrandaría la imagen sin que nadie lo pida; el área invisible lleva lo
107
+ que se toca a 44 sin cambiar el dibujo ni los sizes de hoy.
101
108
 
102
109
  | uso | mobile | web | fuente |
103
110
  |---|---|---|---|
104
111
  | comprobante, captura, QR, portada, banner | `fluid` | `fluid` (en una columna de ≤ 480 px) | propuesta |
105
112
  | logo, foto de producto, foto de perfil | `xl` (200) | `xl` (200), o `lg` (160) al lado del nombre | propuesta |
106
- | lápiz y tacho (`editable`) | 40 px (32 en `sm`) | 40 px | canon (aprobado por el dueño, 03-10-2026), extensión SUI |
107
- | «Quitar» (sin `editable`) | 32 px (`sui-button` `xsmall`) | 32 px | canon (aprobado por el dueño, 03-10-2026) |
113
+ | lápiz y tacho (`editable`) | se ven de 40 (32 en `sm`), se tocan en 44 de alto; a los lados el área crece la mitad del espacio entre los dos (3; 2 en `sm`) para no pisarse | 40 px | canon (dueño, 04-10-2026): piso táctil 44 en el teléfono (área) · canon (aprobado por el dueño, 03-10-2026), extensión SUI (40) |
114
+ | «Quitar» (sin `editable`) | se ve de 32 (`sui-button` `xsmall`), se toca en 44 de alto: crece 4 hacia la foto (la mitad del gap de 8) y 8 hacia abajo | 32 px | canon (dueño, 04-10-2026): piso táctil 44 en el teléfono (área) · canon (aprobado por el dueño, 03-10-2026) |
108
115
 
109
116
  ```html
110
117
  <sui-image-upload shape="rect" [size]="bp.isMobile() ? 'xl' : 'lg'" [editable]="true"
@@ -116,7 +123,8 @@ servicio de breakpoints de la app (`bp`, en `services/breakpoints.service.ts`).
116
123
 
117
124
  Desde el 03-10-2026 el lápiz y el tacho miden **40** (antes 34; en `sm`, de 80 de lado, no entran dos
118
125
  de 40 y quedan en 32) y el «Quitar» es un `sui-button` `xsmall` de **32** (antes 28). En `circle`
119
- los dos botones van centrados abajo, dentro del círculo.
126
+ los dos botones van centrados abajo, dentro del círculo. Lo que haya justo debajo del «Quitar»
127
+ pierde 8 px de toque en el teléfono: no pegarle otro control sin margen.
120
128
 
121
129
  ## «No usar»: por qué no hoy y cuándo sí
122
130
 
@@ -169,7 +177,7 @@ recortador; se llama con una referencia: `#qr` → `qr.abrirSelector()`).
169
177
  (antes en voseo).
170
178
  - **El default de `shape` es `circle`** y el de `size` es `lg`: para un logo o un comprobante hay
171
179
  que pasar los dos.
172
- - **Con `fluid`, `size` no hace nada** (`promociones.html:185` pasa `size="lg"` y `fluid` a la vez).
180
+ - **Con `fluid`, `size` no hace nada** (`promociones.html:186` pasa `size="lg"` y `fluid` a la vez).
173
181
  - **`removed` ya vacía `src`** por dentro; quien lo usa solo limpia su `File` y su estado.
174
182
  - **Al elegir, pone la vista previa sola** (`src` = data URL) y emite el `File` original, sin
175
183
  comprimir ni recortar. Comprimir y recortar es trabajo de la pantalla.
@@ -178,6 +186,10 @@ recortador; se llama con una referencia: `#qr` → `qr.abrirSelector()`).
178
186
  - Con `circle` + `editable` los botones van centrados abajo, sobre la foto (antes, en la esquina, el
179
187
  círculo recortaba el tacho).
180
188
  - Con `src` puesto, tocar el área vacía no hace nada: para elegir otra va el lápiz o `abrirSelector()`.
189
+ - **Teclado (04-10-2026):** vacío, el host es el botón (`role="button"`, Enter/Espacio abren el
190
+ selector). Con imagen deja de serlo, porque adentro hay botones: sin `editable` la foto entera es
191
+ un `<button>` «Cambiar imagen» (antes un `div` que solo respondía al mouse) y «Quitar» va aparte;
192
+ con `editable`, el lápiz y el tacho.
181
193
  - El `alt` de la vista previa dice «Vista previa».
182
194
  - El atributo `title` del host se borra solo (no sale el tooltip gris del navegador).
183
195
  - Ya trae el arreglo de iOS para el `:active` pegado.
@@ -0,0 +1,107 @@
1
+ ---
2
+ name: sui-img-retry
3
+ selector: img[suiImgRetry]
4
+ resumen: Directiva que reintenta cargar un <img> cuando falla la red y marca cuándo cargó o se dio por perdido
5
+ alternativas: [sui-avatar (foto de persona o logo con iniciales de respaldo), sui-image-upload (subir una imagen)]
6
+ ---
7
+
8
+ # sui-img-retry
9
+
10
+ Story: [Utilities/Img Retry](https://sui-design-system.web.app/?path=/docs/utilities-img-retry--docs)
11
+
12
+ ## Cuándo usarlo / cuándo no
13
+
14
+ **Úsalo** en los `<img>` de contenido remoto que **tienen que verse** aunque la red falle un
15
+ segundo: portadas y logos de locales, banners, fotos de productos. Un `<img>` normal que falla
16
+ queda roto hasta que se vuelve a crear; con la directiva se reintenta solo, como en una app
17
+ nativa.
18
+
19
+ **No lo uses** para:
20
+
21
+ - Íconos o imágenes locales del bundle (`/assets/…`): no fallan por red.
22
+ - Una foto de persona con respaldo de iniciales: `sui-avatar` ya resuelve el caso sin foto.
23
+ - Reemplazar el cache: el cache en disco lo dan los headers del Storage
24
+ (`cache-control: public, max-age=31536000, immutable`). La directiva solo cubre las cargas
25
+ que **fallaron**.
26
+
27
+ ## Qué variante usar
28
+
29
+ > **No está en la guía del DS: es una utilidad de SUI**, sin Figma ni variantes.
30
+ >
31
+ > Uso medido el 03-10-2026 en `master-pedidos/src/app`: 20 `<img>` con la directiva (15 en
32
+ > `pages/customer/store-browser/store-browser.html`, 3 en `category-browser`, 1 en `promos`, 1 en
33
+ > `components/sedes`) de 124 `<img>` en total. En el DS la usa `sui-store-card`.
34
+
35
+ No tiene variantes ni inputs. Lo que hace:
36
+
37
+ | momento | qué pasa | fuente |
38
+ |---|---|---|
39
+ | falla la carga | reintenta a 1 s, 3 s y 8 s (tres intentos) | componente |
40
+ | desde el segundo reintento | antes de reintentar, vuelve a bajar la imagen con `fetch(…, { cache: 'reload' })` para pisar una copia rota que haya quedado en el cache | componente |
41
+ | vuelve la red (`online`) | si la imagen no está cargada, reintenta de inmediato y reinicia el contador | componente |
42
+ | carga bien | agrega la clase `sui-img-loaded` y quita `data-sui-img-dead` | componente |
43
+ | se agotan los reintentos | pone el atributo `data-sui-img-dead` | componente |
44
+ | cambia el `src` | el contador arranca de cero para la URL nueva | componente |
45
+
46
+ | dónde | regla | fuente |
47
+ |---|---|---|
48
+ | imágenes del Storage en el home y los listados del cliente | siempre con la directiva | propuesta (es donde está hoy, y donde se vio el bug del 10-07-2026: portadas grises tras un corte) |
49
+ | el resto de `<img>` remotos | sumarla cuando la imagen sea parte de la decisión (la foto del producto en la carta) | propuesta |
50
+
51
+ ## Tamaño en mobile y en web
52
+
53
+ No aplica: es una directiva, no dibuja nada. El tamaño es el del `<img>`.
54
+
55
+ ## API
56
+
57
+ <!-- api:inicio -->
58
+ <!-- generada: no editar a mano — `npm run docs` -->
59
+
60
+ Inputs: ninguno.
61
+
62
+ Outputs: ninguno.
63
+ <!-- api:fin -->
64
+
65
+ Solo se aplica a `<img>` (`selector: img[suiImgRetry]`). El `src` se pone como siempre
66
+ (`[src]="url"`). Lo que expone hacia el CSS:
67
+
68
+ | marca | cuándo |
69
+ |---|---|
70
+ | clase `sui-img-loaded` | la imagen cargó |
71
+ | atributo `data-sui-img-dead` | se rindió tras tres reintentos |
72
+
73
+ ## Trampas
74
+
75
+ - **Sin CSS tuyo no se nota nada de lo de arriba.** Para el fundido y el respaldo, la pantalla
76
+ pone las reglas (así lo hacen `store-browser.scss` y `promos.scss`):
77
+
78
+ ```scss
79
+ img { opacity: 0; transition: opacity 0.25s ease-out; }
80
+ img.sui-img-loaded { opacity: 1; }
81
+ img[data-sui-img-dead] { display: none; } /* o mostrar un placeholder detrás */
82
+ ```
83
+
84
+ Sin la regla de `data-sui-img-dead`, la imagen perdida muestra el ícono roto del navegador.
85
+ - **Con `opacity: 0` y sin la directiva, la imagen nunca aparece.** Si copias el CSS, copia
86
+ también `suiImgRetry`.
87
+ - **El `fetch` del reintento necesita CORS** en el servidor de la imagen (el bucket de Storage ya
88
+ lo tiene). Contra otro dominio sin CORS ese paso falla en silencio y queda el reintento común.
89
+ - **No borra el cache completo** a propósito: solo la entrada de esa URL. Borrarlo todo mataría
90
+ la ventaja de no volver a bajar nada.
91
+ - Funciona igual con `loading="lazy"` y `decoding="async"`.
92
+
93
+ ## Ejemplo
94
+
95
+ ```html
96
+ <img class="tarjeta__img" suiImgRetry [src]="local.coverUrl" [alt]="local.name"
97
+ loading="lazy" decoding="async" />
98
+ ```
99
+
100
+ ```scss
101
+ .tarjeta__img {
102
+ opacity: 0;
103
+ transition: opacity 0.25s ease-out;
104
+ &.sui-img-loaded { opacity: 1; }
105
+ &[data-sui-img-dead] { display: none; }
106
+ }
107
+ ```
@@ -31,14 +31,14 @@ Regla corta: **un dato, en su lugar, que se corrige rápido → inline · varios
31
31
  > Todo lo de abajo es **propuesta, falta aprobación**.
32
32
  >
33
33
  > Uso medido el 03-10-2026 en `master-pedidos/src/app`: **0 usos**. Hay listas con campos siempre
34
- > abiertos que se parecen (`pages/super-admin/master-settings/master-settings.html:99`, nombre de
34
+ > abiertos que se parecen (`pages/super-admin/master-settings/master-settings.html:101`, nombre de
35
35
  > cada categoría del home), pero ahí se editan varias filas y se guarda todo junto: está bien con
36
36
  > `sui-input`.
37
37
 
38
38
  | prop / evento | cuándo | fuente |
39
39
  |---|---|---|
40
40
  | `value` | El dato. `[(value)]` o `formControlName`, nunca los dos. | API |
41
- | `placeholder` | Lo que se ve si está vacío: «Sin nombre». **Siempre**: el default es «Placeholder text...». | propuesta, falta aprobación |
41
+ | `placeholder` | Lo que se ve si está vacío: «Sin nombre». **Siempre**: el default genérico es «Escribe aquí…» (en español desde el 04-10-2026). | propuesta, falta aprobación |
42
42
  | `leftIcon` | Un ícono que dice qué dato es (`price-tag-3-line` para una categoría). `false` si el texto se explica solo. El default es `user-3-line`. | propuesta, falta aprobación |
43
43
  | `editLabel` | Nombre accesible del lápiz: «Editar nombre». | propuesta, falta aprobación |
44
44
  | `error` | El valor escrito no sirve (vacío, repetido). Solo se ve en edición; no trae mensaje. | propuesta, falta aprobación |
@@ -48,14 +48,15 @@ Regla corta: **un dato, en su lugar, que se corrige rápido → inline · varios
48
48
 
49
49
  ## Tamaño en mobile y en web
50
50
 
51
- **No tiene `size`**: mide 36 px de alto y sus botones (lápiz, ✓, ✕) son de 24 × 24. El texto ya
52
- sube a 16 px en mobile (sin zoom de iOS). **No tiene tamaño suficiente para mobile**: los botones
51
+ **No tiene `size`**: mide 38 px de alto (8 + 20 + 8 de padding y línea, más 1 + 1 de borde) y sus
52
+ botones (lápiz, ✓, ✕) son de 24 × 24 (ícono de 20 + 2 de padding). En edición el texto sube a 16 px
53
+ en mobile (sin zoom de iOS). **No tiene tamaño suficiente para mobile**: los botones
53
54
  de 24 px quedan lejos de los 44 que pide un dedo. Usarlo en el panel web; en el teléfono, editar
54
55
  con un `sui-input` `large`.
55
56
 
56
57
  | uso | mobile | web |
57
58
  |---|---|---|
58
- | renombrar en una lista | `sui-input` `large` en un modal | este, 36 px |
59
+ | renombrar en una lista | `sui-input` `large` en un modal | este, 38 px |
59
60
 
60
61
  ## «No usar»: por qué no hoy y cuándo sí
61
62
 
@@ -72,7 +73,7 @@ con un `sui-input` `large`.
72
73
  | input | tipo | default |
73
74
  |---|---|---|
74
75
  | `value` · model, `[(value)]` | `string` | `''` |
75
- | `placeholder` | `string` | `'Placeholder text...'` |
76
+ | `placeholder` | `string` | `'Escribe aquí…'` |
76
77
  | `leftIcon` | `string \| false` | `'user-3-line'` |
77
78
  | `error` | `boolean` | `false` |
78
79
  | `disabled` | `boolean` | `false` |
@@ -33,7 +33,7 @@ Regla corta: **dentro de una frase o al final de un campo → inline · campo
33
33
 
34
34
  | prop | cuándo | fuente |
35
35
  |---|---|---|
36
- | `type="icon"` (default) | Con un ícono delante (atenuado hasta que se elige). | según la guía del DS |
36
+ | `type="icon"` (default) | Con un ícono delante. Texto e ícono van atenuados (`text-sub-600`) salvo en hover, con foco o con el menú abierto. | según la guía del DS |
37
37
  | `type="country"` + `flag` | No usar hoy: todo es Perú. | según la guía del DS (ejemplo «Country») |
38
38
  | `items` | `{ value, label, sublabel?, icon?, flag?, disabled? }`. | API |
39
39
  | `selected` / `selectedChange` | La opción elegida. O `formControlName`, nunca los dos. | API |
@@ -48,10 +48,13 @@ es la palabra, muy por debajo de los 44 px. **No tiene tamaño suficiente para m
48
48
  teléfono, solo dentro de un `sui-input` (que da el alto) o con la frase en una fila que se toque
49
49
  entera.
50
50
 
51
- | uso | mobile | web |
52
- |---|---|---|
53
- | dentro de una frase | evitar: usar `sui-select` | 20 px, en línea con el texto |
54
- | al final de un `sui-input` | el alto lo da el input (`large`) | el alto lo da el input (`medium`) |
51
+ | uso | mobile | web | fuente |
52
+ |---|---|---|---|
53
+ | dentro de una frase | evitar: usar `sui-select` | 20 px, en línea con el texto | propuesta, falta aprobación |
54
+ | al final de un `sui-input` | el alto lo da el input (`large`) | el alto lo da el input (`medium`) | propuesta, falta aprobación |
55
+
56
+ Las opciones del menú miden **36 px también en mobile**: a diferencia de `sui-select` y de los
57
+ compactos, este no tiene la regla de 44 en ≤ 767 px (`sui-inline-select.scss` no la trae).
55
58
 
56
59
  ## «No usar»: por qué no hoy y cuándo sí
57
60
 
@@ -35,11 +35,11 @@ Regla corta: **una línea → input · varias → textarea · de una lista → s
35
35
  > fecha y contador) sin do/don't. Lo marcado «según la guía del DS» sale de esos ejemplos; el
36
36
  > resto es **propuesta, falta aprobación**, salvo lo que ya es canon (CLAUDE.md, CANON-SUI).
37
37
  >
38
- > Uso medido el 03-10-2026 en `master-pedidos/src/app` (misma exclusión que `sui-badge`, más
39
- > `master-ejercicios`): **194 usos en 61 archivos**. Tipos: 53 `text`, 36 sin `type` (`text`),
40
- > 32 `amount`, 22 `number`, 18 `tel`, 10 `email`, 10 `search`, 7 `date`, 3 `password`, 2 `url`,
41
- > 1 `datetime-local`. Tamaños: 163 sin `size` (`medium`), 18 `large`, 3 `xlarge`, 3 `medium`,
42
- > 2 `small`, 5 dinámicos.
38
+ > Uso medido el 04-10-2026 en `master-pedidos/src/app` (misma exclusión que `sui-badge`, más
39
+ > `master-ejercicios`): **195 usos en 61 archivos**. Tipos: 42 `text`, 36 sin `type` (`text`),
40
+ > 34 `amount`, 21 `search`, 21 `number`, 18 `tel`, 10 `email`, 7 `date`, 3 `password-toggle`,
41
+ > 2 `url`, 1 `datetime-local`. Tamaños: 88 `bp.isMobile() ? 'large' : 'medium'`, 77 sin `size`
42
+ > (`medium`), 18 `large`, 3 `xlarge`, 3 `medium`, 1 `small`, 3 `bp.controlSize()`, 2 otros dinámicos.
43
43
 
44
44
  ### `type` — qué dato es
45
45
 
@@ -61,20 +61,9 @@ El `type` decide el teclado del teléfono y el filtro de teclas. Por dentro, `nu
61
61
  | `card` | No usar hoy: no hay pago con tarjeta. | según la guía del DS (ejemplo «Payment Input») |
62
62
  | `button` | No usar hoy: campo de solo lectura con una acción al lado (copiar enlace). | según la guía del DS (ejemplo «With Button») |
63
63
 
64
- **Usos de hoy que rompen la regla:**
65
-
66
- - **11 buscadores con `type="text"`** → `type="search"` (hoy no sale la lupa en el teclado):
67
- `pages/customers/customers.html:28`, `pages/products/products.html:71`,
68
- `components/map-picker-modal/map-picker-modal.html:14`, `pages/settings/team/team.html:59`,
69
- `pages/super-admin/super-admin.html:63`…
70
- - **21 `amount` sin `prefix="S/"`**, 15 de ellos con «(S/)» metido en el label:
71
- `pages/super-admin/master-settings/master-settings.html:273` («Mínimo (S/)»),
72
- `pages/business-onboarding/step-product/step-product.html:33` («Precio (S/)», placeholder «Ej: 25»),
73
- `pages/super-admin/master-drivers/master-drivers.html:99`.
74
- - **2 montos con `type="number"`** → `amount` + `prefix`: `pages/super-admin/super-admin.html:649`
75
- («Monto a cobrar»), `pages/super-admin/master-gastos/master-gastos.html:193` («Monto»).
76
- - **3 `password` sin ojo** → `password-toggle`: `pages/auth/login/login.html:71`,
77
- `pages/auth/register/register.html:121`, `:133`.
64
+ **Usos de hoy que rompen la regla:** ninguno (medido el 04-10-2026). Los 11 buscadores con
65
+ `type="text"`, los 21 `amount` sin `prefix="S/"`, los 2 montos con `type="number"` y los 3
66
+ `password` sin ojo se corrigieron en la app el 03-10-2026 (merge `70f937e4`).
78
67
 
79
68
  ### Las piezas
80
69
 
@@ -103,17 +92,11 @@ El `type` decide el teclado del teléfono y el filtro de teclas. Por dentro, `nu
103
92
  | `closeOnOutsideClick` | Déjalo en `true`: tocar fuera baja el teclado. `false` solo si la pantalla maneja el foco a mano (1 uso). | código del DS |
104
93
  | `leadingControl` / `trailingControl` / `leadingDivider` / `trailingDivider` | Componer un control adentro: el país del teléfono (`sui-compact-select-for-input` en `[data-slot=start]`) o una acción al lado. Hoy sin uso. | según la guía del DS (ejemplos «With Select» y «With Button») |
105
94
 
106
- **Usos de hoy que rompen la regla:**
107
-
108
- - **Los 24 `sublabel` de hoy van sin paréntesis** (input, textarea y select: 17 «Opcional», 4 «No editable», 2 «Máximo a descontar», 1 «Solo interno») y se leen pegados al label → «(Opcional)»:
109
- `components/address-form-modal/address-form-modal.html:134`, `pages/discounts/discounts.html:170`,
110
- `pages/customer/profile/profile.html:234`.
111
- - **16 «(opcional)» escritos en el label** (input, textarea y select juntos) → `sublabel="(Opcional)"`:
112
- `pages/driver/driver-profile/driver-profile.html:431` («Placa (opcional)»),
113
- `pages/super-admin/master-plans/master-plans.html:131`, `pages/super-admin/super-admin.html:661`.
114
- - **13 placeholders con `...`** (input, textarea y select) → `…`: `pages/customers/customers.html:28`
115
- («Buscar clientes...»), `pages/products/products.html:71`, `components/address-form-modal/address-form-modal.html:134`.
116
- - **2 campos sin label en el login** (el placeholder hace de rótulo): `pages/auth/login/login.html:64`, `:71`.
95
+ **Usos de hoy que rompen la regla** (medido el 04-10-2026; los `sublabel` sin paréntesis, los
96
+ «(opcional)» en el label y los placeholders con `...` ya se corrigieron en la app, commits
97
+ `ce4a2d12` y `e0470b34`):
98
+
99
+ - **2 campos sin label en el login** (el placeholder hace de rótulo): `pages/auth/login/login.html:64`, `:72`.
117
100
  - **6 campos con el label afuera** (`<sui-form-label>` suelto encima) en el onboarding del
118
101
  repartidor: `pages/driver-onboarding/step-info/step-info.html:37`. Funciona, pero el error y el
119
102
  `required` quedan desconectados del campo: va el `label` del propio input.
@@ -124,6 +107,11 @@ Los altos de `sui-input` son **los del botón a propósito** (`large` 48 y `xlar
124
107
  extensión de SUI): un campo y un botón puestos lado a lado miden lo mismo. La guía del DS solo
125
108
  tiene `medium` (40), `small` (36) y `xsmall` (32).
126
109
 
110
+ En large y xlarge el texto sube a 16 px (canon, aprobado por el dueño el 03-10-2026): el valor, el placeholder y el
111
+ prefijo van en 16/24 también en desktop. En mobile el valor y el placeholder ya iban en 16 en
112
+ cualquier tamaño (por el zoom de iOS), y desde el 04-10-2026 el prefijo `S/` los acompaña: en el
113
+ teléfono también va en 16 en todos los tamaños (antes se quedaba en 14 al lado de un monto de 16).
114
+
127
115
  | uso | mobile | web | fuente |
128
116
  |---|---|---|---|
129
117
  | campo de formulario | `large` (48), igual que el botón del footer | `medium` (40) | propuesta, falta aprobación |
@@ -137,11 +125,12 @@ tiene `medium` (40), `small` (36) y `xsmall` (32).
137
125
  ```
138
126
 
139
127
  No uses `bp.controlSize()` en campos: da `xlarge` (52) en mobile, más alto que el botón `large`
140
- del footer (3 usos hoy, `pages/customer/checkout/checkout.html:392`). El texto sube solo a 16 px
128
+ del footer (3 usos hoy: `pages/customer/checkout/checkout.html:269`, `:384`,
129
+ `pages/super-admin/master-sonidos-push/master-sonidos-push.html:43`). El texto sube solo a 16 px
141
130
  en mobile (evita el zoom de iOS): no hace falta pedirlo.
142
131
 
143
- Hoy: **163 sin `size`** quedan en 40 px también en el teléfono (cumple el mínimo, no alinea con el
144
- botón `large`).
132
+ Hoy: **88 usos** ya van con `bp.isMobile() ? 'large' : 'medium'`; **77 sin `size`** quedan en 40 px
133
+ también en el teléfono (no alinea con el botón `large`).
145
134
 
146
135
  ## «No usar»: por qué no hoy y cuándo sí
147
136
 
@@ -226,6 +215,11 @@ proyectados con `leadingControl` / `trailingControl`).
226
215
  - Tocar fuera baja el teclado (`closeOnOutsideClick`). Ya distingue tocar otro campo: no hace falta
227
216
  agregar lógica de blur en la pantalla.
228
217
  - El `(keydown.enter)` puesto en el host funciona: el evento sube desde el `<input>` de adentro.
218
+ - **Accesibilidad (04-10-2026)**: cada campo trae su `id`; el `label` interno apunta a él con `for`,
219
+ el hint o el error se enlazan con `aria-describedby` y `error` pone `aria-invalid`. No hace
220
+ falta agregarlos a mano. Un `sui-form-label` puesto **afuera** no conoce ese `id`: usa `[label]`.
221
+ - En el teléfono la X de limpiar y el ojo se ven de 12-20 px pero se tocan en 44 × 44 (área
222
+ invisible, 04-10-2026).
229
223
 
230
224
  ## Ejemplo
231
225
 
@@ -63,20 +63,24 @@ Regla corta: **servicio externo que se prende y se configura → integration-swi
63
63
 
64
64
  ## Tamaño en mobile y en web
65
65
 
66
- No tiene `size`.
66
+ | size | «Administrar» | interruptor | fuente |
67
+ |---|---|---|---|
68
+ | `medium` (default) | 38 (8 + 20 + 8 de padding y 2 de borde), texto 14 | `sui-switch` `medium`, 32 × 20 | Figma |
69
+ | `large` | 44 (9 + 24 + 9 + 2), texto 16 | igual: 32 × 20 | canon (dueño, 04-10-2026): piso táctil 44 en el teléfono. Size nuevo del 04-10-2026 |
67
70
 
68
71
  | uso | mobile | web |
69
72
  |---|---|---|
70
- | interruptor | **32 × 20 fijo: bajo el piso de mobile** | 32 × 20 |
71
- | «Administrar» | **36 de alto: bajo el piso de 44** | 36 |
73
+ | «Administrar» | `large` (44) | `medium` (38) |
72
74
  | layout | `vertical` | `horizontal` |
73
75
 
74
76
  ```html
75
- <sui-integration-switch [type]="bp.isMobile() ? 'vertical' : 'horizontal'" … />
77
+ <sui-integration-switch [size]="bp.isMobile() ? 'large' : 'medium'"
78
+ [type]="bp.isMobile() ? 'vertical' : 'horizontal'" … />
76
79
  ```
77
80
 
78
- **No llega al tamaño de mobile.** El switch es `sui-switch` `medium` fijo y el botón mide 36. Antes
79
- de usarlo en el teléfono hace falta un `size` en el DS (no se inventó aquí).
81
+ **El interruptor sigue bajo el piso**: es `sui-switch` `medium` fijo (20 de alto) en los dos sizes,
82
+ y a diferencia de `sui-switch-card`, tocar la tarjeta no prende nada: solo responde el
83
+ interruptor. Para algo que se prende y apaga en el teléfono, `sui-switch-card` es la salida.
80
84
 
81
85
  ## «No usar»: por qué no hoy y cuándo sí
82
86
 
@@ -94,6 +98,7 @@ de usarlo en el teléfono hace falta un `size` en el DS (no se inventó aquí).
94
98
  |---|---|---|
95
99
  | `type` | `'horizontal' \| 'vertical'` | `'horizontal'` |
96
100
  | `appearance` | `'card' \| 'list'` | `'card'` |
101
+ | `size` | `'medium' \| 'large'` | `'medium'` |
97
102
  | `title` | `string` | `''` |
98
103
  | `description` | `string \| null` | `null` |
99
104
  | `brandIconSrc` | `string \| null` | `null` |
@@ -123,10 +128,12 @@ Slot: `[sui-integration-brand]` (reemplaza al logo). Implementa `ControlValueAcc
123
128
  - **Es controlada**: `active` es input y `activeChange` solo avisa; sin actualizar tu señal el
124
129
  interruptor no se mueve.
125
130
  - El estado se llama `active`, no `checked` (como en `sui-switch-label`).
126
- - El interruptor no tiene `size`: siempre `medium`.
131
+ - El interruptor no cambia con `size`: siempre `sui-switch` `medium`. El `size` del componente (04-10-2026) solo agranda «Administrar».
127
132
  - En `vertical` el interruptor va arriba a la derecha y «Administrar» abajo a ancho completo.
128
133
  - `appearance="list"` no tiene borde ni fondo ni padding: va dentro de algo que los ponga.
129
134
  - El host borra el atributo `title` del DOM; el título se ve como texto, no como `aria-label`.
135
+ El interruptor toma su nombre de ese título (y su descripción de `description`) con
136
+ `aria-labelledby` (revisión 04-10-2026); antes el lector decía solo «interruptor».
130
137
 
131
138
  ## Ejemplo
132
139
 
@@ -46,10 +46,10 @@ Usos de hoy que rompen la regla: **0**.
46
46
 
47
47
  ## Tamaño en mobile y en web
48
48
 
49
- En mobile se lee y se toca con el dedo, así que va más grande; en web, más chico. En las
50
- pantallas que se usan en los dos (panel del local, super admin) se elige con el servicio de
51
- breakpoints de la app (`bp`, en `services/breakpoints.service.ts`); en las que solo existen en
52
- el celular (cliente, repartidor) va directo el valor de mobile. Todo es **propuesta**.
49
+ No es táctil: es una tecla dibujada. En mobile no hay teclado físico, así que no se muestra; en
50
+ web tiene un solo tamaño. Donde la pantalla existe en los dos (panel del local, super admin) se
51
+ oculta con el servicio de breakpoints de la app (`bp`, en `services/breakpoints.service.ts`). Todo
52
+ es **propuesta**.
53
53
 
54
54
  | uso | mobile | web |
55
55
  |---|---|---|
@@ -12,7 +12,7 @@ Story: [Atoms/Icon/Key Icon](https://sui-design-system.web.app/?path=/docs/atoms
12
12
  ## Cuándo usarlo / cuándo no
13
13
 
14
14
  **Úsalo** cuando un ícono tiene que **anclar** algo: el inicio de una fila, la cabecera de un
15
- modal, el resultado de una acción («Cuenta bloqueada», «¡Gracias por calificar!»).
15
+ modal, el resultado de una acción («Cuenta bloqueada», «Gracias por calificar»).
16
16
 
17
17
  **No lo uses** para:
18
18
 
@@ -35,7 +35,11 @@ modal, el resultado de una acción («Cuenta bloqueada», «¡Gracias por califi
35
35
  | `lighter` | El ícono dice un estado: el color del fondo **es** el significado («Cuenta bloqueada» en rojo, «Calificación enviada» en verde). | propuesta |
36
36
  | `stroke` (default) | Ícono neutro al inicio de una fila, sobre fondo blanco. **Siempre con `color="gray"`.** | propuesta |
37
37
 
38
- ### `color` — mismo significado que el badge
38
+ ### `color` — mismo significado que el badge, salvo `teal`
39
+
40
+ Ojo: aquí `teal` pinta el token **verified** (celeste, `--sui-state-verified-*`), que en
41
+ `sui-badge` es `sky`; el `teal` del badge es **stable** (verde agua). La key-icon no tiene `sky`
42
+ ni un color para stable.
39
43
 
40
44
  | valor | estado de la paleta | cuándo | fuente |
41
45
  |---|---|---|---|
@@ -30,7 +30,7 @@ Es el reemplazo del `sui-button` `ghost` `primary`.
30
30
  > los dos tamaños, el subrayado, los íconos y el deshabilitado, sin do/don't. Las reglas de
31
31
  > abajo son **canon (aprobado por el dueño, 03-10-2026)** salvo donde dice otra fuente.
32
32
  >
33
- > Uso medido el 03-10-2026 en `master-pedidos/src/app`: 22 link-buttons en 17 archivos, sin
33
+ > Uso medido el 03-10-2026 en `master-pedidos/src/app` (el 04-10-2026 ya son 23): 22 link-buttons en 17 archivos, sin
34
34
  > contar prototipos ni vitrinas (`master-preview`, `master-prototipos`, `mockup-sheets-*`,
35
35
  > `dx/*`, `master-rutina`, `master-medico`, `dev-index`) ni la copia local del componente en
36
36
  > `components/sui/sui-link-button/`. Variantes: 10 `gray` (1 por default), 7 `primary`,
@@ -44,24 +44,26 @@ Es el reemplazo del `sui-button` `ghost` `primary`.
44
44
  - **`modifiable` no tiene color propio**: hereda el del contenedor, para que lo pinte quien lo usa.
45
45
  - **Subrayado**: aparece al pasar el mouse; con `underline` queda fijo.
46
46
  - **Deshabilitado**: el texto pasa a `text-disabled-300` y se va el subrayado.
47
- - **Tamaños**: `large` (24 px, texto `label-md`, ícono 20; extensión SUI para mobile), `medium` (20 px, `label-sm`, ícono 20) y `small` (16 px, `label-xs`, ícono 16).
47
+ - **Tamaños**: `medium` (20 px, `label-sm`, ícono 20) y `small` (16 px, `label-xs`, ícono 16).
48
+ `large` (24 px, `label-md`, ícono 20) **no está en la guía**: es extensión de SUI para mobile.
48
49
 
49
50
  ### `variant`
50
51
 
51
52
  | variant | cuándo | ejemplo real de la app | fuente |
52
53
  |---|---|---|---|
53
54
  | `primary` | El link principal de una sección: «Ver todas», «Cambiar horario», «Descargar la app». Reemplaza al `sui-button` `ghost` `primary`. | `pages/customer/checkout/checkout.html:165` («Cambiar horario») · `pages/public/landing-business/landing-business.html:208` («Descargar la app») | canon (aprobado por el dueño, 03-10-2026) |
54
- | `gray` (default) | Salida de baja jerarquía: «Omitir», «Ahora no», «Cerrar sesión», «Más información». | `pages/account-suspended/account-suspended.html:70` («Cerrar sesión») · `pages/super-admin/master-approvals/master-approvals.html:90` («Más información») | canon (aprobado por el dueño, 03-10-2026) |
55
+ | `gray` (default) | Salida de baja jerarquía: «Omitir», «Ahora no», «Cerrar sesión», «Más información». | `pages/account-suspended/account-suspended.html:70` («Cerrar sesión») · `pages/super-admin/master-approvals/master-approvals.html:89` («Más información») | canon (aprobado por el dueño, 03-10-2026) |
55
56
  | `black` | Un link dentro de un texto, con `underline`: «Términos y condiciones», «Ver política». | (sin uso hoy) | canon (aprobado por el dueño, 03-10-2026) |
56
57
  | `error` | Quitar algo menor, en texto: «Quitar», «Borrar foto». Nunca para abrir una destructiva grande. | (sin uso correcto hoy) | canon (aprobado por el dueño, 03-10-2026) |
57
58
  | `modifiable` | Toma el color del contenedor: las acciones del alert, del banner y del toast. | `components/sui/sui-toast/sui-toast-outlet.html:36` (acción del toast) · `components/subscription-banner/subscription-banner.html:10` («Renovar plan») | hereda el color: según la guía del DS · dónde va: canon (aprobado por el dueño, 03-10-2026) |
58
59
 
59
60
  **Usos de hoy que rompen la regla:**
60
61
 
61
- - **3 `error` que abren una destructiva grande → `sui-button` `stroke` `error`:**
62
+ - **4 `error` que abren una destructiva grande → `sui-button` `stroke` `error`:**
62
63
  `pages/super-admin/master-orders/master-orders.html:425` («Cancelar pedido»),
63
- `pages/orders/orders.html:232` («Rechazar pedido»), `pages/central/central-gastos/central-gastos.html:101`
64
- («Anular gasto»).
64
+ `pages/orders/orders.html:233` («Rechazar pedido»), `pages/central/central-gastos/central-gastos.html:101`
65
+ («Anular gasto») y `pages/driver/driver-order-detail/driver-order-detail.html:745` («Cancelar» el
66
+ pedido, en `large`; nuevo, medido el 04-10-2026).
65
67
  - A discutir: `pages/super-admin/master-orders/master-orders.html:430` («Liberar» en `gray`): es una
66
68
  acción de operación, no una salida de baja jerarquía.
67
69
 
@@ -96,8 +98,8 @@ Los íconos son nombres RemixIcon sin el prefijo `ri-`. Miden 20 px en `large` y
96
98
  |---|---|---|
97
99
  | `true` | La acción existe pero ahora no se puede: mientras se guarda, mientras se procesa otra acción. Mejor que esconderla si la persona la espera en ese lugar. | cómo se ve: según la guía del DS · cuándo: propuesta |
98
100
 
99
- Ejemplos: `components/add-product-modal/add-product-modal.html:330` («Vista previa» mientras guarda),
100
- `pages/orders/orders.html:232`.
101
+ Ejemplos: `components/add-product-modal/add-product-modal.html:339` («Vista previa» mientras guarda),
102
+ `pages/orders/orders.html:233`.
101
103
 
102
104
  ### `href`, `target`, `rel`, `type`, `ariaLabel`
103
105
 
@@ -113,8 +115,8 @@ Ejemplos: `components/add-product-modal/add-product-modal.html:330` («Vista pre
113
115
  En mobile se toca con el dedo: el área táctil tiene que medir **44 px o más**. En web, con mouse,
114
116
  va un tamaño más chico. La app ya lo resuelve con `BreakpointsService`
115
117
  (`src/app/services/breakpoints.service.ts`, mobile = hasta 767 px):
116
- `[size]="bp.isMobile() ? 'large' : 'small'"`, 27 usos hoy en `master-pedidos` (16 `large`/`small`,
117
- 9 `large`/`medium`, 2 `medium`/`xsmall`). Regla del dueño, 03-10-2026.
118
+ `[size]="bp.isMobile() ? 'large' : 'small'"`. Medido el 04-10-2026 en `master-pedidos`: 166 `[size]`
119
+ con `bp` (142 `large`/`medium`, 22 `large`/`small`, 2 `medium`/`xsmall`). Regla del dueño, 03-10-2026.
118
120
 
119
121
  | size | alto | texto | ícono |
120
122
  |---|---|---|---|
@@ -138,11 +140,13 @@ va un tamaño más chico. La app ya lo resuelve con `BreakpointsService`
138
140
 
139
141
  **Ningún tamaño llega a 44 px**: el link mide 16–24 de alto y no tiene padding. En mobile el área
140
142
  táctil la pone el contenedor: la fila o el bloque donde vive tiene que medir 44 px o más de alto, o
141
- dejar aire alrededor del link. `small` (16) no va en mobile: hoy hay 6 links `small` fijos
142
- (`pages/driver/driver-profile/driver-profile.html:258`, `:264`, `pages/driver/driver-dashboard/driver-dashboard.html:1089`,
143
- `pages/mi-negocio/mi-negocio.html:472`, `pages/customer/order-history/order-history.html:413`,
144
- `components/add-product-modal/add-product-modal.html:330`); los 4 de repartidor y cliente se usan
145
- sí o sí en el teléfono → `[size]="bp.isMobile() ? 'medium' : 'small'"`.
143
+ dejar aire alrededor del link. `small` (16) no va en mobile. Medido el 04-10-2026: los 4 de
144
+ repartidor y cliente ya usan `[size]="bp.isMobile() ? 'medium' : 'small'"`
145
+ (`pages/driver/driver-profile/driver-profile.html:258` y `:264`,
146
+ `pages/driver/driver-dashboard/driver-dashboard.html:1092`,
147
+ `pages/customer/order-history/order-history.html:412`). Quedan 2 `small` fijos, los dos del panel
148
+ de la empresa: `pages/mi-negocio/mi-negocio.html:474` y
149
+ `components/add-product-modal/add-product-modal.html:339`.
146
150
 
147
151
  ## «No usar»: por qué no hoy y cuándo sí
148
152
 
@@ -180,8 +184,8 @@ Slots: `<ng-content>` (el texto).
180
184
 
181
185
  - **El output es `(clicked)`**, no `(click)` como en `sui-button`. `(click)` sobre el host igual
182
186
  funciona porque el clic burbujea, pero hoy hay 6 usos así (`components/subscription-banner/subscription-banner.html:10`,
183
- `pages/super-admin/master-approvals/master-approvals.html:90`, `pages/central/central-gastos/central-gastos.html:101`,
184
- `pages/account-suspended/account-suspended.html:66` y `:70`, `pages/customer/viaje/viaje.html:215`).
187
+ `pages/super-admin/master-approvals/master-approvals.html:89`, `pages/central/central-gastos/central-gastos.html:101`,
188
+ `pages/account-suspended/account-suspended.html:66` y `:70`, `pages/customer/viaje/viaje.html:216`).
185
189
  Usa `(clicked)`, que ya respeta `disabled`.
186
190
  - **`rel` arranca en `null`**, a diferencia de compact, fancy y social, que traen
187
191
  `'noopener noreferrer'`. Con `target="_blank"` hay que ponerlo a mano.