parent
5711b22b4e
commit
1b2fa720c6
@ -0,0 +1,81 @@
|
||||
import { useContext } from "react";
|
||||
import { IoColorPalette } from "react-icons/io5";
|
||||
import { Popover, Transition } from "@headlessui/react";
|
||||
import { Fragment } from "react";
|
||||
|
||||
import { ColorContext } from "utils/color-context";
|
||||
|
||||
const colors = [
|
||||
"slate",
|
||||
"gray",
|
||||
"zinc",
|
||||
"neutral",
|
||||
"stone",
|
||||
"amber",
|
||||
"yellow",
|
||||
"lime",
|
||||
"green",
|
||||
"emerald",
|
||||
"teal",
|
||||
"cyan",
|
||||
"sky",
|
||||
"blue",
|
||||
"indigo",
|
||||
"violet",
|
||||
"purple",
|
||||
"fuchsia",
|
||||
"pink",
|
||||
"rose",
|
||||
"red",
|
||||
];
|
||||
|
||||
export default function ColorToggle() {
|
||||
const { color: active, setColor } = useContext(ColorContext);
|
||||
|
||||
if (!active) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="w-full self-center">
|
||||
<Popover className="relative flex items-center">
|
||||
{({ open }) => (
|
||||
<>
|
||||
<Popover.Button className="outline-none">
|
||||
<IoColorPalette
|
||||
className="h-5 w-5 text-theme-800 dark:text-theme-200 transition duration-150 ease-in-out"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</Popover.Button>
|
||||
<Transition
|
||||
as={Fragment}
|
||||
enter="transition ease-out duration-200"
|
||||
enterFrom="opacity-0 translate-y-1"
|
||||
enterTo="opacity-100 translate-y-0"
|
||||
leave="transition ease-in duration-150"
|
||||
leaveFrom="opacity-100 translate-y-0"
|
||||
leaveTo="opacity-0 translate-y-1"
|
||||
>
|
||||
<Popover.Panel className="absolute -top-[75px] left-0">
|
||||
<div className="rounded-md shadow-lg ring-1 ring-black ring-opacity-5">
|
||||
<div className="relative grid gap-2 p-2 grid-cols-11 shadow-theme-900/10 dark:shadow-theme-900 rounded-md shadow-md">
|
||||
{colors.map((color) => (
|
||||
<button role="button" onClick={() => setColor(color)} key={color}>
|
||||
<div
|
||||
className={
|
||||
(active == color ? "border-2" : "border-0") +
|
||||
` rounded-md w-5 h-5 border-black/50 dark:border-white/50 theme-${color} bg-theme-500`
|
||||
}
|
||||
/>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</Popover.Panel>
|
||||
</Transition>
|
||||
</>
|
||||
)}
|
||||
</Popover>
|
||||
</div>
|
||||
);
|
||||
}
|
@ -0,0 +1,285 @@
|
||||
.theme-slate {
|
||||
--color-50: 248 250 252;
|
||||
--color-100: 241 245 249;
|
||||
--color-200: 226 232 240;
|
||||
--color-300: 203 213 225;
|
||||
--color-400: 148 163 184;
|
||||
--color-500: 100 116 139;
|
||||
--color-600: 71 85 105;
|
||||
--color-700: 51 65 85;
|
||||
--color-800: 30 41 59;
|
||||
--color-900: 15 23 42;
|
||||
}
|
||||
|
||||
.theme-gray {
|
||||
--color-50: 249 250 251;
|
||||
--color-100: 243 244 246;
|
||||
--color-200: 229 231 235;
|
||||
--color-300: 209 213 219;
|
||||
--color-400: 156 163 175;
|
||||
--color-500: 107 114 128;
|
||||
--color-600: 75 85 99;
|
||||
--color-700: 55 65 81;
|
||||
--color-800: 31 41 55;
|
||||
--color-900: 17 24 39;
|
||||
}
|
||||
|
||||
.theme-zinc {
|
||||
--color-50: 250 250 250;
|
||||
--color-100: 244 244 245;
|
||||
--color-200: 228 228 231;
|
||||
--color-300: 212 212 216;
|
||||
--color-400: 161 161 170;
|
||||
--color-500: 113 113 122;
|
||||
--color-600: 82 82 91;
|
||||
--color-700: 63 63 70;
|
||||
--color-800: 39 39 42;
|
||||
--color-900: 24 24 27;
|
||||
}
|
||||
|
||||
.theme-neutral {
|
||||
--color-50: 250 250 250;
|
||||
--color-100: 245 245 245;
|
||||
--color-200: 229 229 229;
|
||||
--color-300: 212 212 212;
|
||||
--color-400: 163 163 163;
|
||||
--color-500: 115 115 115;
|
||||
--color-600: 82 82 82;
|
||||
--color-700: 64 64 64;
|
||||
--color-800: 38 38 38;
|
||||
--color-900: 23 23 23;
|
||||
}
|
||||
|
||||
.theme-stone {
|
||||
--color-50: 250 250 249;
|
||||
--color-100: 245 245 244;
|
||||
--color-200: 231 229 228;
|
||||
--color-300: 214 211 209;
|
||||
--color-400: 168 162 158;
|
||||
--color-500: 120 113 108;
|
||||
--color-600: 87 83 78;
|
||||
--color-700: 68 64 60;
|
||||
--color-800: 41 37 36;
|
||||
--color-900: 28 25 23;
|
||||
}
|
||||
|
||||
.theme-red {
|
||||
--color-50: 254 242 242;
|
||||
--color-100: 254 226 226;
|
||||
--color-200: 254 202 202;
|
||||
--color-300: 252 165 165;
|
||||
--color-400: 248 113 113;
|
||||
--color-500: 239 68 68;
|
||||
--color-600: 220 38 38;
|
||||
--color-700: 185 28 28;
|
||||
--color-800: 153 27 27;
|
||||
--color-900: 127 29 29;
|
||||
}
|
||||
|
||||
.theme-orange {
|
||||
--color-50: 255 247 237;
|
||||
--color-100: 255 237 213;
|
||||
--color-200: 254 215 170;
|
||||
--color-300: 253 186 116;
|
||||
--color-400: 251 146 60;
|
||||
--color-500: 249 115 22;
|
||||
--color-600: 234 88 12;
|
||||
--color-700: 194 65 12;
|
||||
--color-800: 154 52 18;
|
||||
--color-900: 124 45 18;
|
||||
}
|
||||
|
||||
.theme-amber {
|
||||
--color-50: 255 251 235;
|
||||
--color-100: 254 243 199;
|
||||
--color-200: 253 230 138;
|
||||
--color-300: 252 211 77;
|
||||
--color-400: 251 191 36;
|
||||
--color-500: 245 158 11;
|
||||
--color-600: 217 119 6;
|
||||
--color-700: 180 83 9;
|
||||
--color-800: 146 64 14;
|
||||
--color-900: 120 53 15;
|
||||
}
|
||||
|
||||
.theme-yellow {
|
||||
--color-50: 254 252 232;
|
||||
--color-100: 254 249 195;
|
||||
--color-200: 254 240 138;
|
||||
--color-300: 253 224 71;
|
||||
--color-400: 250 204 21;
|
||||
--color-500: 234 179 8;
|
||||
--color-600: 202 138 4;
|
||||
--color-700: 161 98 7;
|
||||
--color-800: 133 77 14;
|
||||
--color-900: 113 63 18;
|
||||
}
|
||||
|
||||
.theme-lime {
|
||||
--color-50: 247 254 231;
|
||||
--color-100: 236 252 203;
|
||||
--color-200: 217 249 157;
|
||||
--color-300: 190 242 100;
|
||||
--color-400: 163 230 53;
|
||||
--color-500: 132 204 22;
|
||||
--color-600: 101 163 13;
|
||||
--color-700: 77 124 15;
|
||||
--color-800: 63 98 18;
|
||||
--color-900: 54 83 20;
|
||||
}
|
||||
|
||||
.theme-green {
|
||||
--color-50: 240 253 244;
|
||||
--color-100: 220 252 231;
|
||||
--color-200: 187 247 208;
|
||||
--color-300: 134 239 172;
|
||||
--color-400: 74 222 128;
|
||||
--color-500: 34 197 94;
|
||||
--color-600: 22 163 74;
|
||||
--color-700: 21 128 61;
|
||||
--color-800: 22 101 52;
|
||||
--color-900: 20 83 45;
|
||||
}
|
||||
|
||||
.theme-emerald {
|
||||
--color-50: 236 253 245;
|
||||
--color-100: 209 250 229;
|
||||
--color-200: 167 243 208;
|
||||
--color-300: 110 231 183;
|
||||
--color-400: 52 211 153;
|
||||
--color-500: 16 185 129;
|
||||
--color-600: 5 150 105;
|
||||
--color-700: 4 120 87;
|
||||
--color-800: 6 95 70;
|
||||
--color-900: 6 78 59;
|
||||
}
|
||||
|
||||
.theme-teal {
|
||||
--color-50: 240 253 250;
|
||||
--color-100: 204 251 241;
|
||||
--color-200: 153 246 228;
|
||||
--color-300: 94 234 212;
|
||||
--color-400: 45 212 191;
|
||||
--color-500: 20 184 166;
|
||||
--color-600: 13 148 136;
|
||||
--color-700: 15 118 110;
|
||||
--color-800: 17 94 89;
|
||||
--color-900: 19 78 74;
|
||||
}
|
||||
|
||||
.theme-cyan {
|
||||
--color-50: 236 254 255;
|
||||
--color-100: 207 250 254;
|
||||
--color-200: 165 243 252;
|
||||
--color-300: 103 232 249;
|
||||
--color-400: 34 211 238;
|
||||
--color-500: 6 182 212;
|
||||
--color-600: 8 145 178;
|
||||
--color-700: 14 116 144;
|
||||
--color-800: 21 94 117;
|
||||
--color-900: 22 78 99;
|
||||
}
|
||||
|
||||
.theme-sky {
|
||||
--color-50: 240 249 255;
|
||||
--color-100: 224 242 254;
|
||||
--color-200: 186 230 253;
|
||||
--color-300: 125 211 252;
|
||||
--color-400: 56 189 248;
|
||||
--color-500: 14 165 233;
|
||||
--color-600: 2 132 199;
|
||||
--color-700: 3 105 161;
|
||||
--color-800: 7 89 133;
|
||||
--color-900: 12 74 110;
|
||||
}
|
||||
|
||||
.theme-blue {
|
||||
--color-50: 239 246 255;
|
||||
--color-100: 219 234 254;
|
||||
--color-200: 191 219 254;
|
||||
--color-300: 147 197 253;
|
||||
--color-400: 96 165 250;
|
||||
--color-500: 59 130 246;
|
||||
--color-600: 37 99 235;
|
||||
--color-700: 29 78 216;
|
||||
--color-800: 30 64 175;
|
||||
--color-900: 30 58 138;
|
||||
}
|
||||
|
||||
.theme-indigo {
|
||||
--color-50: 238 242 255;
|
||||
--color-100: 224 231 255;
|
||||
--color-200: 199 210 254;
|
||||
--color-300: 165 180 252;
|
||||
--color-400: 129 140 248;
|
||||
--color-500: 99 102 241;
|
||||
--color-600: 79 70 229;
|
||||
--color-700: 67 56 202;
|
||||
--color-800: 55 48 163;
|
||||
--color-900: 49 46 129;
|
||||
}
|
||||
|
||||
.theme-violet {
|
||||
--color-50: 245 243 255;
|
||||
--color-100: 237 233 254;
|
||||
--color-200: 221 214 254;
|
||||
--color-300: 196 181 253;
|
||||
--color-400: 167 139 250;
|
||||
--color-500: 139 92 246;
|
||||
--color-600: 124 58 237;
|
||||
--color-700: 109 40 217;
|
||||
--color-800: 91 33 182;
|
||||
--color-900: 76 29 149;
|
||||
}
|
||||
|
||||
.theme-purple {
|
||||
--color-50: 250 245 255;
|
||||
--color-100: 243 232 255;
|
||||
--color-200: 233 213 255;
|
||||
--color-300: 216 180 254;
|
||||
--color-400: 192 132 252;
|
||||
--color-500: 168 85 247;
|
||||
--color-600: 147 51 234;
|
||||
--color-700: 126 34 206;
|
||||
--color-800: 107 33 168;
|
||||
--color-900: 88 28 135;
|
||||
}
|
||||
|
||||
.theme-fuchsia {
|
||||
--color-50: 253 244 255;
|
||||
--color-100: 250 232 255;
|
||||
--color-200: 245 208 254;
|
||||
--color-300: 240 171 252;
|
||||
--color-400: 232 121 249;
|
||||
--color-500: 217 70 239;
|
||||
--color-600: 192 38 211;
|
||||
--color-700: 162 28 175;
|
||||
--color-800: 134 25 143;
|
||||
--color-900: 112 26 117;
|
||||
}
|
||||
|
||||
.theme-pink {
|
||||
--color-50: 253 242 248;
|
||||
--color-100: 252 231 243;
|
||||
--color-200: 251 207 232;
|
||||
--color-300: 249 168 212;
|
||||
--color-400: 244 114 182;
|
||||
--color-500: 236 72 153;
|
||||
--color-600: 219 39 119;
|
||||
--color-700: 190 24 93;
|
||||
--color-800: 157 23 77;
|
||||
--color-900: 131 24 67;
|
||||
}
|
||||
|
||||
.theme-rose {
|
||||
--color-50: 255 241 242;
|
||||
--color-100: 255 228 230;
|
||||
--color-200: 254 205 211;
|
||||
--color-300: 253 164 175;
|
||||
--color-400: 251 113 133;
|
||||
--color-500: 244 63 94;
|
||||
--color-600: 225 29 72;
|
||||
--color-700: 190 18 60;
|
||||
--color-800: 159 18 57;
|
||||
--color-900: 136 19 55;
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
import { createContext, useState, useEffect } from "react";
|
||||
|
||||
let lastColor = false;
|
||||
|
||||
const getInitialColor = () => {
|
||||
if (typeof window !== "undefined" && window.localStorage) {
|
||||
const storedPrefs = window.localStorage.getItem("theme-color");
|
||||
if (typeof storedPrefs === "string") {
|
||||
lastColor = storedPrefs;
|
||||
return storedPrefs;
|
||||
}
|
||||
}
|
||||
|
||||
return "slate"; // slate as the default color;
|
||||
};
|
||||
|
||||
export const ColorContext = createContext();
|
||||
|
||||
export const ColorProvider = ({ initialTheme, children }) => {
|
||||
const [color, setColor] = useState(getInitialColor);
|
||||
|
||||
const rawSetColor = (rawColor) => {
|
||||
const root = window.document.documentElement;
|
||||
|
||||
root.classList.remove(`theme-${lastColor}`);
|
||||
root.classList.add(`theme-${rawColor}`);
|
||||
|
||||
localStorage.setItem("theme-color", rawColor);
|
||||
|
||||
lastColor = rawColor;
|
||||
};
|
||||
|
||||
if (initialTheme) {
|
||||
rawSetColor(initialTheme);
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
rawSetColor(color);
|
||||
}, [color]);
|
||||
|
||||
return <ColorContext.Provider value={{ color, setColor }}>{children}</ColorContext.Provider>;
|
||||
};
|
Loading…
Reference in new issue