better-themes
Frameworks

Vite

Setup guide for Vite and Create React App

Installation

npm install better-themes

Setup

Update your root component

In your main entry file (typically main.tsx or App.tsx), wrap your app with ThemeProvider:

main.tsx
import { ThemeProvider } from "better-themes";
import { createRoot } from "react-dom/client";
import App from "./App";
import "./global.css";

createRoot(document.getElementById("root")!).render(
  <ThemeProvider>
    <App />
  </ThemeProvider>
);

Style your app

global.css
:root {
  --background: white;
  --foreground: black;
}

.dark {
  --background: black;
  --foreground: white;
}

body {
  background: var(--background);
  color: var(--foreground);
}

Create a theme switcher component

components/ThemeSwitcher.tsx
import { useTheme } from "better-themes";
import { useEffect, useState } from "react";

export function ThemeSwitcher() {
  const [mounted, setMounted] = useState(false);
  const { theme, setTheme } = useTheme();

  useEffect(() => {
    setMounted(true);
  }, []);

  if (!mounted) {
    return null;
  }

  return (
    <button onClick={() => setTheme(theme === "dark" ? "light" : "dark")}>
      Toggle theme
    </button>
  );
}

Complete Example

main.tsx
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import "./global.css";
import App from "./App.tsx";
import { ThemeProvider } from "better-themes";

createRoot(document.getElementById("root")!).render(
  <StrictMode>
    <ThemeProvider>
      <App />
    </ThemeProvider>
  </StrictMode>
);
components/ThemeSwitcher.tsx
import { useTheme } from "better-themes";
import { useEffect, useState } from "react";

export function ThemeSwitcher() {
  const [mounted, setMounted] = useState(false);
  const { theme, setTheme } = useTheme();

  useEffect(() => {
    setMounted(true);
  }, []);

  if (!mounted) {
    return null;
  }

  return (
    <button onClick={() => setTheme(theme === "dark" ? "light" : "dark")}>
      {theme === "dark" ? "Light" : "Dark"}
    </button>
  );
}

Notes

  • Use the default export for Vite
  • If using Vite with SSR, add suppressHydrationWarning to the <html> tag
  • Works with both Vite and Create React App

Example

View a complete example implementation: Vite Example

Try the live demo: Live Demo

On this page