Files
wkc-website/src/components/ui/color-mode.tsx
2025-08-14 18:29:30 -04:00

112 lines
2.8 KiB
TypeScript

/* eslint-disable @typescript-eslint/no-empty-object-type */
/* eslint-disable prettier/prettier */
/* eslint-disable no-unused-vars */
"use client";
import type { IconButtonProps, SpanProps } from "@chakra-ui/react";
import { ClientOnly, IconButton, Skeleton, Span } from "@chakra-ui/react";
import { ThemeProvider, useTheme } from "next-themes";
import type { ThemeProviderProps } from "next-themes";
import * as React from "react";
import { LuMoon, LuSun } from "react-icons/lu";
export interface ColorModeProviderProps extends ThemeProviderProps {}
export function ColorModeProvider(props: ColorModeProviderProps) {
return (
<ThemeProvider attribute="class" disableTransitionOnChange {...props} />
);
}
export type ColorMode = "light" | "dark";
export interface UseColorModeReturn {
colorMode: ColorMode;
setColorMode: (colorMode: ColorMode) => void;
toggleColorMode: () => void;
}
export function useColorMode(): UseColorModeReturn {
const { resolvedTheme, setTheme, forcedTheme } = useTheme();
const colorMode = forcedTheme || resolvedTheme;
const toggleColorMode = () => {
setTheme(resolvedTheme === "dark" ? "light" : "dark");
};
return {
colorMode: colorMode as ColorMode,
setColorMode: setTheme,
toggleColorMode
};
}
export function useColorModeValue<T>(light: T, dark: T) {
const { colorMode } = useColorMode();
return colorMode === "dark" ? dark : light;
}
export function ColorModeIcon() {
const { colorMode } = useColorMode();
return colorMode === "dark" ? <LuMoon /> : <LuSun />;
}
interface ColorModeButtonProps extends Omit<IconButtonProps, "aria-label"> {}
export const ColorModeButton = React.forwardRef<
HTMLButtonElement,
ColorModeButtonProps
>(function ColorModeButton(props, ref) {
const { toggleColorMode } = useColorMode();
return (
<ClientOnly fallback={<Skeleton boxSize="8" />}>
<IconButton
onClick={toggleColorMode}
variant="ghost"
aria-label="Toggle color mode"
size="sm"
ref={ref}
{...props}
css={{
_icon: {
width: "5",
height: "5"
}
}}
>
<ColorModeIcon />
</IconButton>
</ClientOnly>
);
});
export const LightMode = React.forwardRef<HTMLSpanElement, SpanProps>(
function LightMode(props, ref) {
return (
<Span
color="fg"
display="contents"
className="chakra-theme light"
colorPalette="gray"
colorScheme="light"
ref={ref}
{...props}
/>
);
}
);
export const DarkMode = React.forwardRef<HTMLSpanElement, SpanProps>(
function DarkMode(props, ref) {
return (
<Span
color="fg"
display="contents"
className="chakra-theme dark"
colorPalette="gray"
colorScheme="dark"
ref={ref}
{...props}
/>
);
}
);