Dark Mode
Every RonakCN component ships with a dark colour scheme out of the box. Enabling it takes a single widget.
How dark mode works
RonakCN piggy-backs on Flutter's native ThemeMode and Brightness system. When you provide both a theme and a darkTheme to MaterialApp, Flutter automatically selects the correct RcnThemeData based on the current ThemeMode. Components read tokens from RcnTheme.of(context), so they adapt automatically — no if (isDark) branches needed.
ThemeMode widget usage
Pass both light and dark RcnThemeData objects to RcnThemeProvider, then control themeMode on your MaterialApp:
import 'package:flutter/material.dart';
import 'components/theme/rcn_theme.dart';
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
ThemeMode _themeMode = ThemeMode.system;
void _toggleTheme() {
setState(() {
_themeMode = _themeMode == ThemeMode.light
? ThemeMode.dark
: ThemeMode.light;
});
}
@override
Widget build(BuildContext context) {
return RcnThemeProvider(
theme: RcnThemeData.light(),
darkTheme: RcnThemeData.dark(),
themeMode: _themeMode,
child: MaterialApp(
title: 'My App',
themeMode: _themeMode,
theme: ThemeData.light(useMaterial3: true),
darkTheme: ThemeData.dark(useMaterial3: true),
home: HomePage(onToggleTheme: _toggleTheme),
),
);
}
}Following the system theme
Set themeMode: ThemeMode.system (the default) to let Flutter automatically pick light or dark based on the device's OS setting. No additional code is required.
MaterialApp(
themeMode: ThemeMode.system, // default — follows OS setting
theme: ThemeData.light(useMaterial3: true),
darkTheme: ThemeData.dark(useMaterial3: true),
home: const HomePage(),
)Persisting the user's preference
Use shared_preferences to save the selected mode across app launches:
import 'package:shared_preferences/shared_preferences.dart';
// Save
Future<void> saveThemeMode(ThemeMode mode) async {
final prefs = await SharedPreferences.getInstance();
await prefs.setString('themeMode', mode.name);
}
// Load
Future<ThemeMode> loadThemeMode() async {
final prefs = await SharedPreferences.getInstance();
final saved = prefs.getString('themeMode');
return ThemeMode.values.firstWhere(
(m) => m.name == saved,
orElse: () => ThemeMode.system,
);
}Customising dark mode tokens
Override specific colours for dark mode by calling RcnThemeData.dark() with custom values:
final myDarkTheme = RcnThemeData.dark().copyWith(
colorPrimary: const Color(0xFF818CF8), // indigo-400
colorBackground: const Color(0xFF0F0F0F), // near-black
colorBorder: const Color(0xFF2A2A2A),
);The copyWith pattern lets you override only the tokens you care about while inheriting sensible defaults for the rest.