[go: nahoru, domu]

blob: 3256c14b63d5c4ea1c91431d03ef33b1ee397243 [file] [log] [blame]
/*
* Copyright 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package androidx.wear.compose.material3
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Immutable
import androidx.compose.runtime.ReadOnlyComposable
import androidx.compose.runtime.Stable
import androidx.compose.runtime.staticCompositionLocalOf
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.takeOrElse
import androidx.wear.compose.material3.tokens.ColorSchemeKeyTokens
import androidx.wear.compose.material3.tokens.ColorTokens
/**
* A [ColorScheme] holds all the named color parameters for a [MaterialTheme].
*
* Color schemes are designed to be harmonious, ensure accessible text, and distinguish UI elements
* and surfaces from one another.
*
* The Material color system and custom schemes provide default values for color as a starting point
* for customization.
*
* To learn more about color schemes, see
* [Material Design Color System](https://m3.material.io/styles/color/the-color-system/color-roles).
*
* @property primary The primary color is the color displayed most frequently across your app’s
* screens and components.
* @property primaryDim is less prominent than [primary] for component backgrounds
* @property primaryContainer is a standout container color for key components.
* @property onPrimary Color used for text and icons displayed on top of the primary color.
* @property onPrimaryContainer The color (and state variants) that should be used for content on
* top of [primaryContainer].
* @property secondary The secondary color provides more ways to accent and distinguish your
* product.
* @property secondaryDim is less prominent than [secondary] for component backgrounds.
* @property secondaryContainer A tonal color to be used in containers.
* @property onSecondary Color used for text and icons displayed on top of the secondary color.
* @property onSecondaryContainer The color (and state variants) that should be used for content on
* top of [secondaryContainer].
* @property tertiary The tertiary color that can be used to balance primary and secondary colors,
* or bring heightened attention to an element.
* @property tertiaryDim A less prominent tertiary color that can be used to balance primary and
* secondary colors, or bring heightened attention to an element.
* @property tertiaryContainer A tonal color to be used in containers.
* @property onTertiary Color used for text and icons displayed on top of the tertiary color.
* @property onTertiaryContainer The color (and state variants) that should be used for content on
* top of [tertiaryContainer].
* @property surfaceContainerLow A surface color used for large containment components such as Card
* and Button with low prominence.
* @property surfaceContainer The main surface color that affect surfaces of components with large
* containment areas, such as Card and Button.
* @property surfaceContainerHigh A surface color used for large containment components such Card
* and Button with high prominence.
* @property onSurface Color used for text and icons displayed on top of the surface color.
* @property onSurfaceVariant The color for secondary text and icons on top of [surfaceContainer].
* @property outline The main color for primary outline components. The outline color role adds
* contrast for accessibility purposes.
* @property outlineVariant The secondary color for secondary outline components.
* @property background The background color that appears behind other content.
* @property onBackground Color used for text and icons displayed on top of the background color.
* @property error Color that indicates remove, delete, close or dismiss actions, such as Swipe to
* Reveal. Added as an errorContainer alternative that is slightly less alarming and urgent color.
* @property onError Color used for text and icons displayed on top of the error color.
* @property errorContainer Color that indicates errors or emergency actions, such as safety alerts.
* This color is for use-cases that are more alarming and urgent than the error color.
* @property onErrorContainer Color used for text and icons on the errorContainer color.
*/
@Immutable
@Stable
public class ColorScheme(
val primary: Color = ColorTokens.Primary,
val primaryDim: Color = ColorTokens.PrimaryDim,
val primaryContainer: Color = ColorTokens.PrimaryContainer,
val onPrimary: Color = ColorTokens.OnPrimary,
val onPrimaryContainer: Color = ColorTokens.OnPrimaryContainer,
val secondary: Color = ColorTokens.Secondary,
val secondaryDim: Color = ColorTokens.SecondaryDim,
val secondaryContainer: Color = ColorTokens.SecondaryContainer,
val onSecondary: Color = ColorTokens.OnSecondary,
val onSecondaryContainer: Color = ColorTokens.OnSecondaryContainer,
val tertiary: Color = ColorTokens.Tertiary,
val tertiaryDim: Color = ColorTokens.TertiaryDim,
val tertiaryContainer: Color = ColorTokens.TertiaryContainer,
val onTertiary: Color = ColorTokens.OnTertiary,
val onTertiaryContainer: Color = ColorTokens.OnTertiaryContainer,
val surfaceContainerLow: Color = ColorTokens.SurfaceContainerLow,
val surfaceContainer: Color = ColorTokens.SurfaceContainer,
val surfaceContainerHigh: Color = ColorTokens.SurfaceContainerHigh,
val onSurface: Color = ColorTokens.OnSurface,
val onSurfaceVariant: Color = ColorTokens.OnSurfaceVariant,
val outline: Color = ColorTokens.Outline,
val outlineVariant: Color = ColorTokens.OutlineVariant,
val background: Color = ColorTokens.Background,
val onBackground: Color = ColorTokens.OnBackground,
val error: Color = ColorTokens.Error,
val onError: Color = ColorTokens.OnError,
val errorContainer: Color = ColorTokens.ErrorContainer,
val onErrorContainer: Color = ColorTokens.OnErrorContainer,
) {
/** Returns a copy of this Colors, optionally overriding some of the values. */
fun copy(
primary: Color = this.primary,
primaryDim: Color = this.primaryDim,
primaryContainer: Color = this.primaryContainer,
onPrimary: Color = this.onPrimary,
onPrimaryContainer: Color = this.onPrimaryContainer,
secondary: Color = this.secondary,
secondaryDim: Color = this.secondaryDim,
secondaryContainer: Color = this.secondaryContainer,
onSecondary: Color = this.onSecondary,
onSecondaryContainer: Color = this.onSecondaryContainer,
tertiary: Color = this.tertiary,
tertiaryDim: Color = this.tertiaryDim,
tertiaryContainer: Color = this.tertiaryContainer,
onTertiary: Color = this.onTertiary,
onTertiaryContainer: Color = this.onTertiaryContainer,
surfaceContainerLow: Color = this.surfaceContainerLow,
surfaceContainer: Color = this.surfaceContainer,
surfaceContainerHigh: Color = this.surfaceContainerHigh,
onSurface: Color = this.onSurface,
onSurfaceVariant: Color = this.onSurfaceVariant,
outline: Color = this.outline,
outlineVariant: Color = this.outlineVariant,
background: Color = this.background,
onBackground: Color = this.onBackground,
error: Color = this.error,
onError: Color = this.onError,
errorContainer: Color = this.errorContainer,
onErrorContainer: Color = this.onErrorContainer,
): ColorScheme =
ColorScheme(
primary = primary,
primaryDim = primaryDim,
primaryContainer = primaryContainer,
onPrimary = onPrimary,
onPrimaryContainer = onPrimaryContainer,
secondary = secondary,
secondaryDim = secondaryDim,
secondaryContainer = secondaryContainer,
onSecondary = onSecondary,
onSecondaryContainer = onSecondaryContainer,
tertiary = tertiary,
tertiaryDim = tertiaryDim,
tertiaryContainer = tertiaryContainer,
onTertiary = onTertiary,
onTertiaryContainer = onTertiaryContainer,
surfaceContainerLow = surfaceContainerLow,
surfaceContainer = surfaceContainer,
surfaceContainerHigh = surfaceContainerHigh,
onSurface = onSurface,
onSurfaceVariant = onSurfaceVariant,
outline = outline,
outlineVariant = outlineVariant,
background = background,
onBackground = onBackground,
error = error,
onError = onError,
errorContainer = errorContainer,
onErrorContainer = onErrorContainer,
)
override fun toString(): String {
return "Colors(" +
"primary=$primary, " +
"primaryDim=$primaryDim, " +
"primaryContainer=$primaryContainer, " +
" " +
" " +
"secondary=$secondary, " +
"secondaryDim=$secondaryDim, " +
"secondaryContainer=$secondaryContainer, " +
" " +
" " +
"tertiary=$tertiary, " +
"tertiaryDim=$tertiaryDim, " +
"tertiaryContainer=$tertiaryContainer, " +
" " +
" " +
"surfaceContainerLow=$surfaceContainerLow, " +
"surfaceContainer=$surfaceContainer, " +
"surfaceContainerHigh=$surfaceContainerHigh, " +
" " +
" " +
"outline=$outline, " +
"outlineVariant=$outlineVariant, " +
"background=$background, " +
" " +
"> +
"errorContainer=$errorContainer, " +
"> +
")"
}
// Button Colors
internal var defaultButtonColorsCached: ButtonColors? = null
internal var defaultFilledButtonColorsCached: ButtonColors? = null
internal var defaultFilledTonalButtonColorsCached: ButtonColors? = null
internal var defaultOutlinedButtonColorsCached: ButtonColors? = null
internal var defaultChildButtonColorsCached: ButtonColors? = null
// Icon Button
internal var defaultIconButtonColorsCached: IconButtonColors? = null
internal var defaultFilledIconButtonColorsCached: IconButtonColors? = null
internal var defaultFilledTonalIconButtonColorsCached: IconButtonColors? = null
internal var defaultOutlinedIconButtonColorsCached: IconButtonColors? = null
// Text Button
internal var defaultTextButtonColorsCached: TextButtonColors? = null
internal var defaultFilledTextButtonColorsCached: TextButtonColors? = null
internal var defaultFilledTonalTextButtonColorsCached: TextButtonColors? = null
internal var defaultOutlinedTextButtonColorsCached: TextButtonColors? = null
// Card
internal var defaultCardColorsCached: CardColors? = null
internal var defaultOutlinedCardColorsCached: CardColors? = null
// Toggle Button
internal var defaultToggleButtonColorsCached: ToggleButtonColors? = null
internal var defaultSplitToggleButtonColorsCached: SplitToggleButtonColors? = null
// Radio Button
internal var defaultRadioButtonColorsCached: RadioButtonColors? = null
internal var defaultSplitRadioButtonColorsCached: SplitRadioButtonColors? = null
}
/**
* The Material color system contains pairs of colors that are typically used for the background and
* content color inside a component. For example, a Button typically uses `primary` for its
* background, and `onPrimary` for the color of its content (usually text or iconography).
*
* This function tries to match the provided [backgroundColor] to a 'background' color in this
* [ColorScheme], and then will return the corresponding color used for content. For example, when
* [backgroundColor] is [ColorScheme.primary], this will return [ColorScheme.onPrimary].
*
* If [backgroundColor] does not match a background color in the theme, this will return
* [Color.Unspecified].
*
* @return the matching content color for [backgroundColor]. If [backgroundColor] is not present in
* the theme's [ColorScheme], then returns [Color.Unspecified].
* @see contentColorFor
*/
fun ColorScheme.contentColorFor(backgroundColor: Color): Color {
return when (backgroundColor) {
primary,
primaryDim -> onPrimary
primaryContainer -> onPrimaryContainer
secondary,
secondaryDim -> onSecondary
secondaryContainer -> onSecondaryContainer
tertiary,
tertiaryDim -> onTertiary
tertiaryContainer -> onTertiaryContainer
surfaceContainer,
surfaceContainerLow,
surfaceContainerHigh -> onSurface
background -> onBackground
error -> onError
errorContainer -> onErrorContainer
else -> Color.Unspecified
}
}
/**
* The Material color system contains pairs of colors that are typically used for the background and
* content color inside a component. For example, a Button typically uses `primary` for its
* background, and `onPrimary` for the color of its content (usually text or iconography).
*
* This function tries to match the provided [backgroundColor] to a 'background' color in this
* [ColorScheme], and then will return the corresponding color used for content. For example, when
* [backgroundColor] is [ColorScheme.primary], this will return [ColorScheme.onPrimary].
*
* If [backgroundColor] does not match a background color in the theme, this will return the current
* value of [LocalContentColor] as a best-effort color.
*
* @return the matching content color for [backgroundColor]. If [backgroundColor] is not present in
* the theme's [ColorScheme], then returns the current value of [LocalContentColor].
* @see ColorScheme.contentColorFor
*/
@Composable
@ReadOnlyComposable
fun contentColorFor(backgroundColor: Color): Color =
MaterialTheme.colorScheme.contentColorFor(backgroundColor).takeOrElse {
LocalContentColor.current
}
/**
* Helper function for component color tokens. Here is an example on how to use component color
* tokens: ``MaterialTheme.colorScheme.fromToken(FilledButtonTokens.ContainerColor)``
*/
internal fun ColorScheme.fromToken(value: ColorSchemeKeyTokens): Color {
return when (value) {
ColorSchemeKeyTokens.Primary -> primary
ColorSchemeKeyTokens.PrimaryDim -> primaryDim
ColorSchemeKeyTokens.PrimaryContainer -> primaryContainer
ColorSchemeKeyTokens.OnPrimary -> onPrimary
ColorSchemeKeyTokens.OnPrimaryContainer -> onPrimaryContainer
ColorSchemeKeyTokens.Secondary -> secondary
ColorSchemeKeyTokens.SecondaryDim -> secondaryDim
ColorSchemeKeyTokens.SecondaryContainer -> secondaryContainer
ColorSchemeKeyTokens.OnSecondary -> onSecondary
ColorSchemeKeyTokens.OnSecondaryContainer -> onSecondaryContainer
ColorSchemeKeyTokens.Tertiary -> tertiary
ColorSchemeKeyTokens.TertiaryDim -> tertiaryDim
ColorSchemeKeyTokens.TertiaryContainer -> tertiaryContainer
ColorSchemeKeyTokens.OnTertiary -> onTertiary
ColorSchemeKeyTokens.OnTertiaryContainer -> onTertiaryContainer
ColorSchemeKeyTokens.SurfaceContainerLow -> surfaceContainerLow
ColorSchemeKeyTokens.SurfaceContainer -> surfaceContainer
ColorSchemeKeyTokens.SurfaceContainerHigh -> surfaceContainerHigh
ColorSchemeKeyTokens.OnSurface -> onSurface
ColorSchemeKeyTokens.OnSurfaceVariant -> onSurfaceVariant
ColorSchemeKeyTokens.Outline -> outline
ColorSchemeKeyTokens.OutlineVariant -> outlineVariant
ColorSchemeKeyTokens.Background -> background
ColorSchemeKeyTokens.OnBackground -> onBackground
ColorSchemeKeyTokens.Error -> error
ColorSchemeKeyTokens.OnError -> onError
ColorSchemeKeyTokens.ErrorContainer -> errorContainer
ColorSchemeKeyTokens.OnErrorContainer -> onErrorContainer
}
}
/**
* CompositionLocal used to pass [ColorScheme] down the tree.
*
* Setting the value here is typically done as part of [MaterialTheme]. To retrieve the current
* value of this CompositionLocal, use [MaterialTheme.colorScheme].
*/
internal val LocalColorScheme = staticCompositionLocalOf<ColorScheme> { ColorScheme() }
/**
* Convert given color to disabled color.
*
* @param disabledAlpha Alpha used to represent disabled colors.
*/
internal fun Color.toDisabledColor(disabledAlpha: Float = DisabledContentAlpha) =
this.copy(alpha = this.alpha * disabledAlpha)
/**
* Converts a color token key to the local color scheme provided by the theme. The color references
* the [LocalColorScheme].
*/
internal val ColorSchemeKeyTokens.value: Color
@ReadOnlyComposable @Composable get() = MaterialTheme.colorScheme.fromToken(this)
internal const val DisabledContentAlpha = 0.38f
internal const val DisabledContainerAlpha = 0.12f
internal const val DisabledBorderAlpha = 0.20f