DSNProvider
App-level provider that manages dark/light mode for all library components. Wrap once at the root — done.
Quick Start
Wrap your app root with DSNProvider. All library components inside will automatically follow the active theme.
// _app.tsx (Next.js Pages Router)
import { DSNProvider } from 'dosieungon-ui';
export default function App({ Component, pageProps }) {
return (
<DSNProvider>
<Component {...pageProps} />
</DSNProvider>
);
}
// layout.tsx (Next.js App Router)
import { DSNProvider } from 'dosieungon-ui';
export default function RootLayout({ children }) {
return (
<html lang="en">
<body>
<DSNProvider>{children}</DSNProvider>
</body>
</html>
);
}How it works
On mount, the Provider reads the user's saved preference from localStorage. If none exists, it defaults to the system preference via prefers-color-scheme.
It wraps its children with data-dsg-theme and — by default — mirrors the same attribute and class="dark" onto <html>. This ensures portal elements (Modal, Drawer) and Tailwind dark: utilities also respond correctly.
useTheme
Access and control the active theme from any component inside DSNProvider.
Scoped Theme
Nest a DSNProvider with syncDocument={false} to force a theme for a specific section without affecting the rest of the page.
Even when the page is in light mode.
Even when the page is in dark mode.
Without Provider (CSS fallback)
If you don't use DSNProvider, components still respond to prefers-color-scheme automatically via CSS media query — no JS needed.
The CSS fallback is always active. DSNProvider adds persistence, toggling, and useTheme — but components work without it.
Next.js App Router
DSNProvider uses useState, useEffect, and localStorage — it must run on the client. Wrap it in a 'use client' component or add the directive to the file that imports it.
// providers.tsx
'use client';
import { DSNProvider } from 'dosieungon-ui';
export function Providers({ children }: { children: React.ReactNode }) {
return <DSNProvider>{children}</DSNProvider>;
}
// layout.tsx
import { Providers } from './providers';
export default function RootLayout({ children }) {
return (
<html lang="en">
<body>
<Providers>{children}</Providers>
</body>
</html>
);
}DSNProvider API
| Property | Type | Default | Description |
|---|---|---|---|
defaultTheme | "light" | "dark" | "system" | "system" | Initial theme when no localStorage value exists. "system" follows prefers-color-scheme. |
theme | "light" | "dark" | "system" | — | Controlled theme. When set, setTheme() from useTheme() is a no-op. |
storageKey | string | "dsg-theme" | localStorage key used to persist the chosen theme across page reloads. |
syncDocument | boolean | true | Mirrors the resolved theme onto document.documentElement — sets data-dsg-theme attribute and toggles class "dark"/"light". Required for portals (Modal, Drawer) and Tailwind dark: utilities. |
useTheme return value
| Property | Type | Default | Description |
|---|---|---|---|
theme | "light" | "dark" | "system" | — | The active setting. Can be "system" if the user chose to follow OS preference. |
resolvedTheme | "light" | "dark" | — | The actual rendered theme — always "light" or "dark", never "system". |
setTheme | (theme: "light" | "dark" | "system") => void | — | Update the theme. Persists to localStorage. No-op when Provider is controlled. |