Theming

RonakCN uses a design token system. Change the tokens once and every component updates automatically.


How the token system works

Every RonakCN component reads colours, spacing, and shape values from a central RcnTheme object that you provide at the top of your widget tree. This is a plain Dart class — no build runner, no code generation. When you change a token value, Flutter rebuilds only the widgets that depend on it.

lib/main.dart
// main.dart
import 'package:flutter/material.dart';
import 'components/theme/rcn_theme.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return RcnThemeProvider(
      theme: RcnThemeData.defaults(),
      child: MaterialApp(
        title: 'My App',
        home: const HomePage(),
      ),
    );
  }
}

Color tokens

Colours follow a semantic naming convention. Each token has a corresponding foreground pair that is guaranteed to meet WCAG AA contrast against the base.

TokenDart fieldPurpose
primarycolorPrimaryBrand / interactive elements
primaryForegroundcolorPrimaryForegroundText on primary backgrounds
secondarycolorSecondarySecondary interactive elements
secondaryForegroundcolorSecondaryForegroundText on secondary backgrounds
backgroundcolorBackgroundPage / screen background
foregroundcolorForegroundDefault text colour
mutedcolorMutedSubtle backgrounds, placeholders
mutedForegroundcolorMutedForegroundMuted text, labels
destructivecolorDestructiveError / danger states
bordercolorBorderDividers and outlines

Customising with ronakcn.json

The ronakcn.json file at your project root controls which preset the CLI uses and what overrides to apply when copying components. Change values here, then re-run ronakcn update --all to propagate changes.

ronakcn.json
{
  "version": "1",
  "outputDir": "lib/components",
  "theme": {
    "preset": "default",
    "radius": "lg",
    "colors": {
      "primary": "#6366f1",
      "primaryForeground": "#ffffff",
      "secondary": "#f1f5f9",
      "secondaryForeground": "#0f172a",
      "destructive": "#ef4444",
      "background": "#ffffff",
      "foreground": "#09090b"
    }
  }
}

Built-in presets

RonakCN ships several named presets. Specify one in ronakcn.json and all token defaults are set automatically. Your colors overrides always take precedence.

defaultoceanforestroseslateamber

Using tokens in your own widgets

Read tokens anywhere in your widget tree via RcnTheme.of(context):

lib/widgets/my_card.dart
import 'package:flutter/material.dart';
import '../theme/rcn_theme.dart';

class MyCard extends StatelessWidget {
  const MyCard({super.key, required this.child});

  final Widget child;

  @override
  Widget build(BuildContext context) {
    final theme = RcnTheme.of(context);

    return Container(
      decoration: BoxDecoration(
        color: theme.colorBackground,
        borderRadius: theme.radiusMd,
        border: Border.all(color: theme.colorBorder),
      ),
      padding: const EdgeInsets.all(16),
      child: child,
    );
  }
}

Tip: Prefer RcnTheme.of(context) over hard-coded colours. Doing so means your widgets automatically adapt when the user switches between light and dark mode, or when you swap presets.