Skip to content

Commit ab752be

Browse files
authored
feat: variantNameOnly (#12)
1 parent e1cd72d commit ab752be

File tree

6 files changed

+226
-20
lines changed

6 files changed

+226
-20
lines changed

.changeset/bold-towns-exist.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
---
2+
"@hebilicious/cssforge": minor
3+
---
4+
5+
# Introduce variantNameOnly feature for themes.
6+
7+
When working with themes, you can choose to only include the variant name in the CSS
8+
variable name by setting `variantNameOnly: true` in the color definition settings. This is
9+
usually used in combination with `condition` to conditionnally apply themes.
10+
11+
- Default: `--theme-${themeName}-${colorName}-${variantName}`
12+
- VariantOnly Name: `--${variantName}`
13+
- Path : `theme.${themeName}.${colorName}.${variantName}`

CHANGELOG.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66

77
- 41bff15: # Conditions and variables access
88

9-
Add the posibility to add conditions for colors modules. This is a breaking change for the
10-
configuration format.
9+
Add the posibility to add conditions for colors modules. This is a breaking change for
10+
the configuration format.
1111

1212
## 0.2.1
1313

README.md

Lines changed: 85 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,10 @@ export default defineConfig({
247247
},
248248
variables: {
249249
1: "palette.simple.white",
250-
2: "gradients.white-green.primary",
250+
2: "gradients.white-green.primary", //Reference the color name directly.
251+
},
252+
settings: {
253+
variantNameOnly: true,
251254
},
252255
},
253256
},
@@ -263,12 +266,35 @@ export default defineConfig({
263266
1: "palette.another.yellow",
264267
2: "palette.another.cyan",
265268
},
269+
settings: {
270+
variantNameOnly: true,
271+
},
266272
},
267273
},
268274
settings: {
269275
condition: "@media (prefers-color-scheme: dark)",
270276
},
271277
},
278+
pink: {
279+
value: {
280+
background: {
281+
value: {
282+
primary: "var(--1)",
283+
secondary: "var(--2)",
284+
},
285+
variables: {
286+
1: "palette.simple.red",
287+
2: "palette.simple.violet",
288+
},
289+
settings: {
290+
variantNameOnly: true,
291+
},
292+
},
293+
},
294+
settings: {
295+
condition: ".ThemePink",
296+
},
297+
},
272298
},
273299
},
274300
});
@@ -325,7 +351,10 @@ export default defineConfig({
325351
},
326352
variables: {
327353
1: "palette.simple.white",
328-
2: "gradients.white-green", //Reference the color name directly.
354+
2: "gradients.white-green.primary", //Reference the color name directly.
355+
},
356+
settings: {
357+
variantNameOnly: true,
329358
},
330359
},
331360
},
@@ -341,12 +370,35 @@ export default defineConfig({
341370
1: "palette.another.yellow",
342371
2: "palette.another.cyan",
343372
},
373+
settings: {
374+
variantNameOnly: true,
375+
},
344376
},
345377
},
346378
settings: {
347379
condition: "@media (prefers-color-scheme: dark)",
348380
},
349381
},
382+
pink: {
383+
value: {
384+
background: {
385+
value: {
386+
primary: "var(--1)",
387+
secondary: "var(--2)",
388+
},
389+
variables: {
390+
1: "palette.simple.red",
391+
2: "palette.simple.violet",
392+
},
393+
settings: {
394+
variantNameOnly: true,
395+
},
396+
},
397+
},
398+
settings: {
399+
condition: ".ThemePink",
400+
},
401+
},
350402
},
351403
},
352404
});
@@ -366,31 +418,56 @@ This will generate the following CSS :
366418
--palette-simple-blue: oklch(45.201% 0.31321 264.05202);
367419
--palette-simple-violet: oklch(70% 0.2 270);
368420
--palette-simple-red: oklch(62.796% 0.25768 29.23388);
421+
/* another */
369422
.Another {
370-
/* another */
371423
--palette-another-yellow: oklch(96.798% 0.21101 109.76924);
372424
--palette-another-cyan: oklch(90.54% 0.15455 194.76896);
373425
}
374-
/* Gradients */
426+
/* Gradients */
427+
/* white-green */
375428
--gradients-white-green-primary: linear-gradient(
376429
to right,
377430
var(--palette-simple-white),
378431
var(--palette-simple-green)
379432
);
380-
/* Themes */
433+
/* Themes */
381434
/* Theme: light */
382435
/* background */
436+
--primary: var(--palette-simple-white);
437+
--secondary: var(--gradients-white-green-primary);
438+
/* Theme: dark */
383439
@media (prefers-color-scheme: dark) {
384-
/* Theme: dark */
385440
/* background */
386-
--theme-dark-background-primary: var(--palette-another-yellow);
387-
--theme-dark-background-secondary: var(--palette-another-cyan);
441+
--primary: var(--palette-another-yellow);
442+
--secondary: var(--palette-another-cyan);
443+
}
444+
/* Theme: pink */
445+
.ThemePink {
446+
/* background */
447+
--primary: var(--palette-simple-red);
448+
--secondary: var(--palette-simple-violet);
388449
}
389450
}
390451
```
391452

392453
<!-- /md:generate -->
393454

455+
#### Condition
456+
457+
You can conditionnally apply colors, gradients or themes by setting the `condition`
458+
property to a selector or media query. Your variables will be wrapped within the
459+
condition.
460+
461+
#### Theme: Variant Name Only
462+
463+
When working with themes, you can choose to only include the variant name in the CSS
464+
variable name by setting `variantNameOnly: true` in the color definition settings. This is
465+
usually used in combination with `condition` to conditionnally apply themes.
466+
467+
- Default: `--theme-${themeName}-${colorName}-${variantName}`
468+
- VariantOnly Name: `--${variantName}`
469+
- Path : `theme.${themeName}.${colorName}.${variantName}`
470+
394471
### Spacing
395472

396473
Define custom spacing scale, that can be referenced for other types, such as primitives.

src/modules/colors.ts

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,13 @@ interface ColorInThemeValues {
9797
interface ColorInTheme {
9898
value: ColorInThemeValues;
9999
variables?: Variables;
100-
settings?: unknown;
100+
settings?: {
101+
/**
102+
* Only include the variant name in the CSS variable name.
103+
* --theme-light-colors-primaryBackground => --primaryBackground
104+
*/
105+
variantNameOnly?: boolean;
106+
};
101107
}
102108

103109
export interface ThemeConfig {
@@ -222,18 +228,19 @@ export function processColors(colors: ColorConfig): Output {
222228
settings: WithCondition | undefined,
223229
initialComment: string,
224230
) {
225-
const comments: string[] = [];
231+
const leadingComments: string[] = [];
232+
const innerComments: string[] = [];
226233
const vars: string[] = [];
227234

228235
if (settings?.condition) {
229-
comments.push(initialComment);
236+
leadingComments.push(initialComment);
230237
} else {
231238
cssOutput.push(initialComment);
232239
}
233240

234241
return {
235242
addComment(c: string) {
236-
if (settings?.condition) comments.push(c);
243+
if (settings?.condition) innerComments.push(c);
237244
else cssOutput.push(c);
238245
},
239246
pushVariable(v: string) {
@@ -242,8 +249,9 @@ export function processColors(colors: ColorConfig): Output {
242249
},
243250
finalize() {
244251
if (settings?.condition && vars.length > 0) {
252+
cssOutput.push(...leadingComments);
245253
cssOutput.push(`${settings.condition} {`);
246-
cssOutput.push(...comments.map((c) => ` ${c}`));
254+
cssOutput.push(...innerComments.map((c) => ` ${c}`));
247255
cssOutput.push(...vars.map((v) => ` ${v}`));
248256
cssOutput.push(`}`);
249257
}
@@ -349,14 +357,18 @@ export function processColors(colors: ColorConfig): Output {
349357
colors: palette,
350358
});
351359

360+
const variantNameOnly = colorInTheme.settings?.variantNameOnly ?? false;
352361
for (const [variantName, variantValue] of Object.entries(colorInTheme.value)) {
353362
validateName(variantName);
354363
const resolvedValue = resolveValue({
355364
map: resolvedMap,
356-
value: variantValue as string,
365+
value: variantValue,
357366
});
358367

359-
const key = `--${moduleKey}-${themeName}-${colorName}-${variantName}`;
368+
const key = variantNameOnly
369+
? `--${variantName}`
370+
: `--${moduleKey}-${themeName}-${colorName}-${variantName}`;
371+
360372
const variable = `${key}: ${resolvedValue};`;
361373

362374
handler.pushVariable(variable);

tests/__snapshots__/colors.test.ts.snap

Lines changed: 52 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -284,8 +284,8 @@ snapshot[`processColors - handles gradients with conditions 1`] = `
284284
/* coral */
285285
--palette-coral-50: oklch(73.58% 0.16378 34.33822);
286286
/* Gradients */
287+
/* orangeGradient */
287288
@media (prefers-color-scheme: dark) {
288-
/* orangeGradient */
289289
--gradients-orangeGradient-primary: linear-gradient(to right, var(--palette-coral-50), var(--palette-coral-50));
290290
}"
291291
`;
@@ -315,8 +315,8 @@ snapshot[`processColors - handles palette colors with conditions 1`] = `
315315
"/* Palette */
316316
/* background */
317317
--palette-background-light: oklch(100% 0 0);
318+
/* backgroundDark */
318319
@media (prefers-color-scheme: dark) {
319-
/* backgroundDark */
320320
--palette-backgroundDark-dark: oklch(0% 0 0);
321321
}"
322322
`;
@@ -347,8 +347,8 @@ snapshot[`processColors - handles themes with class condition 1`] = `
347347
/* base */
348348
--palette-base-primary: oklch(73.511% 0.16799 40.24666);
349349
/* Themes */
350+
/* Theme: dark */
350351
.dark-theme {
351-
/* Theme: dark */
352352
/* background */
353353
--theme-dark-background-primary: var(--palette-base-primary);
354354
}"
@@ -374,3 +374,52 @@ snapshot[`processColors - handles themes with class condition 2`] = `
374374
],
375375
]
376376
`;
377+
378+
snapshot[`processColors - handles theme variantNameOnly 1`] = `
379+
"/* Palette */
380+
/* simple */
381+
--palette-simple-white: oklch(100% 0 0);
382+
--palette-simple-black: oklch(0% 0 0);
383+
/* Themes */
384+
/* Theme: light */
385+
/* background */
386+
--primary: var(--palette-simple-white);
387+
--secondary: var(--palette-simple-black);"
388+
`;
389+
390+
snapshot[`processColors - handles theme variantNameOnly 2`] = `
391+
[
392+
[
393+
"palette.simple.white",
394+
{
395+
key: "--palette-simple-white",
396+
value: "oklch(100% 0 0)",
397+
variable: "--palette-simple-white: oklch(100% 0 0);",
398+
},
399+
],
400+
[
401+
"palette.simple.black",
402+
{
403+
key: "--palette-simple-black",
404+
value: "oklch(0% 0 0)",
405+
variable: "--palette-simple-black: oklch(0% 0 0);",
406+
},
407+
],
408+
[
409+
"theme.light.background.primary",
410+
{
411+
key: "--primary",
412+
value: "var(--palette-simple-white)",
413+
variable: "--primary: var(--palette-simple-white);",
414+
},
415+
],
416+
[
417+
"theme.light.background.secondary",
418+
{
419+
key: "--secondary",
420+
value: "var(--palette-simple-black)",
421+
variable: "--secondary: var(--palette-simple-black);",
422+
},
423+
],
424+
]
425+
`;

tests/colors.test.ts

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -491,3 +491,58 @@ Deno.test("processColors - handles themes with class condition", async (t) => {
491491
await assertSnapshot(t, css);
492492
await assertSnapshot(t, Array.from(resolveMap.entries()));
493493
});
494+
495+
Deno.test("processColors - handles theme variantNameOnly", async (t) => {
496+
const config = defineConfig({
497+
colors: {
498+
palette: {
499+
value: {
500+
simple: {
501+
value: {
502+
white: "oklch(100% 0 0)",
503+
black: { hex: "#000" },
504+
},
505+
},
506+
},
507+
},
508+
theme: {
509+
light: {
510+
value: {
511+
background: {
512+
value: {
513+
primary: "var(--1)",
514+
secondary: "var(--2)",
515+
},
516+
variables: {
517+
1: "palette.simple.white",
518+
2: "palette.simple.black",
519+
},
520+
settings: {
521+
variantNameOnly: true,
522+
},
523+
},
524+
},
525+
},
526+
},
527+
},
528+
});
529+
530+
const { css, resolveMap } = processColors(config.colors);
531+
const lines = getLines(css);
532+
533+
const primaryLine = lines.find((l) => l.includes("--primary:"));
534+
const secondaryLine = lines.find((l) => l.includes("--secondary:"));
535+
536+
assertEquals(primaryLine?.trim(), "--primary: var(--palette-simple-white);");
537+
assertEquals(secondaryLine?.trim(), "--secondary: var(--palette-simple-black);");
538+
539+
assertEquals(Array.from(resolveMap.keys()), [
540+
"palette.simple.white",
541+
"palette.simple.black",
542+
"theme.light.background.primary",
543+
"theme.light.background.secondary",
544+
]);
545+
546+
await assertSnapshot(t, css);
547+
await assertSnapshot(t, Array.from(resolveMap.entries()));
548+
});

0 commit comments

Comments
 (0)