Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions .changeset/bold-towns-exist.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
"@hebilicious/cssforge": minor
---

# Introduce variantNameOnly feature for themes.

When working with themes, you can choose to only include the variant name in the CSS
variable name by setting `variantNameOnly: true` in the color definition settings. This is
usually used in combination with `condition` to conditionnally apply themes.

- Default: `--theme-${themeName}-${colorName}-${variantName}`
- VariantOnly Name: `--${variantName}`
- Path : `theme.${themeName}.${colorName}.${variantName}`
4 changes: 2 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@

- 41bff15: # Conditions and variables access

Add the posibility to add conditions for colors modules. This is a breaking change for the
configuration format.
Add the posibility to add conditions for colors modules. This is a breaking change for
the configuration format.

## 0.2.1

Expand Down
93 changes: 85 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,10 @@ export default defineConfig({
},
variables: {
1: "palette.simple.white",
2: "gradients.white-green.primary",
2: "gradients.white-green.primary", //Reference the color name directly.
},
settings: {
variantNameOnly: true,
},
},
},
Expand All @@ -263,12 +266,35 @@ export default defineConfig({
1: "palette.another.yellow",
2: "palette.another.cyan",
},
settings: {
variantNameOnly: true,
},
},
},
settings: {
condition: "@media (prefers-color-scheme: dark)",
},
},
pink: {
value: {
background: {
value: {
primary: "var(--1)",
secondary: "var(--2)",
},
variables: {
1: "palette.simple.red",
2: "palette.simple.violet",
},
settings: {
variantNameOnly: true,
},
},
},
settings: {
condition: ".ThemePink",
},
},
},
},
});
Expand Down Expand Up @@ -325,7 +351,10 @@ export default defineConfig({
},
variables: {
1: "palette.simple.white",
2: "gradients.white-green", //Reference the color name directly.
2: "gradients.white-green.primary", //Reference the color name directly.
},
settings: {
variantNameOnly: true,
},
},
},
Expand All @@ -341,12 +370,35 @@ export default defineConfig({
1: "palette.another.yellow",
2: "palette.another.cyan",
},
settings: {
variantNameOnly: true,
},
},
},
settings: {
condition: "@media (prefers-color-scheme: dark)",
},
},
pink: {
value: {
background: {
value: {
primary: "var(--1)",
secondary: "var(--2)",
},
variables: {
1: "palette.simple.red",
2: "palette.simple.violet",
},
settings: {
variantNameOnly: true,
},
},
},
settings: {
condition: ".ThemePink",
},
},
},
},
});
Expand All @@ -366,31 +418,56 @@ This will generate the following CSS :
--palette-simple-blue: oklch(45.201% 0.31321 264.05202);
--palette-simple-violet: oklch(70% 0.2 270);
--palette-simple-red: oklch(62.796% 0.25768 29.23388);
/* another */
.Another {
/* another */
--palette-another-yellow: oklch(96.798% 0.21101 109.76924);
--palette-another-cyan: oklch(90.54% 0.15455 194.76896);
}
/* Gradients */
/* Gradients */
/* white-green */
--gradients-white-green-primary: linear-gradient(
to right,
var(--palette-simple-white),
var(--palette-simple-green)
);
/* Themes */
/* Themes */
/* Theme: light */
/* background */
--primary: var(--palette-simple-white);
--secondary: var(--gradients-white-green-primary);
/* Theme: dark */
@media (prefers-color-scheme: dark) {
/* Theme: dark */
/* background */
--theme-dark-background-primary: var(--palette-another-yellow);
--theme-dark-background-secondary: var(--palette-another-cyan);
--primary: var(--palette-another-yellow);
--secondary: var(--palette-another-cyan);
}
/* Theme: pink */
.ThemePink {
/* background */
--primary: var(--palette-simple-red);
--secondary: var(--palette-simple-violet);
}
}
```

<!-- /md:generate -->

#### Condition

You can conditionnally apply colors, gradients or themes by setting the `condition`
property to a selector or media query. Your variables will be wrapped within the
condition.

#### Theme: Variant Name Only

When working with themes, you can choose to only include the variant name in the CSS
variable name by setting `variantNameOnly: true` in the color definition settings. This is
usually used in combination with `condition` to conditionnally apply themes.

- Default: `--theme-${themeName}-${colorName}-${variantName}`
- VariantOnly Name: `--${variantName}`
- Path : `theme.${themeName}.${colorName}.${variantName}`

### Spacing

Define custom spacing scale, that can be referenced for other types, such as primitives.
Expand Down
26 changes: 19 additions & 7 deletions src/modules/colors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,13 @@ interface ColorInThemeValues {
interface ColorInTheme {
value: ColorInThemeValues;
variables?: Variables;
settings?: unknown;
settings?: {
/**
* Only include the variant name in the CSS variable name.
* --theme-light-colors-primaryBackground => --primaryBackground
*/
variantNameOnly?: boolean;
};
}

export interface ThemeConfig {
Expand Down Expand Up @@ -222,18 +228,19 @@ export function processColors(colors: ColorConfig): Output {
settings: WithCondition | undefined,
initialComment: string,
) {
const comments: string[] = [];
const leadingComments: string[] = [];
const innerComments: string[] = [];
const vars: string[] = [];

if (settings?.condition) {
comments.push(initialComment);
leadingComments.push(initialComment);
} else {
cssOutput.push(initialComment);
}

return {
addComment(c: string) {
if (settings?.condition) comments.push(c);
if (settings?.condition) innerComments.push(c);
else cssOutput.push(c);
},
pushVariable(v: string) {
Expand All @@ -242,8 +249,9 @@ export function processColors(colors: ColorConfig): Output {
},
finalize() {
if (settings?.condition && vars.length > 0) {
cssOutput.push(...leadingComments);
cssOutput.push(`${settings.condition} {`);
cssOutput.push(...comments.map((c) => ` ${c}`));
cssOutput.push(...innerComments.map((c) => ` ${c}`));
cssOutput.push(...vars.map((v) => ` ${v}`));
cssOutput.push(`}`);
}
Expand Down Expand Up @@ -349,14 +357,18 @@ export function processColors(colors: ColorConfig): Output {
colors: palette,
});

const variantNameOnly = colorInTheme.settings?.variantNameOnly ?? false;
for (const [variantName, variantValue] of Object.entries(colorInTheme.value)) {
validateName(variantName);
const resolvedValue = resolveValue({
map: resolvedMap,
value: variantValue as string,
value: variantValue,
});

const key = `--${moduleKey}-${themeName}-${colorName}-${variantName}`;
const key = variantNameOnly
? `--${variantName}`
: `--${moduleKey}-${themeName}-${colorName}-${variantName}`;

const variable = `${key}: ${resolvedValue};`;

handler.pushVariable(variable);
Expand Down
55 changes: 52 additions & 3 deletions tests/__snapshots__/colors.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -284,8 +284,8 @@ snapshot[`processColors - handles gradients with conditions 1`] = `
/* coral */
--palette-coral-50: oklch(73.58% 0.16378 34.33822);
/* Gradients */
/* orangeGradient */
@media (prefers-color-scheme: dark) {
/* orangeGradient */
--gradients-orangeGradient-primary: linear-gradient(to right, var(--palette-coral-50), var(--palette-coral-50));
}"
`;
Expand Down Expand Up @@ -315,8 +315,8 @@ snapshot[`processColors - handles palette colors with conditions 1`] = `
"/* Palette */
/* background */
--palette-background-light: oklch(100% 0 0);
/* backgroundDark */
@media (prefers-color-scheme: dark) {
/* backgroundDark */
--palette-backgroundDark-dark: oklch(0% 0 0);
}"
`;
Expand Down Expand Up @@ -347,8 +347,8 @@ snapshot[`processColors - handles themes with class condition 1`] = `
/* base */
--palette-base-primary: oklch(73.511% 0.16799 40.24666);
/* Themes */
/* Theme: dark */
.dark-theme {
/* Theme: dark */
/* background */
--theme-dark-background-primary: var(--palette-base-primary);
}"
Expand All @@ -374,3 +374,52 @@ snapshot[`processColors - handles themes with class condition 2`] = `
],
]
`;

snapshot[`processColors - handles theme variantNameOnly 1`] = `
"/* Palette */
/* simple */
--palette-simple-white: oklch(100% 0 0);
--palette-simple-black: oklch(0% 0 0);
/* Themes */
/* Theme: light */
/* background */
--primary: var(--palette-simple-white);
--secondary: var(--palette-simple-black);"
`;

snapshot[`processColors - handles theme variantNameOnly 2`] = `
[
[
"palette.simple.white",
{
key: "--palette-simple-white",
value: "oklch(100% 0 0)",
variable: "--palette-simple-white: oklch(100% 0 0);",
},
],
[
"palette.simple.black",
{
key: "--palette-simple-black",
value: "oklch(0% 0 0)",
variable: "--palette-simple-black: oklch(0% 0 0);",
},
],
[
"theme.light.background.primary",
{
key: "--primary",
value: "var(--palette-simple-white)",
variable: "--primary: var(--palette-simple-white);",
},
],
[
"theme.light.background.secondary",
{
key: "--secondary",
value: "var(--palette-simple-black)",
variable: "--secondary: var(--palette-simple-black);",
},
],
]
`;
55 changes: 55 additions & 0 deletions tests/colors.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -491,3 +491,58 @@ Deno.test("processColors - handles themes with class condition", async (t) => {
await assertSnapshot(t, css);
await assertSnapshot(t, Array.from(resolveMap.entries()));
});

Deno.test("processColors - handles theme variantNameOnly", async (t) => {
const config = defineConfig({
colors: {
palette: {
value: {
simple: {
value: {
white: "oklch(100% 0 0)",
black: { hex: "#000" },
},
},
},
},
theme: {
light: {
value: {
background: {
value: {
primary: "var(--1)",
secondary: "var(--2)",
},
variables: {
1: "palette.simple.white",
2: "palette.simple.black",
},
settings: {
variantNameOnly: true,
},
},
},
},
},
},
});

const { css, resolveMap } = processColors(config.colors);
const lines = getLines(css);

const primaryLine = lines.find((l) => l.includes("--primary:"));
const secondaryLine = lines.find((l) => l.includes("--secondary:"));

assertEquals(primaryLine?.trim(), "--primary: var(--palette-simple-white);");
assertEquals(secondaryLine?.trim(), "--secondary: var(--palette-simple-black);");

assertEquals(Array.from(resolveMap.keys()), [
"palette.simple.white",
"palette.simple.black",
"theme.light.background.primary",
"theme.light.background.secondary",
]);

await assertSnapshot(t, css);
await assertSnapshot(t, Array.from(resolveMap.entries()));
});
Loading