@ajuarezso/sui-design-system 0.18.10 → 0.20.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 (47) hide show
  1. package/docs/INDEX.md +136 -0
  2. package/docs/sui-alert/README.md +216 -0
  3. package/docs/sui-app-store-badge/README.md +137 -0
  4. package/docs/sui-avatar/README.md +263 -0
  5. package/docs/sui-avatar-group/README.md +115 -0
  6. package/docs/sui-badge/README.md +212 -0
  7. package/docs/sui-brand-logo/README.md +143 -0
  8. package/docs/sui-button/README.md +192 -0
  9. package/docs/sui-button-group/README.md +178 -0
  10. package/docs/sui-button-group-item/README.md +102 -0
  11. package/docs/sui-checkbox/README.md +147 -0
  12. package/docs/sui-checkbox-label/README.md +143 -0
  13. package/docs/sui-circular-progress-bar/README.md +131 -0
  14. package/docs/sui-color-dot/README.md +112 -0
  15. package/docs/sui-color-picker/README.md +124 -0
  16. package/docs/sui-compact-avatar-group/README.md +103 -0
  17. package/docs/sui-compact-button/README.md +190 -0
  18. package/docs/sui-content-divider/README.md +124 -0
  19. package/docs/sui-divider/README.md +102 -0
  20. package/docs/sui-emoji/README.md +138 -0
  21. package/docs/sui-fancy-button/README.md +148 -0
  22. package/docs/sui-file-icon/README.md +103 -0
  23. package/docs/sui-flag/README.md +99 -0
  24. package/docs/sui-form-hint/README.md +124 -0
  25. package/docs/sui-form-label/README.md +148 -0
  26. package/docs/sui-icon/README.md +135 -0
  27. package/docs/sui-kbd/README.md +97 -0
  28. package/docs/sui-key-icon/README.md +125 -0
  29. package/docs/sui-link-button/README.md +221 -0
  30. package/docs/sui-logo/README.md +152 -0
  31. package/docs/sui-payment-icon/README.md +98 -0
  32. package/docs/sui-progress-bar/README.md +132 -0
  33. package/docs/sui-progress-bar-label/README.md +143 -0
  34. package/docs/sui-radio/README.md +134 -0
  35. package/docs/sui-radio-label/README.md +137 -0
  36. package/docs/sui-rating/README.md +198 -0
  37. package/docs/sui-segmented-control/README.md +144 -0
  38. package/docs/sui-slider/README.md +143 -0
  39. package/docs/sui-social-button/README.md +158 -0
  40. package/docs/sui-status-badge/README.md +164 -0
  41. package/docs/sui-switch/README.md +146 -0
  42. package/docs/sui-switch-label/README.md +139 -0
  43. package/docs/sui-tag/README.md +145 -0
  44. package/fesm2022/ajuarezso-sui-design-system.mjs +207 -52
  45. package/fesm2022/ajuarezso-sui-design-system.mjs.map +1 -1
  46. package/package.json +1 -1
  47. package/types/ajuarezso-sui-design-system.d.ts +177 -28
@@ -0,0 +1,158 @@
1
+ ---
2
+ name: sui-social-button
3
+ selector: sui-social-button
4
+ resumen: Botón para iniciar sesión o registrarse con una cuenta de Google o Apple
5
+ alternativas: [sui-button (cualquier otra acción, aunque mencione una marca), sui-app-store-badge (descargar la app de una tienda)]
6
+ ---
7
+
8
+ # sui-social-button
9
+
10
+ Story: [Atoms/Button/Social Button](https://sui-design-system.web.app/?path=/docs/atoms-button-social-button--docs)
11
+
12
+ ## Cuándo usarlo / cuándo no
13
+
14
+ **Úsalo** solo en las pantallas de iniciar sesión y registrarse, para entrar con una cuenta de
15
+ otra marca: hoy Google y Apple.
16
+
17
+ **No lo uses** para:
18
+
19
+ - **Abrir WhatsApp, el mapa u otra app**: `sui-button` `filled` `neutral` con su ícono.
20
+ - **Descargar la app**: `sui-app-store-badge`.
21
+ - **Una marca sin login implementado** «para que se vea completo»: un botón que no hace nada es
22
+ peor que no tenerlo.
23
+
24
+ ## Qué variante usar
25
+
26
+ > **La guía del DS no dice cuándo usar cada marca ni cada estilo.** Su página lo presenta como
27
+ > «simplificar el inicio de sesión y el registro» y muestra las siete marcas en lleno y en borde,
28
+ > sin do/don't. Las reglas de abajo son **canon (aprobado por el dueño, 03-10-2026)** salvo donde
29
+ > dice otra fuente.
30
+ >
31
+ > Uso medido el 03-10-2026 en `master-pedidos/src/app`: 5 social-buttons en 2 archivos, sin contar
32
+ > prototipos ni vitrinas. Marcas: 2 `google`, 1 `apple`, 1 `x-twitter`, 1 `linkedin`. Estilos:
33
+ > 4 `stroke`, 1 `filled`. 3 con `onlyIcon`, 3 con `loading`.
34
+
35
+ ### Lo que sí dice la guía del DS
36
+
37
+ - **Para qué es**: simplificar el inicio de sesión y el registro.
38
+ - **Defaults**: `apple` + `filled`. SUI también arranca en `filled`, pero `brand` es obligatorio.
39
+ - **Siete marcas**: Apple, X (en la guía, `twitter`), Google, Facebook, LinkedIn, GitHub y Dropbox,
40
+ cada una en lleno (`filled`, el color de la marca) y en borde (`stroke`, fondo blanco y logo a
41
+ color). La guía llama `mode` a lo que SUI llama `variantStyle`.
42
+ - **No trae `onlyIcon` ni `loading`**: el primero sale del Figma y el segundo es extensión de SUI.
43
+
44
+ ### `brand` + `variantStyle`
45
+
46
+ | brand + estilo | cuándo | ejemplo real de la app | fuente |
47
+ |---|---|---|---|
48
+ | `google` + `stroke` | Iniciar sesión o registrarse con Google: fondo blanco, logo a color. | `pages/auth/login/login.html:39` («Continuar con Google») | canon (aprobado por el dueño, 03-10-2026) |
49
+ | `apple` + `filled` | Iniciar sesión con Apple: negro lleno, como pide Apple. | `pages/auth/login/login.html:50` («Continuar con Apple») | canon (aprobado por el dueño, 03-10-2026) |
50
+ | `google` + `filled` (rojo) | No: el botón de Google va en blanco. Es lo que sale si se olvida `variantStyle`. | — | propuesta |
51
+ | `apple` + `stroke` | No: Apple va negro lleno en tema claro. | — | propuesta |
52
+ | `facebook`, `x-twitter`, `linkedin`, `github`, `dropbox` (cualquier estilo) | No hay login con esas cuentas. | — | no usar · canon (aprobado por el dueño, 03-10-2026) |
53
+
54
+ ### `onlyIcon`
55
+
56
+ | onlyIcon | cuándo | fuente |
57
+ |---|---|---|
58
+ | `false` (default) | Siempre en el login: logo + «Continuar con …». | canon (aprobado por el dueño, 03-10-2026) |
59
+ | `true` | No: Apple exige el texto en su botón de login. | no usar · canon (aprobado por el dueño, 03-10-2026) |
60
+
61
+ **Usos de hoy que rompen la regla:**
62
+
63
+ - **3 casos, todos en `pages/auth/register/register.html`**: `:86` (`x-twitter`), `:87` (`google`) y
64
+ `:94` (`linkedin`), los tres con `onlyIcon`. X y LinkedIn además están deshabilitados porque no
65
+ hay login con esas cuentas (el comentario del HTML lo dice: son decorativos). Pasar a lo mismo que
66
+ el login: `google` `stroke` con texto (y `apple` `filled` si el registro ofrece Apple), y quitar
67
+ X y LinkedIn.
68
+
69
+ ### `label`, `loading`, `disabled`, `href`
70
+
71
+ | prop | cuándo | fuente |
72
+ |---|---|---|
73
+ | `label` | Sin pasarlo sale «Continuar con Google» / «Continuar con Apple», que sirve igual para entrar y para registrarse. Pasarlo solo si el texto tiene que decir otra cosa. | propuesta |
74
+ | `loading` | Desde el toque hasta que vuelve la ventana de la marca: cambia el logo por un spinner y deshabilita el botón. | propuesta (ya es la práctica del login) |
75
+ | `disabled` | Mientras otro login está en curso, para que no se abran dos (en el login: `processingRedirect`). Nunca para una marca que no tiene login. | propuesta |
76
+ | `href` | Solo si el login se hace navegando a una URL (OAuth por redirect web). Pinta un `<a>`. | propuesta |
77
+ | `ariaLabel` | No hace falta: con texto se lee el texto; con `onlyIcon` el componente usa el label. | propuesta |
78
+
79
+ ## Tamaño en mobile y en web
80
+
81
+ En mobile se toca con el dedo: el área táctil tiene que medir **44 px o más**. En web, con mouse,
82
+ va un tamaño más chico. La app ya lo resuelve con `BreakpointsService`
83
+ (`src/app/services/breakpoints.service.ts`, mobile = hasta 767 px):
84
+ `[size]="bp.isMobile() ? 'large' : 'small'"`, 27 usos hoy en `master-pedidos` (16 `large`/`small`,
85
+ 9 `large`/`medium`, 2 `medium`/`xsmall`). Regla del dueño, 03-10-2026.
86
+
87
+ | uso | mobile | web | fuente |
88
+ |---|---|---|---|
89
+ | login con Google o Apple | 40 de alto, **ancho completo** (`width: 100%`) | 40 de alto, ancho del formulario | propuesta (es lo que ya hace `pages/auth/login/login.html` con `.auth-page__provider-btn`) |
90
+
91
+ **Ancho completo**: `width: 100%` en el host estira el botón (arreglado en el DS el 03-10-2026 con
92
+ `flex: 1 1 auto` en `.sui-social-button__el`; antes el host medía 360 y el botón 193). Sin
93
+ `width` sigue midiendo lo que su texto, como siempre. Con `onlyIcon` el cuadrado de 40 no se
94
+ estira nunca. El host sigue siendo `inline-flex`: para el ancho completo va `width: 100%`, no
95
+ `display: block`. El `::ng-deep .sui-social-button__el { width: 100% }` de
96
+ `pages/auth/auth-shared.scss` queda de más con la versión que trae el arreglo.
97
+
98
+ No tiene input `size`: mide siempre 40 de alto. En mobile no llega a 44; lo compensa el ancho
99
+ completo (el dedo no puede errarle) y 12 px de separación entre los dos botones. Si un día hace
100
+ falta más alto, se pide al DS un `size`, no se estira con CSS (el logo y el padding no escalan).
101
+
102
+ ## «No usar»: por qué no hoy y cuándo sí
103
+
104
+ Nada se borra del DS. Lo marcado «no usar» no tiene caso en la app de hoy; si un flujo nuevo cae
105
+ en la columna de la derecha, se usa (aprobado por el dueño, 03-10-2026).
106
+
107
+ | qué | por qué no hoy | cuándo sí, en un flujo nuevo |
108
+ |---|---|---|
109
+ | `facebook`, `x-twitter`, `linkedin`, `github`, `dropbox` | no hay login con esas cuentas | si se agrega «Continuar con Facebook» (muy usado en Perú) o botones de compartir en redes |
110
+ | `onlyIcon` | Apple exige el texto en su botón de login | una fila de «compartir en» con íconos de redes, fuera del login |
111
+
112
+ ## API
113
+
114
+ <!-- api:inicio -->
115
+ <!-- generada: no editar a mano — `npm run docs` -->
116
+
117
+ | input | tipo | default |
118
+ |---|---|---|
119
+ | `brand` | `'apple' \| 'x-twitter' \| 'google' \| 'facebook' \| 'linkedin' \| 'github' \| 'dropbox'` | — (requerido) |
120
+ | `variantStyle` | `'filled' \| 'stroke'` | `'filled'` |
121
+ | `onlyIcon` | `boolean` | `false` |
122
+ | `label` | `string \| null` | `null` |
123
+ | `disabled` | `boolean` | `false` |
124
+ | `loading` | `boolean` | `false` |
125
+ | `href` | `string \| null` | `null` |
126
+ | `target` | `string \| null` | `null` |
127
+ | `rel` | `string \| null` | `'noopener noreferrer'` |
128
+ | `type` | `'button' \| 'submit' \| 'reset'` | `'button'` |
129
+ | `ariaLabel` | `string \| null` | `null` |
130
+
131
+ | output | payload |
132
+ |---|---|
133
+ | `clicked` | `MouseEvent` |
134
+ <!-- api:fin -->
135
+
136
+ ## Trampas
137
+
138
+ - **`brand` es obligatorio** y **`variantStyle` arranca en `filled`**: `<sui-social-button brand="google" />`
139
+ sale rojo lleno. Para el login de Google hay que pasar `variantStyle="stroke"`.
140
+ - **El estilo se llama `variantStyle`** (en la guía, `mode`) y **X se llama `x-twitter`** (en la
141
+ guía, `twitter`).
142
+ - **No tiene `size`**: mide 40 px de alto. Con `width: 100%` en el host el botón se estira al ancho completo (arreglado en el DS el 03-10-2026; antes no estiraba). El de solo ícono queda en 40 × 40.
143
+ - **`loading` también deshabilita**: no emite `(clicked)` mientras está en `true`.
144
+ - El logo es una imagen distinta por tema: en modo oscuro, Apple, X y GitHub en `stroke` usan el
145
+ logo blanco para no perderse. El componente lo resuelve solo leyendo `data-theme`.
146
+ - El radio es 10 px, no pill como `sui-button`.
147
+ - El output es `(clicked)`.
148
+ - Ya trae el arreglo de iOS para el `:active` pegado: no lo agregues.
149
+
150
+ ## Ejemplo
151
+
152
+ ```html
153
+ <!-- Login: Google en blanco, Apple negro lleno, los dos con texto -->
154
+ <sui-social-button brand="google" variantStyle="stroke" [loading]="cargandoGoogle()"
155
+ [disabled]="procesando()" (clicked)="entrarConGoogle()" />
156
+ <sui-social-button brand="apple" variantStyle="filled" [loading]="cargandoApple()"
157
+ [disabled]="procesando()" (clicked)="entrarConApple()" />
158
+ ```
@@ -0,0 +1,164 @@
1
+ ---
2
+ name: sui-status-badge
3
+ selector: sui-status-badge
4
+ resumen: El resultado de un ciclo (completado, pendiente, fallido, deshabilitado) con su color y su ícono ya resueltos
5
+ alternativas: [sui-badge (estado con muchos valores, categoría o distinción), sui-tag (chip neutro que se puede quitar), sui-alert (mensaje que hay que leer)]
6
+ ---
7
+
8
+ # sui-status-badge
9
+
10
+ Story: [Atoms/Badge/Status Badge](https://sui-design-system.web.app/?path=/docs/atoms-badge-status-badge--docs)
11
+
12
+ ## Cuándo usarlo / cuándo no
13
+
14
+ **Úsalo** cuando el valor es el **resultado de un ciclo** y cae en uno de estos: terminó bien
15
+ («Pagado», «Aprobada»), espera que alguien actúe («Pendiente», «En revisión»), terminó mal
16
+ («Rechazada», «Anulado») o está apagado («Desactivado», «Vencido»). El componente pone el color
17
+ y el ícono a partir del `status`: la pantalla no elige ninguno de los dos.
18
+
19
+ **No lo uses** para:
20
+
21
+ - **Un estado con más valores** que esos cuatro (los de un pedido: preparando, en camino,
22
+ entregado…): `sui-badge`. Es la misma frontera que fija el README del badge.
23
+ - **Una categoría o una distinción de marca** («Hamburguesas», «Local exclusivo»): no es un
24
+ estado. `sui-badge` gray, o el color cuyo significado le calce (pink destacado, sky verificado,
25
+ purple nuevo).
26
+ - Un chip que se quita: `sui-tag`.
27
+ - Un mensaje con explicación: `sui-alert`.
28
+
29
+ Regla corta: **¿es el final (o la espera) de un trámite? → status-badge · cualquier otra
30
+ etiqueta → badge.**
31
+
32
+ ## Qué variante usar
33
+
34
+ > **La guía del DS dice para qué es, no cuándo usar cada estilo.** Su página lo define como
35
+ > «resaltar estados o condiciones en poco espacio», trae cuatro estados (`completed`,
36
+ > `pending`, `failed`, `disabled`), dos estilos (`stroke`, `light`), ícono o punto, y un ícono
37
+ > por estado en sus ejemplos (los mismos que pone SUI). No trae do/don't. Lo marcado
38
+ > «según la guía del DS» sale de ahí; el resto es **propuesta, falta aprobación**.
39
+ >
40
+ > Uso medido el 03-10-2026 en `master-pedidos/src/app`: **0 status-badges** (eran 3), sin contar
41
+ > prototipos ni vitrinas (`master-preview`, `master-prototipos`, `mockup-sheets-*`, `dx/*`,
42
+ > `_guia-*`, `master-rutina`, `master-medico`, `master-ejercicios`, `dev-index`). Los 3 que había
43
+ > eran los distintivos del local y pasaron a `sui-badge` (ver abajo). Fuera de esa cuenta,
44
+ > `master-ejercicios` tiene 2 más (categorías de ejercicio con `withDot`).
45
+
46
+ ### `status` — mismo significado de color que `sui-badge`
47
+
48
+ | status | color (token de estado) | cuándo | copy de ejemplo | fuente |
49
+ |---|---|---|---|---|
50
+ | `completed` (default) | green (`success`) | Terminó bien. | «Pagado», «Aprobada», «Entregado» | según la guía del DS (estado y color) |
51
+ | `pending` | orange (`warning`) | Espera que alguien haga algo. | «Pendiente», «En revisión» | según la guía del DS (estado y color) |
52
+ | `failed` | red (`error`) | Terminó mal. | «Rechazada», «Fallido», «Anulado» | según la guía del DS (estado y color) |
53
+ | `disabled` | gray (`faded`) | Apagado o fuera de uso. | «Desactivado», «Vencido» | según la guía del DS (estado y color; es el default de la guía) |
54
+ | `information` | blue (`information`) | Extensión SUI: avanza solo y nadie tiene que actuar. | «En proceso» | propuesta, falta aprobación |
55
+
56
+ Es el mismo mapa que el badge aprobado (green bien, orange pendiente, red error, blue info,
57
+ gray neutro), porque los dos pintan con los mismos tokens `--sui-state-*`.
58
+
59
+ ### `appearance`, `withDot` e `icon`
60
+
61
+ | propiedad | valor | cuándo | fuente |
62
+ |---|---|---|---|
63
+ | `appearance` | `stroke` (default) | Tablas y listas: fondo blanco, texto gris, solo el ícono lleva color. Es el que menos ruido hace cuando hay muchos. | según la guía del DS (default) |
64
+ | `appearance` | `light` | El estado es **el** dato de la card o de la fila (fondo teñido, texto de color). | propuesta, falta aprobación |
65
+ | `withDot` | `false` (default) | Ícono del estado. Lo normal. | según la guía del DS |
66
+ | `withDot` | `true` con `stroke` | Tabla densa con la misma columna de estado en muchas filas, donde veinte íconos hacen ruido. | propuesta, falta aprobación |
67
+ | `withDot` | `true` con `light` | **No usar** (ver abajo). | propuesta, falta aprobación |
68
+ | `icon` | `''` (default) | Siempre el del estado: es la mitad de su significado. | según la guía del DS (ícono por estado en sus ejemplos) |
69
+ | `icon` | nombre Remix | **No usar** (ver abajo). | propuesta, falta aprobación |
70
+
71
+ ### `sui-status-badge` o `sui-badge`
72
+
73
+ | caso | componente | fuente |
74
+ |---|---|---|
75
+ | El estado cae en completado / pendiente / fallido / deshabilitado | `sui-status-badge` | canon (aprobado por el dueño, 03-10-2026, en el README de sui-badge) |
76
+ | Estado con más valores (pedido) o una categoría | `sui-badge` | canon (aprobado por el dueño, 03-10-2026, en el README de sui-badge) |
77
+
78
+ **Candidatos para pasar de badge a status-badge**: los **17 badges con un estado de ciclo escrito
79
+ a mano** que cuenta el README de `sui-badge` («Pendiente», «Aprobado», «Rechazado», «En
80
+ revisión», «Pagado», «Anulado»), por ejemplo
81
+ `pages/super-admin/master-drivers/master-drivers.html:781` y
82
+ `pages/driver/driver-profile/driver-profile.html:83`.
83
+
84
+ **Usos de hoy que rompen la regla: 0.** Los distintivos del local («Local exclusivo», «Mismo
85
+ precio que en el local») usaban el status-badge en `pending` y `completed`, que se leen como un
86
+ trámite que avanza. Desde el 03-10-2026 son `<sui-badge color="pink" type="left-icon">` y
87
+ `<sui-badge color="sky" type="left-icon">` (pink = destacado, sky = verificado, los dos con modo
88
+ oscuro por sus tokens `--sui-state-*`), en `core/distintivos-local.ts`. Canon (aprobado por el
89
+ dueño, 03-10-2026).
90
+
91
+ ## No usar: por qué no hoy y cuándo sí
92
+
93
+ | qué | por qué no hoy | cuándo sí, en un flujo nuevo |
94
+ |---|---|---|
95
+ | `withDot` + `light` | El fondo teñido ya dice el color; el punto repite. | Ninguno a la vista. Si hace falta punto, va `stroke` + `withDot`. |
96
+ | `icon` propio | El ícono del estado es la mitad del significado: cambiarlo rompe la lectura. | Una espera **por hora** y no por alguien: «Programado 7:00 p. m.» con `pending` + `icon="time-fill"`. |
97
+ | Sin texto (solo ícono) | Sin texto no se sabe qué estado es. | Una columna muy angosta con el texto en `aria-label` y un tooltip. |
98
+
99
+ ## Tamaño en mobile y en web
100
+
101
+ Criterio de la app: **en mobile se lee y se toca con el dedo, así que va más grande; en web
102
+ (desktop), más chico.** Mobile es `≤ 767 px`, el mismo corte de `BreakpointsService.isMobile()`
103
+ en master-pedidos. Fuente: canon del dueño (03-10-2026), el mismo patrón que ya usan 27 controles
104
+ de la app.
105
+
106
+ | size | alto | texto | ícono (caja) | punto |
107
+ |---|---|---|---|---|
108
+ | `medium` (default) | 24 px | `label-xs` 12/16 | 12 (16) | 6 |
109
+ | `large` | 28 px | `label-sm` 14/20 | 16 (20) | 8 |
110
+ | `xlarge` | 32 px | `label-md` 16/24 | 20 (24) | 8 |
111
+
112
+ `medium` es el de Figma; `large` y `xlarge` son extensión SUI (03-10-2026). Siguen la escala del
113
+ `sui-button` (28 · 32) y no la del `sui-badge` (24 · 28), porque el status-badge ya parte de 24.
114
+
115
+ | uso | mobile | web | fuente |
116
+ |---|---|---|---|
117
+ | Estado en una fila, card o tabla | `large` (28) | `medium` (24) | propuesta: el tamaño es extensión SUI aprobada (03-10-2026); el «cuándo» falta aprobarlo |
118
+ | Estado principal de una pantalla de detalle (el pedido que se mira) | `xlarge` (32) | `medium` (24) | propuesta: el tamaño es extensión SUI aprobada (03-10-2026); el «cuándo» falta aprobarlo |
119
+
120
+ ```html
121
+ <sui-status-badge status="completed" appearance="light" [size]="bp.isMobile() ? 'large' : 'medium'">Entregado</sui-status-badge>
122
+ ```
123
+
124
+ No se agranda con CSS en la pantalla: se pasa `size`.
125
+
126
+ ## API
127
+
128
+ <!-- api:inicio -->
129
+ <!-- generada: no editar a mano — `npm run docs` -->
130
+
131
+ | input | tipo | default |
132
+ |---|---|---|
133
+ | `status` | `'completed' \| 'pending' \| 'failed' \| 'information' \| 'disabled'` | `'completed'` |
134
+ | `appearance` | `'stroke' \| 'light'` | `'stroke'` |
135
+ | `size` | `'medium' \| 'large' \| 'xlarge'` | `'medium'` |
136
+ | `withDot` | `boolean` | `false` |
137
+ | `icon` | `string` | `''` |
138
+
139
+ Outputs: ninguno.
140
+ <!-- api:fin -->
141
+
142
+ Slot: `<ng-content>` (el texto).
143
+
144
+ ## Trampas
145
+
146
+ - **El default es `completed`**; el de la guía es `disabled`. Un `<sui-status-badge>` sin
147
+ `status` sale verde con check.
148
+ - **El estilo se llama `appearance`**, no `variant` (badge) ni `tagStyle` (tag).
149
+ - En `stroke` el **texto es gris** siempre; solo el ícono o el punto llevan color.
150
+ - Tamaños: `medium` 24 (default, Figma), `large` 28 y `xlarge` 32 para mobile (extensión SUI, 03-10-2026). No hay uno más chico que 24.
151
+ - **No pasa a mayúsculas** (el `sui-badge` small sí).
152
+ - `icon` no hace nada con `withDot`.
153
+ - El punto mide 6 px; el del `sui-badge with-dot`, 4 px. Son distintos a propósito.
154
+ - El host lleva `role="status"`: el lector de pantalla anuncia los cambios.
155
+
156
+ ## Ejemplo
157
+
158
+ ```html
159
+ <!-- En una tabla de recargas: stroke (default) -->
160
+ <sui-status-badge status="pending">En revisión</sui-status-badge>
161
+
162
+ <!-- El estado es el dato principal de la card -->
163
+ <sui-status-badge status="failed" appearance="light">Rechazada</sui-status-badge>
164
+ ```
@@ -0,0 +1,146 @@
1
+ ---
2
+ name: sui-switch
3
+ selector: sui-switch
4
+ resumen: Interruptor solo para prender o apagar algo que se aplica al instante, sin texto propio
5
+ alternativas: [sui-switch-label (interruptor con su texto, el caso normal), sui-switch-card (cada ajuste es una tarjeta), sui-integration-switch (fila de integración con logo), sui-checkbox (valor que se confirma después con un botón)]
6
+ ---
7
+
8
+ # sui-switch
9
+
10
+ Story: [Atoms/Checkbox, Radio & Switch/Switch](https://sui-design-system.web.app/?path=/docs/atoms-checkbox-radio-switch-switch--docs)
11
+
12
+ ## Cuándo usarlo / cuándo no
13
+
14
+ **Úsalo** para prender o apagar algo que **se aplica en el momento**, sin botón de guardar:
15
+ la disponibilidad de un producto, un cupón activo, un día del horario, una oferta. Pelado,
16
+ solo cuando el texto vive en otra parte: una celda de tabla con su cabecera, una fila con su
17
+ propio título (día de la semana, tarjeta de la oferta).
18
+
19
+ **No lo uses** para:
20
+
21
+ - **Un interruptor con su texto al lado** (casi siempre): `sui-switch-label`, que trae label,
22
+ descripción y el toque en toda la fila.
23
+ - Un valor de formulario que se confirma con «Guardar»: `sui-checkbox`. (Excepción aceptada hoy:
24
+ los formularios de producto y de planes usan switch para «disponible»/«activo» aunque se guarden
25
+ después; es el patrón que la persona reconoce.)
26
+ - Algo destructivo o que no se deshace: el switch promete que se puede volver atrás al toque.
27
+ - Elegir entre dos modos con nombre: `sui-segmented-control` si se aplica al instante (cuadrícula /
28
+ lista); `sui-radio-card` si se guarda después («Por distancia» / «Precio único» en ajustes).
29
+
30
+ Regla corta: **se aplica ya → switch · se confirma después → checkbox · dos modos con nombre → segmented (inmediato) o radio-card (se guarda).**
31
+
32
+ ## Qué variante usar
33
+
34
+ > **La guía del DS lo define en una frase**: se usa «para prender o apagar un ajuste de forma
35
+ > inmediata». Muestra deshabilitado, con label y con label avanzado. No dice nada de tamaños.
36
+ >
37
+ > Uso medido el 03-10-2026 en `master-pedidos/src/app` (misma exclusión que `sui-badge`):
38
+ > **29 switches en 13 archivos**. Tamaños: 25 `bp.controlSize()` / `ctrlSize()` (`large` en
39
+ > desktop, `xlarge` en mobile), 1 `xlarge` fijo, 1 `large` fijo y 2 sin `size` (`medium`, el
40
+ > default). Más **1 `<input type="checkbox">` dibujado como
41
+ > switch**.
42
+
43
+ ### Estado (`checked`, `disabled`)
44
+
45
+ | estado | cuándo | fuente |
46
+ |---|---|---|
47
+ | prendido / apagado | `[(checked)]` o `[checked]` + `(checkedChange)`. | según la guía del DS |
48
+ | `disabled` | Mientras se guarda el cambio (`[disabled]="guardando()"`) o cuando no aplica. | según la guía del DS (existe); el «cuándo» ya es práctica de la app |
49
+
50
+ ### `size`
51
+
52
+ | size | px | cuándo | fuente |
53
+ |---|---|---|---|
54
+ | `xlarge` | 48 × 28 | Mobile, vía `bp.controlSize()`. Y en tarjetas donde el switch es la acción principal (ofertas de Central). | canon (aprobado por el dueño, 28-09-2026: «componentes grandes») |
55
+ | `large` | 40 × 24 | Desktop, vía `bp.controlSize()`. | canon (aprobado por el dueño, 28-09-2026) |
56
+ | `medium` (default) | 32 × 20 | No usar en pantallas nuevas (ver abajo). Es el único tamaño de la guía. | canon (aprobado por el dueño, 28-09-2026) |
57
+
58
+ ### La etiqueta dice lo que hace, no el estado
59
+
60
+ | caso | regla | fuente |
61
+ |---|---|---|
62
+ | Texto al lado del switch | Dice **qué hace prenderlo** y no cambia con el estado: «Recibir pedidos», no «Sucursal en pausa». El estado ya lo dice el switch (y un badge si hace falta). | propuesta, falta aprobación (precedente escrito en `pages/schedule/schedule.html:31`) |
63
+
64
+ **Usos de hoy que rompen las reglas:**
65
+
66
+ - **19 switches con su texto armado a mano → `sui-switch-label`.** Ejemplos:
67
+ `pages/discounts/discounts.html:198` («Un uso por cliente», con `sui-form-label` + `<span>`),
68
+ `pages/drivers/drivers.html:58` («Aceptar pedidos automáticamente»),
69
+ `pages/super-admin/master-plans/master-plans.html:90` («Plan activo», y 8 más en ese archivo).
70
+ El resto: `discounts.html:302`, `pages/super-admin/master-map-overview/master-map-overview.html:67`,
71
+ `pages/schedule/schedule.html:46`, `components/add-product-modal/add-product-modal.html:196`, `:255`, `:280`,
72
+ `components/option-sections-manager/option-sections-manager.html:107`, `:123`.
73
+ - **3 con la etiqueta que repite el estado** («Disponible» / «No disponible», «Activo»):
74
+ `components/option-sections-manager/option-sections-manager.html:143`,
75
+ `components/add-product-modal/add-product-modal.html:303`, `pages/employees/employees.html:99`.
76
+ - **2 en `medium` (sin `size`):** `pages/drivers/drivers.html:58`,
77
+ `pages/super-admin/master-map-overview/master-map-overview.html:67`.
78
+ - **1 nativo dibujado como switch:** `components/settings-panel/settings-panel.html:97`
79
+ («Notificaciones Push») → `sui-switch-label`.
80
+
81
+ Bien pelados (el texto vive en la fila o la tabla): `pages/discounts/discounts.html:96` (columna
82
+ de la tabla), `pages/super-admin/master-settings/master-settings.html:103`, los días de
83
+ `components/weekly-schedule-editor/weekly-schedule-editor.html:5` y
84
+ `pages/driver/driver-schedule/driver-schedule.html:108`, `pages/central/central-ofertas/central-ofertas.html:19`.
85
+
86
+ ## Tamaño en mobile y en web
87
+
88
+ | uso | mobile | web |
89
+ |---|---|---|
90
+ | switch en una fila, tabla o tarjeta | `xlarge` (48 × 28) | `large` (40 × 24) |
91
+ | switch que es la acción principal de la tarjeta (ofertas de Central) | `xlarge` | `xlarge` |
92
+
93
+ ```html
94
+ <sui-switch [size]="bp.controlSize()" … /> <!-- isMobile() ? 'xlarge' : 'large' -->
95
+ ```
96
+
97
+ El más grande mide 28 px de alto: el toque cómodo (≥ 44 px) lo da la fila; por eso con texto
98
+ va `sui-switch-label`, que hace tocable todo el bloque.
99
+
100
+ ## «No usar»: por qué no hoy y cuándo sí
101
+
102
+ | qué | por qué no hoy | cuándo sí, en un flujo nuevo |
103
+ |---|---|---|
104
+ | `size="medium"` | en el teléfono se pierde (el dueño lo marcó en Central, 28-09-2026) | una tabla densa solo de desktop donde 24 px desalinea la fila |
105
+ | pelado con texto al lado | lo hace `sui-switch-label` con el toque en toda la fila | nunca; pelado solo si el texto vive en otra columna o en el título de la tarjeta |
106
+
107
+ ## API
108
+
109
+ <!-- api:inicio -->
110
+ <!-- generada: no editar a mano — `npm run docs` -->
111
+
112
+ | input | tipo | default |
113
+ |---|---|---|
114
+ | `size` | `'medium' \| 'large' \| 'xlarge'` | `'medium'` |
115
+ | `checked` | `boolean` | `false` |
116
+ | `disabled` | `boolean` | `false` |
117
+
118
+ | output | payload |
119
+ |---|---|
120
+ | `checkedChange` | `boolean` |
121
+ <!-- api:fin -->
122
+
123
+ Implementa `ControlValueAccessor` (`[(ngModel)]`, `formControlName`).
124
+
125
+ ## Trampas
126
+
127
+ - **Es controlado: no se mueve solo.** `[checked]` sin `(checkedChange)` ni `[(checked)]` = el
128
+ toque no hace nada visible. Es a propósito: el padre puede rechazar el cambio (abrir una
129
+ confirmación, revertir si falla el guardado).
130
+ - Con `formControlName` sí guarda su propio estado; a partir de ahí **ignora `[checked]`**. No
131
+ mezcles las dos formas.
132
+ - `disabled` no baja la opacidad: cambia el color y achica el círculo. Un `opacity` encima lo duplica.
133
+ - No tiene `aria-label`: pelado, pásalo con `[attr.aria-label]` (como en `central-ofertas`).
134
+ - Ya trae el arreglo de iOS para el `:active` pegado.
135
+
136
+ ## Ejemplo
137
+
138
+ ```html
139
+ <!-- Pelado en una tarjeta que ya tiene su título -->
140
+ <sui-switch [size]="bp.controlSize()" [checked]="oferta.activo" [disabled]="guardando()"
141
+ [attr.aria-label]="'Prender ' + oferta.titulo" (checkedChange)="prender(oferta, $event)" />
142
+
143
+ <!-- Con texto: sui-switch-label -->
144
+ <sui-switch-label [size]="bp.controlSize()" label="Recibir pedidos" [flip]="true"
145
+ [(active)]="abierto" />
146
+ ```
@@ -0,0 +1,139 @@
1
+ ---
2
+ name: sui-switch-label
3
+ selector: sui-switch-label
4
+ resumen: Interruptor con su texto (y opcionalmente descripción, badge y link) para un ajuste que se aplica al instante
5
+ alternativas: [sui-switch (el interruptor solo, el texto vive en otra parte), sui-switch-card (cada ajuste es una tarjeta), sui-integration-switch (fila de integración con logo), sui-checkbox-label (se confirma después)]
6
+ ---
7
+
8
+ # sui-switch-label
9
+
10
+ Story: [Atoms/Checkbox, Radio & Switch/Switch Label](https://sui-design-system.web.app/?path=/docs/atoms-checkbox-radio-switch-switch-label--docs)
11
+
12
+ ## Cuándo usarlo / cuándo no
13
+
14
+ **Úsalo** para cada fila de ajustes que se prende o se apaga: «Disponible para pedir», «Recibir
15
+ pedidos», «Un uso por cliente», «Permitir analítica de uso». Es el default de una lista de
16
+ ajustes: toda la fila se toca y el texto queda alineado con el interruptor.
17
+
18
+ **No lo uses** para:
19
+
20
+ - Un ajuste que merece tarjeta (borde, ícono, más contexto): `sui-switch-card`.
21
+ - Una integración con logo y botón de administrar: `sui-integration-switch`.
22
+ - Algo que se confirma después con «Guardar» y no tiene efecto propio: `sui-checkbox-label`.
23
+ - Algo destructivo o que no se deshace.
24
+
25
+ Regla corta: **ajuste con texto → este · ajuste con peso → switch-card · sin texto → sui-switch.**
26
+
27
+ ## Qué variante usar
28
+
29
+ > **La guía del DS dice para qué es el switch** («prender o apagar un ajuste de forma inmediata»)
30
+ > y su ejemplo avanzado arma Label + (Sublabel) + badge «NEW» + descripción + Link Button, con el
31
+ > interruptor a la izquierda o a la derecha. No dice cuándo va cada lado.
32
+ >
33
+ > Uso medido el 03-10-2026 en `master-pedidos/src/app` (misma exclusión que `sui-badge`):
34
+ > **5 usos en 4 archivos**, todos con `description`. Desde el 03-10-2026, 3 con `flip` (los
35
+ > ajustes del producto en `add-product-modal` y la analítica de `privacidad`) y 2 sin él porque
36
+ > viven dentro de un formulario (el horario de una categoría en `products`, «Cerrar por hoy» en
37
+ > `central-inicio`). Tamaños: 2 `ctrlSize()`
38
+ > (`large`/`xlarge`), 1 `xlarge` fijo, 2 sin `size` (`medium`). Hay **19 `sui-switch` con el texto
39
+ > armado a mano** y 1 nativo que deberían ser este componente.
40
+
41
+ ### Las piezas
42
+
43
+ | prop | cuándo | fuente |
44
+ |---|---|---|
45
+ | `label` | Siempre. Qué hace prenderlo, sin cambiar con el estado: «Recibir pedidos», no «Abierto/Cerrado». | según la guía del DS (pieza); la regla de qué dice es propuesta (precedente en `pages/schedule/schedule.html:31`) |
46
+ | `description` | Cuando conviene decir la consecuencia: «Los clientes pueden agregarlo al carrito. Apágalo si se te acabó.» Es lo que ya hacen los 5 usos. | según la guía del DS (pieza); el «cuándo» ya es práctica de la app |
47
+ | `sublabel` | Precisión corta entre paréntesis: «(beta)». | según la guía del DS |
48
+ | `badge` | Solo novedad. Con string sale naranja `light`: pasa el objeto. | según la guía del DS (pieza «NEW»); el color es propuesta |
49
+ | `link` | «Saber más» que no toca el interruptor. Solo se ve con `description`. | según la guía del DS |
50
+ | `flip` | Interruptor a la **derecha** en listas de ajustes: el texto se lee primero y el control queda bajo el pulgar, como en iOS y Android (es lo que hacen a mano `drivers.html:58`, `discounts.html:198`, `schedule.html:46`). Sin `flip` (izquierda) dentro de un formulario, alineado con las casillas o los switches del resto del form. | canon (aprobado por el dueño, 03-10-2026) |
51
+ | `disabled` | Mientras se guarda el cambio o cuando no aplica. | según la guía del DS |
52
+
53
+ ### `size`
54
+
55
+ | size | cuándo | fuente |
56
+ |---|---|---|
57
+ | `xlarge` | Mobile, vía `bp.controlSize()`; y cuando el ajuste es la acción principal de la pantalla («Cerrar por hoy» en Central). | canon (aprobado por el dueño, 28-09-2026: «componentes grandes») |
58
+ | `large` | Desktop, vía `bp.controlSize()`. | canon (aprobado por el dueño, 28-09-2026) |
59
+ | `medium` (default) | No usar en pantallas nuevas. | canon (aprobado por el dueño, 28-09-2026) |
60
+
61
+ **Usos de hoy que rompen las reglas:**
62
+
63
+ - **2 en `medium`:** `pages/products/products.html:300` («Horario propio
64
+ para esta categoría») y `pages/public/privacidad/privacidad.html:132` («Permitir analítica de uso»).
65
+ - **19 `sui-switch` con texto a mano + 1 nativo** que deberían ser este componente: el detalle
66
+ está en el README de `sui-switch`. Ejemplos: `pages/discounts/discounts.html:198`,
67
+ `pages/drivers/drivers.html:58`, `components/settings-panel/settings-panel.html:97`.
68
+
69
+ ## Tamaño en mobile y en web
70
+
71
+ | uso | mobile | web |
72
+ |---|---|---|
73
+ | fila de ajustes | `xlarge` (48 × 28) | `large` (40 × 24) |
74
+ | ajuste que es la acción principal de la pantalla («Cerrar por hoy») | `xlarge` | `xlarge` |
75
+
76
+ ```html
77
+ <sui-switch-label [size]="bp.controlSize()" … /> <!-- isMobile() ? 'xlarge' : 'large' -->
78
+ ```
79
+
80
+ El bloque entero se toca, así que con descripción la fila pasa los 44 px sola. Sin descripción,
81
+ dale a la fila un alto mínimo de 44 px.
82
+
83
+ ## «No usar»: por qué no hoy y cuándo sí
84
+
85
+ | qué | por qué no hoy | cuándo sí, en un flujo nuevo |
86
+ |---|---|---|
87
+ | `badge` (0 usos) | ningún ajuste es nuevo | un ajuste recién agregado en una pantalla que el usuario ya conoce |
88
+ | `link` (0 usos) | ningún ajuste necesita más detalle | «Permitir analítica de uso» con «Qué se mide» (con `description`) |
89
+ | `size="medium"` | se pierde en el teléfono | una tabla densa solo de desktop |
90
+
91
+ ## API
92
+
93
+ <!-- api:inicio -->
94
+ <!-- generada: no editar a mano — `npm run docs` -->
95
+
96
+ | input | tipo | default |
97
+ |---|---|---|
98
+ | `label` | `string` | `''` |
99
+ | `sublabel` | `string \| null` | `null` |
100
+ | `description` | `string \| null` | `null` |
101
+ | `size` | `'medium' \| 'large' \| 'xlarge'` | `'medium'` |
102
+ | `badge` | `SuiBadgeConfig \| string \| null` | `null` |
103
+ | `link` | `SuiLinkConfig \| string \| null` | `null` |
104
+ | `flip` | `boolean` | `false` |
105
+ | `disabled` | `boolean` | `false` |
106
+ | `active` | `boolean` | `false` |
107
+
108
+ | output | payload |
109
+ |---|---|
110
+ | `activeChange` | `boolean` |
111
+ | `linkClick` | `MouseEvent` |
112
+ <!-- api:fin -->
113
+
114
+ Implementa `ControlValueAccessor` (`[(ngModel)]`, `formControlName`).
115
+
116
+ ## Trampas
117
+
118
+ - **El estado se llama `active` / `activeChange`**, no `checked` como en `sui-switch`.
119
+ - **Es controlado**, como `sui-switch`: sin `[(active)]` o `(activeChange)` el toque no se ve.
120
+ - **El host es `inline-flex`.** Con `flip`, para que el interruptor quede pegado al borde derecho
121
+ de la fila, dale `display: flex` (o `width: 100%`) desde afuera.
122
+ - **`link` solo se dibuja con `description`.**
123
+ - `description` sube el label a peso medio y abre el bloque en columna.
124
+ - Deshabilitado baja todo el bloque a 0.5 de opacidad **además** del gris propio del switch.
125
+ - El badge con string sale naranja; en `sui-switch-card` el default es azul.
126
+ - `flip` usa CSS `order`: el orden de lectura no cambia.
127
+
128
+ ## Ejemplo
129
+
130
+ ```html
131
+ <sui-switch-label
132
+ [size]="bp.controlSize()"
133
+ [flip]="true"
134
+ label="Recibir pedidos"
135
+ description="Desactívalo para cerrar un rato sin tocar el horario."
136
+ [active]="abierto()"
137
+ [disabled]="guardando()"
138
+ (activeChange)="cambiarAbierto($event)" />
139
+ ```