Skip to content

Commit

Permalink
fix: core code updates
Browse files Browse the repository at this point in the history
  • Loading branch information
fluid-design-io committed Oct 18, 2023
1 parent 291caae commit 8dd6043
Show file tree
Hide file tree
Showing 4 changed files with 233 additions and 5 deletions.
21 changes: 20 additions & 1 deletion apps/web/lib/colorHelper.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ColorMode, RawColor } from "@/types/app";
import { BaseColors, ColorMode, RawColor } from "@/types/app";
import tinycolor from "tinycolor2";

const toHex = (color: string | RawColor): string =>
Expand Down Expand Up @@ -35,10 +35,29 @@ const toForeground = (color: string | RawColor): string => {
}
};

const toRaw = (color: string): RawColor => {
const { h, s, l, a } = tinycolor(color).toHsl();
return { h, s, l, a };
};

const colorStringToBaseColors = (
colorString: string,
): Omit<BaseColors, "gray"> => {
const colors = colorString.split(",");
const baseColors = {
primary: colorHelper.toRaw(colors[0]),
secondary: colorHelper.toRaw(colors[1]),
accent: colorHelper.toRaw(colors[2]),
};
return baseColors;
};

export const colorHelper = {
toHex,
toRgba,
toHsla,
toColorMode,
toForeground,
toRaw,
colorStringToBaseColors,
};
174 changes: 174 additions & 0 deletions apps/web/lib/generateVariables.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
import {
AppCSSVariables,
BaseColorTypes,
BaseColors,
ColorMode,
ColorPalettes,
} from "@/types/app";
import { colorStepMap } from "./colorStepMap";
import { colorHelper } from "./colorHelper";
import generateFigmaUrlToken from "./code-gen/generate-figma-url-token";

export enum CodeGenerateType {
CODEGEN = "codegen",
PLUGIN = "plugin",
}
export enum CodeButtonTitle {
RAW = "Raw",
TAILWINDCSS = "Tailwind CSS",
SHADCN = "shadcn/ui",
REACT_NATIVE_PAPER = "React Native Paper",
WEBFLOW = "Webflow",
FIGMA = "Figma",
}

export const getColorHsl = <T extends BaseColorTypes>(
palette: ColorPalettes[T],
step: number,
): string => {
const { h, s, l } = palette.find((color) => color.step === colorStepMap[step])
?.raw;
const hRounded = Math.round(h * 100) / 100;
const sRounded = Math.round(s * 100);
const lRounded = Math.round(l * 100);
return `${hRounded} ${sRounded}% ${lRounded}%`;
};

const generateShadcnCss = (colorPalettes: ColorPalettes) => {
const g = (color: BaseColorTypes, step: number) =>
getColorHsl(colorPalettes[color], step);
const darkTheme: Record<AppCSSVariables, string> = {
"--background": g("gray", 10),
"--foreground": g("gray", 0),
"--card": g("gray", 10),
"--card-foreground": g("gray", 0),
"--popover": g("gray", 10),
"--popover-foreground": g("gray", 0),
"--primary": g("primary", 4),
"--primary-foreground": g("primary", 9),
"--secondary": g("secondary", 9),
"--secondary-foreground": g("secondary", 1),
"--muted": g("gray", 9),
"--muted-foreground": g("gray", 4),
"--accent": g("accent", 8),
"--accent-foreground": g("accent", 1),
"--border": g("gray", 8),
"--input": g("gray", 8),
"--ring": g("gray", 0),
"--background-accent": g("gray", 9),
};

const lightTheme: Record<AppCSSVariables, string> = {
"--background": g("gray", 0),
"--foreground": g("gray", 10),
"--card": g("gray", 0),
"--card-foreground": g("gray", 10),
"--popover": g("gray", 0),
"--popover-foreground": g("gray", 10),
"--primary": g("primary", 6),
"--primary-foreground": g("primary", 1),
"--secondary": g("secondary", 2),
"--secondary-foreground": g("secondary", 9),
"--muted": g("gray", 1),
"--muted-foreground": g("gray", 7),
"--accent": g("accent", 2),
"--accent-foreground": g("accent", 9),
"--border": g("gray", 2),
"--input": g("gray", 2),
"--ring": g("gray", 10),
"--background-accent": g("gray", 1),
};

const cssText = `:root {
${Object.entries(lightTheme)
.map(([variableName, value]) => `\t${variableName}: ${value};`)
.join("\n")}
}
.dark {
${Object.entries(darkTheme)
.map(([variableName, value]) => `\t${variableName}: ${value};`)
.join("\n")}
}`;
return cssText;
};

const generateRawCss = (colorPalettes: ColorPalettes) => {
// using tailwindcss naming convention, e.g. --gray-100
// total 4 base colors, 11 steps each
const g = (color: BaseColorTypes, step: number) =>
getColorHsl(colorPalettes[color], step);
const tailwindCss: Record<string, string> = [
"gray",
"primary",
"secondary",
"accent",
].reduce((acc, color) => {
for (let i = 0; i < 11; i++) {
acc[`\t--${color}-${colorStepMap[i]}`] = g(color as BaseColorTypes, i);
}
return acc;
}, {});
const cssText = `:root{
${Object.entries(tailwindCss)
.map(([variableName, value]) => `${variableName}: ${value};`)
.join("\n")}
}`;
return cssText;
};

const generateTailwindCss = (colorPalettes: ColorPalettes) => {
const text = Object.entries(colorPalettes)
.map(([colorName, colorPalette]) => {
let paletteSection = `\t\t${colorName}: {\n`;
colorPalette.forEach((color) => {
paletteSection += `\t\t\t${color.step}: '${colorHelper.toColorMode(
color.raw,
ColorMode.HEX,
)}',\n`;
});
paletteSection += "\t\t},\n";
return paletteSection;
})
.join("");

return `
/* tailwind.config.js */
module.exports = {
// ...
theme: {
extend: {
colors: {
${text} },
},
},
};
`;
};

export const generateCssVariables = async ({
title,
colorPalettes,
baseColors,
}: {
title: CodeButtonTitle;
colorPalettes: ColorPalettes;
baseColors: Omit<BaseColors, "gray">;
}) => {
switch (title) {
case CodeButtonTitle.RAW:
return generateRawCss(colorPalettes);
case CodeButtonTitle.TAILWINDCSS:
return generateTailwindCss(colorPalettes);
case CodeButtonTitle.SHADCN:
return generateShadcnCss(colorPalettes);
case CodeButtonTitle.REACT_NATIVE_PAPER:
return "";
case CodeButtonTitle.FIGMA:
return await generateFigmaUrlToken(baseColors);
case CodeButtonTitle.WEBFLOW:
return "";
default:
return "";
}
};
34 changes: 34 additions & 0 deletions apps/web/lib/getServerColors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { cookies } from "next/headers";
import { generateBaseColors } from "./generateBaseColors";
import { generateColorPalette } from "./colorCalculator";
import { BaseColorTypes, ColorMode } from "@/types/app";
import { colorHelper } from "./colorHelper";

export const getServerColors = async () => {
const newBaseColors = generateBaseColors();
const cookieStore = cookies();
const mode = cookieStore.get("colorMode");
// short-hand
const [primaryPalette, secondaryPalette, accentPalette, grayPalette] = [
"primary",
"secondary",
"accent",
"gray",
].map((color) =>
generateColorPalette({
color: color === "gray" ? newBaseColors.primary : newBaseColors[color],
type: color as BaseColorTypes,
colorMode: mode ? (mode.value as ColorMode) : ColorMode.HEX,
}),
);
return {
baseColors: newBaseColors,
colorPalettes: {
primary: primaryPalette,
secondary: secondaryPalette,
accent: accentPalette,
gray: grayPalette,
},
colorMode: mode ? (mode.value as ColorMode) : ColorMode.HEX,
};
};
9 changes: 5 additions & 4 deletions apps/web/lib/updateCssVariables.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { BaseColors, ColorPalettes } from "@/types/app";
import {
CSSType,
CodeButtonTitle,
CodeGenerateType,
generateCssVariables,
getColorHsl,
} from "./generateCssVariables";
} from "./generateVariables";

export async function updateCSSVariables(
colorPalettes: ColorPalettes,
Expand All @@ -21,7 +22,7 @@ export async function updateCSSVariables(
// Build the CSS text
const cssText = `
${await generateCssVariables({
type: CSSType.SHADCN,
title: CodeButtonTitle.SHADCN,
colorPalettes,
baseColors,
})}
Expand All @@ -41,7 +42,7 @@ export async function updateCSSVariables(
}
/* Custom constant variables */
${await generateCssVariables({
type: CSSType.RAW,
title: CodeButtonTitle.RAW,
colorPalettes,
baseColors,
})}
Expand Down

0 comments on commit 8dd6043

Please sign in to comment.