Dark Mode
Learn how to enable and manage dark mode in your Fidely UI projects.
π Dark Mode
Fidely UI doesnβt include a built-in color mode manager.
Instead, it integrates seamlessly with next-themes a lightweight and powerful theme switcher for you project.
Install next-themes
npm install next-themespnpm add next-themesWrap your app with ThemeProvider
You can create a provider
//app/provider.tsx
'use client'
import { ThemeProvider } from 'next-themes'
export const Provider = (props: { children: React.ReactNode }) => {
return (
<ThemeProvider
attribute="class"
defaultTheme="system" // optional
enableSystem
disableTransitionOnChange
>
{props.children}
</ThemeProvider>
)
}Explanation:
attribute="class" β adds class="light" or class="dark" to html tag.
defaultTheme="system" β follows user OS preference.
disableTransitionOnChange β prevents flashing when switching themes.
In your app/layout.tsx or _app.tsx, import and wrap your application with the ThemeProvider created above
import { Provider } from '../proider' // your proider file path
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode
}>) {
return (
<html lang="en" suppressHydrationWarning>
<body>
<Provider>{children}</Provider>
</body>
</html>
)
}Styling dark mode
Use the _dark condition to style components for dark mode.
<Box bg={{ base: 'white', _dark: 'black' }}>
<Text>Hello</Text>
</Box>or
<Box bg="white" _dark={{ bg: 'black' }}>
<Text>Hello</Text>
</Box>Using semantic tokens
To reduce repetition and ensure consistency, use semantic tokens.
Fidely UI provides semantic tokens built on Panda CSS, which automatically adjust for light and dark themes.
<Box bg="bg.subtle">
<Text>Hello</Text>
</Box>Semantic Tokens in Fidely UI
-
Background (bg): surface | muted | emphasized | disabled | default
-
Foreground (fg): error | muted | subtle | disabled | default
-
Border (border): outline | muted | subtle | disabled | default | error
These tokens handle both light and dark mode colors automatically.
Forcing Color Mode
You can explicitly force dark or light mode by applying a corresponding class name to a parent element.
Element Specific Dark Mode
To force dark mode, add the dark className to any parent element (including the root of your application). All child components will inherit the dark color scheme.
<Box className="dark">
<Box bg="bg.subtle">
<Text>Hello World</Text>
</Box>
</Box>Element Specific Light Mode
Similarly, to force light mode, apply the light className to a parent element.
This ensures all nested components render using the light color scheme.
<Box className="light">
<Box bg="bg.subtle">
<Text>Hello World</Text>
</Box>
</Box>Add a Theme Toggle Button
Hereβs an example of a simple toggle button:
'use client'
import { ClientOnly, IconButton, Skeleton } from '@fidely-ui/react'
import { IoSunnyOutline } from 'react-icons/io5'
import { FaMoon } from 'react-icons/fa6'
export function ThemeToggle() {
const { theme, setTheme } = useTheme()
const toggleTheme = () => {
setTheme(theme === 'light' ? 'dark' : 'light')
}
return (
<ClientOnly fallback={<Skeleton boxSize="8" />}>
<IconButton
onClick={toggleTheme}
size="xs"
color="inherit"
variant="ghost"
>
{theme === 'light' ? (
<IoSunnyOutline size={'17px'} />
) : (
<FaMoon size={'17px'} />
)}
</IconButton>
</ClientOnly>
)
}Works perfectly with Fidely UI components β all dark mode tokens update instantly.
Example Live Usage
// app/page.tsx
import { ThemeToggle } from '../theme-toggle'
import { Box } from '@fidely-ui/react'
export default function Page() {
return (
<Box p="6">
<ThemeToggle />
<Box>Hello from Fidely UI π</Box>
</Box>
)
}