'use client';
import { Button, type ButtonProps } from '@/components/ui/button';
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu';
import { Skeleton } from '@/components/ui/skeleton';
import { MoonIcon, SunIcon } from 'lucide-react';
import { useTheme } from 'next-themes';
import { useCallback, useEffect, useState } from 'react';
/**
* Props for the ThemeToggle component.
*/
interface ThemeToggleProps {
/** The variant of the button. */
variant?: ButtonProps['variant'];
/** The size of the button. */
size?: ButtonProps['size'];
/** Additional CSS classes to apply to the button. */
className?: string;
}
/**
* Mapping of button sizes to skeleton sizes.
*/
const skeletonSizes = {
icon: 'h-10 w-10',
default: 'h-10 w-16',
sm: 'h-9 w-14',
lg: 'h-11 w-20',
} as const;
/**
* A component that allows users to toggle between different theme options.
* @param props - The component props.
* @returns A dropdown menu for theme selection.
*/
export function ThemeToggle({ variant = 'outline', size = 'icon', className }: ThemeToggleProps) {
const { setTheme, resolvedTheme, themes } = useTheme();
const [mounted, setMounted] = useState(false);
/**
* Handles setting a new theme.
* @param newTheme - The new theme to set.
*/
const handleSetTheme = useCallback(
(newTheme: string) => {
setTheme(newTheme);
},
[setTheme]
);
useEffect(() => {
setMounted(true);
}, []);
if (!mounted) {
const skeletonSize = skeletonSizes[size as keyof typeof skeletonSizes] || skeletonSizes.icon;
return ;
}
return (
{themes.map((theme) => (
handleSetTheme(theme)} className="capitalize">
{theme}
))}
);
}