Skip to content

Commit

Permalink
Merge pull request #236 from Zagrios/feature/add-hex-input-to-color-p…
Browse files Browse the repository at this point in the history
…ickers

[feature] Add hex color input in color picker
  • Loading branch information
Zagrios authored Jun 5, 2023
2 parents c264684 + e349029 commit da64d02
Show file tree
Hide file tree
Showing 5 changed files with 31 additions and 43 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export const EditVersionModal: ModalComponent<{name: string, color: string}, {ve
<div>
<span className="block font-bold tracking-wide text-gray-800 dark:text-gray-200">{t("modals.clone-version.inputs.color.label")}</span>
<div className="relative w-full h-7 mb-4 bg-light-main-color-1 dark:bg-main-color-1 flex justify-center rounded-md py-1 z-[1]">
<SettingColorChooser color={color} onChange={setColor} pickerClassName="!h-32 !w-32"/>
<SettingColorChooser color={color} onChange={setColor} pickerClassName="!h-28"/>
<div className="absolute right-2 top-0 h-full flex items-center">
<BsmButton onClick={resetColor} className="px-2 font-bold italic text-sm rounded-md" text="pages.settings.appearance.reset" withBar={false}/>
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,27 @@
import { useRef, useState } from "react";
import { HexColorPicker } from "react-colorful";
import { HexColorPicker, HexColorInput } from "react-colorful";
import { motion, AnimatePresence } from "framer-motion"
import { useClickOutside } from "renderer/hooks/use-click-outside.hook";
import { BsmButton } from "../shared/bsm-button.component";

export default function SettingColorChooser({color, onChange, pickerClassName}: {color?: string, onChange?: (color: string) => void, pickerClassName?: string}) {

const [colorVisible, setColorVisible] = useState(false);
const ref = useRef(null);
useClickOutside(ref, (e) => setColorVisible(false));
useClickOutside(ref, (e) => setColorVisible(() => false));

return (
<div ref={ref} className="relative cursor-pointer mx-3 h-full aspect-square flex flex-col items-center">
<div ref={ref} className="relative cursor-pointer mx-3 h-full aspect-square flex flex-col items-center z-[1]">
<span className="z-[1] block h-full w-full border-2 border-white rounded-full" onClick={() => setColorVisible(!colorVisible)} style={{backgroundColor: color}}/>
<AnimatePresence>
{colorVisible &&
<motion.div initial={{opacity: 0}} animate={{opacity: 1}} transition={{duration: .1}} exit={{opacity: 0}} className="absolute flex items-center justify-center translate-y-9 shadow-lg rounded-lg shadow-black">
<div className="absolute w-2/4 aspect-square rotate-45 bg-light-main-color-3 dark:bg-main-color-3 -translate-y-12"/>
<HexColorPicker color={color} onChange={onChange} className={pickerClassName} />
<motion.div initial={{opacity: 0}} animate={{opacity: 1}} transition={{duration: .1}} exit={{opacity: 0}} className="absolute flex items-center grow-0 flex-col gap-2 justify-center translate-y-9 shadow-lg rounded-lg bg-light-main-color-3 dark:bg-main-color-3 shadow-black">
<div className="absolute h-2/4 aspect-square rotate-45 bg-light-main-color-3 dark:bg-main-color-3 -translate-y-12"/>
<HexColorPicker color={color} onChange={onChange} className={`${pickerClassName}`} />
<div className="w-full max-w-full flex gap-2 px-1 pb-1">
<HexColorInput color={color} onChange={onChange} placeholder="#FFFFFF" className="grow w-12 text-center uppercase z-10 rounded-md bg-light-main-color-1 dark:bg-main-color-1 text-main-color-1 dark:text-light-main-color-3 outline-none" prefixed/>
<BsmButton className="grow shrink-0 rounded-md text-center" text="misc.apply" typeColor="primary" withBar={false} onClick={() => setColorVisible(() => false)}/>
</div>
</motion.div>
}
</AnimatePresence>
Expand Down
11 changes: 7 additions & 4 deletions src/renderer/components/shared/bsm-button.component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,19 +32,22 @@ type Props = {
export function BsmButton({className, style, imgClassName, iconClassName, icon, image, text, type, active, withBar = true, disabled, onClickOutside, onClick, typeColor, color, title, iconColor, textClassName}: Props) {

const t = useTranslation();
const secondColor = useThemeColor("second-color");
const {firstColor, secondColor} = useThemeColor();
const ref = useRef(null);

useClickOutside(ref, onClickOutside);

const primaryColor = typeColor === "primary" ? useThemeColor("first-color") : typeColor === "secondary" ? secondColor : undefined;
const primaryColor = typeColor === "primary" ? firstColor : typeColor === "secondary" ? secondColor : undefined;

const textColor = (() => {
if(primaryColor){ return getCorrectTextColor(primaryColor); }
if(primaryColor){
console.log(getCorrectTextColor(primaryColor), text);
return getCorrectTextColor(primaryColor);
}
return typeColor ? "white" : undefined;
})();

const renderTypeColor = (() => {
if(typeColor === "primary"){ return ""; }
if(!typeColor){ return `bg-light-main-color-2 dark:bg-main-color-2 ${(!withBar && !disabled) && "hover:brightness-125"}`; }
if(typeColor === "cancel"){ return "bg-gray-500"; }
if(typeColor === "error"){ return "bg-red-500"; }
Expand Down
2 changes: 1 addition & 1 deletion src/renderer/helpers/correct-text-color.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@ import Color from "color";
export function getCorrectTextColor(bgHex: string): string{
if(!bgHex){ return "#000"; }
const color = Color(bgHex);
return color.isLight() ? "#000" : "fff";
return color.isLight() ? "#000" : "#fff";
}
42 changes: 11 additions & 31 deletions src/renderer/hooks/use-theme-color.hook.ts
Original file line number Diff line number Diff line change
@@ -1,44 +1,24 @@
import { useEffect, useState } from "react";
import { DefaultConfigKey } from "renderer/config/default-configuration.config";
import { ConfigurationService } from "renderer/services/configuration.service";
import { useObservable } from "./use-observable.hook";
import { useService } from "./use-service.hook";
import { of, throttleTime } from "rxjs";

export function useThemeColor(): {firstColor: string, secondColor: string};
export function useThemeColor(themeColor: ThemeColor): string;
export function useThemeColor(themeColor?: ThemeColor): string|{firstColor: string, secondColor: string}{
const configService = ConfigurationService.getInstance();

if(themeColor){
const [color, setColor] = useState("");

useEffect(() => {
const sub = configService.watch<string>(themeColor).subscribe(color => {
setColor(color);
})
return () => {
sub.unsubscribe();
}
}, []);

const configService = useService(ConfigurationService);

return color;
}

const [firstColor, setFirstColor] = useState("");
const [secondColor, setSecondColor] = useState("");
const firstColor = useObservable(!themeColor ? configService.watch<string>("first-color" as DefaultConfigKey).pipe(throttleTime(16)) : configService.watch<string>(themeColor).pipe(throttleTime(16)));
const secondColor = useObservable(!themeColor ? configService.watch<string>("second-color" as DefaultConfigKey).pipe(throttleTime(16)) : of(""));

useEffect(() => {
const sub1 = configService.watch<string>("first-color" as DefaultConfigKey).subscribe(color => {
setFirstColor(color);
});
const sub2 = configService.watch<string>("second-color" as DefaultConfigKey).subscribe(color => {
setSecondColor(color);
});
return () => {
sub1.unsubscribe();
sub2.unsubscribe();
}
}, []);
if(themeColor){
return firstColor;
}

return {firstColor, secondColor}
return {firstColor, secondColor}

}

Expand Down

0 comments on commit da64d02

Please sign in to comment.