Theming
CDX UI is themed through a single ThemeExtension — CdxConfig — and a factory function — createCdxTheme — that produces a ThemeData with every Material component theme pre-wired. Apps customize tokens once; every CDX widget picks them up automatically.
Live Example
Open the full route: Theming.
CdxConfig
CdxConfig is registered as a ThemeData.extensions entry. Resolve it anywhere via:
final cdx = CdxConfig.of(context); // never null — falls back to defaults
final maybeCdx = CdxConfig.maybeOf(context); // null if not registeredShape tokens
| Token | Type | Default | Used by |
|---|---|---|---|
controlBorderRadius | BorderRadius | 4 | Badges, chips, dropdown frames, dialog actions |
containerBorderRadius | BorderRadius | 8 | Cards, dialogs, panels, banners |
controlPadding | double | 4 | Badge padding, chip padding (multiplied) |
containerPadding | double | 16 | SectionCard, banner, locked surface |
controlHeight | double | 36 | Button, SplitActionButton, CdxSegmentedTabs, dropdown triggers |
horizontalGap | double | 16 | Dialog footer actions, toolbars, header action rows |
verticalGap | double | 16 | Form groups, settings rows, stacked section rhythm |
compactControlSize | double | 32 | Button.icon(compact: true), CdxChip(size: compact) |
iconSize | double | 16 | In-control icons across buttons, menus, segmented tabs, triggers |
headerHeight | double | 70 | Entity / panel / dialog header bands |
Color tokens
Every color is nullable — null means "use the Material ColorScheme fallback". Resolvers are colocated with the field so call sites read from one place.
| Resolver | Falls back to |
|---|---|
primaryOf(scheme) | scheme.primary |
errorOf(scheme) | scheme.error |
surfaceOf(scheme) | scheme.surface |
borderOf(scheme) | scheme.outline |
disabledOf(scheme) | scheme.onSurface @ 38% |
disabledButtonFillOf(scheme) | scheme.onSurface @ 12% (M3 spec) |
disabledButtonTextOf(scheme) | scheme.onSurface @ 38% (M3 spec) |
hoverTintOf(scheme) | primary @ 8% |
selectedTintOf(scheme) | primary @ 16% |
Status palette (Material does NOT ship this)
CdxConfig adds three brightness-aware palettes Material 3 lacks: success, warning, neutral. critical and info resolve through error and primary respectively (same canonical hex). All container/on-container pairs target ≥7:1 contrast (AAA).
final cdx = CdxConfig.of(context);
final scheme = Theme.of(context).colorScheme;
cdx.successOf(scheme); // Green-700 light / Emerald-400 dark
cdx.successContainerOf(scheme); // Green-100 light / Emerald-900 dark
cdx.warningOf(scheme); // Amber-500 light / Amber-400 dark
cdx.criticalOf(scheme); // == errorOf
cdx.infoOf(scheme); // == primaryOf
cdx.neutralOf(scheme); // Slate-600 light / Slate-400 darkUsed by Banner, StatusBadge, ActivityTimeline (ActivityOutcome), the workflow timeline, and any widget that needs status semantics.
Custom theme
final theme = ThemeData.from(colorScheme: ColorScheme.fromSeed(...))
.copyWith(extensions: [
CdxConfig(
controlHeight: 36, // tighter buttons
selectedTint: Colors.indigo.withValues(alpha: 0.18),
warning: const Color(0xffd97706), // brand-tuned amber
),
]);Or wire everything at once with createCdxTheme.
createCdxTheme
createCdxTheme returns a ThemeData with every Material component theme pre-wired (buttons, dialog, card, snackbar, picker, chip, slider, divider, navigation rail, tab bar, etc.) plus the CdxConfig extension. Brands typically call it once per brightness:
final lightTheme = createCdxTheme(
colorScheme: brand.lightScheme,
textTheme: brand.textTheme,
);
final darkTheme = createCdxTheme(
colorScheme: brand.darkScheme,
textTheme: brand.textTheme,
);
// Tune sizing if needed:
final dense = createCdxTheme(
colorScheme: brand.lightScheme,
textTheme: brand.textTheme,
config: const CdxConfig(controlHeight: 36, compactControlSize: 28),
);The component themes pulled in by createCdxTheme cover:
- Buttons (
elevated,filled,outlined,text,icon,floating,menu) - Inputs (
inputDecorationTheme,dropdownMenuTheme,searchBarTheme,searchViewTheme) - Containers (
cardTheme,dialogTheme,appBarTheme,navigationBarTheme,navigationRailTheme,tabBarTheme) - Form controls (
switchTheme,checkboxTheme,radioTheme,sliderTheme,chipTheme) - Data (
dataTableTheme,segmentedButtonTheme,listTileTheme) - Pickers (
datePickerTheme,timePickerTheme) - Menus & overlays (
popupMenuTheme,menuTheme,tooltipTheme,snackBarTheme) - Misc (
dividerTheme,progressIndicatorTheme)
Cross-links
- Density & Sizing —
controlHeight,compactControlSize,headerHeight - Overlays —
hoverTint,selectedTint,CdxStateLayer - Buttons — read
controlHeightandcontrolBorderRadius - Badges —
StatusBadgereads the status palette