Mihr UI
A complete Flutter UI kit with design tokens, semantic theme extensions, WCAG-compliant palette generation, and production-ready components.
Features
- 6 core + 17 accent + 7 gray color palettes (12 shades each)
- 7 semantic ThemeExtension classes (TextColors, BackgroundColors, BorderColors, ForegroundColors, AlphaColors, UtilityColors, ComponentColors)
- Runtime palette generation from any color with WCAG AA auto-correction
- Typography scale: 11 sizes × 4 weights with Material TextTheme bridge
- Spacing system: 30 primitives + 17 semantic tokens + EdgeInsets/Gap helpers
- Border radius: 11 named sizes with pre-built BorderRadius constants
- Shadows, backdrop blurs, and gradient systems
- Automatic light/dark mode switching
- Button component system: 6 types × 4 sizes with icon variants
- Full Material ColorScheme bridge (30+ properties, 22 widget themes)
Installation
dependencies:
mihr_ui: ^0.1.0-dev.1
Quick Start
import 'package:mihr_ui/mihr_ui.dart';
MaterialApp(
theme: MihrTheme.light(),
darkTheme: MihrTheme.dark(),
home: const MyApp(),
);
Customization
Mihr UI exposes four independent customization layers — pick the narrowest one that solves your problem.
| # | Layer | Scope | API |
|---|---|---|---|
| 1 | Preset | App-wide defaults | MihrThemeConfig |
| 2 | Component theme | One component family | MihrThemeConfig.buttonTheme (and friends) |
| 3 | Per-instance | One widget | style / styleBuilder on the widget |
| 4 | Material escape-hatch | Raw ThemeData |
MihrThemeConfig.materialOverrides |
1. Preset — MihrThemeConfig
The canonical configuration object. Groups brand palette, typography, and every component theme into a single immutable value you can share across apps.
final cfg = MihrThemeConfig(
brand: ColorScaleGenerator.fromHex('#E63946'),
fontFamily: 'Roboto',
);
MaterialApp(
theme: MihrTheme.light(config: cfg),
darkTheme: MihrTheme.dark(config: cfg),
);
2. Component theme
Customize a whole component family (shape, shadows, per-variant style) via a theme extension. Example: flatten every button and override the primary fill.
MihrThemeConfig(
buttonTheme: MihrButtonThemeData(
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(4)),
shadows: MihrButtonShadows.flat,
primaryStyle: const ButtonStyle(
backgroundColor: WidgetStatePropertyAll(Colors.indigo),
),
),
);
3. Per-instance
Every Mihr component accepts a style (and often styleBuilder) prop that
wins over theme-level defaults.
MihrPrimaryButton(
onPressed: _save,
style: const ButtonStyle(
backgroundColor: WidgetStatePropertyAll(Colors.teal),
),
child: const Text('Save'),
);
4. Material escape-hatch — materialOverrides
For Material properties Mihr does not model semantically (e.g.
scaffoldBackgroundColor, AppBarTheme.centerTitle, cardTheme), pass a
callback that receives the fully-built ThemeData with every Mihr default and
returns a modified copy. Use base.bgColors, base.textColors,
base.mihrTypography, and friends to read Mihr tokens ergonomically — no new
classes required.
MihrThemeConfig(
brand: AccentColors.indigo,
materialOverrides: (base) => base.copyWith(
scaffoldBackgroundColor: base.bgColors.secondary,
appBarTheme: base.appBarTheme.copyWith(
centerTitle: true,
backgroundColor: base.bgColors.brandSolid,
foregroundColor: base.textColors.white,
),
cardTheme: base.cardTheme.copyWith(color: base.bgColors.tertiary),
),
);
Accessing tokens anywhere
From a widget, use the BuildContext extension:
context.textColors.primary
context.bgColors.brandSolid
From a ThemeData (inside materialOverrides, tests, or non-widget code),
use the parallel ThemeData extension:
theme.textColors.primary
theme.bgColors.brandSolid
Semantic Token Reference
| Extension | Getter | Tokens |
|---|---|---|
| TextColors | context.textColors |
23 |
| BackgroundColors | context.bgColors |
32 |
| BorderColors | context.borderColors |
10 |
| ForegroundColors | context.fgColors |
21 |
| AlphaColors | context.alphaColors |
20 |
| UtilityColors | context.utilityColors |
18 families |
| ComponentColors | context.componentColors |
29 |
Components
Available button types:
- MihrPrimaryButton — solid brand fill, highest emphasis
- MihrSoftPrimaryButton — tinted brand fill, no border
- MihrSecondaryButton — outlined with gray border
- MihrTertiaryButton — ghost / transparent
- MihrLinkButton — inline text link (brand or gray)
- MihrDestructiveButton — error variants (primary, soft, secondary, tertiary, link)
All buttons support 4 sizes (sm, md, lg, xl) and icon variants.
Contributing
Contributions are welcome! Please read our Contributing Guide before submitting a PR.
License
This project is licensed under the MIT License - see the LICENSE file for details.
Libraries
- Mihr UI button component library.
- core/theme/colors/accent_colors
- core/theme/colors/alpha_colors
- core/theme/colors/background_colors
- core/theme/colors/border_colors
- core/theme/colors/color_scale
- core/theme/colors/color_scale_generator
- core/theme/colors/component_colors
- core/theme/colors/foreground_colors
- core/theme/colors/gray_variants
- core/theme/colors/mihr_colors
- core/theme/colors/mihr_gradients
- core/theme/colors/text_colors
- core/theme/colors/utility_colors
- core/theme/colors/utility_scale
- core/theme/mihr_theme
- core/theme/mihr_theme_config
- core/theme/radius/mihr_radius
- core/theme/shadows/mihr_backdrop_blurs
- core/theme/spacing/mihr_breakpoints
- core/theme/spacing/mihr_spacing
- core/theme/spacing/mihr_widths
- core/theme/typography/mihr_typography
- core/widgets/frosted_container
- mihr_ui
- Mihr UI -- A complete Flutter design system.