Theme Button
Provides an elegant and user-friendly way to cycle through light, dark, and system themes. It's specifically designed to work with next-themes, the most popular theme management library for Next.js applications.
npx shadcn@latest add https://shuip.plvo.dev/r/theme-button.json
pnpm dlx shadcn@latest add https://shuip.plvo.dev/r/theme-button.json
bun x shadcn@latest add https://shuip.plvo.dev/r/theme-button.json
'use client';import type { VariantProps } from 'class-variance-authority';import { Laptop, Moon, Sun } from 'lucide-react';import { useTheme } from 'next-themes';import * as React from 'react';import { Button, type buttonVariants } from '@/components/ui/button';type ButtonProps = React.ComponentProps<'button'> &VariantProps<typeof buttonVariants> & {asChild?: boolean;};type Theme = 'system' | 'light' | 'dark';export interface ThemeButtonProps extends ButtonProps {withText?: boolean;}export function ThemeButton({ withText, ...props }: ThemeButtonProps) {const { theme, setTheme } = useTheme();const [currentTheme, setCurrentTheme] = React.useState<Theme>('system');React.useEffect(() => {setCurrentTheme(theme as Theme);}, [theme]);const cycleTheme = () => {const themes: Theme[] = ['system', 'light', 'dark'];const currentIndex = themes.indexOf(currentTheme);const nextIndex = (currentIndex + 1) % themes.length;setTheme(themes[nextIndex]);};const getThemeIcon = () => {switch (currentTheme) {case 'system':return <Laptop className='size-[1.2rem]' />;case 'light':return <Sun className='size-[1.2rem]' />;case 'dark':return <Moon className='size-[1.2rem]' />;}};const getThemeText = () => {return currentTheme.charAt(0).toUpperCase() + currentTheme.slice(1);};return (<Button variant='outline' size={withText ? 'default' : 'icon'} onClick={cycleTheme} {...props}>{getThemeIcon()}{withText && <span className='ml-2 capitalize'>{getThemeText()}</span>}<span className='sr-only'>Toggle theme</span></Button>);}
Loading...
Ready-to-use theme toggle
The button automatically cycles through these states:
- System: Uses the user's OS preference (🖥️ Laptop icon)
- Light: Forces light mode (☀️ Sun icon)
- Dark: Forces dark mode (🌙 Moon icon)
With ThemeButton, a complete theme switcher in one line:
With ThemeButton - simple and complete
<ThemeButton />With text label
<ThemeButton withText={true} />Setup with next-themes
First, make sure you have next-themes installed and configured:
Examples
Default
Loading...
import { ThemeButton } from '@/components/ui/shuip/theme-button';export default function ThemeButtonExample() {return <ThemeButton />;}
Text
Loading...
import { ThemeButton } from '@/components/ui/shuip/theme-button';export default function ThemeButtonTextExample() {return <ThemeButton withText />;}
Props
Prop
Type
Submit Button
Specifically designed for form submission with built-in loading states, making it perfect for forms that need to show submission progress and prevent double submissions.
Address Field
Address input component with Google Places autocomplete integration. Automatically parses and validates complete address data.