Skip to content

Dark Mode

Every ShadcnStore block ships with dark mode built in. Each block uses shadcn/ui design tokens and Tailwind dark: variants, so it adapts automatically once your app toggles the dark class on the <html> element. You do not need to edit any block code.

How it works

Blocks reference CSS variables (for example bg-background, text-foreground) that resolve to different values under the .dark class. Your job is to add and persist that class. Toggling it flips every block at once.

Next.js

Use next-themes, which persists the choice and avoids a flash of the wrong theme on load.

bash
npm install next-themes
tsx
// app/providers.tsx
"use client"
import { ThemeProvider } from "next-themes"

export function Providers({ children }: { children: React.ReactNode }) {
  return (
    <ThemeProvider attribute="class" defaultTheme="system" enableSystem>
      {children}
    </ThemeProvider>
  )
}

Wrap your app in <Providers> and toggle with useTheme():

tsx
"use client"
import { useTheme } from "next-themes"
import { Button } from "@/components/ui/button"

export function ModeToggle() {
  const { theme, setTheme } = useTheme()
  return (
    <Button variant="outline" size="icon"
      onClick={() => setTheme(theme === "dark" ? "light" : "dark")}>
      Toggle theme
    </Button>
  )
}

Vite (or plain React)

There is no framework provider, so persist the choice yourself. This reads the saved theme, falls back to the system preference, and stores changes so they survive a reload:

tsx
import { useEffect, useState } from "react"

export function useDarkMode() {
  const [isDark, setIsDark] = useState(() => {
    const saved = localStorage.getItem("theme")
    if (saved) return saved === "dark"
    return window.matchMedia("(prefers-color-scheme: dark)").matches
  })

  useEffect(() => {
    document.documentElement.classList.toggle("dark", isDark)
    localStorage.setItem("theme", isDark ? "dark" : "light")
  }, [isDark])

  return { isDark, toggle: () => setIsDark((v) => !v) }
}

To avoid a flash before hydration, set the class in an inline script in your index.html <head> before the app loads.