-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chore: Refactor AnalogousMonochromaticPalettes component
- Loading branch information
1 parent
29faaf8
commit 0830d7d
Showing
1 changed file
with
69 additions
and
97 deletions.
There are no files selected for viewing
166 changes: 69 additions & 97 deletions
166
apps/web/components/palette/analogous-mono-palettes.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,105 +1,77 @@ | ||
"use client"; | ||
'use client' | ||
|
||
import { | ||
Performance, | ||
useColorStore, | ||
useSiteSettingsStore, | ||
} from "@/store/store"; | ||
import { ColorMode, RawColor } from "@/types/app"; | ||
import { cn } from "@ui/lib/utils"; | ||
import tinycolor from "tinycolor2"; | ||
import { memo } from "react"; | ||
import { colorHelper } from "@/lib/colorHelper"; | ||
import { Copy } from "lucide-react"; | ||
import { AnimatePresence, motion, useReducedMotion } from "framer-motion"; | ||
import { textAnimation } from "@/lib/animation"; | ||
import { useColorStore } from '@/context/color-store-provider' | ||
import { useToolStore } from '@/store/toolStore' | ||
import { cn } from '@ui/lib/utils' | ||
import { motion } from 'framer-motion' | ||
import { Copy } from 'lucide-react' | ||
import tinycolor from 'tinycolor2' | ||
|
||
function AnalogousMonochromaticPalettes({ className }: { className?: string }) { | ||
const { baseColors, colorMode } = useColorStore(); | ||
const primary = useColorStore((s) => s.primary) | ||
|
||
return ( | ||
<div className={cn("grid grid-cols-2 gap-4", className)}> | ||
<PillPalette color={baseColors?.primary} type="mono" mode={colorMode} /> | ||
<PillPalette color={baseColors?.primary} type="analog" mode={colorMode} /> | ||
<div className={cn('grid grid-cols-2 gap-4', className)}> | ||
<PillPalette color={primary} type="analogous" /> | ||
<PillPalette color={primary} type="monochromatic" /> | ||
</div> | ||
); | ||
) | ||
} | ||
|
||
const PillPalette = memo( | ||
({ | ||
color, | ||
type, | ||
mode, | ||
}: { | ||
color: RawColor; | ||
type: "mono" | "analog"; | ||
mode: ColorMode; | ||
}) => { | ||
const shouldReduceMotion = useReducedMotion(); | ||
|
||
const { performance } = useSiteSettingsStore(); | ||
const colors = | ||
type === "mono" | ||
? tinycolor(color).monochromatic(6) | ||
: tinycolor(color).analogous(6); | ||
colors.sort((a, b) => { | ||
return tinycolor(b).getBrightness() - tinycolor(a).getBrightness(); | ||
}); | ||
const animationDelay = (i) => { | ||
let springDelay = 0; | ||
switch (performance) { | ||
case Performance.low: | ||
springDelay = i; | ||
default: | ||
springDelay = Math.pow(1.3, i) - 0.8; | ||
} | ||
switch (type) { | ||
case "mono": | ||
return 0.06 * 6 + springDelay * 0.06; | ||
case "analog": | ||
return 0.06 * 8 + springDelay * 0.06; | ||
} | ||
}; | ||
return ( | ||
<div | ||
id="analogous-mono-palette" | ||
className={cn( | ||
"col-span-2 flex flex-col gap-3 md:gap-4", | ||
"@md/section-primary:col-span-1", | ||
"@md/section-secondary:col-span-1", | ||
)} | ||
> | ||
{colors.map((color, i) => { | ||
const c = color.toHexString(); | ||
const isDark = tinycolor(color).isDark(); | ||
const foregroundColor = isDark | ||
? "text-white/30 hover:text-white/70 focus:text-white/70 contrast-more:text-white/80 contrast-more:hover:text-white contrast-more:font-medium" | ||
: "text-black/30 hover:text-black/70 focus:text-black/70 contrast-more:text-black/80 contrast-more:hover:text-black contrast-more:font-medium"; | ||
return ( | ||
<button | ||
key={`${type}-${i}`} | ||
className={cn( | ||
"group/pill-btn flex h-10 w-full items-center justify-between rounded-full border border-border px-2.5 text-xs transition-colors duration-500 focus:outline-none focus:ring focus:ring-accent focus:ring-opacity-50", | ||
foregroundColor, | ||
)} | ||
style={{ | ||
backgroundColor: c, | ||
transitionDelay: `${0.44 + i * 0.06}s`, | ||
}} | ||
type="button" | ||
aria-label={`Copy ${c} to clipboard`} | ||
> | ||
<motion.code key={`${type}-text-${i}`} className="animate-text"> | ||
{colorHelper.toColorMode(color, mode)} | ||
</motion.code> | ||
<Copy className="h-4 w-4 opacity-0 transition-opacity group-hover/pill-btn:opacity-100 group-focus/pill-btn:opacity-100" /> | ||
</button> | ||
); | ||
})} | ||
</div> | ||
); | ||
}, | ||
); | ||
|
||
PillPalette.displayName = "AnalogousMonochromaticPalettes"; | ||
const PillPalette = ({ color, type }: { color: string; type: 'analogous' | 'monochromatic' }) => { | ||
const { colorMode: mode } = useToolStore() | ||
const colors = type === 'monochromatic' ? tinycolor(color).monochromatic(6) : tinycolor(color).analogous(6) | ||
colors.sort((a, b) => { | ||
return tinycolor(b).getBrightness() - tinycolor(a).getBrightness() | ||
}) | ||
const colorString = (c: tinycolor.Instance) => { | ||
switch (mode) { | ||
case 'hex': | ||
return c.toHexString() | ||
case 'rgb': | ||
return c.toRgbString() | ||
case 'hsl': | ||
return c.toHslString() | ||
} | ||
} | ||
return ( | ||
<div | ||
id={`${type}-palette`} | ||
className={cn( | ||
'scroll-mt-8', | ||
'col-span-2 flex flex-col gap-3 md:gap-4', | ||
'@md/section-primary:col-span-1', | ||
'@md/section-secondary:col-span-1' | ||
)} | ||
> | ||
{colors.map((c, i) => { | ||
const isDark = tinycolor(color).isDark() | ||
const foregroundColor = isDark | ||
? 'text-white/30 hover:text-white/70 focus:text-white/70 contrast-more:text-white/80 contrast-more:hover:text-white contrast-more:font-medium' | ||
: 'text-black/30 hover:text-black/70 focus:text-black/70 contrast-more:text-black/80 contrast-more:hover:text-black contrast-more:font-medium' | ||
return ( | ||
<button | ||
aria-label={`Copy ${c} to clipboard`} | ||
className={cn( | ||
'group/pill-btn flex h-10 w-full items-center justify-between rounded-full border border-border px-2.5 text-xs transition-colors duration-500 focus:outline-none focus:ring focus:ring-accent focus:ring-opacity-50', | ||
foregroundColor | ||
)} | ||
key={`${type}-${i}`} | ||
style={{ | ||
backgroundColor: c.toHexString(), | ||
transitionDelay: `${0.44 + i * 0.06}s`, | ||
}} | ||
type="button" | ||
> | ||
<motion.code className="animate-text" key={`${type}-text-${i}`}> | ||
{colorString(c)} | ||
</motion.code> | ||
<Copy className="h-4 w-4 opacity-0 transition-opacity group-hover/pill-btn:opacity-100 group-focus/pill-btn:opacity-100" /> | ||
</button> | ||
) | ||
})} | ||
</div> | ||
) | ||
} | ||
|
||
export default AnalogousMonochromaticPalettes; | ||
export default AnalogousMonochromaticPalettes |