@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
@@ -71,13 +71,31 @@ buscador de mobile, la fila `small` mide 40 y queda debajo de los 44 del dedo.
71
71
 
72
72
  | uso | mobile | web | fuente |
73
73
  |---|---|---|---|
74
- | resultado de una línea | `medium` (64) | `small` (40) | mobile: canon (decisión del dueño 04-10-2026, piso táctil 44: `small` mide 40, `medium` es el único size que llega) · web: propuesta, falta aprobación |
74
+ | resultado de una línea | `medium` (64) | **pendiente** (hoy `small`, 40, el default) | mobile: canon (decisión del dueño 04-10-2026, piso táctil 44: `small` mide 40, `medium` es el único size que llega) · web: pendiente (D16, dueño 05-10-2026: el tamaño cambia el layout) |
75
75
  | resultado con descripción | `medium` (64) | `medium` (64) | mobile: canon (decisión del dueño 04-10-2026, piso táctil 44) · web: lo impone el código (`description` solo se pinta en `medium`) |
76
76
 
77
77
  ```html
78
- <sui-command-menu-item [size]="bp.isMobile() ? 'medium' : 'small'" … /> <!-- bp = BreakpointsService -->
78
+ <sui-command-menu-item [size]="bp.tactil() ? 'medium' : 'small'" … /> <!-- bp = BreakpointsService -->
79
79
  ```
80
80
 
81
+ ### Por dispositivo (D16)
82
+
83
+ Se toca, así que la tablet va con el celular. En la computadora D16 lo deja **pendiente**: `small`
84
+ (40) y `medium` (64) no son el mismo ítem más chico o más grande, porque `description` solo se pinta
85
+ en `medium`; elegir uno cambia qué se lee en la fila.
86
+
87
+ | dispositivo | size | nota |
88
+ |---|---|---|
89
+ | celular chico (< 380) | — | D16 no lo fija: el ⌘K no se arma en el celular. Si se reusa la lista, solo `medium` llega a 44 |
90
+ | celular (380–767) | `medium` | el único que llega a 44 |
91
+ | tablet táctil (`pointer: coarse`) | `medium` | Apple pide 44 también en iPad |
92
+ | computadora (`pointer: fine`) | **pendiente** | falta decidir (D16, nota ⁵); hoy queda el default `small`, y con `description` va `medium` fijo |
93
+
94
+ Ultrawide: igual que la computadora.
95
+
96
+ En master-pedidos: `[size]="bp.tactil() ? 'medium' : 'small'"` (no hay helper; el `'small'` es el
97
+ default de hoy mientras la computadora sigue pendiente). Con `description`: `size="medium"` en todos.
98
+
81
99
  ## API
82
100
 
83
101
  <!-- api:inicio -->
@@ -122,16 +140,57 @@ Slot: `[slot=brand]` (solo con `type="brand"`). `avatar` acepta un string (la UR
122
140
  - Mide como máximo 600 px de ancho.
123
141
  - El host borra el atributo `title` nativo (no aparece el tooltip gris del navegador).
124
142
 
143
+ ## Bien y mal
144
+
145
+ Abrir el resultado
146
+
147
+ ```html
148
+ <!-- ❌ mal: (clicked) nunca sale; el componente no lo conecta a ningún clic -->
149
+ <sui-command-menu-item type="left-icon" icon="file-list-3-line" title="Pedidos"
150
+ (clicked)="ir('/empresa/pedidos')" />
151
+ ```
152
+
153
+ ```html
154
+ <!-- ✅ bien: el (click) nativo del host, y Enter cableado a mano -->
155
+ <sui-command-menu-item type="left-icon" icon="file-list-3-line" title="Pedidos"
156
+ (click)="ir('/empresa/pedidos')" (keydown.enter)="ir('/empresa/pedidos')" />
157
+ ```
158
+
159
+ Resultado con segunda línea
160
+
161
+ ```html
162
+ <!-- ❌ mal: size queda en small (default) y description no se pinta -->
163
+ <sui-command-menu-item title="Pedido #1234" description="Juan Pérez · S/ 45.00" />
164
+ ```
165
+
166
+ ```html
167
+ <!-- ✅ bien -->
168
+ <sui-command-menu-item size="medium" title="Pedido #1234" description="Juan Pérez · S/ 45.00" />
169
+ ```
170
+
171
+ Ir a una pantalla
172
+
173
+ ```html
174
+ <!-- ❌ mal: left-icon sin icon; en medium (celular y tablet) deja el círculo vacío -->
175
+ <sui-command-menu-item type="left-icon" [size]="bp.tactil() ? 'medium' : 'small'" title="Recargas" />
176
+ ```
177
+
178
+ ```html
179
+ <!-- ✅ bien: el size de una línea sigue la expresión vigente (la computadora está pendiente) -->
180
+ <sui-command-menu-item type="left-icon" [size]="bp.tactil() ? 'medium' : 'small'" icon="wallet-3-line"
181
+ title="Recargas" />
182
+ ```
183
+
125
184
  ## Ejemplo
126
185
 
127
186
  ```html
128
187
  <sui-modal [(open)]="buscadorAbierto" size="large" [fullscreen]="true">
129
188
  <sui-command-menu-search [(value)]="q" placeholder="Busca pedidos, locales o repartidores…"
130
- [shortcut]="!bp.isMobile()" [button]="!bp.isMobile()" />
189
+ [shortcut]="!bp.isMobile()" [button]="!bp.tactil()" />
131
190
  <sui-content-divider type="text" text="Pantallas" />
132
191
  @for (p of pantallas(); track p.ruta) {
133
192
  <sui-command-menu-item type="left-icon" [icon]="p.icono" [title]="p.nombre"
134
- [size]="bp.isMobile() ? 'medium' : 'small'"
193
+ [size]="bp.tactil() ? 'medium' : 'small'"
135
194
  (click)="ir(p.ruta)" (keydown.enter)="ir(p.ruta)" />
136
195
  }
137
196
  @if (!bp.isMobile()) {
@@ -43,7 +43,7 @@ más oscuro) y con texto (lupa naranja, X para limpiar).
43
43
  |---|---|---|
44
44
  | `placeholder` | **Siempre**, en español y diciendo qué se busca: «Busca pedidos, locales o repartidores…». El default genérico es `'Buscar o ir a…'`. | canon (CANON-SUI §5: copy en español, elipsis `…`) |
45
45
  | `shortcut` | `true` solo en web; en mobile `false` (no hay teclado físico). | canon (README de `sui-kbd`) |
46
- | `button` | La X de limpiar **solo en web** (`true`): ahorra borrar a mano. En mobile, `false` hasta que el DS tenga un size de 44 (la X mide 20). El ícono de info del estado vacío no hace nada. | canon (aprobado por el dueño, 05-10-2026, bloque B13) |
46
+ | `button` | La X de limpiar **solo en la computadora** (`true`): ahorra borrar a mano. En el celular y en la tablet táctil, `false` hasta que el DS tenga un size de 44 (la X mide 20): se toca, así que la tablet va con el celular (D16). El ícono de info del estado vacío no hace nada. | canon (aprobado por el dueño, 05-10-2026, bloque B13) |
47
47
 
48
48
  ## Tamaño en mobile y en web
49
49
 
@@ -51,13 +51,26 @@ No tiene tamaños: 48 px de alto (14 + 20 + 13 + 1 de borde), texto 14/20, hasta
51
51
 
52
52
  | uso | mobile | web | fuente |
53
53
  |---|---|---|---|
54
- | buscador del command menu | igual, sin chip ⌘K | igual, con chip ⌘K | canon para el chip (README de `sui-kbd`); el resto, propuesta |
54
+ | buscador del command menu | igual, sin chip ⌘K ni X | igual, con chip ⌘K y X | canon para el chip (README de `sui-kbd`) y la X (B13 + D16: la tablet táctil va sin X); el resto, propuesta |
55
55
 
56
56
  ```html
57
57
  <sui-command-menu-search [(value)]="q" placeholder="Busca pedidos, locales o repartidores…"
58
- [shortcut]="!bp.isMobile()" [button]="!bp.isMobile()" /> <!-- bp = BreakpointsService -->
58
+ [shortcut]="!bp.isMobile()" [button]="!bp.tactil()" /> <!-- bp = BreakpointsService -->
59
59
  ```
60
60
 
61
+ ### Por dispositivo (D16)
62
+
63
+ No aplica: no tiene input `size` (48 px de alto y texto 14 en todos los dispositivos), así que D16 no
64
+ lo mueve. Por dispositivo solo cambian dos cosas, y no con la misma señal:
65
+
66
+ - **La X de limpiar se toca** (`sui-compact-button` `medium`, 20 px): va apagada en el celular **y en
67
+ la tablet táctil**, porque D16 pone la tablet con el celular en lo que se toca (Apple pide 44
68
+ también en iPad). `bp.tactil()`, no `bp.isMobile()`: `isMobile()` solo mira el ancho (≤ 767 px) y
69
+ en un iPad la dejaría prendida.
70
+ - **El chip ⌘K no se toca**: sigue la regla de `sui-kbd`, apagado en el celular (`!bp.isMobile()`).
71
+
72
+ En master-pedidos: `[shortcut]="!bp.isMobile()" [button]="!bp.tactil()"`, sin `[size]`.
73
+
61
74
  ## API
62
75
 
63
76
  <!-- api:inicio -->
@@ -94,6 +107,47 @@ No tiene tamaños: 48 px de alto (14 + 20 + 13 + 1 de borde), texto 14/20, hasta
94
107
  - No tiene `disabled`.
95
108
  - El ícono de info del estado vacío es decorativo: no abre ayuda ni tiene `aria-label`.
96
109
 
110
+ ## Bien y mal
111
+
112
+ Devolver el texto al campo
113
+
114
+ ```html
115
+ <!-- ❌ mal: sin [(value)] el componente no sabe que hay texto; la X nunca aparece -->
116
+ <sui-command-menu-search placeholder="Busca pedidos, locales o repartidores…"
117
+ (valueChange)="buscar($event)" />
118
+ ```
119
+
120
+ ```html
121
+ <!-- ✅ bien: el filtro sale de q (un computed), no del evento -->
122
+ <sui-command-menu-search [(value)]="q" placeholder="Busca pedidos, locales o repartidores…" />
123
+ ```
124
+
125
+ Chip ⌘K y X en el celular
126
+
127
+ ```html
128
+ <!-- ❌ mal (en el celular y en la tablet táctil): ⌘K sin teclado físico y una X de 20 px para el dedo -->
129
+ <sui-command-menu-search [(value)]="q" placeholder="Busca pedidos, locales o repartidores…"
130
+ [shortcut]="true" [button]="true" />
131
+ ```
132
+
133
+ ```html
134
+ <!-- ✅ bien: la X se toca, así que también se apaga en la tablet táctil (bp.tactil()) -->
135
+ <sui-command-menu-search [(value)]="q" placeholder="Busca pedidos, locales o repartidores…"
136
+ [shortcut]="!bp.isMobile()" [button]="!bp.tactil()" />
137
+ ```
138
+
139
+ Buscar dentro de una pantalla
140
+
141
+ ```html
142
+ <!-- ❌ mal: suelto, sin caja, parece texto; y no lleva la lupa en el teclado -->
143
+ <sui-command-menu-search [(value)]="q" placeholder="Buscar pedido…" />
144
+ ```
145
+
146
+ ```html
147
+ <!-- ✅ bien: el buscador de una pantalla es sui-input search -->
148
+ <sui-input type="search" [size]="bp.sizeControl()" placeholder="Buscar pedido…" [(value)]="q" />
149
+ ```
150
+
97
151
  ## Ejemplo
98
152
 
99
153
  ```html
@@ -101,6 +155,6 @@ No tiene tamaños: 48 px de alto (14 + 20 + 13 + 1 de borde), texto 14/20, hasta
101
155
  [(value)]="q"
102
156
  placeholder="Busca pedidos, locales o repartidores…"
103
157
  [shortcut]="!bp.isMobile()"
104
- [button]="!bp.isMobile()"
158
+ [button]="!bp.tactil()"
105
159
  (cleared)="resultados.set([])" />
106
160
  ```
@@ -53,8 +53,8 @@ Usos de hoy que rompen la regla: **0** (no hay usos).
53
53
  En mobile va más grande por legibilidad (el grupo no se toca: el área la da la fila); en web, más chico. En las
54
54
  pantallas que se usan en los dos (panel del local, super admin) se elige con el servicio de
55
55
  breakpoints de la app (`bp`, en `services/breakpoints.service.ts`); en las que solo existen en
56
- el celular (cliente, repartidor) va directo el valor de mobile. No se toca, así que la tablet va
57
- con el valor de web, y el celular chico (< 380 px) también (D16).
56
+ el celular (cliente, repartidor) también va `bp.celular()`, porque el celular chico (< 380 px) toma
57
+ el valor de web (D16, dueño 05-10-2026). No se toca, así que la tablet va con el valor de web.
58
58
  Es **canon (dueño, 05-10-2026, P1 b)**: un paso más grande en el celular que en computadora, y
59
59
  se migra todo ahora, no solo al tocar cada pantalla.
60
60
 
@@ -64,9 +64,26 @@ se migra todo ahora, no solo al tocar cada pantalla.
64
64
  | dentro de una card | `'40'` | `'32'` |
65
65
 
66
66
  ```html
67
- <sui-compact-avatar-group [size]="bp.isMobile() ? '32' : '24'" [items]="repartidores" />
67
+ <sui-compact-avatar-group [size]="bp.celular() ? '32' : '24'" [items]="repartidores" />
68
68
  ```
69
69
 
70
+ ### Por dispositivo (D16)
71
+
72
+ No se toca: sube un paso solo en el celular de 380 px o más; el resto va con el valor de web.
73
+
74
+ | dispositivo | size | nota |
75
+ |---|---|---|
76
+ | celular chico (< 380) | valor web: `'24'` fila · `'32'` card | lo que no se toca va como en la computadora (D16) |
77
+ | celular (380–767) | valor mobile: `'32'` fila · `'40'` card | P1 b: un paso más que en la computadora |
78
+ | tablet táctil (`pointer: coarse`) | valor web: `'24'` fila · `'32'` card | no se toca: el puntero no lo mueve |
79
+ | computadora (`pointer: fine`) | valor web: `'24'` fila · `'32'` card | |
80
+
81
+ Ultrawide: igual que la computadora; el espacio extra no agranda el grupo.
82
+
83
+ En master-pedidos: `[size]="bp.celular() ? '32' : '24'"` en una fila y `[size]="bp.celular() ? '40' : '32'"`
84
+ en una card (no hay helper: `bp.sizeAvatar()` usa la escala de `sui-avatar`, no `'24'`/`'32'`/`'40'`).
85
+ `bp.isMobile()` no sirve: incluye al celular chico.
86
+
70
87
  ## «No usar»: por qué no hoy y cuándo sí
71
88
 
72
89
  | qué | por qué no hoy | cuándo sí, en un flujo nuevo |
@@ -100,8 +117,48 @@ Outputs: ninguno.
100
117
  - Las reglas de foto y color de cada persona son las de `sui-avatar`: el `color` por rol va
101
118
  explícito en cada item (canon, aprobado por el dueño, 03-10-2026); sin él cae a `slate`.
102
119
 
120
+ ## Bien y mal
121
+
122
+ El size es un string
123
+
124
+ ```html
125
+ <!-- ❌ mal: con números no compila; el tipo es '24' | '32' | '40' -->
126
+ <sui-compact-avatar-group [size]="bp.celular() ? 32 : 24" [items]="repartidores" />
127
+ ```
128
+
129
+ ```html
130
+ <!-- ✅ bien: los valores van entre comillas (fila: '32' en el celular, '24' en el resto) -->
131
+ <sui-compact-avatar-group [size]="bp.celular() ? '32' : '24'" [items]="repartidores" />
132
+ ```
133
+
134
+ Tamaño en el celular chico
135
+
136
+ ```html
137
+ <!-- ❌ mal: isMobile() también sube el celular chico, que va con el valor de web (D16) -->
138
+ <sui-compact-avatar-group [size]="bp.isMobile() ? '32' : '24'" [items]="repartidores" />
139
+ ```
140
+
141
+ ```html
142
+ <!-- ✅ bien -->
143
+ <sui-compact-avatar-group [size]="bp.celular() ? '32' : '24'" [items]="repartidores" />
144
+ ```
145
+
146
+ El «+N» a mano
147
+
148
+ ```html
149
+ <!-- ❌ mal: items ya trae a todos; count fijo gana al cálculo y miente cuando cambia la lista -->
150
+ <sui-compact-avatar-group [size]="bp.celular() ? '32' : '24'" appearance="stroke" [items]="repartidores"
151
+ count="+3" />
152
+ ```
153
+
154
+ ```html
155
+ <!-- ✅ bien: count solo si items trae menos personas que el total -->
156
+ <sui-compact-avatar-group [size]="bp.celular() ? '32' : '24'" appearance="stroke" [items]="repartidores" />
157
+ ```
158
+
103
159
  ## Ejemplo
104
160
 
105
161
  ```html
106
- <sui-compact-avatar-group size="24" appearance="stroke" [items]="repartidoresDelLocal" />
162
+ <!-- celda de la tabla de locales: '32' en el celular de 380 px o más, '24' en el resto (D16) -->
163
+ <sui-compact-avatar-group [size]="bp.celular() ? '32' : '24'" appearance="stroke" [items]="repartidoresDelLocal" />
107
164
  ```
@@ -27,11 +27,15 @@ carrusel o un mapa.
27
27
  > dos tamaños, el radio completo y el deshabilitado, sin do/don't. Las reglas de abajo son
28
28
  > **canon (aprobado por el dueño, 03-10-2026)** salvo donde dice otra fuente.
29
29
  >
30
- > Uso medido el 04-10-2026 en `master-pedidos/src/app`: 11 compact-buttons en 7 archivos, sin
30
+ > Uso medido el 06-10-2026 en `master-pedidos/src/app`: 12 compact-buttons en 8 archivos, sin
31
31
  > contar prototipos ni vitrinas (`master-preview`, `master-prototipos`, `mockup-sheets-*`,
32
- > `dx/*`, `master-rutina`, `master-medico`, `dev-index`). Estilos: 6 `ghost`, 3 `stroke` (uno
33
- > por error, ver abajo), 2 `white`, 0 `modifiable`. Tamaños: 3 `large`, 2 `medium`, 2 `xlarge` y
34
- > 4 por `bp` (`2xlarge`/`large` y `3xlarge`/`medium`). 4 con `fullRadius`, 1 con `disabled`.
32
+ > `dx/*`, `master-rutina`, `master-medico`, `dev-index`). Estilos: 7 `ghost`, 3 `stroke` (uno
33
+ > por error, ver abajo), 2 `white`, 0 `modifiable`. Tamaños: 7 por `bp` (6 `5xlarge`/`large` y 1
34
+ > `5xlarge`/`medium`, los 7 con `bp.isMobile()`), 2 `large` fijo, 1 `medium` fijo y 2 `xlarge`
35
+ > fijo. 4 con `fullRadius`, 1 con `disabled`.
36
+ >
37
+ > Las líneas citadas en este README son las de **apertura del elemento** (`<sui-compact-button`),
38
+ > aunque el `[size]` o el `(click)` estén unas líneas más abajo.
35
39
 
36
40
  ### Lo que sí dice la guía del DS
37
41
 
@@ -53,14 +57,16 @@ carrusel o un mapa.
53
57
 
54
58
  **Usos de hoy que rompen la regla:**
55
59
 
56
- - **1 bug: `variant="ghost"` en vez de `variantStyle`.** `pages/super-admin/master-settings/master-settings.html:658`
57
- («Quitar este nivel»). `variant` no es un input del compact-button: el atributo se ignora y el
58
- botón sale `stroke`. Pasar a `variantStyle="ghost"`.
60
+ - **Sin estilo explícito.** `pages/super-admin/master-settings/master-settings.html:649` («Quitar este
61
+ nivel»). Antes llevaba `variant="ghost"` (que el compact-button ignora); medido el 06-10-2026, ya
62
+ no lleva `variant`, pero tampoco `variantStyle`, así que sigue saliendo `stroke`. Pasar a
63
+ `variantStyle="ghost"` (además tiene `size="medium"` fijo y `(click)`: ver «Bien y mal»).
59
64
  - **Resuelto — `ghost` en acciones de fila** (canon, dueño 04-10-2026): se permite, igual que en
60
- `sui-button`. Los 5 usos de hoy quedan bien: `components/option-sections-manager/option-sections-manager.html:38`
61
- y `:148`, `components/add-product-modal/add-product-modal.html:315`,
62
- `pages/super-admin/master-settings/master-settings.html:113` y `:658` (este último sigue con el
63
- bug de `variant` en vez de `variantStyle`).
65
+ `sui-button`. En estos usos el **`ghost` queda bien**:
66
+ `components/option-sections-manager/option-sections-manager.html:38` y `:148`,
67
+ `components/add-product-modal/add-product-modal.html:317` y
68
+ `pages/super-admin/master-categorias/master-categorias.html:91` y `:98`. El **tamaño** no: los
69
+ cinco rompen D16 (ver «Usos de hoy que rompen la regla» en `size`).
64
70
 
65
71
  ### `size`
66
72
 
@@ -74,13 +80,26 @@ carrusel o un mapa.
74
80
  | `4xlarge` | 40 (24) | Flotantes sobre el mapa (volver, centrar). | ídem: canon; publicado desde 0.20.0 |
75
81
  | `5xlarge` | 44 (24) | **El del teléfono** cuando el botón se toca solo: cerrar un modal o sheet, flotantes sobre el mapa. El ícono se queda en 24 como `4xlarge`: crece el área, no el dibujo. | canon (dueño, 04-10-2026): piso táctil 44 en el teléfono |
76
82
 
77
- **Migración a tamaños de mobile: hecha** (medido el 04-10-2026). Los 4 casos del cliente ya usan
78
- `bp`: `components/product-detail-view/product-detail-view.html:169` y `:173` y
79
- `pages/customer/order-history/order-history.html:382` con `2xlarge`/`large`, y
80
- `components/store-ratings-modal/store-ratings-modal.html:33` con `3xlarge` en mobile.
83
+ **Migración a tamaños de mobile: a medias** (medido el 06-10-2026). 7 usos ya llevan `bp` con
84
+ `5xlarge` en el celular, pero los 7 con `bp.isMobile()`, que mira solo el ancho: en la tablet quedan
85
+ con el tamaño de web (24 o 20). Hay que pasarlos a `bp.tactil()` (D16):
86
+
87
+ - `components/product-detail-view/product-detail-view.html:169` y `:173` (− / +)
88
+ - `pages/customer/order-history/order-history.html:382` (ver detalle)
89
+ - `components/store-ratings-modal/store-ratings-modal.html:33` (cerrar)
90
+ - `components/add-product-modal/add-product-modal.html:317` (quitar opción)
91
+ - `components/option-sections-manager/option-sections-manager.html:38` (más) y `:148` (quitar opción)
92
+
93
+ **Usos de hoy que rompen la regla** (además de los 7 de arriba):
81
94
 
82
- **Uso de hoy que rompe la regla:** `store-ratings-modal.html:33` cierra en web con `medium` (20);
83
- la tabla de abajo pide `xlarge` (28).
95
+ - `store-ratings-modal.html:33` cierra en web con `medium` (20); la tabla de abajo pide `xlarge` (28).
96
+ - `pages/super-admin/master-settings/master-settings.html:649` («Quitar este nivel»): `size="medium"`
97
+ fijo, así que mide 20 en el celular y la tablet. Va `[size]="bp.tactil() ? '5xlarge' : 'large'"`.
98
+ - `pages/super-admin/master-categorias/master-categorias.html:91` (fijar) y `:98` (editar):
99
+ `size="large"` fijo, 24 en el celular y la tablet. Va `[size]="bp.tactil() ? '5xlarge' : 'large'"`.
100
+
101
+ Las flechas de `arrastre-carrusel.ts:102` y `:104` llevan `xlarge` fijo y están bien: solo aparecen
102
+ con mouse.
84
103
 
85
104
  ### `fullRadius`
86
105
 
@@ -103,12 +122,13 @@ la tabla de abajo pide `xlarge` (28).
103
122
 
104
123
  En mobile se toca con el dedo: el área táctil tiene que medir **44 px o más**. En la tablet
105
124
  (`pointer: coarse`) va igual que en el celular, porque también se toca; en la computadora
106
- (`pointer: fine`), `medium`; en el celular chico (< 380 px), `medium` a la vista sin bajar el área de 44.
125
+ (`pointer: fine`), el tamaño de web de la tabla de abajo. El compact-button no tiene un área tocable
126
+ más grande que lo que se ve, así que en el celular chico (< 380 px) también va el de 44.
107
127
  Nada en `small` ni `xsmall` (canon, dueño, 05-10-2026, D16; reemplaza al «tamaño por plataforma» del
108
- 03-10-2026, que bajaba la web a `small`). Hoy la app lo resuelve con `BreakpointsService`
109
- (`src/app/services/breakpoints.service.ts`, mobile = hasta 767 px): `[size]="bp.isMobile() ? 'large' : 'medium'"`,
110
- que todavía deja la tablet en `medium` (el helper de D16 está propuesto en la hoja de decisiones). Medido el 04-10-2026 en `master-pedidos`: 166 `[size]`
111
- con `bp` (142 `large`/`medium`, 22 `large`/`small`, 2 `medium`/`xsmall`); los 24 que bajan de `medium` se migran.
128
+ 03-10-2026, que bajaba la web a `small`). La app lo resuelve con `BreakpointsService`
129
+ (`src/app/services/breakpoints.service.ts`): `bp.tactil()` es verdadero en todo celular (hasta 767 px)
130
+ y en toda pantalla táctil (`pointer: coarse`), así que cubre la tablet; `bp.isMobile()` solo mira el
131
+ ancho y deja la tablet con el tamaño de web.
112
132
  `sui-compact-button` tiene su propia escala (de `medium` 20 a `5xlarge` 44) y no tiene `small`: D16 no
113
133
  lo mueve por el nombre; la tabla de abajo sigue igual.
114
134
 
@@ -120,7 +140,7 @@ lo mueve por el nombre; la tabla de abajo sigue igual.
120
140
 
121
141
  ```html
122
142
  <sui-compact-button icon="close-line" variantStyle="ghost" ariaLabel="Cerrar"
123
- [size]="bp.isMobile() ? '5xlarge' : 'xlarge'" (clicked)="cerrar()" />
143
+ [size]="bp.tactil() ? '5xlarge' : 'xlarge'" (clicked)="cerrar()" />
124
144
  ```
125
145
 
126
146
  `2xlarge`, `3xlarge` y `4xlarge` están publicados desde la 0.20.0 (la app usa la 0.22.0); `5xlarge`
@@ -129,6 +149,26 @@ entrar un botón de 44, `2xlarge` (32) con aire alrededor (gap o padding) es la
129
149
  dedo no toque el vecino. `medium` y `large` no
130
150
  van en mobile.
131
151
 
152
+ ### Por dispositivo (D16)
153
+
154
+ Fila propia en la tabla de D16 (dueño, 05-10-2026): el compact-button tiene **escala propia** y no
155
+ tiene `small`, así que D16 no lo mueve por el nombre; lo que manda es llegar a 44 donde se toca.
156
+
157
+ | dispositivo | size | nota |
158
+ |---|---|---|
159
+ | celular chico (< 380 px) | `5xlarge` (44) | escala propia: el área tocable es el botón mismo (no hay un `medium` con área de 44), así que va el mismo que en el celular |
160
+ | celular (380–767 px) | `5xlarge` (44) | `2xlarge` (32) con aire solo si la fila no lo deja entrar (propuesta, falta aprobación) |
161
+ | tablet táctil (`pointer: coarse`) | `5xlarge` (44) | igual que el celular: también se toca |
162
+ | computadora (`pointer: fine`) | `large` (24) en filas y cards · `xlarge` (28) en el cerrar y los flotantes | `medium` (20) solo en tablas densas |
163
+
164
+ Ultrawide (≥ 1920 px): igual que la computadora; el espacio extra va a columnas, no a botones más grandes.
165
+ Una flecha que **solo aparece con mouse** (las del carrusel, `arrastre-carrusel.ts:102`) no necesita
166
+ `bp`: va `xlarge` fijo.
167
+
168
+ En master-pedidos: `[size]="bp.tactil() ? '5xlarge' : 'large'"` (filas y cards) o
169
+ `[size]="bp.tactil() ? '5xlarge' : 'xlarge'"` (cerrar y flotantes). No hay helper `size*` propio:
170
+ `bp.sizeControl()` devuelve `large`/`medium`, que aquí miden 24/20.
171
+
132
172
  ## «No usar»: por qué no hoy y cuándo sí
133
173
 
134
174
  Ningún valor del compact-button está en «no usar»: los cuatro estilos y los siete tamaños tienen
@@ -163,10 +203,10 @@ El clic se escucha con `(clicked)`. `icon` recibe el nombre RemixIcon, sin el pr
163
203
  ## Trampas
164
204
 
165
205
  - **El estilo se llama `variantStyle`**, no `variant`. `variant="ghost"` no da error de
166
- compilación: se ignora y sale `stroke` (pasa hoy en `master-settings.html:658`).
206
+ compilación: se ignora y sale `stroke` (pasó en `master-settings.html:649`).
167
207
  - **`icon` y `ariaLabel` son obligatorios**: sin `ariaLabel` no compila.
168
208
  - **El output es `(clicked)`**. `(click)` sobre el host también llega porque el clic burbujea; hoy 6
169
- usos lo escuchan así (`product-detail-view.html:169` y `:173`, `master-settings.html:658`,
209
+ usos lo escuchan así (`product-detail-view.html:169` y `:173`, `master-settings.html:649`,
170
210
  `arrastre-carrusel.ts:102` y `:104`, `order-history.html:382`). Usa `(clicked)`, que ya respeta
171
211
  `disabled`.
172
212
  - En `medium` el ícono mide 16, no los 18 de la guía.
@@ -176,11 +216,55 @@ El clic se escucha con `(clicked)`. `icon` recibe el nombre RemixIcon, sin el pr
176
216
  blanco: es el estado activo del Figma, no un error.
177
217
  - Ya trae el arreglo de iOS para el `:active` pegado: no lo agregues.
178
218
 
219
+ ## Bien y mal
220
+
221
+ **Una acción de fila con size fijo**
222
+
223
+ ```html
224
+ <!-- ❌ mal: size fijo; en el celular y la tablet mide 20 o 24 (master-settings.html:649, master-categorias.html:98) -->
225
+ <sui-compact-button icon="pencil-line" variantStyle="ghost" size="large"
226
+ [ariaLabel]="'Editar ' + f.nombre" (clicked)="abrir(f.id)" />
227
+ ```
228
+
229
+ ```html
230
+ <!-- ✅ bien -->
231
+ <sui-compact-button icon="pencil-line" variantStyle="ghost" [size]="bp.tactil() ? '5xlarge' : 'large'"
232
+ [ariaLabel]="'Editar ' + f.nombre" (clicked)="abrir(f.id)" />
233
+ ```
234
+
235
+ **El cerrar de un modal**
236
+
237
+ ```html
238
+ <!-- ❌ mal: en web cierra en medium (20) y la tablet queda con el de web (store-ratings-modal.html:33) -->
239
+ <sui-compact-button icon="close-line" variantStyle="ghost" ariaLabel="Cerrar"
240
+ [size]="bp.isMobile() ? '5xlarge' : 'medium'" (clicked)="onClosed()" />
241
+ ```
242
+
243
+ ```html
244
+ <!-- ✅ bien -->
245
+ <sui-compact-button icon="close-line" variantStyle="ghost" ariaLabel="Cerrar"
246
+ [size]="bp.tactil() ? '5xlarge' : 'xlarge'" (clicked)="onClosed()" />
247
+ ```
248
+
249
+ **El − / + de una cantidad**
250
+
251
+ ```html
252
+ <!-- ❌ mal: (click) escucha al host; (clicked) es el que respeta disabled (product-detail-view.html:173) -->
253
+ <sui-compact-button icon="add-line" [fullRadius]="true" [size]="bp.tactil() ? '5xlarge' : 'large'"
254
+ [disabled]="sinStock" ariaLabel="Agregar uno" (click)="sumar()" />
255
+ ```
256
+
257
+ ```html
258
+ <!-- ✅ bien -->
259
+ <sui-compact-button icon="add-line" [fullRadius]="true" [size]="bp.tactil() ? '5xlarge' : 'large'"
260
+ [disabled]="sinStock" ariaLabel="Agregar uno" (clicked)="sumar()" />
261
+ ```
262
+
179
263
  ## Ejemplo
180
264
 
181
265
  ```html
182
- <!-- Cerrar en la cabecera de un sheet: 5xlarge (44) en mobile, xlarge en web -->
183
- <sui-compact-button icon="close-line" variantStyle="ghost" [size]="bp.isMobile() ? '5xlarge' : 'xlarge'"
266
+ <!-- Cerrar en la cabecera de un sheet: 5xlarge (44) donde se toca, xlarge en la computadora -->
267
+ <sui-compact-button icon="close-line" variantStyle="ghost" [size]="bp.tactil() ? '5xlarge' : 'xlarge'"
184
268
  ariaLabel="Cerrar" (clicked)="cerrar()" />
185
269
 
186
270
  <!-- Acción de una fila en desktop -->
@@ -188,5 +272,5 @@ El clic se escucha con `(clicked)`. `icon` recibe el nombre RemixIcon, sin el pr
188
272
 
189
273
  <!-- Flotante sobre el mapa -->
190
274
  <sui-compact-button icon="arrow-left-line" variantStyle="white" [fullRadius]="true"
191
- [size]="bp.isMobile() ? '5xlarge' : 'xlarge'" ariaLabel="Volver" (clicked)="volver()" />
275
+ [size]="bp.tactil() ? '5xlarge' : 'xlarge'" ariaLabel="Volver" (clicked)="volver()" />
192
276
  ```
@@ -66,8 +66,8 @@ Las opciones del menú siguen al `size` como en `sui-select`: 36 hasta `medium`,
66
66
  |---|---|---|---|
67
67
  | `large` | 48 | 44 · 44 | canon (aprobado por el dueño, 03-10-2026), extensión SUI |
68
68
  | `medium` (default) | 40 | 36 · 44 | según la guía del DS; 44 en mobile: canon (aprobado por el dueño, 03-10-2026) |
69
- | `small` | 36 | 36 · 44 | ídem |
70
- | `xsmall` | 32 | 36 · 44 | ídem |
69
+ | `small` | 36 | 36 · 44 | ídem · no se usa: D16, dueño 05-10-2026 |
70
+ | `xsmall` | 32 | 36 · 44 | ídem · no se usa: D16, dueño 05-10-2026 (tampoco en la paginación) |
71
71
 
72
72
  | uso | mobile | web | fuente |
73
73
  |---|---|---|---|
@@ -75,10 +75,26 @@ Las opciones del menú siguen al `size` como en `sui-select`: 36 hasta `medium`,
75
75
  | paginación al pie de una tabla | no aplica | `medium` (40) | canon (dueño, 05-10-2026, D16) (la guía del DS lo muestra en `xsmall`) |
76
76
 
77
77
  ```html
78
- <sui-compact-select [size]="bp.isMobile() ? 'large' : 'medium'" placeholder="Todos los roles"
78
+ <sui-compact-select [size]="bp.sizeControl()" placeholder="Todos los roles"
79
79
  [items]="roles" [(selected)]="rolElegido" /> <!-- bp = BreakpointsService -->
80
80
  ```
81
81
 
82
+ ### Por dispositivo (D16)
83
+
84
+ Comparte fila con `input` y `select` en la tabla de D16 (dueño, 05-10-2026): se toca, así que va
85
+ grande en el celular y en la tablet, y `medium` en la computadora.
86
+
87
+ | dispositivo | size | nota |
88
+ |---|---|---|
89
+ | celular chico (< 380 px) | `large` (48) | interino: D16 pide `medium` con área tocable de 44, pero el DS todavía no la estira en `medium` (40); hasta que lo haga, el mismo que el celular |
90
+ | celular (380–767 px) | `large` (48) | junto a botones `large` de la misma barra |
91
+ | tablet táctil (`pointer: coarse`) | `large` (48) | también se toca. Ojo: las opciones del menú de un `medium` solo suben a 44 hasta 767 px, por eso la tablet no se queda en `medium` |
92
+ | computadora (`pointer: fine`) | `medium` (40) | filtros del panel y paginación; `small` y `xsmall` no se usan |
93
+
94
+ Ultrawide (≥ 1920 px): igual que la computadora.
95
+
96
+ En master-pedidos: `[size]="bp.sizeControl()"` (`large` donde se toca, `medium` en la computadora).
97
+
82
98
  ## «No usar»: por qué no hoy y cuándo sí
83
99
 
84
100
  | qué | por qué no hoy | cuándo sí, en un flujo nuevo |
@@ -126,9 +142,47 @@ Implementa `ControlValueAccessor` (el valor es el `value` de la opción).
126
142
  - El menú mide al menos 200 px aunque el campo sea más angosto.
127
143
  - Las opciones miden 36 px en web hasta `medium`; 44 en `large` y en mobile (ver «Tamaño»).
128
144
 
145
+ ## Bien y mal
146
+
147
+ **El tamaño de un filtro del panel**
148
+
149
+ ```html
150
+ <!-- ❌ mal: small fijo; D16 no usa small y en el celular mide 36 (vitrina: master-preview/_guia-moleculas/campos.ts:214) -->
151
+ <sui-compact-select size="small" placeholder="Todos los roles" [items]="roles" [(selected)]="rolElegido" />
152
+ ```
153
+
154
+ ```html
155
+ <!-- ✅ bien -->
156
+ <sui-compact-select [size]="bp.sizeControl()" placeholder="Todos los roles" [items]="roles" [(selected)]="rolElegido" />
157
+ ```
158
+
159
+ **Solo ícono**
160
+
161
+ ```html
162
+ <!-- ❌ mal: type="icon" no muestra texto; sin ariaLabel el lector de pantalla no sabe qué elige (vitrina: campos.ts:218) -->
163
+ <sui-compact-select type="icon" [size]="bp.sizeControl()" [items]="vistas" [(selected)]="vista" />
164
+ ```
165
+
166
+ ```html
167
+ <!-- ✅ bien -->
168
+ <sui-compact-select type="icon" [size]="bp.sizeControl()" ariaLabel="Ver como" [items]="vistas" [(selected)]="vista" />
169
+ ```
170
+
171
+ **Dentro de un formulario reactivo**
172
+
173
+ ```html
174
+ <!-- ❌ mal: dos fuentes de verdad; el formulario no se entera de lo que escribe selected -->
175
+ <sui-compact-select [size]="bp.sizeControl()" [items]="roles" formControlName="rol" [(selected)]="rolElegido" />
176
+ ```
177
+
178
+ ```html
179
+ <!-- ✅ bien -->
180
+ <sui-compact-select [size]="bp.sizeControl()" [items]="roles" formControlName="rol" />
181
+ ```
182
+
129
183
  ## Ejemplo
130
184
 
131
185
  ```html
132
- <sui-compact-select [size]="bp.isMobile() ? 'large' : 'medium'" placeholder="Todos los roles" [items]="roles"
186
+ <sui-compact-select [size]="bp.sizeControl()" placeholder="Todos los roles" [items]="roles"
133
187
  [(selected)]="rolElegido" />
134
188
  ```