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:

lib/main.dart
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.

lib/main.dart
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:

lib/utils/theme_storage.dart
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:

lib/app/themes.dart
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.