Color Operations#
ArcaneColorOps is an extension on String that adds opacity and blend helpers to any CSS color. Colors cross the styling boundary as raw strings — a hex value, a theme variable, an
ArcaneColor.*.css token, or a runtime accent — and these helpers work for every one of those forms.
Source: lib/util/style_types/colors.dart
The problem it replaces#
The historic ${color}30 hex-alpha suffix hack only works on plain hex colors. Applied to anything else it produces invalid CSS:
// Broken: 'var(--primary)30' is not a valid color.
final String faded = '${accent}30';
Hand-writing color-mix(...) works but is verbose and easy to get wrong:
// Correct but repetitive.
final String faded = 'color-mix(in srgb, var(--primary) 30%, transparent)';
ArcaneColorOps gives you both correctly and concisely.
.opacity(double amount)#
Fades a color toward transparent. amount is clamped to 0.0..1.0.
'var(--primary)'.opacity(0.3);
// -> color-mix(in srgb, var(--primary) 30%, transparent)
It works on hex, variables, and tokens alike:
'#4CAF50'.opacity(0.15); // color-mix(in srgb, #4CAF50 15%, transparent)
'var(--foreground)'.opacity(0.6);
Colors.emerald500.css.opacity(0.5);
.on(String base, double amount)#
Blends amount of this color over base, keeping alpha at 1.
'#000'.on('var(--card)', 0.1);
// -> color-mix(in srgb, #000 10%, var(--card))
Use it to darken or tint a surface without introducing transparency:
'var(--primary)'.on('var(--background)', 0.08); // a faint primary wash
Using it in components#
The helpers return plain CSS strings, so they slot directly into any field that takes a color string — decoration colors,
styles: raw maps, and the accentColor fields on the card family:
Card(
decoration: ArcaneDecoration(
color: 'var(--primary)'.opacity(0.08),
border: '1px solid ${'var(--primary)'.opacity(0.4)}',
),
child: const Text.body('Tinted surface, valid on every color form.'),
)
FeatureCard(
title: 'Fast',
description: 'Builds in seconds.',
accentColor: 'var(--primary)'.opacity(0.9),
)
Precision#
The mix percentage keeps one decimal, so small values do not quantize away and whole numbers stay clean:
'#fff'.opacity(0.125); // color-mix(in srgb, #fff 12.5%, transparent)
'#fff'.opacity(0.3); // color-mix(in srgb, #fff 30%, transparent)