87 lines
2.9 KiB
TypeScript
87 lines
2.9 KiB
TypeScript
import React, { useMemo } from 'react'
|
|
import { TAILWIND_COLORS } from '../utils/colors'
|
|
|
|
interface TailwindColorsProps {
|
|
onColorSelect: (color: string) => void
|
|
selectedColor?: string
|
|
}
|
|
|
|
export function TailwindColors({ onColorSelect, selectedColor }: 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 (
|
|
<div className="h-full flex flex-col">
|
|
<div className="text-sm font-medium text-gray-500 mb-2 px-2">
|
|
Tailwind Color Reference
|
|
</div>
|
|
<div className="flex-1 overflow-x-auto overflow-y-auto">
|
|
<div className="grid grid-cols-[auto_repeat(11,minmax(32px,1fr))] gap-1.5 p-2">
|
|
{/* Color rows */}
|
|
{orderedColors.map(colorName => (
|
|
<React.Fragment key={colorName}>
|
|
<div className="flex sticky left-0 z-10 bg-white text-sm font-medium items-center justify-end text-gray-900 py-1 pr-3 whitespace-nowrap border-r border-gray-100">
|
|
{colorName}
|
|
</div>
|
|
{shades.map(shade => {
|
|
const values = TAILWIND_COLORS[colorName][shade]
|
|
const hexColor = typeof values === 'string' ? values : values.hex
|
|
const textColorClass = getTextColor(hexColor)
|
|
|
|
return (
|
|
<button
|
|
key={`${colorName}-${shade}`}
|
|
onClick={() => onColorSelect(hexColor)}
|
|
className={`aspect-square transition-all hover:scale-110 hover:z-10 hover:shadow-lg relative
|
|
${selectedColor === hexColor ? 'ring-2 ring-offset-0 ring-indigo-600 z-10 shadow-lg' : 'shadow-sm ring-1 ring-inset ring-gray-900/5'}`}
|
|
style={{ backgroundColor: hexColor }}
|
|
title={`${colorName}-${shade}`}
|
|
>
|
|
<span className={`absolute inset-0 flex items-center justify-center text-xs font-medium ${textColorClass}`}>
|
|
{shade}
|
|
</span>
|
|
</button>
|
|
)
|
|
})}
|
|
</React.Fragment>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|