diff --git a/app-ui-catalog/build.gradle.kts b/app-ui-catalog/build.gradle.kts index 2e2544b48..c7cb5d06e 100644 --- a/app-ui-catalog/build.gradle.kts +++ b/app-ui-catalog/build.gradle.kts @@ -15,6 +15,8 @@ android { dependencies { implementation(projects.core.ui.compose.designsystem) + implementation(projects.core.ui.compose.theme2.k9mail) + implementation(libs.androidx.compose.material) implementation(libs.androidx.compose.material.icons.extended) } diff --git a/app-ui-catalog/src/main/java/app/k9mail/ui/catalog/CatalogApplication.kt b/app-ui-catalog/src/main/java/app/k9mail/ui/catalog/CatalogApplication.kt index f0703f6a7..4e15b85b5 100644 --- a/app-ui-catalog/src/main/java/app/k9mail/ui/catalog/CatalogApplication.kt +++ b/app-ui-catalog/src/main/java/app/k9mail/ui/catalog/CatalogApplication.kt @@ -1,7 +1,7 @@ package app.k9mail.ui.catalog import android.app.Application -import app.k9mail.ui.catalog.ui.catalogUiModule +import app.k9mail.ui.catalog.di.catalogUiModule import org.koin.android.ext.koin.androidContext import org.koin.core.context.startKoin diff --git a/app-ui-catalog/src/main/java/app/k9mail/ui/catalog/ui/CatalogUiModule.kt b/app-ui-catalog/src/main/java/app/k9mail/ui/catalog/di/CatalogUiModule.kt similarity index 69% rename from app-ui-catalog/src/main/java/app/k9mail/ui/catalog/ui/CatalogUiModule.kt rename to app-ui-catalog/src/main/java/app/k9mail/ui/catalog/di/CatalogUiModule.kt index 1df410012..e2245c9b6 100644 --- a/app-ui-catalog/src/main/java/app/k9mail/ui/catalog/ui/CatalogUiModule.kt +++ b/app-ui-catalog/src/main/java/app/k9mail/ui/catalog/di/CatalogUiModule.kt @@ -1,5 +1,6 @@ -package app.k9mail.ui.catalog.ui +package app.k9mail.ui.catalog.di +import app.k9mail.ui.catalog.ui.CatalogViewModel import org.koin.androidx.viewmodel.dsl.viewModel import org.koin.core.module.Module import org.koin.dsl.module diff --git a/app-ui-catalog/src/main/java/app/k9mail/ui/catalog/ui/CatalogContract.kt b/app-ui-catalog/src/main/java/app/k9mail/ui/catalog/ui/CatalogContract.kt index 2d52d4351..7eecd0a23 100644 --- a/app-ui-catalog/src/main/java/app/k9mail/ui/catalog/ui/CatalogContract.kt +++ b/app-ui-catalog/src/main/java/app/k9mail/ui/catalog/ui/CatalogContract.kt @@ -9,6 +9,9 @@ interface CatalogContract { ) { K9("K-9"), THUNDERBIRD("Thunderbird"), + + // Theme 2 + THEME_2_K9("K-9 (Material3)"), } enum class ThemeVariant( @@ -26,8 +29,8 @@ interface CatalogContract { ) sealed interface Event { - object OnThemeChanged : Event + data object OnThemeChanged : Event - object OnThemeVariantChanged : Event + data object OnThemeVariantChanged : Event } } diff --git a/app-ui-catalog/src/main/java/app/k9mail/ui/catalog/ui/CatalogViewModel.kt b/app-ui-catalog/src/main/java/app/k9mail/ui/catalog/ui/CatalogViewModel.kt index 1f528198d..1df977d93 100644 --- a/app-ui-catalog/src/main/java/app/k9mail/ui/catalog/ui/CatalogViewModel.kt +++ b/app-ui-catalog/src/main/java/app/k9mail/ui/catalog/ui/CatalogViewModel.kt @@ -5,10 +5,8 @@ import app.k9mail.ui.catalog.ui.CatalogContract.Event import app.k9mail.ui.catalog.ui.CatalogContract.Event.OnThemeChanged import app.k9mail.ui.catalog.ui.CatalogContract.Event.OnThemeVariantChanged import app.k9mail.ui.catalog.ui.CatalogContract.State -import app.k9mail.ui.catalog.ui.CatalogContract.Theme.K9 -import app.k9mail.ui.catalog.ui.CatalogContract.Theme.THUNDERBIRD -import app.k9mail.ui.catalog.ui.CatalogContract.ThemeVariant.DARK -import app.k9mail.ui.catalog.ui.CatalogContract.ThemeVariant.LIGHT +import app.k9mail.ui.catalog.ui.CatalogContract.Theme +import app.k9mail.ui.catalog.ui.CatalogContract.ThemeVariant import app.k9mail.ui.catalog.ui.CatalogContract.ViewModel class CatalogViewModel( @@ -17,18 +15,22 @@ class CatalogViewModel( override fun event(event: Event) { when (event) { is OnThemeChanged -> { - when (state.value.theme) { - K9 -> updateState { it.copy(theme = THUNDERBIRD) } - THUNDERBIRD -> updateState { it.copy(theme = K9) } - } + updateState { it.copy(theme = selectNextTheme(it.theme)) } } is OnThemeVariantChanged -> { when (state.value.themeVariant) { - LIGHT -> updateState { it.copy(themeVariant = DARK) } - DARK -> updateState { it.copy(themeVariant = LIGHT) } + ThemeVariant.LIGHT -> updateState { it.copy(themeVariant = ThemeVariant.DARK) } + ThemeVariant.DARK -> updateState { it.copy(themeVariant = ThemeVariant.LIGHT) } } } } } + + private fun selectNextTheme(currentTheme: Theme): Theme { + val themes = Theme.entries + val currentThemeIndex = themes.indexOf(currentTheme) + val nextThemeIndex = (currentThemeIndex + 1) % themes.size + return themes[nextThemeIndex] + } } diff --git a/app-ui-catalog/src/main/java/app/k9mail/ui/catalog/ui/common/theme/ThemeSwitch.kt b/app-ui-catalog/src/main/java/app/k9mail/ui/catalog/ui/common/theme/ThemeSwitch.kt index 5d5e8098f..883400634 100644 --- a/app-ui-catalog/src/main/java/app/k9mail/ui/catalog/ui/common/theme/ThemeSwitch.kt +++ b/app-ui-catalog/src/main/java/app/k9mail/ui/catalog/ui/common/theme/ThemeSwitch.kt @@ -3,6 +3,7 @@ package app.k9mail.ui.catalog.ui.common.theme import androidx.compose.runtime.Composable import app.k9mail.core.ui.compose.theme.K9Theme import app.k9mail.core.ui.compose.theme.ThunderbirdTheme +import app.k9mail.core.ui.compose.theme2.k9mail.K9MailTheme2 import app.k9mail.ui.catalog.ui.CatalogContract.Theme import app.k9mail.ui.catalog.ui.CatalogContract.ThemeVariant @@ -17,10 +18,16 @@ fun ThemeSwitch( themeVariant = themeVariant, content = content, ) + Theme.THUNDERBIRD -> ThunderbirdThemeSwitch( themeVariant = themeVariant, content = content, ) + + Theme.THEME_2_K9 -> K9Theme2Switch( + themeVariant = themeVariant, + content = content, + ) } } @@ -34,6 +41,7 @@ private fun K9ThemeSwitch( darkTheme = false, content = content, ) + ThemeVariant.DARK -> K9Theme( darkTheme = true, content = content, @@ -51,9 +59,28 @@ private fun ThunderbirdThemeSwitch( darkTheme = false, content = content, ) + ThemeVariant.DARK -> ThunderbirdTheme( darkTheme = true, content = content, ) } } + +@Composable +private fun K9Theme2Switch( + themeVariant: ThemeVariant, + content: @Composable () -> Unit, +) { + when (themeVariant) { + ThemeVariant.LIGHT -> K9MailTheme2( + darkTheme = false, + content = content, + ) + + ThemeVariant.DARK -> K9MailTheme2( + darkTheme = true, + content = content, + ) + } +} diff --git a/config/detekt/detekt.yml b/config/detekt/detekt.yml index 697b3419f..9c372dbdd 100644 --- a/config/detekt/detekt.yml +++ b/config/detekt/detekt.yml @@ -790,7 +790,22 @@ style: Compose: CompositionLocalAllowlist: active: true - allowedCompositionLocals: [LocalColors, LocalElevations, LocalImages, LocalShapes, LocalSizes, LocalSpacings, LocalActivity] + allowedCompositionLocals: [ + LocalColors, + LocalElevations, + LocalImages, + LocalShapes, + LocalSizes, + LocalSpacings, + LocalActivity, + LocalThemeColorScheme, + LocalThemeElevations, + LocalThemeImages, + LocalThemeShapes, + LocalThemeSizes, + LocalThemeSpacings, + LocalThemeTypography + ] ContentEmitterReturningValues: active: true ModifierComposable: diff --git a/core/ui/compose/theme2/common/README.md b/core/ui/compose/theme2/common/README.md new file mode 100644 index 000000000..147ca1074 --- /dev/null +++ b/core/ui/compose/theme2/common/README.md @@ -0,0 +1,15 @@ +## Core - UI - Compose - Theme2 - Common + +This provides the common `MainTheme` with dark/light variation support, a wrapper for the Compose Material 3 theme. It supports [CompositionLocal](https://developer.android.com/jetpack/compose/compositionlocal) changes to colors, typography, shapes and adds additionally elevations, sizes, spacings and images. + +To change Material 3 related properties use `MainTheme` instead of `MaterialTheme`: + +- `MainTheme.colors`: Material 3 color scheme +- `MainTheme.elevations`: Elevation levels as [defined](https://m3.material.io/styles/elevation/overview) in Material3 +- `MainTheme.images`: Images used across the theme, e.g. logo +- `MainTheme.shapes`: Shapes as [defined](https://m3.material.io/styles/shape/overview) in Material 3 +- `MainTheme.sizes`: Sizes (smaller, small, medium, large, larger, huge, huger) +- `MainTheme.spacings`: Spacings (quarter, half, default, oneHalf, double, triple, quadruple) while default is 8 dp. +- `MainTheme.typography`: Material 3 typography + +To use the MainTheme, you need to provide a `ThemeConfig` with your desired colors, typography, shapes, elevations, sizes, spacings and images. The `ThemeConfig` is a data class that holds all the necessary information for the `MainTheme` to work. diff --git a/core/ui/compose/theme2/common/build.gradle.kts b/core/ui/compose/theme2/common/build.gradle.kts new file mode 100644 index 000000000..0f6735ee1 --- /dev/null +++ b/core/ui/compose/theme2/common/build.gradle.kts @@ -0,0 +1,17 @@ +plugins { + id(ThunderbirdPlugins.Library.androidCompose) +} + +android { + namespace = "app.k9mail.core.ui.compose.theme2" + resourcePrefix = "core_ui_theme2" +} + +dependencies { + api(projects.core.ui.compose.common) + + implementation(libs.androidx.compose.material3) + implementation(libs.androidx.compose.material.icons.extended) + + implementation(libs.androidx.activity) +} diff --git a/core/ui/compose/theme2/common/src/main/kotlin/app/k9mail/core/ui/compose/theme2/MainTheme.kt b/core/ui/compose/theme2/common/src/main/kotlin/app/k9mail/core/ui/compose/theme2/MainTheme.kt new file mode 100644 index 000000000..d66440f9d --- /dev/null +++ b/core/ui/compose/theme2/common/src/main/kotlin/app/k9mail/core/ui/compose/theme2/MainTheme.kt @@ -0,0 +1,111 @@ +package app.k9mail.core.ui.compose.theme2 + +import androidx.compose.foundation.isSystemInDarkTheme +import androidx.compose.material3.ColorScheme +import androidx.compose.material3.MaterialTheme +import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.runtime.ReadOnlyComposable + +@Composable +fun MainTheme( + themeConfig: ThemeConfig, + darkTheme: Boolean = isSystemInDarkTheme(), + dynamicColor: Boolean = true, + content: @Composable () -> Unit, +) { + val themeColorScheme = selectThemeColorScheme( + themeConfig = themeConfig, + darkTheme = darkTheme, + dynamicColor = dynamicColor, + ) + val themeImages = selectThemeImages( + themeConfig = themeConfig, + darkTheme = darkTheme, + ) + + SystemBar( + darkTheme = darkTheme, + colorScheme = themeColorScheme, + ) + + CompositionLocalProvider( + LocalThemeColorScheme provides themeColorScheme, + LocalThemeElevations provides themeConfig.elevations, + LocalThemeImages provides themeImages, + LocalThemeShapes provides themeConfig.shapes, + LocalThemeSizes provides themeConfig.sizes, + LocalThemeSpacings provides themeConfig.spacings, + LocalThemeTypography provides themeConfig.typography, + ) { + MaterialTheme( + colorScheme = themeColorScheme.toMaterial3ColorScheme(), + shapes = themeConfig.shapes.toMaterial3Shapes(), + typography = themeConfig.typography.toMaterial3Typography(), + content = content, + ) + } +} + +/** + * Contains functions to access the current theme values provided at the call site's position in + * the hierarchy. + */ +object MainTheme { + + /** + * Retrieves the current [ColorScheme] at the call site's position in the hierarchy. + */ + val colors: ThemeColorScheme + @Composable + @ReadOnlyComposable + get() = LocalThemeColorScheme.current + + /** + * Retrieves the current [ThemeElevations] at the call site's position in the hierarchy. + */ + val elevations: ThemeElevations + @Composable + @ReadOnlyComposable + get() = LocalThemeElevations.current + + /** + * Retrieves the current [ThemeImages] at the call site's position in the hierarchy. + */ + val images: ThemeImages + @Composable + @ReadOnlyComposable + get() = LocalThemeImages.current + + /** + * Retrieves the current [ThemeShapes] at the call site's position in the hierarchy. + */ + val shapes: ThemeShapes + @Composable + @ReadOnlyComposable + get() = LocalThemeShapes.current + + /** + * Retrieves the current [ThemeSizes] at the call site's position in the hierarchy. + */ + val sizes: ThemeSizes + @Composable + @ReadOnlyComposable + get() = LocalThemeSizes.current + + /** + * Retrieves the current [ThemeSpacings] at the call site's position in the hierarchy. + */ + val spacings: ThemeSpacings + @Composable + @ReadOnlyComposable + get() = LocalThemeSpacings.current + + /** + * Retrieves the current [ThemeTypography] at the call site's position in the hierarchy. + */ + val typography: ThemeTypography + @Composable + @ReadOnlyComposable + get() = LocalThemeTypography.current +} diff --git a/core/ui/compose/theme2/common/src/main/kotlin/app/k9mail/core/ui/compose/theme2/SelectThemeColorScheme.kt b/core/ui/compose/theme2/common/src/main/kotlin/app/k9mail/core/ui/compose/theme2/SelectThemeColorScheme.kt new file mode 100644 index 000000000..f763e031f --- /dev/null +++ b/core/ui/compose/theme2/common/src/main/kotlin/app/k9mail/core/ui/compose/theme2/SelectThemeColorScheme.kt @@ -0,0 +1,73 @@ +package app.k9mail.core.ui.compose.theme2 + +import androidx.compose.material3.ColorScheme +import androidx.compose.material3.dynamicDarkColorScheme +import androidx.compose.material3.dynamicLightColorScheme +import androidx.compose.runtime.Composable +import androidx.compose.ui.platform.LocalContext + +@Composable +internal fun selectThemeColorScheme( + themeConfig: ThemeConfig, + darkTheme: Boolean, + dynamicColor: Boolean, +): ThemeColorScheme { + return when { + dynamicColor && supportsDynamicColor() -> { + val context = LocalContext.current + val colorScheme = if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context) + colorScheme.toThemeColorScheme() + } + + darkTheme -> themeConfig.colors.dark + else -> themeConfig.colors.light + } +} + +// Supported from Android 12+ +private fun supportsDynamicColor(): Boolean { + return android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S +} + +private fun ColorScheme.toThemeColorScheme() = ThemeColorScheme( + primary = primary, + onPrimary = onPrimary, + primaryContainer = primaryContainer, + onPrimaryContainer = onPrimaryContainer, + + secondary = secondary, + onSecondary = onSecondary, + secondaryContainer = secondaryContainer, + onSecondaryContainer = onSecondaryContainer, + + tertiary = tertiary, + onTertiary = onTertiary, + tertiaryContainer = tertiaryContainer, + onTertiaryContainer = onTertiaryContainer, + + error = error, + onError = onError, + errorContainer = errorContainer, + onErrorContainer = onErrorContainer, + + surface = surface, + onSurface = onSurface, + onSurfaceVariant = onSurfaceVariant, + surfaceContainerLowest = surfaceContainerLowest, + surfaceContainerLow = surfaceContainerLow, + surfaceContainer = surfaceContainer, + surfaceContainerHigh = surfaceContainerHigh, + surfaceContainerHighest = surfaceContainerHighest, + + inverseSurface = inverseSurface, + inverseOnSurface = inverseOnSurface, + inversePrimary = inversePrimary, + + outline = outline, + outlineVariant = outlineVariant, + + surfaceBright = surfaceBright, + surfaceDim = surfaceDim, + + scrim = scrim, +) diff --git a/core/ui/compose/theme2/common/src/main/kotlin/app/k9mail/core/ui/compose/theme2/SelectThemeImages.kt b/core/ui/compose/theme2/common/src/main/kotlin/app/k9mail/core/ui/compose/theme2/SelectThemeImages.kt new file mode 100644 index 000000000..534f45b35 --- /dev/null +++ b/core/ui/compose/theme2/common/src/main/kotlin/app/k9mail/core/ui/compose/theme2/SelectThemeImages.kt @@ -0,0 +1,12 @@ +package app.k9mail.core.ui.compose.theme2 + +import androidx.compose.runtime.Composable + +@Composable +internal fun selectThemeImages( + themeConfig: ThemeConfig, + darkTheme: Boolean, +) = when { + darkTheme -> themeConfig.images.dark + else -> themeConfig.images.light +} diff --git a/core/ui/compose/theme2/common/src/main/kotlin/app/k9mail/core/ui/compose/theme2/SystemBar.kt b/core/ui/compose/theme2/common/src/main/kotlin/app/k9mail/core/ui/compose/theme2/SystemBar.kt new file mode 100644 index 000000000..fe317721b --- /dev/null +++ b/core/ui/compose/theme2/common/src/main/kotlin/app/k9mail/core/ui/compose/theme2/SystemBar.kt @@ -0,0 +1,23 @@ +package app.k9mail.core.ui.compose.theme2 + +import android.app.Activity +import androidx.compose.runtime.Composable +import androidx.compose.runtime.SideEffect +import androidx.compose.ui.graphics.toArgb +import androidx.compose.ui.platform.LocalView +import androidx.core.view.WindowCompat + +@Composable +fun SystemBar( + darkTheme: Boolean, + colorScheme: ThemeColorScheme, +) { + val view = LocalView.current + if (!view.isInEditMode) { + SideEffect { + val window = (view.context as Activity).window + window.statusBarColor = colorScheme.surfaceContainer.toArgb() + WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars = !darkTheme + } + } +} diff --git a/core/ui/compose/theme2/common/src/main/kotlin/app/k9mail/core/ui/compose/theme2/ThemeColorScheme.kt b/core/ui/compose/theme2/common/src/main/kotlin/app/k9mail/core/ui/compose/theme2/ThemeColorScheme.kt new file mode 100644 index 000000000..8bcc3ef09 --- /dev/null +++ b/core/ui/compose/theme2/common/src/main/kotlin/app/k9mail/core/ui/compose/theme2/ThemeColorScheme.kt @@ -0,0 +1,121 @@ +package app.k9mail.core.ui.compose.theme2 + +import androidx.compose.material3.ColorScheme +import androidx.compose.runtime.Immutable +import androidx.compose.runtime.staticCompositionLocalOf +import androidx.compose.ui.graphics.Color + +/** + * Theme color scheme following Material 3 color roles. + * + * This supports tone-based Surfaces introduced for Material 3. + * + * @see: https://m3.material.io/styles/color/roles + * @see: https://material.io/blog/tone-based-surface-color-m3 + */ +@Immutable +data class ThemeColorScheme( + val primary: Color, + val onPrimary: Color, + val primaryContainer: Color, + val onPrimaryContainer: Color, + + val secondary: Color, + val onSecondary: Color, + val secondaryContainer: Color, + val onSecondaryContainer: Color, + + val tertiary: Color, + val onTertiary: Color, + val tertiaryContainer: Color, + val onTertiaryContainer: Color, + + val error: Color, + val onError: Color, + val errorContainer: Color, + val onErrorContainer: Color, + + val surface: Color, + val onSurface: Color, + val onSurfaceVariant: Color, + val surfaceContainerLowest: Color, + val surfaceContainerLow: Color, + val surfaceContainer: Color, + val surfaceContainerHigh: Color, + val surfaceContainerHighest: Color, + + val inverseSurface: Color, + val inverseOnSurface: Color, + val inversePrimary: Color, + + val outline: Color, + val outlineVariant: Color, + + val surfaceBright: Color, + val surfaceDim: Color, + + val scrim: Color, +) + +/** + * Convert a [ThemeColorScheme] to a Material 3 [ColorScheme]. + * + * Note: background, onBackground are deprecated and mapped to surface, onSurface. + */ +internal fun ThemeColorScheme.toMaterial3ColorScheme(): ColorScheme { + return ColorScheme( + primary = primary, + onPrimary = onPrimary, + primaryContainer = primaryContainer, + onPrimaryContainer = onPrimaryContainer, + + secondary = secondary, + onSecondary = onSecondary, + secondaryContainer = secondaryContainer, + onSecondaryContainer = onSecondaryContainer, + + tertiary = tertiary, + onTertiary = onTertiary, + tertiaryContainer = tertiaryContainer, + onTertiaryContainer = onTertiaryContainer, + + error = error, + onError = onError, + errorContainer = errorContainer, + onErrorContainer = onErrorContainer, + + surface = surface, + onSurface = onSurface, + onSurfaceVariant = onSurfaceVariant, + + surfaceContainerLowest = surfaceContainerLowest, + surfaceContainerLow = surfaceContainerLow, + surfaceContainer = surfaceContainer, + surfaceContainerHigh = surfaceContainerHigh, + surfaceContainerHighest = surfaceContainerHighest, + + inverseSurface = inverseSurface, + inverseOnSurface = inverseOnSurface, + inversePrimary = inversePrimary, + + outline = outline, + outlineVariant = outlineVariant, + + surfaceBright = surfaceBright, + surfaceDim = surfaceDim, + + scrim = scrim, + + // Remapping properties due to changes in Material 3 tone based surface colors + // https://material.io/blog/tone-based-surface-color-m3 + background = surface, + onBackground = onSurface, + surfaceVariant = surfaceContainerHighest, + + surfaceTint = surfaceContainerHighest, + ) +} + +internal val LocalThemeColorScheme = staticCompositionLocalOf { + error("No ThemeColorScheme provided") +} diff --git a/core/ui/compose/theme2/common/src/main/kotlin/app/k9mail/core/ui/compose/theme2/ThemeConfig.kt b/core/ui/compose/theme2/common/src/main/kotlin/app/k9mail/core/ui/compose/theme2/ThemeConfig.kt new file mode 100644 index 000000000..756d70e8d --- /dev/null +++ b/core/ui/compose/theme2/common/src/main/kotlin/app/k9mail/core/ui/compose/theme2/ThemeConfig.kt @@ -0,0 +1,26 @@ +package app.k9mail.core.ui.compose.theme2 + +import androidx.compose.runtime.Immutable + +@Immutable +data class ThemeConfig( + val colors: ThemeColorSchemeVariants, + val elevations: ThemeElevations, + val images: ThemeImageVariants, + val shapes: ThemeShapes, + val sizes: ThemeSizes, + val spacings: ThemeSpacings, + val typography: ThemeTypography, +) + +@Immutable +data class ThemeColorSchemeVariants( + val dark: ThemeColorScheme, + val light: ThemeColorScheme, +) + +@Immutable +data class ThemeImageVariants( + val dark: ThemeImages, + val light: ThemeImages, +) diff --git a/core/ui/compose/theme2/common/src/main/kotlin/app/k9mail/core/ui/compose/theme2/ThemeElevations.kt b/core/ui/compose/theme2/common/src/main/kotlin/app/k9mail/core/ui/compose/theme2/ThemeElevations.kt new file mode 100644 index 000000000..2a8989cab --- /dev/null +++ b/core/ui/compose/theme2/common/src/main/kotlin/app/k9mail/core/ui/compose/theme2/ThemeElevations.kt @@ -0,0 +1,29 @@ +package app.k9mail.core.ui.compose.theme2 + +import androidx.compose.runtime.Immutable +import androidx.compose.runtime.staticCompositionLocalOf +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.dp + +/** + * Elevation values used in the app. + * + * Material uses six levels of elevation, each with a corresponding dp value. These values are named for their + * relative distance above the UI’s surface: 0, +1, +2, +3, +4, and +5. An element’s resting state can be on + * levels 0 to +3, while levels +4 and +5 are reserved for user-interacted states such as hover and dragged. + * + * @see: https://m3.material.io/styles/elevation/tokens + */ +@Immutable +data class ThemeElevations( + val level0: Dp = 0.dp, + val level1: Dp = 1.dp, + val level2: Dp = 3.dp, + val level3: Dp = 6.dp, + val level4: Dp = 8.dp, + val level5: Dp = 12.dp, +) + +internal val LocalThemeElevations = staticCompositionLocalOf { + error("No ThemeElevations provided") +} diff --git a/core/ui/compose/theme2/common/src/main/kotlin/app/k9mail/core/ui/compose/theme2/ThemeImages.kt b/core/ui/compose/theme2/common/src/main/kotlin/app/k9mail/core/ui/compose/theme2/ThemeImages.kt new file mode 100644 index 000000000..2f700dfc5 --- /dev/null +++ b/core/ui/compose/theme2/common/src/main/kotlin/app/k9mail/core/ui/compose/theme2/ThemeImages.kt @@ -0,0 +1,14 @@ +package app.k9mail.core.ui.compose.theme2 + +import androidx.annotation.DrawableRes +import androidx.compose.runtime.Immutable +import androidx.compose.runtime.staticCompositionLocalOf + +@Immutable +data class ThemeImages( + @DrawableRes val logo: Int, +) + +internal val LocalThemeImages = staticCompositionLocalOf { + error("No ThemeImages provided") +} diff --git a/core/ui/compose/theme2/common/src/main/kotlin/app/k9mail/core/ui/compose/theme2/ThemeShapes.kt b/core/ui/compose/theme2/common/src/main/kotlin/app/k9mail/core/ui/compose/theme2/ThemeShapes.kt new file mode 100644 index 000000000..9f1402d5a --- /dev/null +++ b/core/ui/compose/theme2/common/src/main/kotlin/app/k9mail/core/ui/compose/theme2/ThemeShapes.kt @@ -0,0 +1,51 @@ +package app.k9mail.core.ui.compose.theme2 + +import androidx.compose.foundation.shape.CornerBasedShape +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Shapes +import androidx.compose.runtime.Immutable +import androidx.compose.runtime.staticCompositionLocalOf +import androidx.compose.ui.unit.dp + +/** + * The shapes used in the app. + * + * The shapes are defined as: + * + * - None + * - ExtraSmall + * - Small + * - Medium + * - Large + * - ExtraLarge + * - Full + * + * The default values are based on the Material Design guidelines. + * + * Shapes None and Full are omitted as None is a RectangleShape and Full is a CircleShape. + * + * @see: https://m3.material.io/styles/shape/overview + */ +@Immutable +data class ThemeShapes( + val extraSmall: CornerBasedShape = RoundedCornerShape(4.dp), + val small: CornerBasedShape = RoundedCornerShape(8.dp), + val medium: CornerBasedShape = RoundedCornerShape(12.dp), + val large: CornerBasedShape = RoundedCornerShape(16.dp), + val extraLarge: CornerBasedShape = RoundedCornerShape(28.dp), +) + +/** + * Converts the [ThemeShapes] to Material 3 [Shapes]. + */ +internal fun ThemeShapes.toMaterial3Shapes() = Shapes( + extraSmall = extraSmall, + small = small, + medium = medium, + large = large, + extraLarge = extraLarge, +) + +internal val LocalThemeShapes = staticCompositionLocalOf { + error("No ThemeShapes provided") +} diff --git a/core/ui/compose/theme2/common/src/main/kotlin/app/k9mail/core/ui/compose/theme2/ThemeSizes.kt b/core/ui/compose/theme2/common/src/main/kotlin/app/k9mail/core/ui/compose/theme2/ThemeSizes.kt new file mode 100644 index 000000000..77ca911c5 --- /dev/null +++ b/core/ui/compose/theme2/common/src/main/kotlin/app/k9mail/core/ui/compose/theme2/ThemeSizes.kt @@ -0,0 +1,26 @@ +package app.k9mail.core.ui.compose.theme2 + +import androidx.compose.runtime.Immutable +import androidx.compose.runtime.staticCompositionLocalOf +import androidx.compose.ui.unit.Dp + +@Immutable +data class ThemeSizes( + val smaller: Dp, + val small: Dp, + val medium: Dp, + val large: Dp, + val larger: Dp, + val huge: Dp, + val huger: Dp, + + val icon: Dp, + val largeIcon: Dp, + + val topBarHeight: Dp, + val bottomBarHeight: Dp, +) + +internal val LocalThemeSizes = staticCompositionLocalOf { + error("No ThemeSizes provided") +} diff --git a/core/ui/compose/theme2/common/src/main/kotlin/app/k9mail/core/ui/compose/theme2/ThemeSpacings.kt b/core/ui/compose/theme2/common/src/main/kotlin/app/k9mail/core/ui/compose/theme2/ThemeSpacings.kt new file mode 100644 index 000000000..d8c831a9f --- /dev/null +++ b/core/ui/compose/theme2/common/src/main/kotlin/app/k9mail/core/ui/compose/theme2/ThemeSpacings.kt @@ -0,0 +1,21 @@ +package app.k9mail.core.ui.compose.theme2 + +import androidx.compose.runtime.Immutable +import androidx.compose.runtime.staticCompositionLocalOf +import androidx.compose.ui.unit.Dp + +@Immutable +data class ThemeSpacings( + val zero: Dp, + val quarter: Dp, + val half: Dp, + val default: Dp, + val oneHalf: Dp, + val double: Dp, + val triple: Dp, + val quadruple: Dp, +) + +internal val LocalThemeSpacings = staticCompositionLocalOf { + error("No ThemeSpacings provided") +} diff --git a/core/ui/compose/theme2/common/src/main/kotlin/app/k9mail/core/ui/compose/theme2/ThemeTypography.kt b/core/ui/compose/theme2/common/src/main/kotlin/app/k9mail/core/ui/compose/theme2/ThemeTypography.kt new file mode 100644 index 000000000..4387a6915 --- /dev/null +++ b/core/ui/compose/theme2/common/src/main/kotlin/app/k9mail/core/ui/compose/theme2/ThemeTypography.kt @@ -0,0 +1,50 @@ +package app.k9mail.core.ui.compose.theme2 + +import androidx.compose.material3.Typography +import androidx.compose.runtime.Immutable +import androidx.compose.runtime.staticCompositionLocalOf +import androidx.compose.ui.text.TextStyle + +@Immutable +data class ThemeTypography( + val displayLarge: TextStyle, + val displayMedium: TextStyle, + val displaySmall: TextStyle, + val headlineLarge: TextStyle, + val headlineMedium: TextStyle, + val headlineSmall: TextStyle, + val titleLarge: TextStyle, + val titleMedium: TextStyle, + val titleSmall: TextStyle, + val bodyLarge: TextStyle, + val bodyMedium: TextStyle, + val bodySmall: TextStyle, + val labelLarge: TextStyle, + val labelMedium: TextStyle, + val labelSmall: TextStyle, +) + +/** + * Convert [ThemeTypography] to Material 3 [Typography] + */ +internal fun ThemeTypography.toMaterial3Typography() = Typography( + displayLarge = displayLarge, + displayMedium = displayMedium, + displaySmall = displaySmall, + headlineLarge = headlineLarge, + headlineMedium = headlineMedium, + headlineSmall = headlineSmall, + titleLarge = titleLarge, + titleMedium = titleMedium, + titleSmall = titleSmall, + bodyLarge = bodyLarge, + bodyMedium = bodyMedium, + bodySmall = bodySmall, + labelLarge = labelLarge, + labelMedium = labelMedium, + labelSmall = labelSmall, +) + +internal val LocalThemeTypography = staticCompositionLocalOf { + error("No ThemeTypography provided") +} diff --git a/core/ui/compose/theme2/common/src/main/kotlin/app/k9mail/core/ui/compose/theme2/default/DefaultThemeElevations.kt b/core/ui/compose/theme2/common/src/main/kotlin/app/k9mail/core/ui/compose/theme2/default/DefaultThemeElevations.kt new file mode 100644 index 000000000..9bd0a3cbc --- /dev/null +++ b/core/ui/compose/theme2/common/src/main/kotlin/app/k9mail/core/ui/compose/theme2/default/DefaultThemeElevations.kt @@ -0,0 +1,16 @@ +package app.k9mail.core.ui.compose.theme2.default + +import androidx.compose.ui.unit.dp +import app.k9mail.core.ui.compose.theme2.ThemeElevations + +/** + * Default values for Material elevation taken from https://m3.material.io/styles/elevation/tokens + */ +val defaultThemeElevations = ThemeElevations( + level0 = 0.dp, + level1 = 1.dp, + level2 = 3.dp, + level3 = 6.dp, + level4 = 8.dp, + level5 = 12.dp, +) diff --git a/core/ui/compose/theme2/common/src/main/kotlin/app/k9mail/core/ui/compose/theme2/default/DefaultThemeShapes.kt b/core/ui/compose/theme2/common/src/main/kotlin/app/k9mail/core/ui/compose/theme2/default/DefaultThemeShapes.kt new file mode 100644 index 000000000..7a1c6a5ce --- /dev/null +++ b/core/ui/compose/theme2/common/src/main/kotlin/app/k9mail/core/ui/compose/theme2/default/DefaultThemeShapes.kt @@ -0,0 +1,13 @@ +package app.k9mail.core.ui.compose.theme2.default + +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.ui.unit.dp +import app.k9mail.core.ui.compose.theme2.ThemeShapes + +val defaultThemeShapes = ThemeShapes( + extraSmall = RoundedCornerShape(4.dp), + small = RoundedCornerShape(8.dp), + medium = RoundedCornerShape(12.dp), + large = RoundedCornerShape(16.dp), + extraLarge = RoundedCornerShape(28.dp), +) diff --git a/core/ui/compose/theme2/common/src/main/kotlin/app/k9mail/core/ui/compose/theme2/default/DefaultThemeSizes.kt b/core/ui/compose/theme2/common/src/main/kotlin/app/k9mail/core/ui/compose/theme2/default/DefaultThemeSizes.kt new file mode 100644 index 000000000..48cc23f79 --- /dev/null +++ b/core/ui/compose/theme2/common/src/main/kotlin/app/k9mail/core/ui/compose/theme2/default/DefaultThemeSizes.kt @@ -0,0 +1,20 @@ +package app.k9mail.core.ui.compose.theme2.default + +import androidx.compose.ui.unit.dp +import app.k9mail.core.ui.compose.theme2.ThemeSizes + +val defaultThemeSizes = ThemeSizes( + smaller = 8.dp, + small = 16.dp, + medium = 32.dp, + large = 64.dp, + larger = 128.dp, + huge = 256.dp, + huger = 384.dp, + + icon = 24.dp, + largeIcon = 32.dp, + + topBarHeight = 56.dp, + bottomBarHeight = 56.dp, +) diff --git a/core/ui/compose/theme2/common/src/main/kotlin/app/k9mail/core/ui/compose/theme2/default/DefaultThemeSpacings.kt b/core/ui/compose/theme2/common/src/main/kotlin/app/k9mail/core/ui/compose/theme2/default/DefaultThemeSpacings.kt new file mode 100644 index 000000000..95c6c600e --- /dev/null +++ b/core/ui/compose/theme2/common/src/main/kotlin/app/k9mail/core/ui/compose/theme2/default/DefaultThemeSpacings.kt @@ -0,0 +1,15 @@ +package app.k9mail.core.ui.compose.theme2.default + +import androidx.compose.ui.unit.dp +import app.k9mail.core.ui.compose.theme2.ThemeSpacings + +val defaultThemeSpacings = ThemeSpacings( + zero = 0.dp, + quarter = 2.dp, + half = 4.dp, + default = 8.dp, + oneHalf = 12.dp, + double = 16.dp, + triple = 24.dp, + quadruple = 32.dp, +) diff --git a/core/ui/compose/theme2/common/src/main/kotlin/app/k9mail/core/ui/compose/theme2/default/DefaultThemeTypography.kt b/core/ui/compose/theme2/common/src/main/kotlin/app/k9mail/core/ui/compose/theme2/default/DefaultThemeTypography.kt new file mode 100644 index 000000000..8dd6ed679 --- /dev/null +++ b/core/ui/compose/theme2/common/src/main/kotlin/app/k9mail/core/ui/compose/theme2/default/DefaultThemeTypography.kt @@ -0,0 +1,116 @@ +package app.k9mail.core.ui.compose.theme2.default + +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.FontFamily +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.sp +import app.k9mail.core.ui.compose.theme2.ThemeTypography + +@Suppress("MagicNumber") +val defaultTypography = ThemeTypography( + displayLarge = TextStyle( + fontFamily = FontFamily.SansSerif, + fontWeight = FontWeight.Normal, + fontSize = 57.sp, + lineHeight = 64.sp, + letterSpacing = (-0.2).sp, + ), + displayMedium = TextStyle( + fontFamily = FontFamily.SansSerif, + fontWeight = FontWeight.Normal, + fontSize = 45.sp, + lineHeight = 52.sp, + letterSpacing = 0.sp, + ), + displaySmall = TextStyle( + fontFamily = FontFamily.SansSerif, + fontWeight = FontWeight.Normal, + fontSize = 36.sp, + lineHeight = 44.sp, + letterSpacing = 0.sp, + ), + headlineLarge = TextStyle( + fontFamily = FontFamily.SansSerif, + fontWeight = FontWeight.Normal, + fontSize = 32.sp, + lineHeight = 40.sp, + letterSpacing = 0.sp, + ), + headlineMedium = TextStyle( + fontFamily = FontFamily.SansSerif, + fontWeight = FontWeight.Normal, + fontSize = 28.sp, + lineHeight = 36.sp, + letterSpacing = 0.sp, + ), + headlineSmall = TextStyle( + fontFamily = FontFamily.SansSerif, + fontWeight = FontWeight.Normal, + fontSize = 24.sp, + lineHeight = 32.sp, + letterSpacing = 0.sp, + ), + titleLarge = TextStyle( + fontFamily = FontFamily.SansSerif, + fontWeight = FontWeight.Normal, + fontSize = 22.sp, + lineHeight = 28.sp, + letterSpacing = 0.sp, + ), + titleMedium = TextStyle( + fontFamily = FontFamily.SansSerif, + fontWeight = FontWeight.Medium, + fontSize = 16.sp, + lineHeight = 24.sp, + letterSpacing = 0.2.sp, + ), + titleSmall = TextStyle( + fontFamily = FontFamily.SansSerif, + fontWeight = FontWeight.Medium, + fontSize = 14.sp, + lineHeight = 20.sp, + letterSpacing = 0.1.sp, + ), + bodyLarge = TextStyle( + fontFamily = FontFamily.SansSerif, + fontWeight = FontWeight.Normal, + fontSize = 16.sp, + lineHeight = 24.sp, + letterSpacing = 0.5.sp, + ), + bodyMedium = TextStyle( + fontFamily = FontFamily.SansSerif, + fontWeight = FontWeight.Normal, + fontSize = 14.sp, + lineHeight = 20.sp, + letterSpacing = 0.2.sp, + ), + bodySmall = TextStyle( + fontFamily = FontFamily.SansSerif, + fontWeight = FontWeight.Normal, + fontSize = 12.sp, + lineHeight = 16.sp, + letterSpacing = 0.4.sp, + ), + labelLarge = TextStyle( + fontFamily = FontFamily.SansSerif, + fontWeight = FontWeight.Medium, + fontSize = 14.sp, + lineHeight = 20.sp, + letterSpacing = 0.1.sp, + ), + labelMedium = TextStyle( + fontFamily = FontFamily.SansSerif, + fontWeight = FontWeight.Medium, + fontSize = 12.sp, + lineHeight = 16.sp, + letterSpacing = 0.5.sp, + ), + labelSmall = TextStyle( + fontFamily = FontFamily.SansSerif, + fontWeight = FontWeight.Medium, + fontSize = 11.sp, + lineHeight = 16.sp, + letterSpacing = 0.5.sp, + ), +) diff --git a/core/ui/compose/theme2/k9mail/README.md b/core/ui/compose/theme2/k9mail/README.md new file mode 100644 index 000000000..c0c25acb2 --- /dev/null +++ b/core/ui/compose/theme2/k9mail/README.md @@ -0,0 +1,12 @@ +## Core - UI - Compose - Theme2 - K9Mail + +This provides the `K9MailTheme2` composable, that's setting up the `MainTheme` with K-9 Mail specific colors, typography, shapes, elevations, sizes, spacings and images. + +```kotlin +@Composable +fun MyComposable() { + K9MailTheme2 { + // Your app content + } +} +``` diff --git a/core/ui/compose/theme2/k9mail/build.gradle.kts b/core/ui/compose/theme2/k9mail/build.gradle.kts new file mode 100644 index 000000000..a81554730 --- /dev/null +++ b/core/ui/compose/theme2/k9mail/build.gradle.kts @@ -0,0 +1,12 @@ +plugins { + id(ThunderbirdPlugins.Library.androidCompose) +} + +android { + namespace = "app.k9mail.core.ui.compose.theme2.k9mail" + resourcePrefix = "core_ui_theme2_k9mail" +} + +dependencies { + api(projects.core.ui.compose.theme2.common) +} diff --git a/core/ui/compose/theme2/k9mail/src/main/kotlin/app/k9mail/core/ui/compose/theme2/k9mail/K9MailTheme2.kt b/core/ui/compose/theme2/k9mail/src/main/kotlin/app/k9mail/core/ui/compose/theme2/k9mail/K9MailTheme2.kt new file mode 100644 index 000000000..f9c8d6b51 --- /dev/null +++ b/core/ui/compose/theme2/k9mail/src/main/kotlin/app/k9mail/core/ui/compose/theme2/k9mail/K9MailTheme2.kt @@ -0,0 +1,48 @@ +package app.k9mail.core.ui.compose.theme2.k9mail + +import androidx.compose.foundation.isSystemInDarkTheme +import androidx.compose.runtime.Composable +import app.k9mail.core.ui.compose.theme2.MainTheme +import app.k9mail.core.ui.compose.theme2.ThemeColorSchemeVariants +import app.k9mail.core.ui.compose.theme2.ThemeConfig +import app.k9mail.core.ui.compose.theme2.ThemeImageVariants +import app.k9mail.core.ui.compose.theme2.ThemeImages +import app.k9mail.core.ui.compose.theme2.default.defaultThemeElevations +import app.k9mail.core.ui.compose.theme2.default.defaultThemeShapes +import app.k9mail.core.ui.compose.theme2.default.defaultThemeSizes +import app.k9mail.core.ui.compose.theme2.default.defaultThemeSpacings +import app.k9mail.core.ui.compose.theme2.default.defaultTypography + +@Composable +fun K9MailTheme2( + darkTheme: Boolean = isSystemInDarkTheme(), + dynamicColor: Boolean = false, + content: @Composable () -> Unit, +) { + val images = ThemeImages( + logo = R.drawable.core_ui_theme2_k9mail_logo, + ) + + val themeConfig = ThemeConfig( + colors = ThemeColorSchemeVariants( + dark = darkThemeColorScheme, + light = lightThemeColorScheme, + ), + elevations = defaultThemeElevations, + images = ThemeImageVariants( + light = images, + dark = images, + ), + sizes = defaultThemeSizes, + spacings = defaultThemeSpacings, + shapes = defaultThemeShapes, + typography = defaultTypography, + ) + + MainTheme( + themeConfig = themeConfig, + darkTheme = darkTheme, + dynamicColor = dynamicColor, + content = content, + ) +} diff --git a/core/ui/compose/theme2/k9mail/src/main/kotlin/app/k9mail/core/ui/compose/theme2/k9mail/ThemeColors.kt b/core/ui/compose/theme2/k9mail/src/main/kotlin/app/k9mail/core/ui/compose/theme2/k9mail/ThemeColors.kt new file mode 100644 index 000000000..87cb12a34 --- /dev/null +++ b/core/ui/compose/theme2/k9mail/src/main/kotlin/app/k9mail/core/ui/compose/theme2/k9mail/ThemeColors.kt @@ -0,0 +1,89 @@ +package app.k9mail.core.ui.compose.theme2.k9mail + +import app.k9mail.core.ui.compose.theme2.ThemeColorScheme + +internal val darkThemeColorScheme = ThemeColorScheme( + primary = TonalColorPalette.primary080, + onPrimary = TonalColorPalette.primary020, + primaryContainer = TonalColorPalette.primary030, + onPrimaryContainer = TonalColorPalette.primary090, + + secondary = TonalColorPalette.secondary080, + onSecondary = TonalColorPalette.secondary020, + secondaryContainer = TonalColorPalette.secondary030, + onSecondaryContainer = TonalColorPalette.secondary090, + + tertiary = TonalColorPalette.tertiary080, + onTertiary = TonalColorPalette.tertiary020, + tertiaryContainer = TonalColorPalette.tertiary030, + onTertiaryContainer = TonalColorPalette.tertiary090, + + error = TonalColorPalette.error080, + onError = TonalColorPalette.error020, + errorContainer = TonalColorPalette.error030, + onErrorContainer = TonalColorPalette.error090, + + surface = TonalColorPalette.neutral006, + onSurface = TonalColorPalette.neutral090, + onSurfaceVariant = TonalColorPalette.neutralVariant080, + surfaceContainerLowest = TonalColorPalette.neutral004, + surfaceContainerLow = TonalColorPalette.neutral010, + surfaceContainer = TonalColorPalette.neutral012, + surfaceContainerHigh = TonalColorPalette.neutral017, + surfaceContainerHighest = TonalColorPalette.neutral022, + + inverseSurface = TonalColorPalette.neutral090, + inverseOnSurface = TonalColorPalette.neutral020, + inversePrimary = TonalColorPalette.primary040, + + outline = TonalColorPalette.neutralVariant060, + outlineVariant = TonalColorPalette.neutralVariant030, + + surfaceBright = TonalColorPalette.neutral024, + surfaceDim = TonalColorPalette.neutral006, + + scrim = TonalColorPalette.neutral000, +) + +internal val lightThemeColorScheme = ThemeColorScheme( + primary = TonalColorPalette.primary040, + onPrimary = TonalColorPalette.primary100, + primaryContainer = TonalColorPalette.primary090, + onPrimaryContainer = TonalColorPalette.primary010, + + secondary = TonalColorPalette.secondary040, + onSecondary = TonalColorPalette.secondary100, + secondaryContainer = TonalColorPalette.secondary090, + onSecondaryContainer = TonalColorPalette.secondary010, + + tertiary = TonalColorPalette.tertiary040, + onTertiary = TonalColorPalette.tertiary100, + tertiaryContainer = TonalColorPalette.tertiary090, + onTertiaryContainer = TonalColorPalette.tertiary010, + + error = TonalColorPalette.error040, + onError = TonalColorPalette.error100, + errorContainer = TonalColorPalette.error090, + onErrorContainer = TonalColorPalette.error010, + + surface = TonalColorPalette.neutral098, + onSurface = TonalColorPalette.neutral010, + onSurfaceVariant = TonalColorPalette.neutralVariant030, + surfaceContainerLowest = TonalColorPalette.neutral100, + surfaceContainerLow = TonalColorPalette.neutral096, + surfaceContainer = TonalColorPalette.neutral094, + surfaceContainerHigh = TonalColorPalette.neutral092, + surfaceContainerHighest = TonalColorPalette.neutral090, + + inverseSurface = TonalColorPalette.neutral020, + inverseOnSurface = TonalColorPalette.neutral095, + inversePrimary = TonalColorPalette.primary080, + + outline = TonalColorPalette.neutralVariant050, + outlineVariant = TonalColorPalette.neutralVariant080, + + surfaceBright = TonalColorPalette.neutral098, + surfaceDim = TonalColorPalette.neutral087, + + scrim = TonalColorPalette.neutral000, +) diff --git a/core/ui/compose/theme2/k9mail/src/main/kotlin/app/k9mail/core/ui/compose/theme2/k9mail/TonalColorPalette.kt b/core/ui/compose/theme2/k9mail/src/main/kotlin/app/k9mail/core/ui/compose/theme2/k9mail/TonalColorPalette.kt new file mode 100644 index 000000000..dc9438400 --- /dev/null +++ b/core/ui/compose/theme2/k9mail/src/main/kotlin/app/k9mail/core/ui/compose/theme2/k9mail/TonalColorPalette.kt @@ -0,0 +1,100 @@ +package app.k9mail.core.ui.compose.theme2.k9mail + +import androidx.compose.ui.graphics.Color + +internal object TonalColorPalette { + val primary010 = Color(color = 0xFF3F001B) + val primary020 = Color(color = 0xFF5E112F) + val primary030 = Color(color = 0xFF7B2946) + val primary000 = Color(color = 0xFF000000) + val primary040 = Color(color = 0xFF99405D) + val primary050 = Color(color = 0xFFB75876) + val primary060 = Color(color = 0xFFD6718F) + val primary070 = Color(color = 0xFFF68BAA) + val primary080 = Color(color = 0xFFFFB1C5) + val primary090 = Color(color = 0xFFFFD9E1) + val primary095 = Color(color = 0xFFFFECEF) + val primary099 = Color(color = 0xFFFFFBFF) + val primary100 = Color(color = 0xFFFFFFFF) + + val secondary000 = Color(color = 0xFF000000) + val secondary010 = Color(color = 0xFF2B151B) + val secondary020 = Color(color = 0xFF422930) + val secondary030 = Color(color = 0xFF5B3F46) + val secondary040 = Color(color = 0xFF74565E) + val secondary050 = Color(color = 0xFF8F6F76) + val secondary060 = Color(color = 0xFFAA8890) + val secondary070 = Color(color = 0xFFC6A2AA) + val secondary080 = Color(color = 0xFFE3BDC5) + val secondary090 = Color(color = 0xFFFFD9E1) + val secondary095 = Color(color = 0xFFFFECEF) + val secondary099 = Color(color = 0xFFFFFBFF) + val secondary100 = Color(color = 0xFFFFFFFF) + + val tertiary000 = Color(color = 0xFF000000) + val tertiary010 = Color(color = 0xFF260059) + val tertiary020 = Color(color = 0xFF3C1D70) + val tertiary030 = Color(color = 0xFF533688) + val tertiary040 = Color(color = 0xFF6B4EA2) + val tertiary050 = Color(color = 0xFF8567BD) + val tertiary060 = Color(color = 0xFF9F81D9) + val tertiary070 = Color(color = 0xFFBA9CF6) + val tertiary080 = Color(color = 0xFFD3BBFF) + val tertiary090 = Color(color = 0xFFEBDDFF) + val tertiary095 = Color(color = 0xFFF7EDFF) + val tertiary099 = Color(color = 0xFFFFFBFF) + val tertiary100 = Color(color = 0xFFFFFFFF) + + val error000 = Color(color = 0xFF000000) + val error010 = Color(color = 0xFF410002) + val error020 = Color(color = 0xFF690005) + val error030 = Color(color = 0xFF93000A) + val error040 = Color(color = 0xFFBA1A1A) + val error050 = Color(color = 0xFFDE3730) + val error060 = Color(color = 0xFFFF5449) + val error070 = Color(color = 0xFFFF897D) + val error080 = Color(color = 0xFFFFB4AB) + val error090 = Color(color = 0xFFFFDAD6) + val error095 = Color(color = 0xFFFFEDEA) + val error099 = Color(color = 0xFFFFFBFF) + val error100 = Color(color = 0xFFFFFFFF) + + val neutral000 = Color(color = 0xFF000000) + val neutral004 = Color(color = 0xFF120D0E) + val neutral006 = Color(color = 0xFF171213) + val neutral010 = Color(color = 0xFF201A1B) + val neutral012 = Color(color = 0xFF241E1F) + val neutral017 = Color(color = 0xFF2F282A) + val neutral020 = Color(color = 0xFF352F30) + val neutral022 = Color(color = 0xFF3A3334) + val neutral024 = Color(color = 0xFF3E3739) + val neutral030 = Color(color = 0xFF4C4546) + val neutral040 = Color(color = 0xFF655C5E) + val neutral050 = Color(color = 0xFF7E7576) + val neutral060 = Color(color = 0xFF988E90) + val neutral070 = Color(color = 0xFFB3A9AA) + val neutral080 = Color(color = 0xFFCFC4C5) + val neutral087 = Color(color = 0xFFE3D7D8) + val neutral090 = Color(color = 0xFFECE0E1) + val neutral092 = Color(color = 0xFFF1E5E6) + val neutral094 = Color(color = 0xFFF7EBEC) + val neutral095 = Color(color = 0xFFFAEEEF) + val neutral096 = Color(color = 0xFFFDF1F2) + val neutral098 = Color(color = 0xFFFFF8F8) + val neutral099 = Color(color = 0xFFFFFBFF) + val neutral100 = Color(color = 0xFFFFFFFF) + + val neutralVariant000 = Color(color = 0xFF000000) + val neutralVariant010 = Color(color = 0xFF24191B) + val neutralVariant020 = Color(color = 0xFF3A2D30) + val neutralVariant030 = Color(color = 0xFF514346) + val neutralVariant040 = Color(color = 0xFF6A5A5E) + val neutralVariant050 = Color(color = 0xFF847376) + val neutralVariant060 = Color(color = 0xFF9E8C90) + val neutralVariant070 = Color(color = 0xFFBAA7AA) + val neutralVariant080 = Color(color = 0xFFD6C2C5) + val neutralVariant090 = Color(color = 0xFFF3DDE1) + val neutralVariant095 = Color(color = 0xFFFFECEF) + val neutralVariant099 = Color(color = 0xFFFFFBFF) + val neutralVariant100 = Color(color = 0xFFFFFFFF) +} diff --git a/core/ui/compose/theme2/k9mail/src/main/res/drawable/core_ui_theme2_k9mail_logo.xml b/core/ui/compose/theme2/k9mail/src/main/res/drawable/core_ui_theme2_k9mail_logo.xml new file mode 100644 index 000000000..2637f9700 --- /dev/null +++ b/core/ui/compose/theme2/k9mail/src/main/res/drawable/core_ui_theme2_k9mail_logo.xml @@ -0,0 +1,151 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/settings.gradle.kts b/settings.gradle.kts index 3f091fb7c..3f08adb60 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -76,6 +76,8 @@ include( ":core:ui:compose:common", ":core:ui:compose:designsystem", ":core:ui:compose:theme", + ":core:ui:compose:theme2:common", + ":core:ui:compose:theme2:k9mail", ":core:ui:compose:testing", )