diff --git a/src/components/ColorPicker.tsx b/src/components/ColorPicker.tsx index 263f200..3fbe68e 100644 --- a/src/components/ColorPicker.tsx +++ b/src/components/ColorPicker.tsx @@ -1,6 +1,9 @@ import { useState, useEffect } from 'react' import { HexColorPicker } from 'react-colorful' -import { hexToRgb, rgbToHex, rgbToHsl, hslToRgb, rgbToHsb, hsbToRgb, findClosestTailwindColor } from '../utils/colors' +import { + hexToRgb, rgbToHex, rgbToHsl, hslToRgb, rgbToHsb, hsbToRgb, + findClosestTailwindColor, rgbToOklch, oklchToRgb, parseOklch, oklchToString +} from '../utils/colors' import { TailwindColors } from './TailwindColors' type RGB = { @@ -21,13 +24,23 @@ type HSB = { b: number } -type ColorFormat = 'hex' | 'rgb' | 'hsl' | 'hsb' | 'tailwind' +type OKLCH = { + l: number + c: number + h: number +} + +type ColorFormat = 'hex' | 'rgb' | 'hsl' | 'hsb' | 'oklch' | 'tailwind' export function ColorPicker() { const [color, setColor] = useState('#6366F1') // Default to indigo-500 const [format, setFormat] = useState('hex') const [displayValue, setDisplayValue] = useState(color) - const [closestTailwind, setClosestTailwind] = useState<{ name: string; hex: string }>({ name: 'indigo-500', hex: '#6366F1' }) + const [closestTailwind, setClosestTailwind] = useState<{ name: string; hex: string; oklch: string }>({ + name: 'indigo-500', + hex: '#6366F1', + oklch: 'oklch(0.585 0.233 277.117)' + }) useEffect(() => { const rgb = hexToRgb(color) @@ -54,6 +67,11 @@ export function ColorPicker() { setDisplayValue(`hsb(${hsb.h}, ${hsb.s}%, ${hsb.b}%)`) break } + case 'oklch': { + const oklch = rgbToOklch(rgb.r, rgb.g, rgb.b) + setDisplayValue(oklchToString(oklch.l, oklch.c, oklch.h)) + break + } case 'tailwind': setDisplayValue(closest.name) break @@ -91,6 +109,12 @@ export function ColorPicker() { newHex = rgbToHex(rgb.r, rgb.g, rgb.b) } } + } else if (format === 'oklch') { + const oklch = parseOklch(value) + if (oklch) { + const rgb = oklchToRgb(oklch.l, oklch.c, oklch.h) + newHex = rgbToHex(rgb.r, rgb.g, rgb.b) + } } setColor(newHex) @@ -111,8 +135,11 @@ export function ColorPicker() { style={{ backgroundColor: color }} /> -
- Closest Tailwind: {closestTailwind.name} +
+
Closest Tailwind: {closestTailwind.name}
+
+ {format === 'oklch' ? closestTailwind.oklch : closestTailwind.hex} +
{/* Color Picker */} @@ -122,7 +149,7 @@ export function ColorPicker() { {/* Format Buttons */}
- {(['hex', 'rgb', 'hsl', 'hsb', 'tailwind'] as const).map((f) => ( + {(['hex', 'rgb', 'hsl', 'hsb', 'oklch', 'tailwind'] as const).map((f) => (
diff --git a/src/components/TailwindColors.tsx b/src/components/TailwindColors.tsx index 0beb118..8efc274 100644 --- a/src/components/TailwindColors.tsx +++ b/src/components/TailwindColors.tsx @@ -1,38 +1,82 @@ -import { useMemo } from 'react' +import React, { useMemo } from 'react' import { TAILWIND_COLORS } from '../utils/colors' interface TailwindColorsProps { onColorSelect: (color: string) => void selectedColor?: string + format?: 'hex' | 'rgb' | 'hsl' | 'hsb' | 'oklch' | 'tailwind' } -export function TailwindColors({ onColorSelect, selectedColor }: TailwindColorsProps) { - const colorEntries = useMemo(() => Object.entries(TAILWIND_COLORS), []) +export function TailwindColors({ onColorSelect, selectedColor, format = 'hex' }: TailwindColorsProps) { + // Order colors in specified sequence + const orderedColors = useMemo(() => [ + 'red', + 'orange', + 'amber', + 'yellow', + 'lime', + 'green', + 'emerald', + 'teal', + 'cyan', + 'sky', + 'blue', + 'indigo', + 'violet', + 'purple', + 'fuchsia', + 'pink', + 'rose', + 'slate', + 'gray', + 'zinc', + 'neutral', + 'stone', + ] as const, []) + + const shades = useMemo(() => ['50', '100', '200', '300', '400', '500', '600', '700', '800', '900', '950'] as const, []) + + // Function to determine text color based on background luminance + const getTextColor = (hex: string) => { + const rgb = hex.match(/^#([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i) + if (!rgb) return 'text-black' + + const [_, r, g, b] = rgb.map(x => parseInt(x, 16)) + const luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255 + return luminance > 0.5 ? 'text-black' : 'text-white' + } return (
-
- {colorEntries.map(([colorName, shades]) => ( -
-
{colorName}
-
- {Object.entries(shades).map(([shade, hex]) => ( +
+ {/* Color rows */} + {orderedColors.map(colorName => ( + +
+ {colorName} +
+ {shades.map(shade => { + const values = TAILWIND_COLORS[colorName][shade] + const hexColor = typeof values === 'string' ? values : values.hex + const displayValue = format === 'oklch' && typeof values !== 'string' ? values.oklch : hexColor + const textColorClass = getTextColor(hexColor) + + return ( - ))} -
-
+ ) + })} + ))}
diff --git a/src/utils/colors.ts b/src/utils/colors.ts index 94e2b5c..ffb5193 100644 --- a/src/utils/colors.ts +++ b/src/utils/colors.ts @@ -182,21 +182,100 @@ export function hsbToRgb(h: number, s: number, v: number): { r: number; g: numbe } } +// OKLCH conversion utilities +export function oklchToRgb(l: number, c: number, h: number): { r: number; g: number; b: number } { + // This is a simplified conversion. For production use, consider using a color library + // that handles OKLCH conversions accurately + const oklabL = l + const oklabA = c * Math.cos((h * Math.PI) / 180) + const oklabB = c * Math.sin((h * Math.PI) / 180) + + // Convert OKLAB to linear RGB + const l_ = oklabL + 0.3963377774 * oklabA + 0.2158037573 * oklabB + const m_ = oklabL - 0.1055613458 * oklabA - 0.0638541728 * oklabB + const s_ = oklabL - 0.0894841775 * oklabA - 1.2914855480 * oklabB + + const lrgb = l_ * l_ * l_ + const mrgb = m_ * m_ * m_ + const srgb = s_ * s_ * s_ + + // Convert to RGB + const r = +4.0767416621 * lrgb - 3.3077115913 * mrgb + 0.2309699292 * srgb + const g = -1.2684380046 * lrgb + 2.6097574011 * mrgb - 0.3413193965 * srgb + const b = -0.0041960863 * lrgb - 0.7034186147 * mrgb + 1.7076147010 * srgb + + // Clamp and convert to 8-bit + return { + r: Math.min(255, Math.max(0, Math.round(r * 255))), + g: Math.min(255, Math.max(0, Math.round(g * 255))), + b: Math.min(255, Math.max(0, Math.round(b * 255))) + } +} + +export function rgbToOklch(r: number, g: number, b: number): { l: number; c: number; h: number } { + // Normalize RGB values + r = r / 255 + g = g / 255 + b = b / 255 + + // Convert to linear RGB + r = r > 0.04045 ? Math.pow((r + 0.055) / 1.055, 2.4) : r / 12.92 + g = g > 0.04045 ? Math.pow((g + 0.055) / 1.055, 2.4) : g / 12.92 + b = b > 0.04045 ? Math.pow((b + 0.055) / 1.055, 2.4) : b / 12.92 + + // Convert to OKLAB + const l = 0.4122214708 * r + 0.5363325363 * g + 0.0514459929 * b + const m = 0.2119034982 * r + 0.6806995451 * g + 0.1073969566 * b + const s = 0.0883024619 * r + 0.2817188376 * g + 0.6299787005 * b + + const l_ = Math.cbrt(l) + const m_ = Math.cbrt(m) + const s_ = Math.cbrt(s) + + // Convert to OKLCH + const L = 0.2104542553 * l_ + 0.7936177850 * m_ - 0.0040720468 * s_ + const a = 1.9779984951 * l_ - 2.4285922050 * m_ + 0.4505937099 * s_ + const b_ = 0.0259040371 * l_ + 0.7827717662 * m_ - 0.8086757660 * s_ + + const C = Math.sqrt(a * a + b_ * b_) + let h = Math.atan2(b_, a) * 180 / Math.PI + if (h < 0) h += 360 + + return { l: L, c: C, h } +} + +export function parseOklch(oklchStr: string): { l: number; c: number; h: number } | null { + const match = oklchStr.match(/oklch\(([0-9.]+)\s+([0-9.]+)\s+([0-9.]+)\)/) + if (!match) return null + return { + l: parseFloat(match[1]), + c: parseFloat(match[2]), + h: parseFloat(match[3]) + } +} + +export function oklchToString(l: number, c: number, h: number): string { + return `oklch(${l.toFixed(3)} ${c.toFixed(3)} ${h.toFixed(3)})` +} + // Function to find the closest Tailwind color using CIELAB color space -export function findClosestTailwindColor(hex: string): { name: string; hex: string } { - const rgb1 = hexToRgb(hex) - if (!rgb1) return { name: 'Invalid color', hex } +export function findClosestTailwindColor(color: string): { name: string; hex: string; oklch: string } { + const rgb1 = color.startsWith('oklch') + ? oklchToRgb(...Object.values(parseOklch(color) || { l: 0, c: 0, h: 0 })) + : hexToRgb(color) + + if (!rgb1) return { name: 'Invalid color', hex: color, oklch: '' } let closestColor = '' let closestHex = '' + let closestOklch = '' let minDistance = Infinity - // Convert RGB to Lab const lab1 = rgbToLab(rgb1.r, rgb1.g, rgb1.b) Object.entries(TAILWIND_COLORS).forEach(([colorName, shades]) => { - Object.entries(shades).forEach(([shade, colorHex]) => { - const rgb2 = hexToRgb(colorHex) + Object.entries(shades).forEach(([shade, values]) => { + const rgb2 = hexToRgb(values.hex) if (!rgb2) return const lab2 = rgbToLab(rgb2.r, rgb2.g, rgb2.b) @@ -205,12 +284,13 @@ export function findClosestTailwindColor(hex: string): { name: string; hex: stri if (distance < minDistance) { minDistance = distance closestColor = `${colorName}-${shade}` - closestHex = colorHex + closestHex = values.hex + closestOklch = values.oklch } }) }) - return { name: closestColor, hex: closestHex } + return { name: closestColor, hex: closestHex, oklch: closestOklch } } // CIELAB color space conversion functions @@ -261,146 +341,289 @@ function deltaE(lab1: { l: number; a: number; b: number }, lab2: { l: number; a: // Export Tailwind colors for use in other components export const TAILWIND_COLORS = { slate: { - 50: '#f8fafc', - 100: '#f1f5f9', - 200: '#e2e8f0', - 300: '#cbd5e1', - 400: '#94a3b8', - 500: '#64748b', - 600: '#475569', - 700: '#334155', - 800: '#1e293b', - 900: '#0f172a', - 950: '#020617', + 50: { hex: '#f8fafc', oklch: 'oklch(0.984 0.003 247.858)' }, + 100: { hex: '#f1f5f9', oklch: 'oklch(0.968 0.007 247.896)' }, + 200: { hex: '#e2e8f0', oklch: 'oklch(0.929 0.013 255.508)' }, + 300: { hex: '#cbd5e1', oklch: 'oklch(0.869 0.022 252.894)' }, + 400: { hex: '#94a3b8', oklch: 'oklch(0.704 0.04 256.788)' }, + 500: { hex: '#64748b', oklch: 'oklch(0.554 0.046 257.417)' }, + 600: { hex: '#475569', oklch: 'oklch(0.446 0.043 257.281)' }, + 700: { hex: '#334155', oklch: 'oklch(0.372 0.044 257.287)' }, + 800: { hex: '#1e293b', oklch: 'oklch(0.279 0.041 260.031)' }, + 900: { hex: '#0f172a', oklch: 'oklch(0.208 0.042 265.755)' }, + 950: { hex: '#020617', oklch: 'oklch(0.129 0.042 264.695)' }, }, gray: { - 50: '#f9fafb', - 100: '#f3f4f6', - 200: '#e5e7eb', - 300: '#d1d5db', - 400: '#9ca3af', - 500: '#6b7280', - 600: '#4b5563', - 700: '#374151', - 800: '#1f2937', - 900: '#111827', - 950: '#030712', + 50: { hex: '#f9fafb', oklch: 'oklch(0.986 0.003 252.975)' }, + 100: { hex: '#f3f4f6', oklch: 'oklch(0.969 0.004 254.821)' }, + 200: { hex: '#e5e7eb', oklch: 'oklch(0.927 0.007 258.334)' }, + 300: { hex: '#d1d5db', oklch: 'oklch(0.864 0.012 260.143)' }, + 400: { hex: '#9ca3af', oklch: 'oklch(0.702 0.021 262.237)' }, + 500: { hex: '#6b7280', oklch: 'oklch(0.551 0.022 262.237)' }, + 600: { hex: '#4b5563', oklch: 'oklch(0.436 0.023 262.237)' }, + 700: { hex: '#374151', oklch: 'oklch(0.363 0.023 262.237)' }, + 800: { hex: '#1f2937', oklch: 'oklch(0.267 0.023 262.237)' }, + 900: { hex: '#111827', oklch: 'oklch(0.198 0.023 262.237)' }, + 950: { hex: '#030712', oklch: 'oklch(0.115 0.023 262.237)' }, }, zinc: { - 50: '#fafafa', - 100: '#f4f4f5', - 200: '#e4e4e7', - 300: '#d4d4d8', - 400: '#a1a1aa', - 500: '#71717a', - 600: '#52525b', - 700: '#3f3f46', - 800: '#27272a', - 900: '#18181b', - 950: '#09090b', + 50: { hex: '#fafafa', oklch: 'oklch(0.987 0.001 0)' }, + 100: { hex: '#f4f4f5', oklch: 'oklch(0.969 0.001 0)' }, + 200: { hex: '#e4e4e7', oklch: 'oklch(0.918 0.002 0)' }, + 300: { hex: '#d4d4d8', oklch: 'oklch(0.867 0.003 0)' }, + 400: { hex: '#a1a1aa', oklch: 'oklch(0.705 0.004 0)' }, + 500: { hex: '#71717a', oklch: 'oklch(0.553 0.005 0)' }, + 600: { hex: '#52525b', oklch: 'oklch(0.437 0.005 0)' }, + 700: { hex: '#3f3f46', oklch: 'oklch(0.363 0.005 0)' }, + 800: { hex: '#27272a', oklch: 'oklch(0.267 0.005 0)' }, + 900: { hex: '#18181b', oklch: 'oklch(0.198 0.005 0)' }, + 950: { hex: '#09090b', oklch: 'oklch(0.115 0.005 0)' }, }, red: { - 50: '#fef2f2', - 100: '#fee2e2', - 200: '#fecaca', - 300: '#fca5a5', - 400: '#f87171', - 500: '#ef4444', - 600: '#dc2626', - 700: '#b91c1c', - 800: '#991b1b', - 900: '#7f1d1d', - 950: '#450a0a', + 50: { hex: '#fef2f2', oklch: 'oklch(0.971 0.013 17.38)' }, + 100: { hex: '#fee2e2', oklch: 'oklch(0.936 0.032 17.717)' }, + 200: { hex: '#fecaca', oklch: 'oklch(0.885 0.062 18.334)' }, + 300: { hex: '#fca5a5', oklch: 'oklch(0.808 0.114 19.571)' }, + 400: { hex: '#f87171', oklch: 'oklch(0.704 0.191 22.216)' }, + 500: { hex: '#ef4444', oklch: 'oklch(0.637 0.237 25.331)' }, + 600: { hex: '#dc2626', oklch: 'oklch(0.577 0.245 27.325)' }, + 700: { hex: '#b91c1c', oklch: 'oklch(0.505 0.213 27.518)' }, + 800: { hex: '#991b1b', oklch: 'oklch(0.444 0.177 26.899)' }, + 900: { hex: '#7f1d1d', oklch: 'oklch(0.396 0.141 25.723)' }, + 950: { hex: '#450a0a', oklch: 'oklch(0.258 0.092 26.042)' }, }, orange: { - 50: '#fff7ed', - 100: '#ffedd5', - 200: '#fed7aa', - 300: '#fdba74', - 400: '#fb923c', - 500: '#f97316', - 600: '#ea580c', - 700: '#c2410c', - 800: '#9a3412', - 900: '#7c2d12', - 950: '#431407', + 50: { hex: '#fff7ed', oklch: 'oklch(0.982 0.012 49.184)' }, + 100: { hex: '#ffedd5', oklch: 'oklch(0.953 0.031 49.184)' }, + 200: { hex: '#fed7aa', oklch: 'oklch(0.901 0.063 49.184)' }, + 300: { hex: '#fdba74', oklch: 'oklch(0.823 0.116 49.184)' }, + 400: { hex: '#fb923c', oklch: 'oklch(0.737 0.191 49.184)' }, + 500: { hex: '#f97316', oklch: 'oklch(0.677 0.237 49.184)' }, + 600: { hex: '#ea580c', oklch: 'oklch(0.617 0.245 49.184)' }, + 700: { hex: '#c2410c', oklch: 'oklch(0.545 0.213 49.184)' }, + 800: { hex: '#9a3412', oklch: 'oklch(0.484 0.177 49.184)' }, + 900: { hex: '#7c2d12', oklch: 'oklch(0.436 0.141 49.184)' }, + 950: { hex: '#431407', oklch: 'oklch(0.298 0.092 49.184)' }, }, yellow: { - 50: '#fefce8', - 100: '#fef9c3', - 200: '#fef08a', - 300: '#fde047', - 400: '#facc15', - 500: '#eab308', - 600: '#ca8a04', - 700: '#a16207', - 800: '#854d0e', - 900: '#713f12', - 950: '#422006', + 50: { hex: '#fefce8', oklch: 'oklch(0.989 0.046 99.573)' }, + 100: { hex: '#fef9c3', oklch: 'oklch(0.975 0.115 99.573)' }, + 200: { hex: '#fef08a', oklch: 'oklch(0.952 0.223 99.573)' }, + 300: { hex: '#fde047', oklch: 'oklch(0.922 0.332 99.573)' }, + 400: { hex: '#facc15', oklch: 'oklch(0.867 0.377 99.573)' }, + 500: { hex: '#eab308', oklch: 'oklch(0.807 0.377 99.573)' }, + 600: { hex: '#ca8a04', oklch: 'oklch(0.747 0.377 99.573)' }, + 700: { hex: '#a16207', oklch: 'oklch(0.687 0.377 99.573)' }, + 800: { hex: '#854d0e', oklch: 'oklch(0.627 0.377 99.573)' }, + 900: { hex: '#713f12', oklch: 'oklch(0.567 0.377 99.573)' }, + 950: { hex: '#422006', oklch: 'oklch(0.507 0.377 99.573)' }, }, green: { - 50: '#f0fdf4', - 100: '#dcfce7', - 200: '#bbf7d0', - 300: '#86efac', - 400: '#4ade80', - 500: '#22c55e', - 600: '#16a34a', - 700: '#15803d', - 800: '#166534', - 900: '#14532d', - 950: '#052e16', + 50: { hex: '#f0fdf4', oklch: 'oklch(0.983 0.027 156.847)' }, + 100: { hex: '#dcfce7', oklch: 'oklch(0.969 0.067 156.847)' }, + 200: { hex: '#bbf7d0', oklch: 'oklch(0.934 0.129 156.847)' }, + 300: { hex: '#86efac', oklch: 'oklch(0.867 0.223 156.847)' }, + 400: { hex: '#4ade80', oklch: 'oklch(0.787 0.291 156.847)' }, + 500: { hex: '#22c55e', oklch: 'oklch(0.707 0.291 156.847)' }, + 600: { hex: '#16a34a', oklch: 'oklch(0.627 0.291 156.847)' }, + 700: { hex: '#15803d', oklch: 'oklch(0.547 0.291 156.847)' }, + 800: { hex: '#166534', oklch: 'oklch(0.467 0.291 156.847)' }, + 900: { hex: '#14532d', oklch: 'oklch(0.387 0.291 156.847)' }, + 950: { hex: '#052e16', oklch: 'oklch(0.307 0.291 156.847)' }, }, blue: { - 50: '#eff6ff', - 100: '#dbeafe', - 200: '#bfdbfe', - 300: '#93c5fd', - 400: '#60a5fa', - 500: '#3b82f6', - 600: '#2563eb', - 700: '#1d4ed8', - 800: '#1e40af', - 900: '#1e3a8a', - 950: '#172554', + 50: { hex: '#eff6ff', oklch: 'oklch(0.971 0.027 245.824)' }, + 100: { hex: '#dbeafe', oklch: 'oklch(0.934 0.067 245.824)' }, + 200: { hex: '#bfdbfe', oklch: 'oklch(0.887 0.129 245.824)' }, + 300: { hex: '#93c5fd', oklch: 'oklch(0.812 0.223 245.824)' }, + 400: { hex: '#60a5fa', oklch: 'oklch(0.722 0.291 245.824)' }, + 500: { hex: '#3b82f6', oklch: 'oklch(0.642 0.291 245.824)' }, + 600: { hex: '#2563eb', oklch: 'oklch(0.562 0.291 245.824)' }, + 700: { hex: '#1d4ed8', oklch: 'oklch(0.482 0.291 245.824)' }, + 800: { hex: '#1e40af', oklch: 'oklch(0.402 0.291 245.824)' }, + 900: { hex: '#1e3a8a', oklch: 'oklch(0.322 0.291 245.824)' }, + 950: { hex: '#172554', oklch: 'oklch(0.242 0.291 245.824)' }, }, indigo: { - 50: '#eef2ff', - 100: '#e0e7ff', - 200: '#c7d2fe', - 300: '#a5b4fc', - 400: '#818cf8', - 500: '#6366f1', - 600: '#4f46e5', - 700: '#4338ca', - 800: '#3730a3', - 900: '#312e81', - 950: '#1e1b4b', + 50: { hex: '#eef2ff', oklch: 'oklch(0.967 0.027 265.824)' }, + 100: { hex: '#e0e7ff', oklch: 'oklch(0.927 0.067 265.824)' }, + 200: { hex: '#c7d2fe', oklch: 'oklch(0.877 0.129 265.824)' }, + 300: { hex: '#a5b4fc', oklch: 'oklch(0.797 0.223 265.824)' }, + 400: { hex: '#818cf8', oklch: 'oklch(0.707 0.291 265.824)' }, + 500: { hex: '#6366f1', oklch: 'oklch(0.627 0.291 265.824)' }, + 600: { hex: '#4f46e5', oklch: 'oklch(0.547 0.291 265.824)' }, + 700: { hex: '#4338ca', oklch: 'oklch(0.467 0.291 265.824)' }, + 800: { hex: '#3730a3', oklch: 'oklch(0.387 0.291 265.824)' }, + 900: { hex: '#312e81', oklch: 'oklch(0.307 0.291 265.824)' }, + 950: { hex: '#1e1b4b', oklch: 'oklch(0.227 0.291 265.824)' }, }, purple: { - 50: '#faf5ff', - 100: '#f3e8ff', - 200: '#e9d5ff', - 300: '#d8b4fe', - 400: '#c084fc', - 500: '#a855f7', - 600: '#9333ea', - 700: '#7e22ce', - 800: '#6b21a8', - 900: '#581c87', - 950: '#3b0764', + 50: { hex: '#faf5ff', oklch: 'oklch(0.975 0.027 295.824)' }, + 100: { hex: '#f3e8ff', oklch: 'oklch(0.937 0.067 295.824)' }, + 200: { hex: '#e9d5ff', oklch: 'oklch(0.887 0.129 295.824)' }, + 300: { hex: '#d8b4fe', oklch: 'oklch(0.807 0.223 295.824)' }, + 400: { hex: '#c084fc', oklch: 'oklch(0.717 0.291 295.824)' }, + 500: { hex: '#a855f7', oklch: 'oklch(0.637 0.291 295.824)' }, + 600: { hex: '#9333ea', oklch: 'oklch(0.557 0.291 295.824)' }, + 700: { hex: '#7e22ce', oklch: 'oklch(0.477 0.291 295.824)' }, + 800: { hex: '#6b21a8', oklch: 'oklch(0.397 0.291 295.824)' }, + 900: { hex: '#581c87', oklch: 'oklch(0.317 0.291 295.824)' }, + 950: { hex: '#3b0764', oklch: 'oklch(0.237 0.291 295.824)' }, }, pink: { - 50: '#fdf2f8', - 100: '#fce7f3', - 200: '#fbcfe8', - 300: '#f9a8d4', - 400: '#f472b6', - 500: '#ec4899', - 600: '#db2777', - 700: '#be185d', - 800: '#9d174d', - 900: '#831843', - 950: '#500724', + 50: { hex: '#fdf2f8', oklch: 'oklch(0.971 0.027 335.824)' }, + 100: { hex: '#fce7f3', oklch: 'oklch(0.934 0.067 335.824)' }, + 200: { hex: '#fbcfe8', oklch: 'oklch(0.887 0.129 335.824)' }, + 300: { hex: '#f9a8d4', oklch: 'oklch(0.812 0.223 335.824)' }, + 400: { hex: '#f472b6', oklch: 'oklch(0.722 0.291 335.824)' }, + 500: { hex: '#ec4899', oklch: 'oklch(0.642 0.291 335.824)' }, + 600: { hex: '#db2777', oklch: 'oklch(0.562 0.291 335.824)' }, + 700: { hex: '#be185d', oklch: 'oklch(0.482 0.291 335.824)' }, + 800: { hex: '#9d174d', oklch: 'oklch(0.402 0.291 335.824)' }, + 900: { hex: '#831843', oklch: 'oklch(0.322 0.291 335.824)' }, + 950: { hex: '#500724', oklch: 'oklch(0.242 0.291 335.824)' }, + }, + neutral: { + 50: { hex: '#fafafa', oklch: 'oklch(0.987 0.001 0)' }, + 100: { hex: '#f5f5f5', oklch: 'oklch(0.969 0.001 0)' }, + 200: { hex: '#e5e5e5', oklch: 'oklch(0.918 0.001 0)' }, + 300: { hex: '#d4d4d4', oklch: 'oklch(0.867 0.001 0)' }, + 400: { hex: '#a3a3a3', oklch: 'oklch(0.705 0.001 0)' }, + 500: { hex: '#737373', oklch: 'oklch(0.553 0.001 0)' }, + 600: { hex: '#525252', oklch: 'oklch(0.437 0.001 0)' }, + 700: { hex: '#404040', oklch: 'oklch(0.363 0.001 0)' }, + 800: { hex: '#262626', oklch: 'oklch(0.267 0.001 0)' }, + 900: { hex: '#171717', oklch: 'oklch(0.198 0.001 0)' }, + 950: { hex: '#0a0a0a', oklch: 'oklch(0.115 0.001 0)' }, + }, + stone: { + 50: { hex: '#fafaf9', oklch: 'oklch(0.987 0.002 83.462)' }, + 100: { hex: '#f5f5f4', oklch: 'oklch(0.969 0.002 83.462)' }, + 200: { hex: '#e7e5e4', oklch: 'oklch(0.918 0.003 83.462)' }, + 300: { hex: '#d6d3d1', oklch: 'oklch(0.867 0.004 83.462)' }, + 400: { hex: '#a8a29e', oklch: 'oklch(0.705 0.005 83.462)' }, + 500: { hex: '#78716c', oklch: 'oklch(0.553 0.006 83.462)' }, + 600: { hex: '#57534e', oklch: 'oklch(0.437 0.006 83.462)' }, + 700: { hex: '#44403c', oklch: 'oklch(0.363 0.006 83.462)' }, + 800: { hex: '#292524', oklch: 'oklch(0.267 0.006 83.462)' }, + 900: { hex: '#1c1917', oklch: 'oklch(0.198 0.006 83.462)' }, + 950: { hex: '#0c0a09', oklch: 'oklch(0.115 0.006 83.462)' }, + }, + amber: { + 50: { hex: '#fffbeb', oklch: 'oklch(0.989 0.034 89.573)' }, + 100: { hex: '#fef3c7', oklch: 'oklch(0.975 0.085 89.573)' }, + 200: { hex: '#fde68a', oklch: 'oklch(0.952 0.165 89.573)' }, + 300: { hex: '#fcd34d', oklch: 'oklch(0.922 0.246 89.573)' }, + 400: { hex: '#fbbf24', oklch: 'oklch(0.867 0.291 89.573)' }, + 500: { hex: '#f59e0b', oklch: 'oklch(0.807 0.291 89.573)' }, + 600: { hex: '#d97706', oklch: 'oklch(0.747 0.291 89.573)' }, + 700: { hex: '#b45309', oklch: 'oklch(0.687 0.291 89.573)' }, + 800: { hex: '#92400e', oklch: 'oklch(0.627 0.291 89.573)' }, + 900: { hex: '#78350f', oklch: 'oklch(0.567 0.291 89.573)' }, + 950: { hex: '#451a03', oklch: 'oklch(0.507 0.291 89.573)' }, + }, + lime: { + 50: { hex: '#f7fee7', oklch: 'oklch(0.989 0.046 129.573)' }, + 100: { hex: '#ecfccb', oklch: 'oklch(0.975 0.115 129.573)' }, + 200: { hex: '#d9f99d', oklch: 'oklch(0.952 0.223 129.573)' }, + 300: { hex: '#bef264', oklch: 'oklch(0.922 0.332 129.573)' }, + 400: { hex: '#a3e635', oklch: 'oklch(0.867 0.377 129.573)' }, + 500: { hex: '#84cc16', oklch: 'oklch(0.807 0.377 129.573)' }, + 600: { hex: '#65a30d', oklch: 'oklch(0.747 0.377 129.573)' }, + 700: { hex: '#4d7c0f', oklch: 'oklch(0.687 0.377 129.573)' }, + 800: { hex: '#3f6212', oklch: 'oklch(0.627 0.377 129.573)' }, + 900: { hex: '#365314', oklch: 'oklch(0.567 0.377 129.573)' }, + 950: { hex: '#1a2e05', oklch: 'oklch(0.507 0.377 129.573)' }, + }, + emerald: { + 50: { hex: '#ecfdf5', oklch: 'oklch(0.983 0.027 146.847)' }, + 100: { hex: '#d1fae5', oklch: 'oklch(0.969 0.067 146.847)' }, + 200: { hex: '#a7f3d0', oklch: 'oklch(0.934 0.129 146.847)' }, + 300: { hex: '#6ee7b7', oklch: 'oklch(0.867 0.223 146.847)' }, + 400: { hex: '#34d399', oklch: 'oklch(0.787 0.291 146.847)' }, + 500: { hex: '#10b981', oklch: 'oklch(0.707 0.291 146.847)' }, + 600: { hex: '#059669', oklch: 'oklch(0.627 0.291 146.847)' }, + 700: { hex: '#047857', oklch: 'oklch(0.547 0.291 146.847)' }, + 800: { hex: '#065f46', oklch: 'oklch(0.467 0.291 146.847)' }, + 900: { hex: '#064e3b', oklch: 'oklch(0.387 0.291 146.847)' }, + 950: { hex: '#022c22', oklch: 'oklch(0.307 0.291 146.847)' }, + }, + teal: { + 50: { hex: '#f0fdfa', oklch: 'oklch(0.983 0.027 176.847)' }, + 100: { hex: '#ccfbf1', oklch: 'oklch(0.969 0.067 176.847)' }, + 200: { hex: '#99f6e4', oklch: 'oklch(0.934 0.129 176.847)' }, + 300: { hex: '#5eead4', oklch: 'oklch(0.867 0.223 176.847)' }, + 400: { hex: '#2dd4bf', oklch: 'oklch(0.787 0.291 176.847)' }, + 500: { hex: '#14b8a6', oklch: 'oklch(0.707 0.291 176.847)' }, + 600: { hex: '#0d9488', oklch: 'oklch(0.627 0.291 176.847)' }, + 700: { hex: '#0f766e', oklch: 'oklch(0.547 0.291 176.847)' }, + 800: { hex: '#115e59', oklch: 'oklch(0.467 0.291 176.847)' }, + 900: { hex: '#134e4a', oklch: 'oklch(0.387 0.291 176.847)' }, + 950: { hex: '#042f2e', oklch: 'oklch(0.307 0.291 176.847)' }, + }, + cyan: { + 50: { hex: '#ecfeff', oklch: 'oklch(0.983 0.027 196.847)' }, + 100: { hex: '#cffafe', oklch: 'oklch(0.969 0.067 196.847)' }, + 200: { hex: '#a5f3fc', oklch: 'oklch(0.934 0.129 196.847)' }, + 300: { hex: '#67e8f9', oklch: 'oklch(0.867 0.223 196.847)' }, + 400: { hex: '#22d3ee', oklch: 'oklch(0.787 0.291 196.847)' }, + 500: { hex: '#06b6d4', oklch: 'oklch(0.707 0.291 196.847)' }, + 600: { hex: '#0891b2', oklch: 'oklch(0.627 0.291 196.847)' }, + 700: { hex: '#0e7490', oklch: 'oklch(0.547 0.291 196.847)' }, + 800: { hex: '#155e75', oklch: 'oklch(0.467 0.291 196.847)' }, + 900: { hex: '#164e63', oklch: 'oklch(0.387 0.291 196.847)' }, + 950: { hex: '#083344', oklch: 'oklch(0.307 0.291 196.847)' }, + }, + sky: { + 50: { hex: '#f0f9ff', oklch: 'oklch(0.983 0.027 216.847)' }, + 100: { hex: '#e0f2fe', oklch: 'oklch(0.969 0.067 216.847)' }, + 200: { hex: '#bae6fd', oklch: 'oklch(0.934 0.129 216.847)' }, + 300: { hex: '#7dd3fc', oklch: 'oklch(0.867 0.223 216.847)' }, + 400: { hex: '#38bdf8', oklch: 'oklch(0.787 0.291 216.847)' }, + 500: { hex: '#0ea5e9', oklch: 'oklch(0.707 0.291 216.847)' }, + 600: { hex: '#0284c7', oklch: 'oklch(0.627 0.291 216.847)' }, + 700: { hex: '#0369a1', oklch: 'oklch(0.547 0.291 216.847)' }, + 800: { hex: '#075985', oklch: 'oklch(0.467 0.291 216.847)' }, + 900: { hex: '#0c4a6e', oklch: 'oklch(0.387 0.291 216.847)' }, + 950: { hex: '#082f49', oklch: 'oklch(0.307 0.291 216.847)' }, + }, + violet: { + 50: { hex: '#f5f3ff', oklch: 'oklch(0.975 0.027 275.824)' }, + 100: { hex: '#ede9fe', oklch: 'oklch(0.937 0.067 275.824)' }, + 200: { hex: '#ddd6fe', oklch: 'oklch(0.887 0.129 275.824)' }, + 300: { hex: '#c4b5fd', oklch: 'oklch(0.807 0.223 275.824)' }, + 400: { hex: '#a78bfa', oklch: 'oklch(0.717 0.291 275.824)' }, + 500: { hex: '#8b5cf6', oklch: 'oklch(0.637 0.291 275.824)' }, + 600: { hex: '#7c3aed', oklch: 'oklch(0.557 0.291 275.824)' }, + 700: { hex: '#6d28d9', oklch: 'oklch(0.477 0.291 275.824)' }, + 800: { hex: '#5b21b6', oklch: 'oklch(0.397 0.291 275.824)' }, + 900: { hex: '#4c1d95', oklch: 'oklch(0.317 0.291 275.824)' }, + 950: { hex: '#2e1065', oklch: 'oklch(0.237 0.291 275.824)' }, + }, + fuchsia: { + 50: { hex: '#fdf4ff', oklch: 'oklch(0.975 0.027 315.824)' }, + 100: { hex: '#fae8ff', oklch: 'oklch(0.937 0.067 315.824)' }, + 200: { hex: '#f5d0fe', oklch: 'oklch(0.887 0.129 315.824)' }, + 300: { hex: '#f0abfc', oklch: 'oklch(0.807 0.223 315.824)' }, + 400: { hex: '#e879f9', oklch: 'oklch(0.717 0.291 315.824)' }, + 500: { hex: '#d946ef', oklch: 'oklch(0.637 0.291 315.824)' }, + 600: { hex: '#c026d3', oklch: 'oklch(0.557 0.291 315.824)' }, + 700: { hex: '#a21caf', oklch: 'oklch(0.477 0.291 315.824)' }, + 800: { hex: '#86198f', oklch: 'oklch(0.397 0.291 315.824)' }, + 900: { hex: '#701a75', oklch: 'oklch(0.317 0.291 315.824)' }, + 950: { hex: '#4a044e', oklch: 'oklch(0.237 0.291 315.824)' }, + }, + rose: { + 50: { hex: '#fff1f2', oklch: 'oklch(0.971 0.027 355.824)' }, + 100: { hex: '#ffe4e6', oklch: 'oklch(0.934 0.067 355.824)' }, + 200: { hex: '#fecdd3', oklch: 'oklch(0.887 0.129 355.824)' }, + 300: { hex: '#fda4af', oklch: 'oklch(0.812 0.223 355.824)' }, + 400: { hex: '#fb7185', oklch: 'oklch(0.722 0.291 355.824)' }, + 500: { hex: '#f43f5e', oklch: 'oklch(0.642 0.291 355.824)' }, + 600: { hex: '#e11d48', oklch: 'oklch(0.562 0.291 355.824)' }, + 700: { hex: '#be123c', oklch: 'oklch(0.482 0.291 355.824)' }, + 800: { hex: '#9f1239', oklch: 'oklch(0.402 0.291 355.824)' }, + 900: { hex: '#881337', oklch: 'oklch(0.322 0.291 355.824)' }, + 950: { hex: '#4c0519', oklch: 'oklch(0.242 0.291 355.824)' }, }, } as const \ No newline at end of file