KMPalette-Theme-Library

Dynamic theme management library enabling custom theme families, mode switching, persistence, and previewing with Theme Picker UI. Integrates with Material 3 for adaptable styling.

Android JVMJVMWasm
GitHub stars3
Open issues0
LicenseMIT License
Creation date9 months ago

Last activity3 months ago
Latest release0.0.5 (3 months ago)

🌌 KMPalette – Kotlin Multiplatform Library

Maven Central Kotlin License Platforms Publish

A Kotlin Multiplatform library for dynamic theme management using Jetpack Compose Multiplatform.

It allows you to:

  • Register custom theme families (Light + Dark variants)
  • Switch between System / Light / Dark modes
  • Persist theme selection with pluggable ThemeStore
  • Provide Material 3 adapters with support for custom typography & shapes
  • Preview and switch themes dynamically with a built-in Theme Picker UI

✨ Features

  • 🎨 Theme Registry – register and manage theme families
  • πŸ›  Theme Controller – central manager for selection, persistence, and system integration
  • πŸ“¦ Composable Adapter – plug your UI with Material 3 (typography, shapes, colors)
  • πŸŒ— Theme Families – group Light/Dark variants under a single name
  • πŸ’Ύ Persistence – pluggable ThemeStore (works with MultiplatformSettings or custom stores)
  • πŸ–₯ System-aware – respects system theme if enabled
  • πŸ“± Composable UI – ThemePickerBottomSheet & sample AppScaffold

Theme Picker Bottom Sheet Preview

πŸš€ Installation

Add the dependency to your commonMain:

commonMain.dependencies {
    implementation("io.github.iammohdzaki.kmpalette:theme-core:<check-tag-eg.0.0.1>")
}

πŸ“ Architecture

Below is the high-level architecture of the Dynamic Theme Multiplatform Library:

Theme Picker Bottom Sheet Preview


πŸ“¦ Core Concepts

1. ThemeDefinition

Represents a single theme variant (Light or Dark).

val lightTheme = ThemeDefinition(
    id = ThemeId("ocean_light"),
    displayName = "Ocean Light",
    palette = lightPalette
)

2. ThemeFamily

A pair of Light/Dark themes grouped under a single name.

val oceanFamily = ThemeFamily(
    displayName = "Ocean",
    light = oceanLight,
    dark = oceanDark
)

3. ThemeRegistry

Registers all available themes.

val registry = DefaultThemeRegistry().apply {
    registerFamily(oceanFamily)
    registerFamily(forestFamily)
}

4. ThemeController

Manages active theme, system mode, and persistence.

val controller = ThemeController(
    registry = registry,
    store = SettingsThemeStore(Settings()), // pluggable
    system = PlatformSystemThemeProvider(),
    defaultThemeId = ThemeId("m3_light")
)

5. Compose Adapter

Applies theme to your UI (Material 3).

DynamicThemeProvider(
    controller = controller,
    adapter = Material3Adapter(
        typography = CustomTypography(),
        shapes = CustomShapes()
    )
) {
    AppScaffold()
}

🎨 Theme Picker UI

A ready-to-use Bottom Sheet for switching themes:

ThemePickerBottomSheet(
    onDismiss = { showSheet = false }
)

It shows:

  • Theme mode toggle β†’ System / Light / Dark
  • Theme families β†’ Select from available themes
  • DualVariantCircle β†’ Preview both Light & Dark variant in one icon

πŸ›  Persistence

Implement your own ThemeStore if you don’t want to use MultiplatformSettings:

interface ThemeStore {
    suspend fun load(): ThemeSelection?
    suspend fun save(selection: ThemeSelection)
}

Example: SettingsThemeStore using MultiplatformSettings.


πŸ§‘β€πŸ’» Example :

A sample scaffold to showcase theme switching:

@Composable
fun App() {
    val controller = remember {
        val registry = DefaultThemeRegistry().apply {
            registerFamilies(DefaultMaterial3Themes.families)
        }
        ThemeController(
            registry = registry,
            store = SettingsThemeStore(Settings()), // You can plug any persistence like Multiplatform Settings,DataStore etc.
            system = PlatformSystemThemeProvider(),
            defaultThemeId = ThemeId("m3_light")
        )
    }

    DynamicThemeProvider(
        controller = controller,
        adapter = Material3Adapter(),
        typography = SansTypography()
    ) {
        AppScaffold()
    }
}

πŸ”§ Extending the Library

  • Add new themes by registering families in the registry
  • Provide custom adapters (e.g., Material 2, your own design system)
  • Replace persistence with your own store (e.g., DataStore, Database)
  • Add new UI components (custom pickers, theme previews)

πŸ“„ License

MIT License

Android JVMJVMWasm
GitHub stars3
Open issues0
LicenseMIT License
Creation date9 months ago

Last activity3 months ago
Latest release0.0.5 (3 months ago)

🌌 KMPalette – Kotlin Multiplatform Library

Maven Central Kotlin License Platforms Publish

A Kotlin Multiplatform library for dynamic theme management using Jetpack Compose Multiplatform.

It allows you to:

  • Register custom theme families (Light + Dark variants)
  • Switch between System / Light / Dark modes
  • Persist theme selection with pluggable ThemeStore
  • Provide Material 3 adapters with support for custom typography & shapes
  • Preview and switch themes dynamically with a built-in Theme Picker UI

✨ Features

  • 🎨 Theme Registry – register and manage theme families
  • πŸ›  Theme Controller – central manager for selection, persistence, and system integration
  • πŸ“¦ Composable Adapter – plug your UI with Material 3 (typography, shapes, colors)
  • πŸŒ— Theme Families – group Light/Dark variants under a single name
  • πŸ’Ύ Persistence – pluggable ThemeStore (works with MultiplatformSettings or custom stores)
  • πŸ–₯ System-aware – respects system theme if enabled
  • πŸ“± Composable UI – ThemePickerBottomSheet & sample AppScaffold

Theme Picker Bottom Sheet Preview

πŸš€ Installation

Add the dependency to your commonMain:

commonMain.dependencies {
    implementation("io.github.iammohdzaki.kmpalette:theme-core:<check-tag-eg.0.0.1>")
}

πŸ“ Architecture

Below is the high-level architecture of the Dynamic Theme Multiplatform Library:

Theme Picker Bottom Sheet Preview


πŸ“¦ Core Concepts

1. ThemeDefinition

Represents a single theme variant (Light or Dark).

val lightTheme = ThemeDefinition(
    id = ThemeId("ocean_light"),
    displayName = "Ocean Light",
    palette = lightPalette
)

2. ThemeFamily

A pair of Light/Dark themes grouped under a single name.

val oceanFamily = ThemeFamily(
    displayName = "Ocean",
    light = oceanLight,
    dark = oceanDark
)

3. ThemeRegistry

Registers all available themes.

val registry = DefaultThemeRegistry().apply {
    registerFamily(oceanFamily)
    registerFamily(forestFamily)
}

4. ThemeController

Manages active theme, system mode, and persistence.

val controller = ThemeController(
    registry = registry,
    store = SettingsThemeStore(Settings()), // pluggable
    system = PlatformSystemThemeProvider(),
    defaultThemeId = ThemeId("m3_light")
)

5. Compose Adapter

Applies theme to your UI (Material 3).

DynamicThemeProvider(
    controller = controller,
    adapter = Material3Adapter(
        typography = CustomTypography(),
        shapes = CustomShapes()
    )
) {
    AppScaffold()
}

🎨 Theme Picker UI

A ready-to-use Bottom Sheet for switching themes:

ThemePickerBottomSheet(
    onDismiss = { showSheet = false }
)

It shows:

  • Theme mode toggle β†’ System / Light / Dark
  • Theme families β†’ Select from available themes
  • DualVariantCircle β†’ Preview both Light & Dark variant in one icon

πŸ›  Persistence

Implement your own ThemeStore if you don’t want to use MultiplatformSettings:

interface ThemeStore {
    suspend fun load(): ThemeSelection?
    suspend fun save(selection: ThemeSelection)
}

Example: SettingsThemeStore using MultiplatformSettings.


πŸ§‘β€πŸ’» Example :

A sample scaffold to showcase theme switching:

@Composable
fun App() {
    val controller = remember {
        val registry = DefaultThemeRegistry().apply {
            registerFamilies(DefaultMaterial3Themes.families)
        }
        ThemeController(
            registry = registry,
            store = SettingsThemeStore(Settings()), // You can plug any persistence like Multiplatform Settings,DataStore etc.
            system = PlatformSystemThemeProvider(),
            defaultThemeId = ThemeId("m3_light")
        )
    }

    DynamicThemeProvider(
        controller = controller,
        adapter = Material3Adapter(),
        typography = SansTypography()
    ) {
        AppScaffold()
    }
}

πŸ”§ Extending the Library

  • Add new themes by registering families in the registry
  • Provide custom adapters (e.g., Material 2, your own design system)
  • Replace persistence with your own store (e.g., DataStore, Database)
  • Add new UI components (custom pickers, theme previews)

πŸ“„ License

MIT License