diff --git a/apps/www/config/docs.ts b/apps/www/config/docs.ts index e41fdf49d..e192c0a94 100644 --- a/apps/www/config/docs.ts +++ b/apps/www/config/docs.ts @@ -120,6 +120,21 @@ export const docsConfig: DocsConfig = { }, ], }, + { + title: "Dark Mode", + items: [ + { + title: "Next.js", + href: "/docs/dark-mode/next", + items: [], + }, + { + title: "Vite", + href: "/docs/dark-mode/vite", + items: [], + }, + ], + }, { title: "Components", items: [ diff --git a/apps/www/content/docs/dark-mode/index.mdx b/apps/www/content/docs/dark-mode/index.mdx new file mode 100644 index 000000000..214118d60 --- /dev/null +++ b/apps/www/content/docs/dark-mode/index.mdx @@ -0,0 +1,37 @@ +--- +title: Dark Mode +description: Adding dark mode to your site. +--- + +
+ + + Next.js + + +

Next.js

+
+ + + Vite + + +

Vite

+
+
+ +## Other frameworks + +I'm looking for help writing guides for other frameworks. Help me write guides for Remix, Astro and Vite by [opening an PR](https://github.com/shadcn/ui). diff --git a/apps/www/content/docs/dark-mode.mdx b/apps/www/content/docs/dark-mode/next.mdx similarity index 81% rename from apps/www/content/docs/dark-mode.mdx rename to apps/www/content/docs/dark-mode/next.mdx index 2c85e38da..ef7489cad 100644 --- a/apps/www/content/docs/dark-mode.mdx +++ b/apps/www/content/docs/dark-mode/next.mdx @@ -1,9 +1,9 @@ --- -title: Dark Mode -description: Adding dark mode to your site. +title: Next.js +description: Adding dark mode to your next app. --- -## Next.js +## Dark mode @@ -51,7 +51,3 @@ Place a mode toggle on your site to toggle between light and dark mode. - -## Other frameworks - -I'm looking for help writing guides for other frameworks. Help me write guides for Remix, Astro and Vite by [opening an PR](https://github.com/shadcn/ui). diff --git a/apps/www/content/docs/dark-mode/vite.mdx b/apps/www/content/docs/dark-mode/vite.mdx new file mode 100644 index 000000000..53afa9961 --- /dev/null +++ b/apps/www/content/docs/dark-mode/vite.mdx @@ -0,0 +1,148 @@ +--- +title: Vite +description: Adding dark mode to your vite app. +--- + +## Dark mode + + + +### Create a theme provider + +```tsx title="components/theme-provider.tsx" +import { createContext, useContext, useEffect, useState } from "react" + +type ThemeProviderProps = { + children: React.ReactNode + defaultTheme?: string + storageKey?: string +} + +type ThemeProviderState = { + theme: string + setTheme: (theme: string) => void +} + +const initialState = { + theme: "system", + setTheme: () => null, +} + +const ThemeProviderContext = createContext(initialState) + +export function ThemeProvider({ + children, + defaultTheme = "system", + storageKey = "vite-ui-theme", + ...props +}: ThemeProviderProps) { + const [theme, setTheme] = useState( + () => localStorage.getItem(storageKey) || defaultTheme + ) + + useEffect(() => { + const root = window.document.documentElement + + root.classList.remove("light", "dark") + + if (theme === "system") { + const systemTheme = window.matchMedia("(prefers-color-scheme: dark)") + .matches + ? "dark" + : "light" + + root.classList.add(systemTheme) + return + } + + root.classList.add(theme) + }, [theme]) + + const value = { + theme, + setTheme: (theme: string) => { + localStorage.setItem(storageKey, theme) + setTheme(theme) + }, + } + + return ( + + {children} + + ) +} + +export const useTheme = () => { + const context = useContext(ThemeProviderContext) + + if (context === undefined) + throw new Error("useTheme must be used within a ThemeProvider") + + return context +} +``` + +### Wrap your root layout + +Add the `ThemeProvider` to your root layout. + +```tsx {1,5-7} title="App.tsx" +import { ThemeProvider } from "@/components/theme-provider" + +function App() { + return ( + + {children} + + ) +} + +export default App +``` + +### Add a mode toggle + +Place a mode toggle on your site to toggle between light and dark mode. + +```tsx title="components/mode-toggle.tsx" +import { Moon, Sun } from "lucide-react" + +import { Button } from "@/components/ui/button" +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuTrigger, +} from "@/components/ui/dropdown-menu" +import { useTheme } from "@/components/theme-provider" + +export function ModeToggle() { + const { setTheme } = useTheme() + + return ( + + + + + + setTheme("light")}> + Light + + setTheme("dark")}> + Dark + + setTheme("system")}> + System + + + + ) +} +``` + +