Jaspr Material Color scheme
A package for the Jaspr framework that automatically generates a full Material 3 color scheme, injects it as global CSS variables, and provides a type-safe way to use the theme colors in your components.
This package uses the official material color utilities algorithms to generate themes that are fully compliant with the Material 3 specification.
Features
- Automatic Theming: Automatically adapts to the user's system settings for light/dark mode and contrast levels (
prefers-color-scheme
,prefers-contrast
). - One-Liner Setup: Generate a complete, beautiful, and accessible theme from a single seed color.
- Multiple Variants: Choose from various Material 3 theme generation styles like
tonalSpot
,expressive
,content
,fidelity
, and more. - Type-Safe Colors: Use the provided
MaterialColors
class to access theme colors in your component styles with autocompletion and compile-time safety. - Dynamic Theme Switching: Easily build UI controls (like a dark mode toggle) to change the theme at runtime on the client.
- Deep Customization: Offers an advanced API to override seed colors for every palette and fine-tune your theme.
Getting Started
1. Installation
Add the package to your pubspec.yaml
dependencies:
dart pub add jaspr_material_colors
2. Setup
The core of the package is the Document.withColorScheme
component. You need to use it in place of the standard Document
at the root of your application.
This component sets up all the necessary CSS variables and media queries.
import package:jaspr_material_color_scheme/document.dart
with an alias to avoid conflict with the core jaspr APIs
only import
package:jaspr_material_color_scheme/document.dart
for the document part. for the rest of the codebase , usepakage:jaspr_material_color_scheme/jaspr_material_color_scheme.dart
instead.
Here is a complete example of a minimal setup:
import 'package:jaspr_material_color_scheme/document.dart' as csd; // <---------|
import 'package:jaspr/jaspr.dart';
import 'app.dart';
import 'jaspr_options.dart';
void main() {
Jaspr.initializeApp(
options: defaultJasprOptions,
);
// creates a color scheme from scratch
final colorscheme = csd.MaterialColorScheme(
styleVariant: csd.Variant.vibrant,
sourceColor: Color('#38db9b'),
primarySeed: Color('#38db9b'),
secondarySeed: Color('#859ee9'),
tertiarySeed: Color('#7b65e3'),
neutralSeed: Color('#f2fdf9'),
neutralVariantSeed: Color('#03100b'),
errorSeed: Color('#9c1b1b'),
);
runApp(
csd.Document.withColorScheme(
colorScheme: colorscheme,
// optionally specify which mode to use (will default to using media queries according to user browser prefrences)
// defaultScheme: ColorScheme.light, <----
// defaultContrast: Contrast.more <----
title: 'example',
body: App(),
),
);
}
check Advanced Usage for more info.
Using Theme Colors
Once the Document.withColorScheme
is set up, you can access all the theme colors using the static getters on the MaterialColors
class. This class provides Color
objects that point directly to the generated CSS variables.
This provides a great developer experience with autocompletion and prevents typos from using raw strings.
return div(
styles: Styles(
padding: Padding.all(16.px),
backgroundColor: MaterialColors.surfaceContainer,
color: MaterialColors.onSurface,
border: Border(color: MaterialColors.outlineVariant),
radius: BorderRadius.circular(1.rem),
),
[
h1([Text('Card Title')],
styles: Styles(color: MaterialColors.primary)),
p([Text('This card is styled using the generated Material 3 colors.')]),
],
);
Switching Themes at Runtime
The package provides an extension method on BuildContext
to easily switch the active theme or contrast level on the client side. This is perfect for building a theme toggle in your app's settings.
div([
button(
onClick: () =>
// Change the theme to light mode
context.setColorScheme(colorScheme: ColorScheme.light)
,
[text('Switch to Light Mode')],
),
button(
onClick: () =>
// Change the theme to dark mode
context.setColorScheme(colorScheme: ColorScheme.dark)
,
[text('Switch to Dark Mode')],
),
button(
onClick: () =>
// Change the contrast level
context.setColorScheme(contrastLevel: Contrast.more)
,
[text('Higher color Contrast')],
),
]);
Advanced Usage
Theme Generation Variants
You can generate different styles of color schemes using the various named constructors on the MaterialColorScheme
class. Each constructor takes a single source Color
and generates all six theme sets (light/dark with normal/medium/high contrast).
Constructor | Description |
---|---|
MaterialColorScheme.tonalSpot(color) |
Pastel tokens, low chroma palettes. The default Material You theme. |
MaterialColorScheme.fidelity(color) |
Tokens and palettes closely match the source color. |
MaterialColorScheme.content(color) |
Almost identical to Fidelity, but the tertiary palette is an analogue of the source color. |
MaterialColorScheme.vibrant(color) |
Pastel colors with high chroma palettes. |
MaterialColorScheme.expressive(color) |
Pastel colors with medium chroma palettes. The primary palette's hue is shifted from the source color for variety. |
MaterialColorScheme.neutral(color) |
A theme close to grayscale with only a hint of chroma. |
MaterialColorScheme.monochrome(color) |
A completely grayscale theme with no chroma. |
MaterialColorScheme.rainbow(color) |
A playful theme where the source color's hue does not appear in the theme. |
MaterialColorScheme.fruitSalad(color) |
A playful theme where the source color's hue does not appear in the theme. |
Full Customization
For ultimate control, you can use the default MaterialColorScheme()
constructor to specify the seed color for each individual palette (primary
, secondary
, tertiary
, neutral
, etc.) and select a generation Variant
.
import 'package:jaspr_material_colors/jaspr_material_colors.dart';
import 'package:material_color_utilities/material_color_utilities.dart' show Variant;
final myCustomScheme = MaterialColorScheme(
sourceColor: Color.hex('#yourSource'),
styleVariant: Variant.expressive, // Choose from any variant
primarySeed: Color.hex('#overridePrimary'),
secondarySeed: Color.hex('#overrideSecondary'),
tertiarySeed: Color.hex('#overrideTertiary'),
neutralSeed: Color.hex('#overrideNeutral'),
neutralVariantSeed: Color.hex('#overrideNeutralVariant'),
errorSeed: Color.hex('#overrideError'),
);
using with tailwind
if you are using tailwind for styling your project, past the following into styles.tw.css
to make working with the colors easier and to have auto completion in your IDE
@theme {
--color-primary-palette-key: var(--color-primary-palette-key);
--color-secondary-palette-key: var(--color-secondary-palette-key);
--color-tertiary-palette-key: var(--color-tertiary-palette-key);
--color-neutral-palette-key: var(--color-neutral-palette-key);
--color-neutral-variant-palette-key: var(--color-neutral-variant-palette-key);
--color-background: var(--color-background);
--color-on-background: var(--color-on-background);
--color-surface: var(--color-surface);
--color-surface-dim: var(--color-surface-dim);
--color-surface-bright: var(--color-surface-bright);
--color-surface-container-lowest: var(--color-surface-container-lowest);
--color-surface-container-low: var(--color-surface-container-low);
--color-surface-container: var(--color-surface-container);
--color-surface-container-high: var(--color-surface-container-high);
--color-surface-container-highest: var(--color-surface-container-highest);
--color-on-surface: var(--color-on-surface);
--color-surface-variant: var(--color-surface-variant);
--color-on-surface-variant: var(--color-on-surface-variant);
--color-inverse-surface: var(--color-inverse-surface);
--color-inverse-on-surface: var(--color-inverse-on-surface);
--color-outline: var(--color-outline);
--color-outline-variant: var(--color-outline-variant);
--color-shadow: var(--color-shadow);
--color-scrim: var(--color-scrim);
--color-surface-tint: var(--color-surface-tint);
--color-primary: var(--color-primary);
--color-on-primary: var(--color-on-primary);
--color-primary-container: var(--color-primary-container);
--color-on-primary-container: var(--color-on-primary-container);
--color-inverse-primary: var(--color-inverse-primary);
--color-secondary: var(--color-secondary);
--color-on-secondary: var(--color-on-secondary);
--color-secondary-container: var(--color-secondary-container);
--color-on-secondary-container: var(--color-on-secondary-container);
--color-tertiary: var(--color-tertiary);
--color-on-tertiary: var(--color-on-tertiary);
--color-tertiary-container: var(--color-tertiary-container);
--color-on-tertiary-container: var(--color-on-tertiary-container);
--color-error: var(--color-error);
--color-on-error: var(--color-on-error);
--color-error-container: var(--color-error-container);
--color-on-error-container: var(--color-on-error-container);
--color-primary-fixed: var(--color-primary-fixed);
--color-primary-fixed-dim: var(--color-primary-fixed-dim);
--color-on-primary-fixed: var(--color-on-primary-fixed);
--color-on-primary-fixed-variant: var(--color-on-primary-fixed-variant);
--color-secondary-fixed: var(--color-secondary-fixed);
--color-secondary-fixed-dim: var(--color-secondary-fixed-dim);
--color-on-secondary-fixed: var(--color-on-secondary-fixed);
--color-on-secondary-fixed-variant: var(--color-on-secondary-fixed-variant);
--color-tertiary-fixed: var(--color-tertiary-fixed);
--color-tertiary-fixed-dim: var(--color-tertiary-fixed-dim);
--color-on-tertiary-fixed: var(--color-on-tertiary-fixed);
--color-on-tertiary-fixed-variant: var(--color-on-tertiary-fixed-variant);
}
License
this package is published under the terms of MIT license.