MaterialKolor

822 stars
by Jordon de Hoog

🎨 Generate Material 3 color schemes from any color. Compose Multiplatform library for dynamic theming.

View on GitHub

Documentation

logo

Maven Central
Kotlin
Build
License

Compose Multiplatform
badge-android
badge-ios
badge-desktop
badge-js

A Compose Multiplatform library for creating dynamic Material Design 3 color palettes from any
color.

Check out MaterialKolor Builder to see MaterialKolor in action and
generate your own color schemes. It can export to MaterialKolor code, or plain Material 3 code.

The KDoc is published at docs.materialkolor.com

Table of Contents

Platforms

This library is written for Compose Multiplatform, and can be used on the following platforms:

  • Android
  • iOS
  • JVM (Desktop)
  • JavaScript/wasm (Browser)

You can see it in action by using MaterialKolor Builder.

Inspiration

The heart of this library comes from
the material-color-utilities
repository. It is currently
only a Java library, and I wanted to make it available to Kotlin Multiplatform projects. The source
code was taken and converted into a Kotlin Multiplatform library.

I also incorporated the Compose ideas from another open source
library m3color.

Setup

You can add this library to your project using Gradle.

Multiplatform

To add to a multiplatform project, add the dependency to the common source-set:

kotlin {
    sourceSets {
        commonMain {
            dependencies {
              implementation("com.materialkolor:material-kolor:4.1.1")
            }
        }
    }
}

Single Platform

For an Android only project, add the dependency to app level build.gradle.kts:

dependencies {
  implementation("com.materialkolor:material-kolor:4.1.1")
}

Version Catalog

[versions]
materialKolor = "4.1.1"

[libraries]
materialKolor = { module = "com.materialkolor:material-kolor", version.ref = "materialKolor" }

Without compose

If you don't use Compose and don't need any of the extension functions provided by material-kolor,
you can use the material-color-utilities artifact instead.
It is a Kotlin Multiplatform port of
Google's Material Color Utilities.

[versions]
materialKolor = "4.1.1"

[libraries]
materialKolor-utilities = { module = "com.materialkolor:material-color-utilities", version.ref = "materialKolor" }

Usage

To generate a custom ColorScheme you simply need to call dynamicColorScheme() with your target
seed color:

@Composable
fun MyTheme(
    seedColor: Color,
    isDark: Boolean = isSystemInDarkTheme(),
    content: @Composable () -> Unit
) {
    val colorScheme = rememberDynamicColorScheme(seedColor = seedColor, isDark = isDark)

    MaterialTheme(
        colors = colorScheme,
        content = content,
    )
}

You can also pass in
a PaletteStyle to
customize the generated palette:

dynamicColorScheme(
    seedColor = seedColor,
    isDark = isDark,
  style = PaletteStyle.Expressive,
)

Updated Colors

With the release of Material3 Expressive, Google has added a new color spec used when generating
colors. By default MaterialKolor uses the SPEC_2021 version. If you want to try out the new colors
you will need to use ColorSpec.SpecVersion.SPEC_2025:

val scheme = rememberDynamicColorScheme(
  seedColor = seedColor,
  isDark = isDark,
  specVersion = ColorSpec.SpecVersion.SPEC_2025,
  style = PaletteStyle.Expressive, // Optional but recommended if you are using `MaterialExpressiveTheme`
)

DynamicMaterialTheme

A DynamicMaterialTheme Composable is also available. It is a wrapper around MaterialTheme that
uses dynamicColorScheme() to generate a ColorScheme for you. You can animate the color scheme by
passing in animate = true.

Example:

@Composable
fun MyTheme(
    seedColor: Color,
    isDark: Boolean = isSystemInDarkTheme(),
    content: @Composable () -> Unit
) {
    DynamicMaterialTheme(
        seedColor = seedColor,
        isDark = isDark,
        animate = true,
        content = content,
    )
}

DynamicMaterialExpressiveTheme

Support for Material Expressive was removed in MaterialKolor 4.0.0 because Compose Multiplatform
1.9
uses a version of Material 3 that no longer supports Material Expressive.

If you still want to use Material Expressive, you can use the MaterialKolor
5.0.0 preview version
.

You can view the README for 5.0.0 here

Extensions

Included in the library are some extensions for working with colors. You can check out
the /ktx package for more information.

But here are a couple useful examples:

Harmonize Colors

If you want to harmonize a color with another you can use the Color.harmonize() function. You can
read more about color harmonization on
the Material 3 Documentation.

Example:

val newColor = MaterialTheme.colorScheme.primary.harmonize(Color.Blue)

There is an additional function specifically for harmonizing with the primary color:

val newColor = Color.Blue.harmonizeWithPrimary()

Note: Color.harmonize() has an optional parameter matchSaturation which when set to true
will adjust the saturation from the other color.

Lighten and Darken

You can lighten or darken a color using the Color.lighten() and Color.darken() functions.

For example:

val newColor = MaterialTheme.colorScheme.primary.lighten(0.2f)

Check out the demo app for a full example.

Color Temperature

You can determine if a Color is warm or cold using the following:

val isWarm = MaterialTheme.colorScheme.primary.isWarm()
val isCold = MaterialTheme.colorScheme.primary.isCold()

Generating from an Image

You can calculate a seed color, or colors that are suitable for UI theming from an image. This is
useful for generating a color scheme from a user's profile picture, or a background image.

To do so you can call ImageBitmap.themeColors(), ImageBitmap.themeColor() or the @Composable
function rememberThemeColors() or rememberThemeColor():

fun calculateSeedColor(bitmap: ImageBitmap): Color {
    val suitableColors = bitmap.themeColors(fallback = Color.Blue)
    return suitableColors.first()
}

See ImageBitmap.kt
for more information.

Or in Compose land:

@Composable
fun DynamicTheme(image: ImageBitmap, content: @Composable () -> Unit) {
    val seedColor = rememberThemeColor(image, fallback = MaterialTheme.colorScheme.primary)

  DynamicMaterialTheme(
        seedColor = seedColor,
        content = content
    )
}

Note: This approach can be pretty slow, so I wouldn't really recommend using it in your UI
unless you are eagerly loading the colors.

License

The module material-color-utilities is licensed under the Apache License, Version 2.0. See
their LICENSE and their
repository here for more
information.

Changes from original source

  • Convert Java code to Kotlin
  • Convert library to Kotlin Multiplatform

For the remaining code see LICENSE for more information.

Dispatch Newsletter
Be the first to discover new Compose libraries
Curated Insights
Digest in 5 minutes or less
Android Analysis
Entertaining takes on happenings
Insider Tips
From top Android developers
Hidden Gems
You won't find elsewhere
"
"Keep up the good work with the newsletter πŸ’ͺ I really enjoy it."
β€” SaΓΊl Molinero
Senior Android Engineer @ Significo
Join thousands of Android devs who look forward to Dispatch every week