Skip to content

Commit d7a6b25

Browse files
committed
change colors dynamically with variables
1 parent ca2c229 commit d7a6b25

2 files changed

Lines changed: 45 additions & 17 deletions

File tree

CLAUDE.md

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,18 @@ La demo de "Theming" inyecta un `<style>` global de forma imperativa vía `Rende
7777

7878
Pero a diferencia de `sau-table` (que usa `ViewEncapsulation.None`), **`SAUDateRangePickerModule` usa encapsulación Emulated por defecto**. Eso significa que la propia regla `.sau-date-range { ... }` de la librería se compila como `.sau-date-range[_ngcontent-xxx] { ... }` — una clase + un atributo, exactamente la misma especificidad que nuestro override `.theme-live .sau-date-range` (dos clases). Con especificidad empatada, gana el orden de inserción en el `<head>`, que no es fiable (depende de cuándo Angular registra el stylesheet del componente vs. cuándo se ejecuta nuestro constructor). La solución es añadir `!important` a cada declaración generada (función `withImportant()` en `demos.ts`) — confirmado con pruebas, no es una suposición. Si se porta este patrón a otra librería, comprobar primero qué `ViewEncapsulation` usa el componente raíz antes de asumir que la especificidad por selectores basta.
7979

80-
Las variables CSS `--sau-color-primary`/`--sau-color-background` en `date-range-picker.component.scss` no existían en el componente original — se añadieron expresamente para que la demo de Theming tuviera algo que tocar, siguiendo el mismo patrón que ya usaba `sau-filter`. Solo cubren el acento principal (texto "Rango personalizado...", botón Aplicar, día inicio/fin seleccionado) — los tonos secundarios del hover dentro del calendario quedaron hardcodeados a propósito, igual que en el `sau-filter` original.
80+
Las variables CSS públicas en `date-range-picker.component.scss` son tres: `--sau-color-primary` (acento), `--sau-color-background` (superficie) y `--sau-color-danger` (acciones destructivas: botón "Limpiar" del footer y fila "Limpiar rango" del dropdown). A partir de ellas el componente deriva internamente seis tintes con `color-mix()` — prefijados `--_*` para señalar que son privados y no forman parte de la API pública:
81+
82+
| Variable interna | Mezcla | Uso |
83+
|----------------------|-----------------------------------------------|---------------------------------------------|
84+
| `--_primary-subtle` | `primary 15% + background` | fondo de días dentro del rango seleccionado |
85+
| `--_primary-faint` | `primary 8% + background` | fondo de días en hover mientras se elige fin|
86+
| `--_primary-ghost` | `primary 5% + background` | hover del botón "Rango personalizado..." |
87+
| `--_primary-muted` | `primary 65% + background` | color de texto en días en hover-range |
88+
| `--_primary-ring` | `primary 10% + transparent` | focus ring de inputs (box-shadow) |
89+
| `--_danger-faint` | `danger 6% + background` | hover del botón "Limpiar rango" |
90+
91+
Si cambias `--sau-color-primary` o `--sau-color-background` desde fuera (como hace la demo de Theming), todos los tintes derivados se recalculan solos. No hay valores de color hardcodeados para primary/background/danger — solo los grises neutros de la escala slate (`#334155`, `#64748b`, `#e2e8f0`, etc.) siguen siendo literales porque no son parte de la API de tematización.
8192

8293
## Cómo funciona el editor de las demos en vivo (`src/app/components/demos`)
8394

projects/some-angular-utils/date-range-picker/src/lib/date-range-picker.component.scss

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,16 @@
11
.sau-date-range {
2+
/* — Public API: customizable by the host app — */
23
--sau-color-primary: rgb(147, 51, 234);
34
--sau-color-background: rgb(255, 255, 255);
5+
--sau-color-danger: rgb(220, 38, 38);
6+
7+
/* — Internal tints derived with color-mix — */
8+
--_primary-subtle: color-mix(in srgb, var(--sau-color-primary) 15%, var(--sau-color-background));
9+
--_primary-faint: color-mix(in srgb, var(--sau-color-primary) 8%, var(--sau-color-background));
10+
--_primary-ghost: color-mix(in srgb, var(--sau-color-primary) 5%, var(--sau-color-background));
11+
--_primary-muted: color-mix(in srgb, var(--sau-color-primary) 65%, var(--sau-color-background));
12+
--_primary-ring: color-mix(in srgb, var(--sau-color-primary) 10%, transparent);
13+
--_danger-faint: color-mix(in srgb, var(--sau-color-danger) 6%, var(--sau-color-background));
414

515
display: flex;
616
flex-direction: column;
@@ -43,14 +53,14 @@
4353

4454
&:focus {
4555
border-color: var(--sau-color-primary);
46-
box-shadow: 0 0 0 3px rgba(147, 51, 234, 0.1);
47-
background-color: #ffffff;
56+
box-shadow: 0 0 0 3px var(--_primary-ring);
57+
background-color: var(--sau-color-background);
4858
}
4959

5060
&.is-active-view {
5161
font-weight: 500;
5262
color: #0f172a;
53-
background-color: #ffffff;
63+
background-color: var(--sau-color-background);
5464
border-color: #cbd5e1;
5565
}
5666
}
@@ -86,7 +96,7 @@
8696
right: 0;
8797
z-index: 50;
8898
margin-top: 0.25rem;
89-
background: #ffffff;
99+
background: var(--sau-color-background);
90100
border: 1px solid #e2e8f0;
91101
border-radius: 0.5rem;
92102
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
@@ -113,10 +123,10 @@
113123

114124
&.is-clear-trigger {
115125
font-weight: 500;
116-
color: #dc2626;
126+
color: var(--sau-color-danger);
117127

118128
&:hover {
119-
background-color: #fef2f2;
129+
background-color: var(--_danger-faint);
120130
}
121131
}
122132

@@ -125,7 +135,7 @@
125135
color: var(--sau-color-primary);
126136

127137
&:hover {
128-
background-color: rgb(250, 245, 255);
138+
background-color: var(--_primary-ghost);
129139
}
130140
}
131141
}
@@ -141,10 +151,9 @@
141151
position: absolute;
142152
top: 100%;
143153
left: 0;
144-
/* Alineado a la izquierda */
145154
z-index: 50;
146155
margin-top: 0.25rem;
147-
background: #ffffff;
156+
background: var(--sau-color-background);
148157
border: 1px solid #e2e8f0;
149158
border-radius: 0.65rem;
150159
box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 8px 10px -6px rgba(0, 0, 0, 0.1);
@@ -275,20 +284,27 @@
275284
}
276285

277286
&.is-within-range {
278-
background-color: rgb(243, 232, 255);
287+
background-color: var(--_primary-subtle);
279288
color: var(--sau-color-primary);
280289
border-radius: 0;
281290
}
282291

283292
&.is-hover-range {
284-
background-color: rgb(248, 242, 255);
285-
color: rgb(168, 85, 247);
293+
background-color: var(--_primary-faint);
294+
color: var(--_primary-muted);
286295
border-radius: 0;
287296
}
288297

289298
&.is-today {
290-
box-shadow: inset 0 0 0 1.5px var(--sau-color-primary);
291-
border-radius: 9999px;
299+
300+
&::after {
301+
content: '';
302+
position: absolute;
303+
inset: 0;
304+
border-radius: 9999px;
305+
border: 1.5px solid var(--sau-color-primary);
306+
pointer-events: none;
307+
}
292308
}
293309

294310
&.is-start {
@@ -312,6 +328,7 @@
312328
display: flex;
313329
justify-content: space-between;
314330
align-items: center;
331+
flex-wrap: wrap;
315332
gap: 0.5rem;
316333
margin-top: 0.5rem;
317334
padding-top: 0.75rem;
@@ -341,14 +358,14 @@
341358

342359
&:focus {
343360
border-color: var(--sau-color-primary);
344-
box-shadow: 0 0 0 2px rgba(147, 51, 234, 0.1);
361+
box-shadow: 0 0 0 2px var(--_primary-ring);
345362
}
346363
}
347364

348365
&__clear-btn {
349366
background: none;
350367
border: none;
351-
color: #dc2626;
368+
color: var(--sau-color-danger);
352369
font-size: 0.75rem;
353370
cursor: pointer;
354371
font-weight: 500;

0 commit comments

Comments
 (0)