Skip to content

Commit 6071993

Browse files
refactor: update color presets with new color definitions and improve structure
1 parent e3cab56 commit 6071993

File tree

2 files changed

+256
-69
lines changed

2 files changed

+256
-69
lines changed

src/lib/colors.ts

+93-24
Original file line numberDiff line numberDiff line change
@@ -3,39 +3,85 @@ export function generateHarmonizedColors(baseHue: number, isDarkMode: boolean =
33
const analogous1 = (baseHue + 30) % 360;
44
const analogous2 = (baseHue - 30 + 360) % 360;
55

6-
// Calculate harmonized saturations based on primary color
7-
const secondarySatLight = 15 + Math.random() * 20; // 15-35%
8-
const accentSatLight = 15 + Math.random() * 20; // 15-35%
9-
const mutedSatLight = 15 + Math.random() * 20; // 15-35%
10-
11-
const secondarySatDark = 75 + Math.random() * 20; // 75-95%
12-
const accentSatDark = 75 + Math.random() * 20; // 75-95%
13-
const mutedSatDark = 75 + Math.random() * 20; // 75-95%
14-
15-
// Random lightness values
16-
const lightModeLightness = 80 + Math.random() * 20; // 80-100%
17-
const darkModeLightness = Math.random() * 20; // 0-20%
18-
19-
// Generate light variants
6+
// Calculate harmonized saturations with randomization
7+
const primarySat = 60 + Math.random() * 20; // 60-80%
8+
const primaryLightLight = 40 + Math.random() * 40; // 40-90%
9+
const primaryDarkLight = 30 + Math.random() * 30; // 30-60%
10+
const primary = `${baseHue.toFixed(2)} ${primarySat.toFixed(2)}% ${primaryLightLight.toFixed(2)}%`;
11+
const primaryDark = `${baseHue.toFixed(2)} ${primarySat.toFixed(2)}% ${primaryDarkLight.toFixed(2)}%`;
12+
13+
// Secondary colors with dynamic saturation
14+
const secondarySatLight = Math.max(10, Math.random() * primarySat * 0.4); // 10-32%
15+
const secondarySatDark = Math.min(90, primarySat + Math.random() * 20); // primarySat-(primarySat+20)%
16+
17+
// Accent colors with slightly higher saturation
18+
const accentSatLight = Math.max(15, secondarySatLight * (1 + Math.random() * 0.5));
19+
const accentSatDark = Math.min(95, secondarySatDark * (1 + Math.random() * 0.3));
20+
21+
// Dynamic lightness values
22+
const lightModeLightness = 90 + Math.random() * 10; // 90-100%
23+
const darkModeLightness = Math.random() * 15; // 0-15%
24+
25+
// Generate light mode colors
2026
const secondaryLight = `${analogous1.toFixed(2)} ${secondarySatLight.toFixed(2)}% ${lightModeLightness.toFixed(2)}%`;
2127
const accentLight = `${analogous2.toFixed(2)} ${accentSatLight.toFixed(2)}% ${lightModeLightness.toFixed(2)}%`;
22-
const mutedLight = `${analogous2.toFixed(2)} ${mutedSatLight.toFixed(2)}% ${lightModeLightness.toFixed(2)}%`;
2328

24-
// Generate dark variants (same hue, different saturation and lightness)
29+
// Generate dark mode colors
2530
const secondaryDark = `${analogous1.toFixed(2)} ${secondarySatDark.toFixed(2)}% ${darkModeLightness.toFixed(2)}%`;
2631
const accentDark = `${analogous2.toFixed(2)} ${accentSatDark.toFixed(2)}% ${darkModeLightness.toFixed(2)}%`;
27-
const mutedDark = `${analogous2.toFixed(2)} ${mutedSatDark.toFixed(2)}% ${darkModeLightness.toFixed(2)}%`;
2832

29-
return {
30-
primary: generateRandomHSL("primary"),
33+
// Muted colors based on secondary
34+
const mutedSatLight = secondarySatLight * (0.5 + Math.random() * 0.3); // 50-80% of secondary saturation
35+
const mutedSatDark = secondarySatDark * (0.4 + Math.random() * 0.3); // 40-70% of secondary saturation
36+
const mutedLightLight = lightModeLightness * (0.9 + Math.random() * 0.1); // 90-100% of light mode lightness
37+
const mutedDarkLight = darkModeLightness * (1.2 + Math.random() * 0.3); // 120-150% of dark mode lightness
38+
39+
const mutedLight = `${analogous1.toFixed(2)} ${mutedSatLight.toFixed(2)}% ${mutedLightLight.toFixed(2)}%`;
40+
const mutedDark = `${analogous1.toFixed(2)} ${mutedSatDark.toFixed(2)}% ${mutedDarkLight.toFixed(2)}%`;
41+
42+
// Border and input colors based on secondary with reduced saturation
43+
const borderSatLight = secondarySatLight * (0.7 + Math.random() * 0.2);
44+
const borderSatDark = secondarySatDark * (0.6 + Math.random() * 0.2);
45+
const borderLight = `${analogous1.toFixed(2)} ${borderSatLight.toFixed(2)}% ${(lightModeLightness * 0.9).toFixed(2)}%`;
46+
const borderDark = `${analogous1.toFixed(2)} ${borderSatDark.toFixed(2)}% ${(darkModeLightness * 1.2).toFixed(2)}%`;
47+
48+
// Destructive color with random variation in the red range
49+
const destructiveHue = Math.random() * 10; // 0-10 (red range)
50+
const destructiveSat = 70 + Math.random() * 20; // 70-90%
51+
const destructiveLight = 45 + Math.random() * 25; // 45-70%
52+
const destructive = `${destructiveHue.toFixed(2)} ${destructiveSat.toFixed(2)}% ${destructiveLight.toFixed(2)}%`;
53+
54+
// Calculate foreground colors dynamically
55+
const colors: ColorConfig = {
56+
// Base colors
57+
primary,
58+
"primary-dark": primaryDark,
3159
secondary: secondaryLight,
3260
"secondary-dark": secondaryDark,
3361
accent: accentLight,
3462
"accent-dark": accentDark,
35-
destructive: generateRandomHSL("destructive"),
36-
muted: mutedDark,
37-
"muted-dark": "0 0% 0%"
63+
destructive,
64+
muted: mutedLight,
65+
"muted-dark": mutedDark,
66+
border: borderLight,
67+
"border-dark": borderDark,
68+
input: borderLight,
69+
"input-dark": borderDark,
70+
ring: primary,
71+
72+
// Foreground colors
73+
"primary-foreground": calculateForegroundColor(primary),
74+
"primary-dark-foreground": calculateForegroundColor(primary),
75+
"secondary-foreground": calculateForegroundColor(secondaryLight),
76+
"secondary-dark-foreground": calculateForegroundColor(secondaryLight),
77+
"accent-foreground": calculateForegroundColor(accentLight),
78+
"accent-dark-foreground": calculateForegroundColor(accentLight),
79+
"destructive-foreground": calculateForegroundColor(destructive),
80+
"muted-foreground": `${analogous1.toFixed(2)} ${(mutedSatLight * 1.5).toFixed(2)}% ${(lightModeLightness * 0.4).toFixed(2)}%`,
81+
"muted-dark-foreground": `${analogous1.toFixed(2)} ${(mutedSatDark * 1.2).toFixed(2)}% ${Math.min(98, mutedDarkLight * 4).toFixed(2)}%`
3882
};
83+
84+
return colors;
3985
}
4086

4187
export function generateRandomHSL(type: keyof ColorConfig = "primary"): string {
@@ -58,6 +104,8 @@ export function generateRandomColors(isDarkMode: boolean = false): ColorConfig {
58104
}
59105

60106
export function generateBackground(primary: string, isDarkMode: boolean): string {
107+
if (!primary) return isDarkMode ? "20 14.3% 4.1%" : "0 0% 100%";
108+
61109
const [h, s, l] = primary.split(" ").map(parseFloat);
62110
if (isNaN(h) || isNaN(s) || isNaN(l)) {
63111
return isDarkMode ? "20 14.3% 4.1%" : "0 0% 100%";
@@ -69,6 +117,8 @@ export function generateBackground(primary: string, isDarkMode: boolean): string
69117
}
70118

71119
export function generateCard(primary: string, isDarkMode: boolean): string {
120+
if (!primary) return isDarkMode ? "24 9.8% 10%" : "0 0% 100%";
121+
72122
const [h, s, l] = primary.split(" ").map(parseFloat);
73123
if (isNaN(h) || isNaN(s) || isNaN(l)) {
74124
return isDarkMode ? "24 9.8% 10%" : "0 0% 100%";
@@ -80,6 +130,8 @@ export function generateCard(primary: string, isDarkMode: boolean): string {
80130
}
81131

82132
export function generatePopover(primary: string, isDarkMode: boolean): string {
133+
if (!primary) return isDarkMode ? "0 0% 9%" : "0 0% 100%";
134+
83135
const [h, s, l] = primary.split(" ").map(parseFloat);
84136
if (isNaN(h) || isNaN(s) || isNaN(l)) {
85137
return isDarkMode ? "0 0% 9%" : "0 0% 100%";
@@ -91,21 +143,33 @@ export function generatePopover(primary: string, isDarkMode: boolean): string {
91143
}
92144

93145
export function generateBorder(primary: string, isDarkMode: boolean): string {
146+
if (!primary) return isDarkMode ? "240 3.7% 15.9%" : "240 5.9% 90%";
147+
94148
const [h, s] = primary.split(" ").map(parseFloat);
149+
if (isNaN(h) || isNaN(s)) {
150+
return isDarkMode ? "240 3.7% 15.9%" : "240 5.9% 90%";
151+
}
152+
95153
return isDarkMode
96154
? `${h} ${Math.max(s * 0.15, 3.7).toFixed(1)}% 15.9%`
97155
: `${h} ${Math.max(s * 0.15, 5.9).toFixed(1)}% 90%`;
98156
}
99157

100158
export function generateInput(primary: string, isDarkMode: boolean): string {
159+
if (!primary) return isDarkMode ? "240 3.7% 15.9%" : "240 5.9% 90%";
160+
101161
const [h, s] = primary.split(" ").map(parseFloat);
162+
if (isNaN(h) || isNaN(s)) {
163+
return isDarkMode ? "240 3.7% 15.9%" : "240 5.9% 90%";
164+
}
165+
102166
return isDarkMode
103167
? `${h} ${Math.max(s * 0.15, 3.7).toFixed(1)}% 15.9%`
104168
: `${h} ${Math.max(s * 0.15, 5.9).toFixed(1)}% 90%`;
105169
}
106170

107171
export function generateRing(primary: string): string {
108-
return primary;
172+
return primary || "346.8 77.2% 49.8%";
109173
}
110174

111175
export function hslToHex(h: number, s: number, l: number): string {
@@ -156,16 +220,21 @@ export function hexToHSL(hex: string): string {
156220
}
157221

158222
export function isValidDestructiveColor(hslString: string): boolean {
223+
if (!hslString) return false;
159224
const [h] = hslString.split(" ").map(v => parseFloat(v));
225+
if (isNaN(h)) return false;
160226
return (h >= 350 || h <= 10);
161227
}
162228

163229
export function calculateForegroundColor(hslString: string): string {
230+
if (!hslString) return "0 0% 100%";
164231
const [, , l] = hslString.split(" ").map(v => parseFloat(v));
165-
return l > 60 ? "240 10% 3.9%" : "0 0% 98%";
232+
return l > 52 ? "240 10% 3.9%" : "0 0% 98%";
166233
}
167234

168235
export function parseHSLString(input: string): string | null {
236+
if (!input) return null;
237+
169238
const cleaned = input.toLowerCase().replace(/\s+/g, '');
170239
const match = cleaned.match(/^(\d{1,3})[,\s](\d{1,3})%[,\s](\d{1,3})%$/);
171240

0 commit comments

Comments
 (0)