/* * Copyright 2021 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.compose.material3 import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.interaction.Interaction import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.size import androidx.compose.foundation.selection.toggleable import androidx.compose.material.ripple.rememberRipple import androidx.compose.material3.tokens.FilledIconButtonTokens import androidx.compose.material3.tokens.FilledTonalIconButtonTokens import androidx.compose.material3.tokens.IconButtonTokens import androidx.compose.material3.tokens.OutlinedIconButtonTokens import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.Immutable import androidx.compose.runtime.State import androidx.compose.runtime.remember import androidx.compose.runtime.rememberUpdatedState import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Shape import androidx.compose.ui.semantics.Role import androidx.compose.ui.semantics.role import androidx.compose.ui.semantics.semantics /** * Material Design standard icon button. * * Icon buttons help people take supplementary actions with a single tap. They’re used when a * compact button is required, such as in a toolbar or image list. * * ![Standard icon button image](https://developer.android.com/images/reference/androidx/compose/material3/standard-icon-button.png) * * [content] should typically be an [Icon] (see [androidx.compose.material.icons.Icons]). If using a * custom icon, note that the typical size for the internal icon is 24 x 24 dp. * This icon button has an overall minimum touch target size of 48 x 48dp, to meet accessibility * guidelines. * * @sample androidx.compose.material3.samples.IconButtonSample * * @param onClick called when this icon button is clicked * @param modifier the [Modifier] to be applied to this icon button * @param enabled controls the enabled state of this icon button. When `false`, this component will * not respond to user input, and it will appear visually disabled and disabled to accessibility * services. * @param colors [IconButtonColors] that will be used to resolve the colors used for this icon * button in different states. See [IconButtonDefaults.iconButtonColors]. * @param interactionSource the [MutableInteractionSource] representing the stream of [Interaction]s * for this icon button. You can create and pass in your own `remember`ed instance to observe * [Interaction]s and customize the appearance / behavior of this icon button in different states. * @param content the content of this icon button, typically an [Icon] */ @Composable fun IconButton( onClick: () -> Unit, modifier: Modifier = Modifier, enabled: Boolean = true, colors: IconButtonColors = IconButtonDefaults.iconButtonColors(), interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, content: @Composable () -> Unit ) { Box( modifier = modifier .minimumInteractiveComponentSize() .size(IconButtonTokens.StateLayerSize) .clip(IconButtonTokens.StateLayerShape.value) .background(color = colors.containerColor(enabled)) .clickable( onClick = onClick, enabled = enabled, role = Role.Button, interactionSource = interactionSource, indication = rememberRipple( bounded = false, radius = IconButtonTokens.StateLayerSize / 2 ) ), contentAlignment = Alignment.Center ) { val contentColor = colors.contentColor(enabled) CompositionLocalProvider(LocalContentColor provides contentColor, content = content) } } /** * Material Design standard icon toggle button. * * Icon buttons help people take supplementary actions with a single tap. They’re used when a * compact button is required, such as in a toolbar or image list. * * ![Standard icon toggle button image](https://developer.android.com/images/reference/androidx/compose/material3/standard-icon-toggle-button.png) * * [content] should typically be an [Icon] (see [androidx.compose.material.icons.Icons]). If using a * custom icon, note that the typical size for the internal icon is 24 x 24 dp. * This icon button has an overall minimum touch target size of 48 x 48dp, to meet accessibility * guidelines. * * @sample androidx.compose.material3.samples.IconToggleButtonSample * * @param checked whether this icon button is toggled on or off * @param onCheckedChange called when this icon button is clicked * @param modifier the [Modifier] to be applied to this icon button * @param enabled controls the enabled state of this icon button. When `false`, this component will * not respond to user input, and it will appear visually disabled and disabled to accessibility * services. * @param colors [IconToggleButtonColors] that will be used to resolve the colors used for this icon * button in different states. See [IconButtonDefaults.iconToggleButtonColors]. * @param interactionSource the [MutableInteractionSource] representing the stream of [Interaction]s * for this icon button. You can create and pass in your own `remember`ed instance to observe * [Interaction]s and customize the appearance / behavior of this icon button in different states. * @param content the content of this icon button, typically an [Icon] */ @Composable fun IconToggleButton( checked: Boolean, onCheckedChange: (Boolean) -> Unit, modifier: Modifier = Modifier, enabled: Boolean = true, colors: IconToggleButtonColors = IconButtonDefaults.iconToggleButtonColors(), interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, content: @Composable () -> Unit ) { Box( modifier = modifier .minimumInteractiveComponentSize() .size(IconButtonTokens.StateLayerSize) .clip(IconButtonTokens.StateLayerShape.value) .background(color = colors.containerColor(enabled, checked).value) .toggleable( value = checked, onValueChange = onCheckedChange, enabled = enabled, role = Role.Checkbox, interactionSource = interactionSource, indication = rememberRipple( bounded = false, radius = IconButtonTokens.StateLayerSize / 2 ) ), contentAlignment = Alignment.Center ) { val contentColor = colors.contentColor(enabled, checked).value CompositionLocalProvider(LocalContentColor provides contentColor, content = content) } } /** * Material Design filled icon button. * * Icon buttons help people take supplementary actions with a single tap. They’re used when a * compact button is required, such as in a toolbar or image list. * * ![Filled icon button image](https://developer.android.com/images/reference/androidx/compose/material3/filled-icon-button.png) * * [content] should typically be an [Icon] (see [androidx.compose.material.icons.Icons]). If using a * custom icon, note that the typical size for the internal icon is 24 x 24 dp. * This icon button has an overall minimum touch target size of 48 x 48dp, to meet accessibility * guidelines. * * Filled icon button sample: * @sample androidx.compose.material3.samples.FilledIconButtonSample * * @param onClick called when this icon button is clicked * @param modifier the [Modifier] to be applied to this icon button * @param enabled controls the enabled state of this icon button. When `false`, this component will * not respond to user input, and it will appear visually disabled and disabled to accessibility * services. * @param shape defines the shape of this icon button's container * @param colors [IconButtonColors] that will be used to resolve the colors used for this icon * button in different states. See [IconButtonDefaults.filledIconButtonColors]. * @param interactionSource the [MutableInteractionSource] representing the stream of [Interaction]s * for this icon button. You can create and pass in your own `remember`ed instance to observe * [Interaction]s and customize the appearance / behavior of this icon button in different states. * @param content the content of this icon button, typically an [Icon] */ @Composable fun FilledIconButton( onClick: () -> Unit, modifier: Modifier = Modifier, enabled: Boolean = true, shape: Shape = IconButtonDefaults.filledShape, colors: IconButtonColors = IconButtonDefaults.filledIconButtonColors(), interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, content: @Composable () -> Unit ) = Surface( onClick = onClick, modifier = modifier.semantics { role = Role.Button }, enabled = enabled, shape = shape, color = colors.containerColor(enabled), contentColor = colors.contentColor(enabled), interactionSource = interactionSource ) { Box( modifier = Modifier.size(FilledIconButtonTokens.ContainerSize), contentAlignment = Alignment.Center ) { content() } } /** * Material Design filled tonal icon button. * * Icon buttons help people take supplementary actions with a single tap. They’re used when a * compact button is required, such as in a toolbar or image list. * * ![Filled tonal icon button image](https://developer.android.com/images/reference/androidx/compose/material3/filled-tonal-icon-button.png) * * A filled tonal icon button is a medium-emphasis icon button that is an alternative middle * ground between the default [FilledIconButton] and [OutlinedIconButton]. * They can be used in contexts where the lower-priority icon button requires slightly more emphasis * than an outline would give. * * [content] should typically be an [Icon] (see [androidx.compose.material.icons.Icons]). If using a * custom icon, note that the typical size for the internal icon is 24 x 24 dp. * This icon button has an overall minimum touch target size of 48 x 48dp, to meet accessibility * guidelines. * * Filled tonal icon button sample: * @sample androidx.compose.material3.samples.FilledTonalIconButtonSample * * @param onClick called when this icon button is clicked * @param modifier the [Modifier] to be applied to this icon button * @param enabled controls the enabled state of this icon button. When `false`, this component will * not respond to user input, and it will appear visually disabled and disabled to accessibility * services. * @param shape defines the shape of this icon button's container * @param colors [IconButtonColors] that will be used to resolve the colors used for this icon * button in different states. See [IconButtonDefaults.filledIconButtonColors]. * @param interactionSource the [MutableInteractionSource] representing the stream of [Interaction]s * for this icon button. You can create and pass in your own `remember`ed instance to observe * [Interaction]s and customize the appearance / behavior of this icon button in different states. * @param content the content of this icon button, typically an [Icon] */ @Composable fun FilledTonalIconButton( onClick: () -> Unit, modifier: Modifier = Modifier, enabled: Boolean = true, shape: Shape = IconButtonDefaults.filledShape, colors: IconButtonColors = IconButtonDefaults.filledTonalIconButtonColors(), interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, content: @Composable () -> Unit ) = Surface( onClick = onClick, modifier = modifier.semantics { role = Role.Button }, enabled = enabled, shape = shape, color = colors.containerColor(enabled), contentColor = colors.contentColor(enabled), interactionSource = interactionSource ) { Box( modifier = Modifier.size(FilledTonalIconButtonTokens.ContainerSize), contentAlignment = Alignment.Center ) { content() } } /** * Material Design filled icon toggle button. * * Icon buttons help people take supplementary actions with a single tap. They’re used when a * compact button is required, such as in a toolbar or image list. * * ![Filled icon toggle button image](https://developer.android.com/images/reference/androidx/compose/material3/filled-icon-toggle-button.png) * * [content] should typically be an [Icon] (see [androidx.compose.material.icons.Icons]). If using a * custom icon, note that the typical size for the internal icon is 24 x 24 dp. * This icon button has an overall minimum touch target size of 48 x 48dp, to meet accessibility * guidelines. * * Toggleable filled icon button sample: * @sample androidx.compose.material3.samples.FilledIconToggleButtonSample * * @param checked whether this icon button is toggled on or off * @param onCheckedChange called when this icon button is clicked * @param modifier the [Modifier] to be applied to this icon button * @param enabled controls the enabled state of this icon button. When `false`, this component will * not respond to user input, and it will appear visually disabled and disabled to accessibility * services. * @param shape defines the shape of this icon button's container * @param colors [IconToggleButtonColors] that will be used to resolve the colors used for this icon * button in different states. See [IconButtonDefaults.filledIconToggleButtonColors]. * @param interactionSource the [MutableInteractionSource] representing the stream of [Interaction]s * for this icon button. You can create and pass in your own `remember`ed instance to observe * [Interaction]s and customize the appearance / behavior of this icon button in different states. * @param content the content of this icon button, typically an [Icon] */ @OptIn(ExperimentalMaterial3Api::class) @Composable fun FilledIconToggleButton( checked: Boolean, onCheckedChange: (Boolean) -> Unit, modifier: Modifier = Modifier, enabled: Boolean = true, shape: Shape = IconButtonDefaults.filledShape, colors: IconToggleButtonColors = IconButtonDefaults.filledIconToggleButtonColors(), interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, content: @Composable () -> Unit ) = Surface( checked = checked, onCheckedChange = onCheckedChange, modifier = modifier.semantics { role = Role.Checkbox }, enabled = enabled, shape = shape, color = colors.containerColor(enabled, checked).value, contentColor = colors.contentColor(enabled, checked).value, interactionSource = interactionSource ) { Box( modifier = Modifier.size(FilledIconButtonTokens.ContainerSize), contentAlignment = Alignment.Center ) { content() } } /** * Material Design filled tonal icon toggle button. * * Icon buttons help people take supplementary actions with a single tap. They’re used when a * compact button is required, such as in a toolbar or image list. * * ![Filled tonal icon toggle button image](https://developer.android.com/images/reference/androidx/compose/material3/filled-tonal-icon-toggle-button.png) * * A filled tonal toggle icon button is a medium-emphasis icon button that is an alternative * middle ground between the default [FilledIconToggleButton] and [OutlinedIconToggleButton]. * They can be used in contexts where the lower-priority icon button requires slightly more emphasis * than an outline would give. * * [content] should typically be an [Icon] (see [androidx.compose.material.icons.Icons]). If using a * custom icon, note that the typical size for the internal icon is 24 x 24 dp. * This icon button has an overall minimum touch target size of 48 x 48dp, to meet accessibility * guidelines. * * Toggleable filled tonal icon button sample: * @sample androidx.compose.material3.samples.FilledTonalIconToggleButtonSample * * @param checked whether this icon button is toggled on or off * @param onCheckedChange called when this icon button is clicked * @param modifier the [Modifier] to be applied to this icon button * @param enabled controls the enabled state of this icon button. When `false`, this component will * not respond to user input, and it will appear visually disabled and disabled to accessibility * services. * @param shape defines the shape of this icon button's container * @param colors [IconToggleButtonColors] that will be used to resolve the colors used for this icon * button in different states. See [IconButtonDefaults.filledIconToggleButtonColors]. * @param interactionSource the [MutableInteractionSource] representing the stream of [Interaction]s * for this icon button. You can create and pass in your own `remember`ed instance to observe * [Interaction]s and customize the appearance / behavior of this icon button in different states. * @param content the content of this icon button, typically an [Icon] */ @OptIn(ExperimentalMaterial3Api::class) @Composable fun FilledTonalIconToggleButton( checked: Boolean, onCheckedChange: (Boolean) -> Unit, modifier: Modifier = Modifier, enabled: Boolean = true, shape: Shape = IconButtonDefaults.filledShape, colors: IconToggleButtonColors = IconButtonDefaults.filledTonalIconToggleButtonColors(), interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, content: @Composable () -> Unit ) = Surface( checked = checked, onCheckedChange = onCheckedChange, modifier = modifier.semantics { role = Role.Checkbox }, enabled = enabled, shape = shape, color = colors.containerColor(enabled, checked).value, contentColor = colors.contentColor(enabled, checked).value, interactionSource = interactionSource ) { Box( modifier = Modifier.size(FilledTonalIconButtonTokens.ContainerSize), contentAlignment = Alignment.Center ) { content() } } /** * Material Design outlined icon button. * * Icon buttons help people take supplementary actions with a single tap. They’re used when a * compact button is required, such as in a toolbar or image list. * * ![Outlined icon button image](https://developer.android.com/images/reference/androidx/compose/material3/outlined-icon-button.png) * * Icon buttons help people take supplementary actions with a single tap. They’re used when a * compact button is required, such as in a toolbar or image list. * * Use this "contained" icon button when the component requires more visual separation from the * background. * * [content] should typically be an [Icon] (see [androidx.compose.material.icons.Icons]). If using a * custom icon, note that the typical size for the internal icon is 24 x 24 dp. * The outlined icon button has an overall minimum touch target size of 48 x 48dp, to meet * accessibility guidelines. * * @sample androidx.compose.material3.samples.OutlinedIconButtonSample * * @param onClick called when this icon button is clicked * @param modifier the [Modifier] to be applied to this icon button * @param enabled controls the enabled state of this icon button. When `false`, this component will * not respond to user input, and it will appear visually disabled and disabled to accessibility * services. * @param shape defines the shape of this icon button's container and border (when [border] is not * null) * @param colors [IconButtonColors] that will be used to resolve the colors used for this icon * button in different states. See [IconButtonDefaults.outlinedIconButtonColors]. * @param border the border to draw around the container of this icon button. Pass `null` for no * border. See [IconButtonDefaults.outlinedIconButtonBorder]. * @param interactionSource the [MutableInteractionSource] representing the stream of [Interaction]s * for this icon button. You can create and pass in your own `remember`ed instance to observe * [Interaction]s and customize the appearance / behavior of this icon button in different states. * @param content the content of this icon button, typically an [Icon] */ @Composable fun OutlinedIconButton( onClick: () -> Unit, modifier: Modifier = Modifier, enabled: Boolean = true, shape: Shape = IconButtonDefaults.outlinedShape, colors: IconButtonColors = IconButtonDefaults.outlinedIconButtonColors(), border: BorderStroke? = IconButtonDefaults.outlinedIconButtonBorder(enabled), interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, content: @Composable () -> Unit ) = Surface( onClick = onClick, modifier = modifier.semantics { role = Role.Button }, enabled = enabled, shape = shape, color = colors.containerColor(enabled), contentColor = colors.contentColor(enabled), border = border, interactionSource = interactionSource ) { Box( modifier = Modifier.size(OutlinedIconButtonTokens.ContainerSize), contentAlignment = Alignment.Center ) { content() } } /** * Material Design outlined icon toggle button. * * Icon buttons help people take supplementary actions with a single tap. They’re used when a * compact button is required, such as in a toolbar or image list. * * ![Outlined icon toggle button image](https://developer.android.com/images/reference/androidx/compose/material3/outlined-icon-toggle-button.png) * * [content] should typically be an [Icon] (see [androidx.compose.material.icons.Icons]). If using a * custom icon, note that the typical size for the internal icon is 24 x 24 dp. * This icon button has an overall minimum touch target size of 48 x 48dp, to meet accessibility * guidelines. * * @sample androidx.compose.material3.samples.OutlinedIconToggleButtonSample * * @param checked whether this icon button is toggled on or off * @param onCheckedChange called when this icon button is clicked * @param modifier the [Modifier] to be applied to this icon button * @param enabled controls the enabled state of this icon button. When `false`, this component will * not respond to user input, and it will appear visually disabled and disabled to accessibility * services. * @param shape defines the shape of this icon button's container and border (when [border] is not * null) * @param colors [IconToggleButtonColors] that will be used to resolve the colors used for this icon * button in different states. See [IconButtonDefaults.outlinedIconToggleButtonColors]. * @param border the border to draw around the container of this icon button. Pass `null` for no * border. See [IconButtonDefaults.outlinedIconToggleButtonBorder]. * @param interactionSource the [MutableInteractionSource] representing the stream of [Interaction]s * for this icon button. You can create and pass in your own `remember`ed instance to observe * [Interaction]s and customize the appearance / behavior of this icon button in different states. * @param content the content of this icon button, typically an [Icon] */ @OptIn(ExperimentalMaterial3Api::class) @Composable fun OutlinedIconToggleButton( checked: Boolean, onCheckedChange: (Boolean) -> Unit, modifier: Modifier = Modifier, enabled: Boolean = true, shape: Shape = IconButtonDefaults.outlinedShape, colors: IconToggleButtonColors = IconButtonDefaults.outlinedIconToggleButtonColors(), border: BorderStroke? = IconButtonDefaults.outlinedIconToggleButtonBorder(enabled, checked), interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, content: @Composable () -> Unit ) = Surface( checked = checked, onCheckedChange = onCheckedChange, modifier = modifier.semantics { role = Role.Checkbox }, enabled = enabled, shape = shape, color = colors.containerColor(enabled, checked).value, contentColor = colors.contentColor(enabled, checked).value, border = border, interactionSource = interactionSource ) { Box( modifier = Modifier.size(OutlinedIconButtonTokens.ContainerSize), contentAlignment = Alignment.Center ) { content() } } /** * Contains the default values used by all icon button types. */ object IconButtonDefaults { /** Default shape for a filled icon button. */ val filledShape: Shape @Composable get() = FilledIconButtonTokens.ContainerShape.value /** Default shape for an outlined icon button. */ val outlinedShape: Shape @Composable get() = OutlinedIconButtonTokens.ContainerShape.value /** * Creates a [IconButtonColors] that represents the default colors used in a [IconButton]. * * @param containerColor the container color of this icon button when enabled. * @param contentColor the content color of this icon button when enabled. * @param disabledContainerColor the container color of this icon button when not enabled. * @param disabledContentColor the content color of this icon button when not enabled. */ @Composable fun iconButtonColors( containerColor: Color = Color.Transparent, contentColor: Color = LocalContentColor.current, disabledContainerColor: Color = Color.Transparent, disabledContentColor: Color = contentColor.copy(alpha = IconButtonTokens.DisabledIconOpacity) ): IconButtonColors = IconButtonColors( containerColor = containerColor, contentColor = contentColor, disabledContainerColor = disabledContainerColor, disabledContentColor = disabledContentColor, ) /** * Creates a [IconToggleButtonColors] that represents the default colors used in a * [IconToggleButton]. * * @param containerColor the container color of this icon button when enabled. * @param contentColor the content color of this icon button when enabled. * @param disabledContainerColor the container color of this icon button when not enabled. * @param disabledContentColor the content color of this icon button when not enabled. * @param checkedContainerColor the container color of this icon button when checked. * @param checkedContentColor the content color of this icon button when checked. */ @Composable fun iconToggleButtonColors( containerColor: Color = Color.Transparent, contentColor: Color = LocalContentColor.current, disabledContainerColor: Color = Color.Transparent, disabledContentColor: Color = contentColor.copy(alpha = IconButtonTokens.DisabledIconOpacity), checkedContainerColor: Color = Color.Transparent, checkedContentColor: Color = IconButtonTokens.SelectedIconColor.value ): IconToggleButtonColors = IconToggleButtonColors( containerColor = containerColor, contentColor = contentColor, disabledContainerColor = disabledContainerColor, disabledContentColor = disabledContentColor, checkedContainerColor = checkedContainerColor, checkedContentColor = checkedContentColor, ) /** * Creates a [IconButtonColors] that represents the default colors used in a [FilledIconButton]. * * @param containerColor the container color of this icon button when enabled. * @param contentColor the content color of this icon button when enabled. * @param disabledContainerColor the container color of this icon button when not enabled. * @param disabledContentColor the content color of this icon button when not enabled. */ @Composable fun filledIconButtonColors( containerColor: Color = FilledIconButtonTokens.ContainerColor.value, contentColor: Color = contentColorFor(containerColor), disabledContainerColor: Color = FilledIconButtonTokens.DisabledContainerColor.value .copy(alpha = FilledIconButtonTokens.DisabledContainerOpacity), disabledContentColor: Color = FilledIconButtonTokens.DisabledColor.value .copy(alpha = FilledIconButtonTokens.DisabledOpacity) ): IconButtonColors = IconButtonColors( containerColor = containerColor, contentColor = contentColor, disabledContainerColor = disabledContainerColor, disabledContentColor = disabledContentColor, ) /** * Creates a [IconToggleButtonColors] that represents the default colors used in a * [FilledIconToggleButton]. * * @param containerColor the container color of this icon button when enabled. * @param contentColor the content color of this icon button when enabled. * @param disabledContainerColor the container color of this icon button when not enabled. * @param disabledContentColor the content color of this icon button when not enabled. * @param checkedContainerColor the container color of this icon button when checked. * @param checkedContentColor the content color of this icon button when checked. */ @Composable fun filledIconToggleButtonColors( containerColor: Color = FilledIconButtonTokens.UnselectedContainerColor.value, // TODO(b/228455081): Using contentColorFor here will return OnSurfaceVariant, // while the token value is Primary. contentColor: Color = FilledIconButtonTokens.ToggleUnselectedColor.value, disabledContainerColor: Color = FilledIconButtonTokens.DisabledContainerColor.value .copy(alpha = FilledIconButtonTokens.DisabledContainerOpacity), disabledContentColor: Color = FilledIconButtonTokens.DisabledColor.value .copy(alpha = FilledIconButtonTokens.DisabledOpacity), checkedContainerColor: Color = FilledIconButtonTokens.SelectedContainerColor.value, checkedContentColor: Color = contentColorFor(checkedContainerColor) ): IconToggleButtonColors = IconToggleButtonColors( containerColor = containerColor, contentColor = contentColor, disabledContainerColor = disabledContainerColor, disabledContentColor = disabledContentColor, checkedContainerColor = checkedContainerColor, checkedContentColor = checkedContentColor, ) /** * Creates a [IconButtonColors] that represents the default colors used in a * [FilledTonalIconButton]. * * @param containerColor the container color of this icon button when enabled. * @param contentColor the content color of this icon button when enabled. * @param disabledContainerColor the container color of this icon button when not enabled. * @param disabledContentColor the content color of this icon button when not enabled. */ @Composable fun filledTonalIconButtonColors( containerColor: Color = FilledTonalIconButtonTokens.ContainerColor.value, contentColor: Color = contentColorFor(containerColor), disabledContainerColor: Color = FilledTonalIconButtonTokens.DisabledContainerColor.value .copy(alpha = FilledTonalIconButtonTokens.DisabledContainerOpacity), disabledContentColor: Color = FilledTonalIconButtonTokens.DisabledColor.value .copy(alpha = FilledTonalIconButtonTokens.DisabledOpacity) ): IconButtonColors = IconButtonColors( containerColor = containerColor, contentColor = contentColor, disabledContainerColor = disabledContainerColor, disabledContentColor = disabledContentColor, ) /** * Creates a [IconToggleButtonColors] that represents the default colors used in a * [FilledTonalIconToggleButton]. * * @param containerColor the container color of this icon button when enabled. * @param contentColor the content color of this icon button when enabled. * @param disabledContainerColor the container color of this icon button when not enabled. * @param disabledContentColor the content color of this icon button when not enabled. * @param checkedContainerColor the container color of this icon button when checked. * @param checkedContentColor the content color of this icon button when checked. */ @Composable fun filledTonalIconToggleButtonColors( containerColor: Color = FilledTonalIconButtonTokens.UnselectedContainerColor.value, contentColor: Color = contentColorFor(containerColor), disabledContainerColor: Color = FilledTonalIconButtonTokens.DisabledContainerColor.value .copy(alpha = FilledTonalIconButtonTokens.DisabledContainerOpacity), disabledContentColor: Color = FilledTonalIconButtonTokens.DisabledColor.value .copy(alpha = FilledTonalIconButtonTokens.DisabledOpacity), checkedContainerColor: Color = FilledTonalIconButtonTokens.SelectedContainerColor.value, checkedContentColor: Color = FilledTonalIconButtonTokens.ToggleSelectedColor.value ): IconToggleButtonColors = IconToggleButtonColors( containerColor = containerColor, contentColor = contentColor, disabledContainerColor = disabledContainerColor, disabledContentColor = disabledContentColor, checkedContainerColor = checkedContainerColor, checkedContentColor = checkedContentColor, ) /** * Creates a [IconButtonColors] that represents the default colors used in a * [OutlinedIconButton]. * * @param containerColor the container color of this icon button when enabled. * @param contentColor the content color of this icon button when enabled. * @param disabledContainerColor the container color of this icon button when not enabled. * @param disabledContentColor the content color of this icon button when not enabled. */ @Composable fun outlinedIconButtonColors( containerColor: Color = Color.Transparent, contentColor: Color = LocalContentColor.current, disabledContainerColor: Color = Color.Transparent, disabledContentColor: Color = contentColor.copy(alpha = OutlinedIconButtonTokens.DisabledOpacity) ): IconButtonColors = IconButtonColors( containerColor = containerColor, contentColor = contentColor, disabledContainerColor = disabledContainerColor, disabledContentColor = disabledContentColor, ) /** * Creates a [IconToggleButtonColors] that represents the default colors used in a * [OutlinedIconToggleButton]. * * @param containerColor the container color of this icon button when enabled. * @param contentColor the content color of this icon button when enabled. * @param disabledContainerColor the container color of this icon button when not enabled. * @param disabledContentColor the content color of this icon button when not enabled. * @param checkedContainerColor the container color of this icon button when checked. * @param checkedContentColor the content color of this icon button when checked. */ @Composable fun outlinedIconToggleButtonColors( containerColor: Color = Color.Transparent, contentColor: Color = LocalContentColor.current, disabledContainerColor: Color = Color.Transparent, disabledContentColor: Color = contentColor.copy(alpha = OutlinedIconButtonTokens.DisabledOpacity), checkedContainerColor: Color = OutlinedIconButtonTokens.SelectedContainerColor.value, checkedContentColor: Color = contentColorFor(checkedContainerColor) ): IconToggleButtonColors = IconToggleButtonColors( containerColor = containerColor, contentColor = contentColor, disabledContainerColor = disabledContainerColor, disabledContentColor = disabledContentColor, checkedContainerColor = checkedContainerColor, checkedContentColor = checkedContentColor, ) /** * Represents the [BorderStroke] for an [OutlinedIconButton], depending on its [enabled] and * [checked] state. * * @param enabled whether the icon button is enabled * @param checked whether the icon button is checked */ @Composable fun outlinedIconToggleButtonBorder(enabled: Boolean, checked: Boolean): BorderStroke? { if (checked) { return null } return outlinedIconButtonBorder(enabled) } /** * Represents the [BorderStroke] for an [OutlinedIconButton], depending on its [enabled] state. * * @param enabled whether the icon button is enabled */ @Composable fun outlinedIconButtonBorder(enabled: Boolean): BorderStroke { val color: Color = if (enabled) { LocalContentColor.current } else { LocalContentColor.current .copy(alpha = OutlinedIconButtonTokens.DisabledUnselectedOutlineOpacity) } return remember(color) { BorderStroke(OutlinedIconButtonTokens.UnselectedOutlineWidth, color) } } } /** * Represents the container and content colors used in an icon button in different states. * * @constructor create an instance with arbitrary colors. * - See [IconButtonDefaults.filledIconButtonColors] and * [IconButtonDefaults.filledTonalIconButtonColors] for the default colors used in a * [FilledIconButton]. * - See [IconButtonDefaults.outlinedIconButtonColors] for the default colors used in an * [OutlinedIconButton]. * * @param containerColor the container color of this icon button when enabled. * @param contentColor the content color of this icon button when enabled. * @param disabledContainerColor the container color of this icon button when not enabled. * @param disabledContentColor the content color of this icon button when not enabled. */ @Immutable class IconButtonColors constructor( val containerColor: Color, val contentColor: Color, val disabledContainerColor: Color, val disabledContentColor: Color, ) { /** * Represents the container color for this icon button, depending on [enabled]. * * @param enabled whether the icon button is enabled */ internal fun containerColor(enabled: Boolean): Color = if (enabled) containerColor else disabledContainerColor /** * Represents the content color for this icon button, depending on [enabled]. * * @param enabled whether the icon button is enabled */ internal fun contentColor(enabled: Boolean): Color = if (enabled) contentColor else disabledContentColor override fun equals(other: Any?): Boolean { if (this === other) return true if (other == null || other !is IconButtonColors) return false if (containerColor != other.containerColor) return false if (contentColor != other.contentColor) return false if (disabledContainerColor != other.disabledContainerColor) return false if (disabledContentColor != other.disabledContentColor) return false return true } override fun hashCode(): Int { var result = containerColor.hashCode() result = 31 * result + contentColor.hashCode() result = 31 * result + disabledContainerColor.hashCode() result = 31 * result + disabledContentColor.hashCode() return result } } /** * Represents the container and content colors used in a toggleable icon button in * different states. * * @constructor create an instance with arbitrary colors. * - See [IconButtonDefaults.filledIconToggleButtonColors] and * [IconButtonDefaults.filledTonalIconToggleButtonColors] for the default colors used in a * [FilledIconButton]. * - See [IconButtonDefaults.outlinedIconToggleButtonColors] for the default colors used in a * toggleable [OutlinedIconButton]. * * @param containerColor the container color of this icon button when enabled. * @param contentColor the content color of this icon button when enabled. * @param disabledContainerColor the container color of this icon button when not enabled. * @param disabledContentColor the content color of this icon button when not enabled. * @param checkedContainerColor the container color of this icon button when checked. * @param checkedContentColor the content color of this icon button when checked. */ @Immutable class IconToggleButtonColors constructor( val containerColor: Color, val contentColor: Color, val disabledContainerColor: Color, val disabledContentColor: Color, val checkedContainerColor: Color, val checkedContentColor: Color, ) { /** * Represents the container color for this icon button, depending on [enabled] and [checked]. * * @param enabled whether the icon button is enabled * @param checked whether the icon button is checked */ @Composable internal fun containerColor(enabled: Boolean, checked: Boolean): State { val target = when { !enabled -> disabledContainerColor !checked -> containerColor else -> checkedContainerColor } return rememberUpdatedState(target) } /** * Represents the content color for this icon button, depending on [enabled] and [checked]. * * @param enabled whether the icon button is enabled * @param checked whether the icon button is checked */ @Composable internal fun contentColor(enabled: Boolean, checked: Boolean): State { val target = when { !enabled -> disabledContentColor !checked -> contentColor else -> checkedContentColor } return rememberUpdatedState(target) } override fun equals(other: Any?): Boolean { if (this === other) return true if (other == null || other !is IconToggleButtonColors) return false if (containerColor != other.containerColor) return false if (contentColor != other.contentColor) return false if (disabledContainerColor != other.disabledContainerColor) return false if (disabledContentColor != other.disabledContentColor) return false if (checkedContainerColor != other.checkedContainerColor) return false if (checkedContentColor != other.checkedContentColor) return false return true } override fun hashCode(): Int { var result = containerColor.hashCode() result = 31 * result + contentColor.hashCode() result = 31 * result + disabledContainerColor.hashCode() result = 31 * result + disabledContentColor.hashCode() result = 31 * result + checkedContainerColor.hashCode() result = 31 * result + checkedContentColor.hashCode() return result } }