Jaspr Material Color scheme

pub package

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 , use pakage: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.