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.
// 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.
| Token | Dart field | Purpose |
|---|---|---|
primary | colorPrimary | Brand / interactive elements |
primaryForeground | colorPrimaryForeground | Text on primary backgrounds |
secondary | colorSecondary | Secondary interactive elements |
secondaryForeground | colorSecondaryForeground | Text on secondary backgrounds |
background | colorBackground | Page / screen background |
foreground | colorForeground | Default text colour |
muted | colorMuted | Subtle backgrounds, placeholders |
mutedForeground | colorMutedForeground | Muted text, labels |
destructive | colorDestructive | Error / danger states |
border | colorBorder | Dividers 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.
{
"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.
Using tokens in your own widgets
Read tokens anywhere in your widget tree via RcnTheme.of(context):
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.