diff --git a/package-lock.json b/package-lock.json index a3415931..0aaf2ac9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,7 @@ "name": "vite-project", "version": "0.0.0", "dependencies": { + "@adobe/leonardo-contrast-colors": "^1.0.0", "@hey-api/client-fetch": "^0.6.0", "@radix-ui/react-avatar": "^1.1.1", "@radix-ui/react-dialog": "^1.1.4", @@ -76,6 +77,18 @@ "dev": true, "license": "MIT" }, + "node_modules/@adobe/leonardo-contrast-colors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@adobe/leonardo-contrast-colors/-/leonardo-contrast-colors-1.0.0.tgz", + "integrity": "sha512-a4mD0JZ1zNu2wIem/vWJqdaiuQZgxwOph/gpHA75mlXcs6iiIQx9G+W0jtssRFgdYYAi/ceQYOlYwiSQj1AUCw==", + "dependencies": { + "apca-w3": "^0.1.9", + "chroma-js": "^2.4.2", + "ciebase": "^0.1.1", + "ciecam02": "^0.4.6", + "hsluv": "^0.1.0" + } + }, "node_modules/@alloc/quick-lru": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", @@ -3508,6 +3521,14 @@ "node": ">= 8" } }, + "node_modules/apca-w3": { + "version": "0.1.9", + "resolved": "https://registry.npmjs.org/apca-w3/-/apca-w3-0.1.9.tgz", + "integrity": "sha512-Zrf6AeBeQjNe/fxK7U1jCo5zfdjDl6T4/kdw5Xlky3G7u+EJTZkyItjMYQGtwf9pkftsINxcYyOpuLkzKf1ITQ==", + "dependencies": { + "colorparsley": "^0.1.8" + } + }, "node_modules/arg": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", @@ -3941,6 +3962,28 @@ "node": ">=10" } }, + "node_modules/chroma-js": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/chroma-js/-/chroma-js-2.6.0.tgz", + "integrity": "sha512-BLHvCB9s8Z1EV4ethr6xnkl/P2YRFOGqfgvuMG/MyCbZPrTA+NeiByY6XvgF0zP4/2deU2CXnWyMa3zu1LqQ3A==" + }, + "node_modules/ciebase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ciebase/-/ciebase-0.1.1.tgz", + "integrity": "sha512-KEnf/WVT5E+Gn+LsfMHGJFATltSOeW0qm7dpzQYL/Qe5PEpyTM+UI5bMoBo16FE81zMpu+U6032USTP6Cz1XNA==", + "dependencies": { + "mout": "^0.11.1" + } + }, + "node_modules/ciecam02": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/ciecam02/-/ciecam02-0.4.6.tgz", + "integrity": "sha512-nh/Kl8s5lgtyEl7lA381JFinLhgUwDhJaAVgbVx2BaiiJIzJLumQvuFXwdS76tSch7jDjWejP+MtKYCCEk/brg==", + "dependencies": { + "ciebase": "^0.1.1", + "mout": "^0.11.1" + } + }, "node_modules/citty": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/citty/-/citty-0.1.6.tgz", @@ -4128,6 +4171,11 @@ "dev": true, "license": "MIT" }, + "node_modules/colorparsley": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/colorparsley/-/colorparsley-0.1.8.tgz", + "integrity": "sha512-rObESTTTE6G5qO5WFwFxWPggpw4KfpxnLC6Ssl8bITBnNVRhDsyCeTRAUxWQNVTx2pRknKlO2nddYTxjkdNFaw==" + }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -5519,6 +5567,11 @@ "integrity": "sha512-PDEfEF102G23vHmPhLyPboFCD+BkMGu+GuJe2d9/eH4FsCwvgBpnc9n0pGE+ffKdph38s6foEZiEjdgHdzp+IA==", "license": "CC0-1.0" }, + "node_modules/hsluv": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/hsluv/-/hsluv-0.1.0.tgz", + "integrity": "sha512-ERcanKLAszD2XN3Vh5r5Szkrv9q0oSTudmP0rkiKAGM/3NMc9FLmMZBB7TSqTaXJfSDBOreYTfjezCOYbRKqlw==" + }, "node_modules/html-encoding-sniffer": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz", @@ -7443,6 +7496,11 @@ "ufo": "^1.5.4" } }, + "node_modules/mout": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/mout/-/mout-0.11.1.tgz", + "integrity": "sha512-pK9VNiLE3QgGBrC/3ICAscwOLU7oTNeK2l32uqNAioBYtB2tQAfSsGDNChUlk7CP23126mc5lUt6+na9FlN8JA==" + }, "node_modules/mrmime": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.0.tgz", diff --git a/package.json b/package.json index ae01c6c6..37132ed0 100644 --- a/package.json +++ b/package.json @@ -15,9 +15,11 @@ "preview": "vite preview", "test": "vitest", "test:coverage": "vitest run --coverage", - "type-check": "tsc --noEmit -p ./tsconfig.app.json" + "type-check": "tsc --noEmit -p ./tsconfig.app.json", + "generate-colors": "node ./src/scripts/generateColorTokens.js" }, "dependencies": { + "@adobe/leonardo-contrast-colors": "^1.0.0", "@hey-api/client-fetch": "^0.6.0", "@radix-ui/react-avatar": "^1.1.1", "@radix-ui/react-dialog": "^1.1.4", @@ -81,4 +83,4 @@ "overrides": { "vite": "^6.0.1" } -} \ No newline at end of file +} diff --git a/src/App.tsx b/src/App.tsx index fafa5bf0..a096bde6 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -28,8 +28,12 @@ function App() { fetchPrompts(); }, [fetchPrompts]); + const prefersDarkMode = window.matchMedia( + "(prefers-color-scheme: dark)", + ).matches; + return ( -
+
diff --git a/src/baseColors.json b/src/baseColors.json new file mode 100644 index 00000000..1006ba15 --- /dev/null +++ b/src/baseColors.json @@ -0,0 +1,9 @@ +{ + "background": "#fff", + "foreground": "#000", + "teal": "#c2e6ff", + "blue": "#5058FF", + "red": "#ff5058", + "orange": "#ffa050", + "green": "#58ff50" +} diff --git a/src/components/Chat.tsx b/src/components/Chat.tsx index 597c973e..815ee7b5 100644 --- a/src/components/Chat.tsx +++ b/src/components/Chat.tsx @@ -30,8 +30,8 @@ export function Chat() {
- - + + {sanitizeQuestionPrompt({ question: question?.message ?? "", answer: answer?.message ?? "", diff --git a/src/components/Header.tsx b/src/components/Header.tsx index 74dc4121..3c0b45bf 100644 --- a/src/components/Header.tsx +++ b/src/components/Header.tsx @@ -4,7 +4,7 @@ import { Separator } from "./ui/separator"; export function Header() { return ( -
+
@@ -18,20 +18,20 @@ export function Header() {
-
+
Certificates
-
+
Download Certificate Security @@ -39,20 +39,20 @@ export function Header() {
-
+
Help
-
+
Continue Setup Copilot Setup @@ -61,7 +61,7 @@ export function Header() {
-
+
+
); }, - p({ children }) { - return ( -

- {children} -

- ); - }, pre({ children }) { return
{children}
; }, diff --git a/src/components/Sidebar.tsx b/src/components/Sidebar.tsx index cf6ac142..7b7cf1cc 100644 --- a/src/components/Sidebar.tsx +++ b/src/components/Sidebar.tsx @@ -18,11 +18,11 @@ export function Sidebar({ }) { if (loading) { return ( - - + + History Prompts - + {Array.from({ length: 20 }).map((_, index) => ( @@ -37,11 +37,11 @@ export function Sidebar({ } return ( - - + + History Prompts - + {children} diff --git a/src/components/ui/chat/chat-bubble.tsx b/src/components/ui/chat/chat-bubble.tsx index eed61fd3..0aad1695 100644 --- a/src/components/ui/chat/chat-bubble.tsx +++ b/src/components/ui/chat/chat-bubble.tsx @@ -75,9 +75,8 @@ const ChatBubbleAvatar: React.FC = ({ const chatBubbleMessageVariants = cva("p-4", { variants: { variant: { - received: - "bg-secondary text-secondary-foreground rounded-r-lg rounded-tl-lg", - sent: "bg-primary text-primary-foreground rounded-l-lg rounded-tr-lg", + received: "rounded-r-lg rounded-tl-lg bg-teal-100", + sent: "rounded-l-lg rounded-tr-lg bg-teal-100", }, layout: { default: "", diff --git a/src/components/ui/input.tsx b/src/components/ui/input.tsx index 58e1aea7..7300f320 100644 --- a/src/components/ui/input.tsx +++ b/src/components/ui/input.tsx @@ -12,7 +12,7 @@ const Input = React.forwardRef(
{icon} @@ -20,11 +20,11 @@ const Input = React.forwardRef( {...props} type="search" ref={ref} - className="w-full p-2 placeholder:text-muted-foreground focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50" + className="w-full p-2 placeholder:text-muted-foreground focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50 bg-white" />
); - } + }, ); Input.displayName = "Input"; diff --git a/src/components/ui/skeleton.tsx b/src/components/ui/skeleton.tsx index e3534338..ba03ba70 100644 --- a/src/components/ui/skeleton.tsx +++ b/src/components/ui/skeleton.tsx @@ -1,4 +1,4 @@ -import { cn } from "@/lib/utils" +import { cn } from "@/lib/utils"; function Skeleton({ className, @@ -6,10 +6,10 @@ function Skeleton({ }: React.HTMLAttributes) { return (
- ) + ); } -export { Skeleton } +export { Skeleton }; diff --git a/src/design-tokens.css b/src/design-tokens.css new file mode 100644 index 00000000..93460c5c --- /dev/null +++ b/src/design-tokens.css @@ -0,0 +1,124 @@ + + +:root { + --background: 0deg, 0%, 100%; + --gray-100: 0deg, 0%, 100%; + --gray-200: 0deg, 0%, 91%; + --gray-300: 0deg, 1%, 77%; + --gray-400: 0deg, 0%, 65%; + --gray-500: 0deg, 0%, 54%; + --gray-600: 0deg, 0%, 45%; + --gray-700: 0deg, 1%, 37%; + --gray-800: 0deg, 1%, 29%; + --gray-900: 0deg, 1%, 26%; + --teal-100: 180deg, 100%, 98%; + --teal-200: 199deg, 100%, 90%; + --teal-300: 205deg, 46%, 77%; + --teal-400: 205deg, 26%, 65%; + --teal-500: 205deg, 15%, 54%; + --teal-600: 204deg, 12%, 45%; + --teal-700: 205deg, 12%, 37%; + --teal-800: 208deg, 10%, 29%; + --teal-900: 208deg, 10%, 26%; + --blue-100: 0deg, 0%, 100%; + --blue-200: 225deg, 42%, 93%; + --blue-300: 227deg, 64%, 83%; + --blue-400: 228deg, 84%, 76%; + --blue-500: 232deg, 100%, 71%; + --blue-600: 236deg, 100%, 66%; + --blue-700: 238deg, 72%, 57%; + --blue-800: 237deg, 53%, 44%; + --blue-900: 236deg, 52%, 38%; + --red-100: 0deg, 0%, 100%; + --red-200: 2deg, 100%, 94%; + --red-300: 2deg, 100%, 84%; + --red-400: 0deg, 100%, 75%; + --red-500: 357deg, 93%, 63%; + --red-600: 357deg, 61%, 53%; + --red-700: 358deg, 50%, 44%; + --red-800: 359deg, 45%, 35%; + --red-900: 0deg, 43%, 30%; + --orange-100: 0deg, 0%, 100%; + --orange-200: 33deg, 100%, 88%; + --orange-300: 30deg, 100%, 70%; + --orange-400: 27deg, 79%, 59%; + --orange-500: 27deg, 54%, 50%; + --orange-600: 27deg, 50%, 42%; + --orange-700: 27deg, 47%, 35%; + --orange-800: 26deg, 42%, 28%; + --orange-900: 28deg, 40%, 24%; + --green-100: 120deg, 100%, 99%; + --green-200: 112deg, 100%, 78%; + --green-300: 117deg, 72%, 57%; + --green-400: 115deg, 51%, 49%; + --green-500: 114deg, 45%, 42%; + --green-600: 113deg, 40%, 36%; + --green-700: 111deg, 35%, 30%; + --green-800: 111deg, 31%, 25%; + --green-900: 111deg, 29%, 22%; + --background: var(--gray-100); + --foreground: var(--gray-900); +} + + +@media (prefers-color-scheme: dark) { + :root { + --background: 0deg, 0%, 0%; + --gray-100: 0deg, 1%, 19%; + --gray-200: 0deg, 0%, 25%; + --gray-300: 0deg, 1%, 34%; + --gray-400: 0deg, 0%, 42%; + --gray-500: 0deg, 0%, 52%; + --gray-600: 0deg, 0%, 61%; + --gray-700: 0deg, 1%, 72%; + --gray-800: 0deg, 0%, 84%; + --gray-900: 0deg, 2%, 89%; + --teal-100: 207deg, 9%, 19%; + --teal-200: 208deg, 10%, 25%; + --teal-300: 207deg, 10%, 34%; + --teal-400: 204deg, 12%, 42%; + --teal-500: 205deg, 14%, 51%; + --teal-600: 205deg, 22%, 61%; + --teal-700: 205deg, 35%, 72%; + --teal-800: 204deg, 69%, 83%; + --teal-900: 203deg, 100%, 88%; + --blue-100: 233deg, 47%, 27%; + --blue-200: 235deg, 51%, 36%; + --blue-300: 238deg, 58%, 52%; + --blue-400: 238deg, 96%, 65%; + --blue-500: 233deg, 100%, 69%; + --blue-600: 229deg, 91%, 74%; + --blue-700: 228deg, 71%, 80%; + --blue-800: 225deg, 52%, 87%; + --blue-900: 227deg, 42%, 91%; + --red-100: 0deg, 39%, 23%; + --red-200: 0deg, 42%, 29%; + --red-300: 359deg, 49%, 40%; + --red-400: 357deg, 53%, 49%; + --red-500: 357deg, 81%, 60%; + --red-600: 359deg, 100%, 71%; + --red-700: 1deg, 100%, 80%; + --red-800: 2deg, 100%, 89%; + --red-900: 2deg, 100%, 93%; + --orange-100: 26deg, 37%, 19%; + --orange-200: 26deg, 40%, 24%; + --orange-300: 27deg, 45%, 32%; + --orange-400: 27deg, 49%, 39%; + --orange-500: 27deg, 53%, 47%; + --orange-600: 27deg, 69%, 56%; + --orange-700: 28deg, 100%, 66%; + --orange-800: 32deg, 100%, 78%; + --orange-900: 33deg, 100%, 85%; + --green-100: 109deg, 26%, 17%; + --green-200: 108deg, 29%, 21%; + --green-300: 111deg, 34%, 28%; + --green-400: 112deg, 39%, 34%; + --green-500: 114deg, 44%, 40%; + --green-600: 115deg, 49%, 46%; + --green-700: 117deg, 61%, 54%; + --green-800: 117deg, 88%, 62%; + --green-900: 115deg, 100%, 72%; + --background: var(--gray-100); + --foreground: var(--gray-900); + } +} diff --git a/src/index.css b/src/index.css index 5a9a1255..27286a6c 100644 --- a/src/index.css +++ b/src/index.css @@ -1,7 +1,10 @@ +@import 'design-tokens.css'; + @tailwind base; @tailwind components; @tailwind utilities; + html, body { height: 100%; @@ -15,7 +18,7 @@ body { font-weight: 400; /* color-scheme: light dark; */ - background-color: #ffffff; + background-color: var(--background); font-synthesis: none; text-rendering: optimizeLegibility; @@ -25,80 +28,16 @@ body { @layer base { :root { - --background: 0 0% 100%; - --foreground: 0 0% 3.9%; - --card: 0 0% 100%; - --card-foreground: 0 0% 3.9%; - --popover: 0 0% 100%; - --popover-foreground: 0 0% 3.9%; - --primary: 0 0% 9%; - --primary-foreground: 0 0% 98%; - --secondary: 0 0% 96.1%; - --secondary-foreground: 0 0% 9%; - --muted: 0 0% 96.1%; - --muted-foreground: 0 0% 45.1%; - --accent: 0 0% 96.1%; - --accent-foreground: 0 0% 9%; - --destructive: 0 84.2% 60.2%; - --destructive-foreground: 0 0% 98%; - --border: 0 0% 89.8%; - --input: 0 0% 89.8%; - --ring: 0 0% 3.9%; --chart-1: 12 76% 61%; --chart-2: 173 58% 39%; --chart-3: 197 37% 24%; --chart-4: 43 74% 66%; --chart-5: 27 87% 67%; --radius: 0.5rem; - --sidebar-background: 0 0% 98%; - --sidebar-foreground: 240 5.3% 26.1%; - --sidebar-primary: 240 5.9% 10%; - --sidebar-primary-foreground: 0 0% 98%; - --sidebar-accent: 240 4.8% 95.9%; - --sidebar-accent-foreground: 240 5.9% 10%; - --sidebar-border: 220 13% 91%; - --sidebar-ring: 217.2 91.2% 59.8%; - } - .dark { - --background: 0 0% 3.9%; - --foreground: 0 0% 98%; - --card: 0 0% 3.9%; - --card-foreground: 0 0% 98%; - --popover: 0 0% 3.9%; - --popover-foreground: 0 0% 98%; - --primary: 0 0% 98%; - --primary-foreground: 0 0% 9%; - --secondary: 0 0% 14.9%; - --secondary-foreground: 0 0% 98%; - --muted: 0 0% 14.9%; - --muted-foreground: 0 0% 63.9%; - --accent: 0 0% 14.9%; - --accent-foreground: 0 0% 98%; - --destructive: 0 62.8% 30.6%; - --destructive-foreground: 0 0% 98%; - --border: 0 0% 14.9%; - --input: 0 0% 14.9%; - --ring: 0 0% 83.1%; - --chart-1: 220 70% 50%; - --chart-2: 160 60% 45%; - --chart-3: 30 80% 55%; - --chart-4: 280 65% 60%; - --chart-5: 340 75% 55%; - --sidebar-background: 240 5.9% 10%; - --sidebar-foreground: 240 4.8% 95.9%; - --sidebar-primary: 224.3 76.3% 48%; - --sidebar-primary-foreground: 0 0% 100%; - --sidebar-accent: 240 3.7% 15.9%; - --sidebar-accent-foreground: 240 4.8% 95.9%; - --sidebar-border: 240 3.7% 15.9%; - --sidebar-ring: 217.2 91.2% 59.8%; } } @layer base { - * { - @apply border-border; - } body { @apply bg-background text-foreground; } diff --git a/src/scripts/generateColorTokens.js b/src/scripts/generateColorTokens.js new file mode 100644 index 00000000..eecaec9f --- /dev/null +++ b/src/scripts/generateColorTokens.js @@ -0,0 +1,161 @@ +// code mostly copied from my personal project and modified with ChatGPT +// used to generate color tokens based on contrast values + +import { writeFileSync } from "fs"; +import { join } from "path"; +import path from "path"; +import { fileURLToPath } from "url"; +import { Theme, Color, BackgroundColor } from "@adobe/leonardo-contrast-colors"; +import baseColors from "../baseColors.json" with { type: "json" }; + +console.log(baseColors); + +const __filename = fileURLToPath(import.meta.url); // get the resolved path to the file +const __dirname = path.dirname(__filename); // get the name of the directory + +// ------------------------------------- +// 2. Utility Functions +// ------------------------------------- +function generateRatios(multiplier = 1) { + const baseRatio = 1.35; + const ratioCount = 9; + return Array.from( + { length: ratioCount }, + (_, i) => (Math.pow(baseRatio, i + 1) - baseRatio + 1) * multiplier, + ); +} + +function smoothRatios(ratios, windowSize = 3) { + const smoothed = [...ratios]; + const halfWindow = Math.floor(windowSize / 2); + + for (let i = 0; i < ratios.length; i++) { + let sum = 0; + let count = 0; + for ( + let j = Math.max(0, i - halfWindow); + j < Math.min(ratios.length, i + halfWindow + 1); + j++ + ) { + sum += ratios[j]; + count++; + } + smoothed[i] = sum / count; + } + return smoothed; +} + +// ------------------------------------- +// 3. Generate Ratios for light, dark, and print modes +// ------------------------------------- +const lightRatios = smoothRatios(generateRatios(0.8)); +const darkRatios = smoothRatios(generateRatios(1.3)); + +// ------------------------------------- +// 4. Generate the entire color scheme +// ------------------------------------- +function generateColorScheme(baseColors, isLightMode, ratios) { + const backgroundColor = isLightMode + ? baseColors.background + : baseColors.foreground; + const textColor = isLightMode ? baseColors.foreground : baseColors.background; + + const background = new BackgroundColor({ + name: "gray", + colorKeys: [backgroundColor, textColor], + colorspace: "CAM02", + output: "HSL", + ratios, + smooth: true, + }); + + // Generate color scales for all keys except background/foreground + const colorScales = Object.entries(baseColors) + .filter(([key]) => !["background", "foreground"].includes(key)) + .map( + ([name, color]) => + new Color({ + name, + colorKeys: [color], + colorspace: "CAM02", + output: "HSL", + ratios, + smooth: true, + }), + ); + + const theme = new Theme({ + colors: [background, ...colorScales], + output: "HSL", + backgroundColor: background, + lightness: isLightMode ? 100 : 0, + contrast: 1, + }); + + return theme.contrastColorPairs; +} + +// Generate light, dark, and print color schemes +const lightColors = generateColorScheme(baseColors, true, lightRatios); +const darkColors = generateColorScheme(baseColors, false, darkRatios); + +// ------------------------------------- +// 5. Utility to convert color objects into CSS variables +// ------------------------------------- +function generateColorVariables(colors) { + const variables = Object.entries(colors) + .map(([key, value]) => { + // Convert trailing digit to -digit, e.g. "red100" -> "red-100" + const modifiedKey = key.replace(/(\d+)$/, "-$1"); + return `--${modifiedKey}: ${value.replace("hsl(", "").replace(")", "")};`; + }) + .join("\n "); + + const backgroundAlias = "var(--gray-100)"; + const foregroundAlias = "var(--gray-900)"; + const additionalVariables = ` + --background: ${backgroundAlias}; + --foreground: ${foregroundAlias};`; + + return variables + additionalVariables; +} + +// ------------------------------------- +// 6. Generate final CSS (without prefers-color-scheme) +// ------------------------------------- +function generateThemeVariables(lightVars, darkVars) { + return ` + +:root { + ${lightVars} +} + + +@media (prefers-color-scheme: dark) { + :root { + ${darkVars} + } +} +`; +} + +function generateCssVariables() { + const lightVariables = generateColorVariables(lightColors); + const darkVariables = generateColorVariables(darkColors); + + return generateThemeVariables(lightVariables, darkVariables); +} + +// ------------------------------------- +// 7. Main logic to write to design-tokens.css +// ------------------------------------- +function main() { + const css = generateCssVariables(); + writeFileSync(join(__dirname, "..", "design-tokens.css"), css); + console.log("Design tokens saved to design-tokens.css"); +} + +// ------------------------------------- +// Run the script +// ------------------------------------- +main(); diff --git a/tailwind.config.ts b/tailwind.config.ts index 4662bd0d..b2239f41 100644 --- a/tailwind.config.ts +++ b/tailwind.config.ts @@ -1,5 +1,23 @@ /* eslint-disable @typescript-eslint/no-require-imports */ +import baseColors from "./src/baseColors.json" with { type: "json" }; + +const colors = {}; + +[ + ...Object.keys(baseColors).filter( + (key) => !["background", "foreground"].includes(key), + ), + "gray", +].forEach((colorName) => { + ["100", "200", "300", "400", "500", "600", "700", "800", "900"].forEach( + (shade) => { + const colorId = `${colorName}-${shade}`; + colors[colorId] = `hsl(var(--${colorId}))`; + }, + ); +}); + /** @type {import('tailwindcss').Config} */ export default { darkMode: ["class"], @@ -9,64 +27,92 @@ export default { "./node_modules/@shadcn/ui/components/**/*.{js,ts,jsx,tsx}", ], theme: { + colors: { + ...colors, + white: "hsl(var(--gray-100))", + black: "hsl(var(--gray-900))", + background: "hsl(var(--background))", + foreground: "hsl(var(--foreground))", + card: { + DEFAULT: "hsl(var(--gray-100))", + foreground: "hsl(var(--gray-900))", + }, + popover: { + DEFAULT: "hsl(var(--gray-200))", + foreground: "hsl(var(--gray-900))", + }, + primary: { + DEFAULT: "hsl(var(--blue-500))", + foreground: "hsl(var(--gray-900))", + }, + secondary: { + DEFAULT: "hsl(var(--gray-500))", + foreground: "hsl(var(--gray-900))", + }, + muted: { + DEFAULT: "hsl(var(--gray-200))", + foreground: "hsl(var(--gray-800))", + }, + accent: { + DEFAULT: "hsl(var(--blue-100))", + foreground: "hsl(var(--blue-900))", + }, + destructive: { + DEFAULT: "hsl(var(--red-100))", + foreground: "hsl(var(--red-900))", + }, + border: "hsl(var(--gray-700))", + input: "hsl(var(--gray-700))", + ring: "hsl(var(--blue-700))", + chart: { + "1": "hsl(var(--chart-1))", + "2": "hsl(var(--chart-2))", + "3": "hsl(var(--chart-3))", + "4": "hsl(var(--chart-4))", + "5": "hsl(var(--chart-5))", + }, + //sidebar: { + // DEFAULT: "hsl(var(--sidebar-background))", + // foreground: "hsl(var(--sidebar-foreground))", + // primary: "hsl(var(--sidebar-primary))", + // "primary-foreground": "hsl(var(--sidebar-primary-foreground))", + // accent: "hsl(var(--sidebar-accent))", + // "accent-foreground": "hsl(var(--sidebar-accent-foreground))", + // border: "hsl(var(--sidebar-border))", + // ring: "hsl(var(--sidebar-ring))", + //}, + }, extend: { + typography: () => ({ + DEFAULT: { + css: { + "--tw-prose-body": "var(--gray-900)", + "--tw-prose-headings": "var(--gray-900)", + "--tw-prose-lead": "var(--gray-600)", + "--tw-prose-links": "var(--gray-900)", + "--tw-prose-bold": "var(--gray-900)", + "--tw-prose-counters": "var(--gray-500)", + "--tw-prose-bullets": "var(--gray-300)", + "--tw-prose-hr": "var(--gray-200)", + "--tw-prose-quotes": "var(--gray-900)", + "--tw-prose-quote-borders": "var(--gray-200)", + "--tw-prose-captions": "var(--gray-500)", + "--tw-prose-code": "var(--gray-900)", + "--tw-prose-pre-code": "var(--gray-200)", + "--tw-prose-pre-bg": "var(--gray-800)", + "--tw-prose-th-borders": "var(--gray-300)", + "--tw-prose-td-borders": "var(--gray-200)", + "h1, h2, h3, h4, h5, h6": { + fontFamily: "var(--font-title)", + fontWeight: "600", + }, + }, + }, + }), boxShadow: { custom: "0px 0px 0px 1px #daedfd, 0px 4px 6px rgba(0, 0, 0, 0.1)", }, - colors: { - "teal-25": "#f5fbff", - "blue-200": "#daedfd", - background: "hsl(var(--background))", - foreground: "hsl(var(--foreground))", - card: { - DEFAULT: "hsl(var(--card))", - foreground: "hsl(var(--card-foreground))", - }, - popover: { - DEFAULT: "hsl(var(--popover))", - foreground: "hsl(var(--popover-foreground))", - }, - primary: { - DEFAULT: "hsl(var(--primary))", - foreground: "hsl(var(--primary-foreground))", - }, - secondary: { - DEFAULT: "hsl(var(--secondary))", - foreground: "hsl(var(--secondary-foreground))", - }, - muted: { - DEFAULT: "hsl(var(--muted))", - foreground: "hsl(var(--muted-foreground))", - }, - accent: { - DEFAULT: "hsl(var(--accent))", - foreground: "hsl(var(--accent-foreground))", - }, - destructive: { - DEFAULT: "hsl(var(--destructive))", - foreground: "hsl(var(--destructive-foreground))", - }, - border: "hsl(var(--border))", - input: "hsl(var(--input))", - ring: "hsl(var(--ring))", - chart: { - "1": "hsl(var(--chart-1))", - "2": "hsl(var(--chart-2))", - "3": "hsl(var(--chart-3))", - "4": "hsl(var(--chart-4))", - "5": "hsl(var(--chart-5))", - }, - sidebar: { - DEFAULT: "hsl(var(--sidebar-background))", - foreground: "hsl(var(--sidebar-foreground))", - primary: "hsl(var(--sidebar-primary))", - "primary-foreground": "hsl(var(--sidebar-primary-foreground))", - accent: "hsl(var(--sidebar-accent))", - "accent-foreground": "hsl(var(--sidebar-accent-foreground))", - border: "hsl(var(--sidebar-border))", - ring: "hsl(var(--sidebar-ring))", - }, - }, + fontFamily: { sans: ["Inter", "sans-serif"], },