Dark Mode
Wind makes it incredibly easy to support dark mode using the dark: variant modifier. Instead of managing complex theme objects or multiple style sheets, you simply prefix your utility classes to apply styles only when dark mode is active.
WDiv(
className: "p-6 bg-white dark:bg-slate-900 rounded-xl shadow-lg dark:shadow-none border border-gray-200 dark:border-slate-800",
child: WText(
"Dark Mode Support",
className: "text-gray-900 dark:text-white font-bold",
),
)
Basic Usage
To style an element for dark mode, add the dark: prefix to any utility class. This works for colors, borders, shadows, and even opacity.
Let's look at a practical example:
WDiv(
className: "bg-gray-100 text-gray-900 dark:bg-gray-800 dark:text-gray-100",
child: WText("Adaptive text colors"),
)
In this example, the background will be light gray in light mode and shift to a dark gray when dark mode is enabled. The text color behaves similarly, maintaining readability across themes.
System vs Manual Mode
By default, Wind follows the system's brightness settings via MediaQuery.platformBrightness. However, you can manually override this behavior to allow users to toggle themes within your app.
Manual Toggling
You can use the WindTheme controller to toggle the theme or set a specific brightness programmatically:
// Toggle between light and dark
context.windTheme.toggleTheme();
// Force dark mode
context.windTheme.setTheme(
context.windThemeData.copyWith(brightness: Brightness.dark),
);
Material Sync
If you want your Material ThemeData to stay in sync with Wind's dark mode, use the toThemeData() helper in your MaterialApp. This is particularly useful for styling native Material components that aren't yet wrapped in Wind widgets.
WindTheme(
data: WindThemeData(),
builder: (context, controller) => MaterialApp(
theme: controller.toThemeData(),
home: const HomePage(),
),
)
Responsive Dark Mode
You can combine the dark: modifier with responsive breakpoints to create highly specific layouts. The order of modifiers doesn't strictly matter, but following a consistent pattern like {breakpoint}:{state}:{utility} is recommended for readability.
WDiv(
// Blue background on mobile, but red on large screens ONLY in dark mode
className: "bg-blue-500 lg:dark:bg-red-500",
)
Best Practices
Avoid Pure Black
Using pure black (#000000) for backgrounds can often lead to high contrast that causes eye strain. We recommend using deep grays or slates like slate-900 or gray-900 for a more polished dark mode experience.
// Recommended
className: "dark:bg-slate-900"
// Use sparingly
className: "dark:bg-black"
Soften Your Borders
Borders that look great in light mode might appear too harsh in dark mode. Consider reducing the opacity or choosing a darker shade for borders to keep the design soft.
WDiv(className: "border border-gray-200 dark:border-gray-700")