Skip to content

Commit

Permalink
refactor: theme builder provider
Browse files Browse the repository at this point in the history
  • Loading branch information
xylish7 committed Sep 12, 2024
1 parent 876816d commit 81869d0
Show file tree
Hide file tree
Showing 15 changed files with 374 additions and 298 deletions.
19 changes: 16 additions & 3 deletions apps/docs/components/themes/components/color-picker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,32 @@ import {readableColor} from "color2k";
import waterDrop from "@iconify/icons-solar/waterdrop-linear";
import {Icon} from "@iconify/react/dist/offline";
import {useTheme} from "next-themes";
import {clsx} from "@nextui-org/shared-utils";

import {ColorPickerType, ThemeType} from "../types";
import {colorValuesToRgb, getColorWeight} from "../utils/colors";

import {CopyButton} from "./copy-button";

interface ColorPickerProps {
hexColor: string;
icon?: React.ReactNode;
label: string;
type: ColorPickerType;
onChange: (hexColor: string) => void;
onClose: (hexColor: string) => void;
onCopy: (theme: ThemeType) => void;
}

export function ColorPicker({hexColor, icon, label, type, onChange, onClose}: ColorPickerProps) {
export function ColorPicker({
hexColor,
icon,
label,
type,
onChange,
onClose,
onCopy,
}: ColorPickerProps) {
const [selectedColor, setSelectedColor] = useState(hexColor);

const [isOpen, setIsOpen] = useState(false);
Expand All @@ -40,7 +52,7 @@ export function ColorPicker({hexColor, icon, label, type, onChange, onClose}: Co
}, [hexColor, isOpen]);

return (
<div>
<div className="flex">
<Popover
isOpen={isOpen}
placement="bottom"
Expand All @@ -50,7 +62,7 @@ export function ColorPicker({hexColor, icon, label, type, onChange, onClose}: Co
<PopoverTrigger>
<Button
fullWidth
className={getColor(type)}
className={clsx(getColor(type), "rounded-r-none")}
size="sm"
style={{
color: ["background", "foreground", "focus", "overlay"].includes(type)
Expand Down Expand Up @@ -87,6 +99,7 @@ export function ColorPicker({hexColor, icon, label, type, onChange, onClose}: Co
</div>
</PopoverContent>
</Popover>
<CopyButton className="rounded-l-none" size="sm" variant="flat" onCopy={onCopy} />
</div>
);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import {useContext} from "react";

import {baseColorsId} from "../../constants";
import {setCssBackground, setCssColor, setCssContentColor} from "../../css-vars";
import {ThemeBuilderContext} from "../../provider";
import {useThemeBuilder} from "../../provider";
import {Config, ThemeType} from "../../types";
import {copyBaseColorConfig} from "../../utils/config";
import {ColorPicker} from "../color-picker";
import {ConfigSection} from "../config-section";

Expand All @@ -13,7 +12,7 @@ interface BaseColorsProps {
}

export function BaseColors({config, theme}: BaseColorsProps) {
const {setBaseColor} = useContext(ThemeBuilderContext);
const {setBaseColor} = useThemeBuilder();

return (
<ConfigSection id={baseColorsId} title="Base colors">
Expand All @@ -23,41 +22,47 @@ export function BaseColors({config, theme}: BaseColorsProps) {
type="background"
onChange={(hexColor) => setCssBackground(hexColor)}
onClose={(hexColor) => setBaseColor({background: hexColor}, theme)}
onCopy={(theme) => copyBaseColorConfig(config, "background", theme)}
/>
<ColorPicker
hexColor={config[theme].baseColor.foreground}
label="Foreground"
type="foreground"
onChange={(hexColor) => setCssColor("foreground", hexColor, theme)}
onClose={(hexColor) => setBaseColor({foreground: hexColor}, theme)}
onCopy={(theme) => copyBaseColorConfig(config, "foreground", theme)}
/>
<ColorPicker
hexColor={config[theme].baseColor.content1}
label="Content 1"
type="content1"
onChange={(hexColor) => setCssContentColor(1, hexColor)}
onClose={(hexColor) => setBaseColor({content1: hexColor}, theme)}
onCopy={(theme) => copyBaseColorConfig(config, "content1", theme)}
/>
<ColorPicker
hexColor={config[theme].baseColor.content2}
label="Content 2"
type="content2"
onChange={(hexColor) => setCssContentColor(2, hexColor)}
onClose={(hexColor) => setBaseColor({content2: hexColor}, theme)}
onCopy={(theme) => copyBaseColorConfig(config, "content2", theme)}
/>
<ColorPicker
hexColor={config[theme].baseColor.content3}
label="Content 3"
type="content3"
onChange={(hexColor) => setCssContentColor(3, hexColor)}
onClose={(hexColor) => setBaseColor({content3: hexColor}, theme)}
onCopy={(theme) => copyBaseColorConfig(config, "content3", theme)}
/>
<ColorPicker
hexColor={config[theme].baseColor.content4}
label="Content 4"
type="content4"
onChange={(hexColor) => setCssContentColor(4, hexColor)}
onClose={(hexColor) => setBaseColor({content4: hexColor}, theme)}
onCopy={(theme) => copyBaseColorConfig(config, "content4", theme)}
/>
</ConfigSection>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import {useContext} from "react";

import {setCssBorderWidth} from "../../css-vars";
import {ThemeBuilderContext} from "../../provider";
import {useThemeBuilder} from "../../provider";
import {Config} from "../../types";
import {ConfigSection} from "../config-section";
import {NumberInput} from "../number-input";
Expand All @@ -11,7 +9,7 @@ interface BorderWidthsProps {
}

export function BorderWidths({config}: BorderWidthsProps) {
const {setBorderWidth} = useContext(ThemeBuilderContext);
const {setBorderWidth} = useThemeBuilder();

const handleChange = (key: keyof Config["layout"]["borderWidth"], value: string) => {
setBorderWidth({[key]: value});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import {useContext} from "react";

import {colorsId} from "../../constants";
import {setCssColor} from "../../css-vars";
import {ThemeBuilderContext} from "../../provider";
import {useThemeBuilder} from "../../provider";
import {Config, ThemeType} from "../../types";
import {copyBrandColorConfig} from "../../utils/config";
import {ColorPicker} from "../color-picker";
import {ConfigSection} from "../config-section";

Expand All @@ -15,7 +14,7 @@ interface BrandColorsProps {
}

export function BrandColors({config, syncIcon, syncThemes, theme}: BrandColorsProps) {
const {setBrandColor} = useContext(ThemeBuilderContext);
const {setBrandColor} = useThemeBuilder();

return (
<ConfigSection id={colorsId} title="Brand colors">
Expand All @@ -25,6 +24,7 @@ export function BrandColors({config, syncIcon, syncThemes, theme}: BrandColorsPr
type="default"
onChange={(hexColor) => setCssColor("default", hexColor, theme)}
onClose={(hexColor) => setBrandColor({default: hexColor}, theme, false)}
onCopy={(theme) => copyBrandColorConfig(config, "default", theme)}
/>
<ColorPicker
hexColor={config[theme].brandColor.primary}
Expand All @@ -33,6 +33,7 @@ export function BrandColors({config, syncIcon, syncThemes, theme}: BrandColorsPr
type="primary"
onChange={(hexColor) => setCssColor("primary", hexColor, theme)}
onClose={(hexColor) => setBrandColor({primary: hexColor}, theme, syncThemes)}
onCopy={(theme) => copyBrandColorConfig(config, "primary", theme)}
/>
<ColorPicker
hexColor={config[theme].brandColor.secondary}
Expand All @@ -41,6 +42,7 @@ export function BrandColors({config, syncIcon, syncThemes, theme}: BrandColorsPr
type="secondary"
onChange={(hexColor) => setCssColor("secondary", hexColor, theme)}
onClose={(hexColor) => setBrandColor({secondary: hexColor}, theme, syncThemes)}
onCopy={(theme) => copyBrandColorConfig(config, "secondary", theme)}
/>
<ColorPicker
hexColor={config[theme].brandColor.success}
Expand All @@ -49,6 +51,7 @@ export function BrandColors({config, syncIcon, syncThemes, theme}: BrandColorsPr
type="success"
onChange={(hexColor) => setCssColor("success", hexColor, theme)}
onClose={(hexColor) => setBrandColor({success: hexColor}, theme, syncThemes)}
onCopy={(theme) => copyBrandColorConfig(config, "success", theme)}
/>
<ColorPicker
hexColor={config[theme].brandColor.warning}
Expand All @@ -57,6 +60,7 @@ export function BrandColors({config, syncIcon, syncThemes, theme}: BrandColorsPr
type="warning"
onChange={(hexColor) => setCssColor("warning", hexColor, theme)}
onClose={(hexColor) => setBrandColor({warning: hexColor}, theme, syncThemes)}
onCopy={(theme) => copyBrandColorConfig(config, "warning", theme)}
/>
<ColorPicker
hexColor={config[theme].brandColor.danger}
Expand All @@ -65,6 +69,7 @@ export function BrandColors({config, syncIcon, syncThemes, theme}: BrandColorsPr
type="danger"
onChange={(hexColor) => setCssColor("danger", hexColor, theme)}
onClose={(hexColor) => setBrandColor({danger: hexColor}, theme, syncThemes)}
onCopy={(theme) => copyBrandColorConfig(config, "danger", theme)}
/>
</ConfigSection>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import {useContext} from "react";

import {setCssFontSize} from "../../css-vars";
import {ThemeBuilderContext} from "../../provider";
import {useThemeBuilder} from "../../provider";
import {Config} from "../../types";
import {ConfigSection} from "../config-section";
import {NumberInput} from "../number-input";
Expand All @@ -11,7 +9,7 @@ interface FontSizesProps {
}

export function FontSizes({config}: FontSizesProps) {
const {setFontSize} = useContext(ThemeBuilderContext);
const {setFontSize} = useThemeBuilder();

return (
<ConfigSection title="Font size (rem)">
Expand Down
10 changes: 5 additions & 5 deletions apps/docs/components/themes/components/configuration/index.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import {useContext, useEffect, useState} from "react";
import {useEffect, useState} from "react";
import {Card, CardBody, Switch} from "@nextui-org/react";
import {useTheme} from "next-themes";
import {useLocalStorage} from "usehooks-ts";
import {Icon} from "@iconify/react/dist/offline";
import LinkSquareIcon from "@iconify/icons-solar/link-square-linear";

import {ThemeBuilderContext} from "../../provider";
import {useThemeBuilder} from "../../provider";
import {Config, Template, ThemeType} from "../../types";
import {configKey, syncThemesKey, initialConfig} from "../../constants";
import {SelectTemplate} from "../select-template";
Expand All @@ -26,15 +26,15 @@ import usePrevious from "@/hooks/use-previous";

export default function Configuration() {
const [selectedTemplate, setSelectedTemplate] = useState<Template | null>(null);
const {config, resetConfig, setConfiguration} = useContext(ThemeBuilderContext);
const {config, resetConfig, setConfiguration} = useThemeBuilder();
const themeProps = useTheme();
const theme = themeProps.theme as ThemeType;
const prevTheme = usePrevious(theme);
const {setTheme} = themeProps;
const [, setLsConfig] = useLocalStorage<Config>(configKey, initialConfig);
const [syncThemes, setSyncThemes] = useLocalStorage<boolean>(syncThemesKey, true);
const isLight = theme === "light";
const syncIcon = syncThemes ? <Icon icon={LinkSquareIcon} /> : null;
const syncIcon = syncThemes ? <Icon className="flex-shrink-0" icon={LinkSquareIcon} /> : null;

/**
* Update the CSS variables and the configuration when the theme changes.
Expand Down Expand Up @@ -81,7 +81,7 @@ export default function Configuration() {
}

return (
<Card className="max-w-xs w-full p-2 h-min relative mx-auto md:sticky md:top-28 z-30 md:h-[calc(100vh-12rem)]">
<Card className="max-w-md w-full p-2 h-min relative mx-auto md:sticky md:top-28 z-30 md:h-[calc(100vh-12rem)]">
<CardBody className="flex flex-col">
<div className="flex flex-col gap-6">
<Actions
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import {useContext} from "react";

import {setCssLineHeight} from "../../css-vars";
import {ThemeBuilderContext} from "../../provider";
import {useThemeBuilder} from "../../provider";
import {Config} from "../../types";
import {ConfigSection} from "../config-section";
import {NumberInput} from "../number-input";
Expand All @@ -11,7 +9,7 @@ interface LineHeightsProps {
}

export function LineHeights({config}: LineHeightsProps) {
const {setLineHeight} = useContext(ThemeBuilderContext);
const {setLineHeight} = useThemeBuilder();

return (
<ConfigSection title="Line height (rem)">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import {useContext} from "react";

import {otherColorsId} from "../../constants";
import {ThemeBuilderContext} from "../../provider";
import {useThemeBuilder} from "../../provider";
import {Config, ThemeType} from "../../types";
import {copyOtherColorConfig} from "../../utils/config";
import {ColorPicker} from "../color-picker";
import {ConfigSection} from "../config-section";
import {setCssOtherColor} from "../../css-vars";
Expand All @@ -15,7 +14,7 @@ interface OtherColorsProps {
}

export function OtherColors({config, syncIcon, syncThemes, theme}: OtherColorsProps) {
const {setOtherColor} = useContext(ThemeBuilderContext);
const {setOtherColor} = useThemeBuilder();

return (
<ConfigSection id={otherColorsId} title="Other colors">
Expand All @@ -26,20 +25,23 @@ export function OtherColors({config, syncIcon, syncThemes, theme}: OtherColorsPr
type="focus"
onChange={(hexColor) => setCssOtherColor("focus", hexColor)}
onClose={(hexColor) => setOtherColor({focus: hexColor}, theme, syncThemes)}
onCopy={(theme) => copyOtherColorConfig(config, "focus", theme)}
/>
<ColorPicker
hexColor={config[theme].otherColor.overlay}
label="Overlay"
type="overlay"
onChange={(hexColor) => setCssOtherColor("overlay", hexColor)}
onClose={(hexColor) => setOtherColor({overlay: hexColor}, theme, false)}
onCopy={(theme) => copyOtherColorConfig(config, "overlay", theme)}
/>
<ColorPicker
hexColor={config[theme].otherColor.divider}
label="Divider"
type="divider"
onChange={(hexColor) => setCssOtherColor("divider", hexColor)}
onClose={(hexColor) => setOtherColor({divider: hexColor}, theme, false)}
onCopy={(theme) => copyOtherColorConfig(config, "divider", theme)}
/>
</ConfigSection>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import {useContext} from "react";

import {setOtherCssParams} from "../../css-vars";
import {ThemeBuilderContext} from "../../provider";
import {useThemeBuilder} from "../../provider";
import {Config} from "../../types";
import {ConfigSection} from "../config-section";
import {NumberInput} from "../number-input";
Expand All @@ -11,7 +9,7 @@ interface OtherProps {
}

export function Other({config}: OtherProps) {
const {setOtherParams} = useContext(ThemeBuilderContext);
const {setOtherParams} = useThemeBuilder();

const handleChange = (key: keyof Config["layout"]["otherParams"], value: string) => {
setOtherParams({[key]: value});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import {useContext} from "react";

import {setCssRadius} from "../../css-vars";
import {ThemeBuilderContext} from "../../provider";
import {useThemeBuilder} from "../../provider";
import {Config} from "../../types";
import {ConfigSection} from "../config-section";
import {NumberInput} from "../number-input";
Expand All @@ -11,7 +9,7 @@ interface RadiusesProps {
}

export function Radiuses({config}: RadiusesProps) {
const {setRadius} = useContext(ThemeBuilderContext);
const {setRadius} = useThemeBuilder();

return (
<ConfigSection cols={3} title="Radius (rem)">
Expand Down
Loading

0 comments on commit 81869d0

Please sign in to comment.