"use client"; import React from "react"; import styles from "./ColorChanger.module.css"; import Image from "next/image"; type ColorScheme = { name: string; bg: string; bgDark: string; bgDarker: string; fg: string; fgDark: string; fgDarker: string; error: string; warning: string; }; const colors: ColorScheme[] = [ { // https://monokai.pro name: "Monokai Pro", bg: "#2d2a2e", bgDark: "#403e41", bgDarker: "#221f22", fg: "#fcfcfa", fgDark: "#727072", fgDarker: "#5b595c", error: "#ff6188", warning: "#ffd866" }, { // https://github.com/morhetz/gruvbox name: "Gruvbox Dark", bg: "#282828", bgDark: "#3c3836", bgDarker: "#1d2021", fg: "#ebdbb2", fgDark: "#a89984", fgDarker: "#928374", error: "#fb4934", warning: "#fabd2f" }, { // https://github.com/owozsh/amora name: "Amora Focus", bg: "#1a1a1a", bgDark: "#171717", bgDarker: "#141414", fg: "#DEDBEB", fgDark: "#5c5c5c", fgDarker: "#292929", error: "#fb5c8e", warning: "#eacac0" }, { // https://rosepinetheme.com/palette name: "Rosé Pine", bg: "#191724", bgDark: "#26233a", bgDarker: "#1f1d2e", fg: "#e0def4", fgDark: "#908caa", fgDarker: "#6e6a86", error: "#eb6f92", warning: "#f6c177" }, { // https://www.nordtheme.com/docs/colors-and-palettes name: "Nord", bg: "#2e3440", bgDark: "#3b4252", bgDarker: "#2E3440", fg: "#eceff4", fgDark: "#d8dee9", fgDarker: "#E5E9F0", error: "#BF616A", warning: "#EBCB8B" }, { // https://github.com/elenapan/dotfiles/blob/master/.xfiles/lovelace name: "lovelace", bg: "#1d1f28", bgDark: "#282a36", bgDarker: "#141721", fg: "#fdfdfd", fgDark: "#414458", fgDarker: "#bebec1", error: "#F37F97", warning: "#F2A272" }, { // https://github.com/elenapan/dotfiles/blob/master/.xfiles/skyfall name: "skyfall", bg: "#282f37", bgDark: "#20262c", bgDarker: "#1d2228", // guestimated, -6 value fg: "#f1fcf9", fgDark: "#465463", fgDarker: "#e0e5e5", error: "#DB86BA", warning: "#E49186" }, // {{{ https://github.com/catppuccin/catppuccin#-palette { name: "Catppuccin Frappe", bg: "#303446", // base bgDark: "#51576d", // surface 1 bgDarker: "#292c3c", // mantle fg: "#c6d0f5", // text fgDark: "#a5adce", // subtext 0 fgDarker: "#949cbb", // overlay 2 error: "#e78284", warning: "#e5c890" }, { name: "Catppuccin Macchiato", bg: "#24273a", bgDark: "#494d64", bgDarker: "#1e2030", fg: "#cad3f5", fgDark: "#a5adcb", fgDarker: "#939ab7", error: "#ed8796", warning: "#eed49f" }, { name: "Catppuccin Mocha", bg: "#1e1e2e", bgDark: "#45475a", bgDarker: "#181825", fg: "#cdd6f4", fgDark: "#a6adc8", fgDarker: "#9399b2", error: "#f38ba8", warning: "#f9e2af" } // }}} ]; const fallback = colors[0]; function getFromLocalStorage() { let color = localStorage.getItem("colorscheme"); if (!color) localStorage.setItem("colorscheme", fallback.name); return color ?? fallback.name; } function set(colorScheme: ColorScheme) { const fixedColors = { "--bg": colorScheme.bg, "--bg-dark": colorScheme.bgDark, "--bg-darker": colorScheme.bgDarker, "--fg": colorScheme.fg, "--fg-dark": colorScheme.fgDark, "--fg-darker": colorScheme.fgDarker, "--error": colorScheme.error ?? fallback.error!, "--warning": colorScheme.warning ?? fallback.warning! }; for (const [k, v] of Object.entries(fixedColors)) { document.documentElement.style.setProperty(k, v); } } export default function ColorChanger() { const [current, setCurrent] = React.useState(fallback.name); // this is a FOUC, but it's fine, right? right? React.useEffect(() => { const color = getFromLocalStorage(); setCurrent(color); set(colors.find((x) => x.name === color)!); }, []); return ( paint { const pool = colors.filter((x) => x.name !== current); const idx = Math.floor(Math.random() * pool.length); const colorScheme = pool[idx]; set(colorScheme); setCurrent(colorScheme.name); localStorage.setItem("colorscheme", colorScheme.name); }} className={styles["colorChanger"]} /> ); }