| /* |
| * 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.foundation.BorderStroke |
| import androidx.compose.foundation.border |
| 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.BoxScope |
| import androidx.compose.foundation.layout.Column |
| import androidx.compose.foundation.layout.IntrinsicSize |
| import androidx.compose.foundation.layout.PaddingValues |
| import androidx.compose.foundation.layout.Row |
| import androidx.compose.foundation.layout.RowScope |
| import androidx.compose.foundation.layout.Spacer |
| import androidx.compose.foundation.layout.defaultMinSize |
| import androidx.compose.foundation.layout.fillMaxHeight |
| import androidx.compose.foundation.layout.fillMaxSize |
| import androidx.compose.foundation.layout.height |
| import androidx.compose.foundation.layout.padding |
| import androidx.compose.foundation.layout.size |
| import androidx.compose.foundation.layout.width |
| import androidx.compose.foundation.layout.wrapContentSize |
| import androidx.compose.foundation.shape.CircleShape |
| import androidx.compose.runtime.Composable |
| 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.draw.paint |
| import androidx.compose.ui.graphics.Brush |
| import androidx.compose.ui.graphics.Color |
| import androidx.compose.ui.graphics.Shape |
| import androidx.compose.ui.graphics.painter.ColorPainter |
| import androidx.compose.ui.graphics.painter.Painter |
| import androidx.compose.ui.layout.ContentScale |
| import androidx.compose.ui.semantics.Role |
| import androidx.compose.ui.text.TextStyle |
| import androidx.compose.ui.unit.Dp |
| import androidx.compose.ui.unit.dp |
| import androidx.wear.compose.material3.tokens.ChildButtonTokens |
| import androidx.wear.compose.material3.tokens.FilledButtonTokens |
| import androidx.wear.compose.material3.tokens.FilledTonalButtonTokens |
| import androidx.wear.compose.material3.tokens.ImageButtonTokens |
| import androidx.wear.compose.material3.tokens.OutlinedButtonTokens |
| |
| /** |
| * Base level Wear Material3 [Button] that offers a single slot to take any content. |
| * Used as the container for more opinionated [Button] components that take specific |
| * content such as icons and labels. |
| * |
| * The [Button] is stadium-shaped by default and its standard height is designed to take 2 lines of |
| * text of [Typography.labelMedium] style. With localisation and/or large font sizes, the text can |
| * extend to a maximum of 3 lines in which case, the [Button] height adjusts to accommodate the |
| * contents. |
| * |
| * [Button] takes the [ButtonDefaults.filledButtonColors] color scheme by default, |
| * with colored background, contrasting content color and no border. This is a high-emphasis button |
| * for the primary, most important or most common action on a screen. |
| * |
| * Other recommended buttons with [ButtonColors] for different levels of emphasis are: |
| * [FilledTonalButton] which defaults to [ButtonDefaults.filledTonalButtonColors], |
| * [OutlinedButton] which defaults to [ButtonDefaults.outlinedButtonColors] and |
| * [ChildButton] which defaults to [ButtonDefaults.childButtonColors]. |
| * Buttons can also take an image background using [ButtonDefaults.imageBackgroundButtonColors]. |
| * |
| * Button can be enabled or disabled. A disabled button will not respond to click events. |
| * |
| * TODO(b/261838497) Add Material3 UX guidance links |
| * |
| * Example of a [Button]: |
| * @sample androidx.wear.compose.material3.samples.SimpleButtonSample |
| * |
| * @param onClick Will be called when the user clicks the button |
| * @param modifier Modifier to be applied to the button |
| * @param enabled Controls the enabled state of the button. When `false`, this button will not |
| * be clickable |
| * @param shape Defines the button's shape. It is strongly recommended to use the default as this |
| * shape is a key characteristic of the Wear Material3 Theme |
| * @param colors [ButtonColors] that will be used to resolve the background and content color for |
| * this button in different states. See [ButtonDefaults.filledButtonColors]. |
| * @param border Optional [BorderStroke] that will be used to resolve the border for this |
| * button in different states. |
| * @param contentPadding The spacing values to apply internally between the container and the |
| * content |
| * @param interactionSource an optional hoisted [MutableInteractionSource] for observing and |
| * emitting [Interaction]s for this button. You can use this to change the button's appearance |
| * or preview the button in different states. Note that if `null` is provided, interactions will |
| * still happen internally. |
| */ |
| @Composable |
| fun Button( |
| onClick: () -> Unit, |
| modifier: Modifier = Modifier, |
| enabled: Boolean = true, |
| shape: Shape = FilledButtonTokens.ContainerShape.value, |
| colors: ButtonColors = ButtonDefaults.filledButtonColors(), |
| border: BorderStroke? = null, |
| contentPadding: PaddingValues = ButtonDefaults.ContentPadding, |
| interactionSource: MutableInteractionSource? = null, |
| content: @Composable RowScope.() -> Unit, |
| ) = ButtonImpl( |
| onClick = onClick, |
| modifier = modifier.buttonSizeModifier(), |
| enabled = enabled, |
| shape = shape, |
| labelFont = FilledButtonTokens.LabelFont.value, |
| colors = colors, |
| border = border, |
| contentPadding = contentPadding, |
| interactionSource = interactionSource, |
| content = content |
| ) |
| |
| /** |
| * Base level Wear Material3 [FilledTonalButton] that offers a single slot to take any content. |
| * Used as the container for more opinionated [FilledTonalButton] components that take specific |
| * content such as icons and labels. |
| * |
| * The [FilledTonalButton] is Stadium-shaped by default and has a max height designed to take no |
| * more than two lines of text of [Typography.labelMedium] style. |
| * With localisation and/or large font sizes, the text can extend to a maximum of 3 lines in which |
| * case, the [FilledTonalButton] height adjusts to accommodate the contents. |
| * The [FilledTonalButton] can have an icon or image horizontally parallel to the two lines of text. |
| * |
| * [FilledTonalButton] takes the [ButtonDefaults.filledTonalButtonColors] color scheme by default, |
| * with muted background, contrasting content color and no border. This is a medium-emphasis button |
| * for important actions that don't distract from other onscreen elements, such as final or |
| * unblocking actions in a flow with less emphasis than [Button]. |
| * |
| * Other recommended buttons with [ButtonColors] for different levels of emphasis are: |
| * [Button] which defaults to [ButtonDefaults.filledButtonColors], |
| * [OutlinedButton] which defaults to [ButtonDefaults.outlinedButtonColors] and |
| * [ChildButton] which defaults to [ButtonDefaults.childButtonColors]. |
| * Buttons can also take an image background using [ButtonDefaults.imageBackgroundButtonColors]. |
| * |
| * Button can be enabled or disabled. A disabled button will not respond to click events. |
| * |
| * TODO(b/261838497) Add Material3 UX guidance links |
| * |
| * Example of a [FilledTonalButton]: |
| * @sample androidx.wear.compose.material3.samples.SimpleFilledTonalButtonSample |
| * |
| * @param onClick Will be called when the user clicks the button |
| * @param modifier Modifier to be applied to the button |
| * @param enabled Controls the enabled state of the button. When `false`, this button will not |
| * be clickable |
| * @param shape Defines the button's shape. It is strongly recommended to use the default as this |
| * shape is a key characteristic of the Wear Material3 Theme |
| * @param colors [ButtonColors] that will be used to resolve the background and content color for |
| * this button in different states. See [ButtonDefaults.filledTonalButtonColors]. |
| * @param border Optional [BorderStroke] that will be used to resolve the border for this |
| * button in different states. |
| * @param contentPadding The spacing values to apply internally between the container and the |
| * content |
| * @param interactionSource an optional hoisted [MutableInteractionSource] for observing and |
| * emitting [Interaction]s for this button. You can use this to change the button's appearance |
| * or preview the button in different states. Note that if `null` is provided, interactions will |
| * still happen internally. |
| */ |
| @Composable |
| fun FilledTonalButton( |
| onClick: () -> Unit, |
| modifier: Modifier = Modifier, |
| enabled: Boolean = true, |
| shape: Shape = FilledTonalButtonTokens.ContainerShape.value, |
| colors: ButtonColors = ButtonDefaults.filledTonalButtonColors(), |
| border: BorderStroke? = null, |
| contentPadding: PaddingValues = ButtonDefaults.ContentPadding, |
| interactionSource: MutableInteractionSource? = null, |
| content: @Composable RowScope.() -> Unit, |
| ) = ButtonImpl( |
| onClick = onClick, |
| modifier = modifier.buttonSizeModifier(), |
| enabled = enabled, |
| shape = shape, |
| labelFont = FilledTonalButtonTokens.LabelFont.value, |
| colors = colors, |
| border = border, |
| contentPadding = contentPadding, |
| interactionSource = interactionSource, |
| content = content |
| ) |
| |
| /** |
| * Base level Wear Material3 [OutlinedButton] that offers a single slot to take any content. Used as |
| * the container for more opinionated [OutlinedButton] components that take specific content such |
| * as icons and labels. |
| * |
| * The [OutlinedButton] is Stadium-shaped by default and has a max height designed to take no more |
| * than two lines of text of [Typography.labelMedium] style. |
| * With localisation and/or large font sizes, the text can extend to a maximum of 3 lines in which |
| * case, the [OutlinedButton] height adjusts to accommodate the contents. |
| * The [OutlinedButton] can have an icon or image horizontally parallel to the two lines of text. |
| * |
| * [OutlinedButton] takes the [ButtonDefaults.outlinedButtonColors] color scheme by default, |
| * with a transparent background and a thin border. This is a medium-emphasis button |
| * for important, non-primary actions that need attention. |
| * |
| * Other recommended buttons with [ButtonColors] for different levels of emphasis are: |
| * [Button] which defaults to [ButtonDefaults.filledButtonColors], |
| * [FilledTonalButton] which defaults to [ButtonDefaults.filledTonalButtonColors], |
| * [ChildButton] which defaults to [ButtonDefaults.childButtonColors]. |
| * Buttons can also take an image background using [ButtonDefaults.imageBackgroundButtonColors]. |
| * |
| * Button can be enabled or disabled. A disabled button will not respond to click events. |
| * |
| * TODO(b/261838497) Add Material3 UX guidance links |
| * |
| * Example of an [OutlinedButton]: |
| * @sample androidx.wear.compose.material3.samples.SimpleOutlinedButtonSample |
| * |
| * @param onClick Will be called when the user clicks the button |
| * @param modifier Modifier to be applied to the button |
| * @param enabled Controls the enabled state of the button. When `false`, this button will not |
| * be clickable |
| * @param shape Defines the button's shape. It is strongly recommended to use the default as this |
| * shape is a key characteristic of the Wear Material3 Theme |
| * @param colors [ButtonColors] that will be used to resolve the background and content color for |
| * this button in different states. See [ButtonDefaults.outlinedButtonColors]. |
| * @param border Optional [BorderStroke] that will be used to resolve the border for this |
| * button in different states. See [ButtonDefaults.outlinedButtonBorder]. |
| * @param contentPadding The spacing values to apply internally between the container and the |
| * content |
| * @param interactionSource an optional hoisted [MutableInteractionSource] for observing and |
| * emitting [Interaction]s for this button. You can use this to change the button's appearance |
| * or preview the button in different states. Note that if `null` is provided, interactions will |
| * still happen internally. |
| */ |
| @Composable |
| fun OutlinedButton( |
| onClick: () -> Unit, |
| modifier: Modifier = Modifier, |
| enabled: Boolean = true, |
| shape: Shape = OutlinedButtonTokens.ContainerShape.value, |
| colors: ButtonColors = ButtonDefaults.outlinedButtonColors(), |
| border: BorderStroke? = ButtonDefaults.outlinedButtonBorder(enabled), |
| contentPadding: PaddingValues = ButtonDefaults.ContentPadding, |
| interactionSource: MutableInteractionSource? = null, |
| content: @Composable RowScope.() -> Unit, |
| ) = ButtonImpl( |
| onClick = onClick, |
| modifier = modifier.buttonSizeModifier(), |
| enabled = enabled, |
| shape = shape, |
| labelFont = OutlinedButtonTokens.LabelFont.value, |
| colors = colors, |
| border = border, |
| contentPadding = contentPadding, |
| interactionSource = interactionSource, |
| content = content |
| ) |
| |
| /** |
| * Base level Wear Material3 [ChildButton] that offers a single slot to take any content. Used as |
| * the container for more opinionated [ChildButton] components that take specific content such |
| * as icons and labels. |
| * |
| * The [ChildButton] is stadium-shaped by default and its standard height is designed to |
| * take 2 lines of text of [Typography.labelMedium] style. |
| * With localisation and/or large font sizes, the text can extend to a maximum of 3 lines in which |
| * case, the [ChildButton] height adjusts to accommodate the contents. |
| * The [ChildButton] can have an icon or image horizontally parallel to the two lines of text. |
| * |
| * [ChildButton] takes the [ButtonDefaults.childButtonColors] color scheme by default, |
| * with a transparent background and no border. This is a low-emphasis button for optional |
| * or supplementary actions with the least amount of prominence. |
| * |
| * Other recommended buttons with [ButtonColors] for different levels of emphasis are: |
| * [Button] which defaults to [ButtonDefaults.filledButtonColors], |
| * [FilledTonalButton] which defaults to [ButtonDefaults.filledTonalButtonColors], |
| * [OutlinedButton] which defaults to [ButtonDefaults.outlinedButtonColors] and |
| * Buttons can also take an image background using [ButtonDefaults.imageBackgroundButtonColors]. |
| * |
| * Button can be enabled or disabled. A disabled button will not respond to click events. |
| * |
| * TODO(b/261838497) Add Material3 UX guidance links |
| * |
| * Example of a [ChildButton]: |
| * @sample androidx.wear.compose.material3.samples.SimpleChildButtonSample |
| * |
| * @param onClick Will be called when the user clicks the button |
| * @param modifier Modifier to be applied to the button |
| * @param enabled Controls the enabled state of the button. When `false`, this button will not |
| * be clickable |
| * @param shape Defines the button's shape. It is strongly recommended to use the default as this |
| * shape is a key characteristic of the Wear Material3 Theme |
| * @param colors [ButtonColors] that will be used to resolve the background and content color for |
| * this button in different states. See [ButtonDefaults.childButtonColors]. |
| * @param border Optional [BorderStroke] that will be used to resolve the border for this |
| * button in different states. |
| * @param contentPadding The spacing values to apply internally between the container and the |
| * content |
| * @param interactionSource an optional hoisted [MutableInteractionSource] for observing and |
| * emitting [Interaction]s for this button. You can use this to change the button's appearance |
| * or preview the button in different states. Note that if `null` is provided, interactions will |
| * still happen internally. |
| */ |
| @Composable |
| fun ChildButton( |
| onClick: () -> Unit, |
| modifier: Modifier = Modifier, |
| enabled: Boolean = true, |
| shape: Shape = ChildButtonTokens.ContainerShape.value, |
| colors: ButtonColors = ButtonDefaults.childButtonColors(), |
| border: BorderStroke? = null, |
| contentPadding: PaddingValues = ButtonDefaults.ContentPadding, |
| interactionSource: MutableInteractionSource? = null, |
| content: @Composable RowScope.() -> Unit, |
| ) = ButtonImpl( |
| onClick = onClick, |
| modifier = modifier.buttonSizeModifier(), |
| enabled = enabled, |
| shape = shape, |
| labelFont = OutlinedButtonTokens.LabelFont.value, |
| colors = colors, |
| border = border, |
| contentPadding = contentPadding, |
| interactionSource = interactionSource, |
| content = content |
| ) |
| |
| /** |
| * Wear Material3 [Button] that offers three slots and a specific layout for an |
| * icon, label and secondaryLabel. The icon and secondaryLabel are optional. |
| * The items are laid out with the icon, if provided, at the start of a row, with a column next |
| * containing the two label slots. |
| * |
| * The [Button] is stadium-shaped by default and its standard height is designed to take 2 lines of |
| * text of [Typography.labelMedium] style - either a two-line label or both a single line label |
| * and a secondary label. |
| * With localisation and/or large font sizes, the [Button] height adjusts to |
| * accommodate the contents. The label and secondary label should be consistently aligned. |
| * |
| * If a icon is provided then the labels should be "start" aligned, e.g. left aligned in ltr so that |
| * the text starts next to the icon. |
| * |
| * [Button] takes the [ButtonDefaults.filledButtonColors] color scheme by default, |
| * with colored background, contrasting content color and no border. This is a high-emphasis button |
| * for the primary, most important or most common action on a screen. |
| * |
| * Other recommended buttons with [ButtonColors] for different levels of emphasis are: |
| * [FilledTonalButton] which defaults to [ButtonDefaults.filledTonalButtonColors], |
| * [OutlinedButton] which defaults to [ButtonDefaults.outlinedButtonColors] and |
| * [ChildButton] which defaults to [ButtonDefaults.childButtonColors]. |
| * Buttons can also take an image background using [ButtonDefaults.imageBackgroundButtonColors]. |
| * |
| * [Button] can be enabled or disabled. A disabled button will not respond to click events. |
| * |
| * TODO(b/261838497) Add Material3 UX guidance links |
| * |
| * Example of a [Button] with an icon and secondary label: |
| * @sample androidx.wear.compose.material3.samples.ButtonSample |
| * |
| * @param onClick Will be called when the user clicks the button |
| * @param modifier Modifier to be applied to the button |
| * @param secondaryLabel A slot for providing the button's secondary label. The contents are |
| * expected to be text which is "start" aligned if there is an icon preset and |
| * "start" or "center" aligned if not. |
| * label and secondaryLabel contents should be consistently aligned. |
| * @param icon A slot for providing the button's icon. The contents are expected to be a |
| * horizontally and vertically aligned icon of size [ButtonDefaults.IconSize] or |
| * [ButtonDefaults.LargeIconSize]. In order to correctly render when the Button is not enabled, |
| * the icon must set its alpha value to [LocalContentAlpha]. |
| * @param enabled Controls the enabled state of the button. When `false`, this button will not |
| * be clickable |
| * @param shape Defines the button's shape. It is strongly recommended to use the default as this |
| * shape is a key characteristic of the Wear Material3 Theme |
| * @param colors [ButtonColors] that will be used to resolve the background and content color for |
| * this button in different states. See [ButtonDefaults.buttonColors]. Defaults to |
| * [ButtonDefaults.filledButtonColors] |
| * @param border Optional [BorderStroke] that will be used to resolve the button border in |
| * different states. |
| * @param contentPadding The spacing values to apply internally between the container and the |
| * content |
| * @param interactionSource an optional hoisted [MutableInteractionSource] for observing and |
| * emitting [Interaction]s for this button. You can use this to change the button's appearance |
| * or preview the button in different states. Note that if `null` is provided, interactions will |
| * still happen internally. |
| * @param label A slot for providing the button's main label. The contents are expected to be text |
| * which is "start" aligned if there is an icon preset and "start" or "center" aligned if not. |
| */ |
| @Composable |
| fun Button( |
| onClick: () -> Unit, |
| modifier: Modifier = Modifier, |
| secondaryLabel: (@Composable RowScope.() -> Unit)? = null, |
| icon: (@Composable BoxScope.() -> Unit)? = null, |
| enabled: Boolean = true, |
| shape: Shape = FilledButtonTokens.ContainerShape.value, |
| colors: ButtonColors = ButtonDefaults.filledButtonColors(), |
| border: BorderStroke? = null, |
| contentPadding: PaddingValues = ButtonDefaults.ContentPadding, |
| interactionSource: MutableInteractionSource? = null, |
| label: @Composable RowScope.() -> Unit, |
| ) = ButtonImpl( |
| onClick = onClick, |
| modifier = modifier.buttonSizeModifier(), |
| secondaryLabel = secondaryLabel, |
| icon = icon, |
| enabled = enabled, |
| shape = shape, |
| labelFont = FilledButtonTokens.LabelFont.value, |
| secondaryLabelFont = FilledButtonTokens.SecondaryLabelFont.value, |
| colors = colors, |
| border = border, |
| contentPadding = contentPadding, |
| interactionSource = interactionSource, |
| label = label |
| ) |
| |
| /** |
| * Wear Material3 [FilledTonalButton] that offers three slots and a specific layout for an |
| * icon, label and secondaryLabel. The icon and secondaryLabel are optional. |
| * The items are laid out with the icon, if provided, at the start of a row, with a column next |
| * containing the two label slots. |
| * |
| * The [FilledTonalButton] is stadium-shaped by default and its standard height is designed to take |
| * 2 lines of text of [Typography.labelMedium] style - either a two-line label or both a single |
| * line label and a secondary label. |
| * With localisation and/or large font sizes, the [FilledTonalButton] height adjusts |
| * to accommodate the contents. The label and secondary label should be consistently aligned. |
| * |
| * If a icon is provided then the labels should be "start" aligned, e.g. left aligned in ltr so that |
| * the text starts next to the icon. |
| * |
| * If a icon is provided then the labels should be "start" aligned, e.g. left aligned in ltr so that |
| * the text starts next to the icon. |
| * |
| * [FilledTonalButton] takes the [ButtonDefaults.filledTonalButtonColors] color scheme by default, |
| * with muted background, contrasting content color and no border. This is a medium-emphasis button |
| * for important actions that don't distract from other onscreen elements, such as final or |
| * unblocking actions in a flow with less emphasis than [Button]. |
| * |
| * Other recommended buttons with [ButtonColors] for different levels of emphasis are: |
| * [Button] which defaults to [ButtonDefaults.filledButtonColors], |
| * [OutlinedButton] which defaults to [ButtonDefaults.outlinedButtonColors] and |
| * [ChildButton] which defaults to [ButtonDefaults.childButtonColors]. |
| * Buttons can also take an image background using [ButtonDefaults.imageBackgroundButtonColors]. |
| * |
| * [FilledTonalButton] can be enabled or disabled. A disabled button will not respond to |
| * click events. |
| * |
| * TODO(b/261838497) Add Material3 UX guidance links |
| * |
| * Example of a [FilledTonalButton] with an icon and secondary label: |
| * @sample androidx.wear.compose.material3.samples.FilledTonalButtonSample |
| * |
| * @param onClick Will be called when the user clicks the button |
| * @param modifier Modifier to be applied to the button |
| * @param secondaryLabel A slot for providing the button's secondary label. The contents are |
| * expected to be text which is "start" aligned if there is an icon preset and |
| * "start" or "center" aligned if not. |
| * label and secondaryLabel contents should be consistently aligned. |
| * @param icon A slot for providing the button's icon. The contents are expected to be a |
| * horizontally and vertically aligned icon of size [ButtonDefaults.IconSize] or |
| * [ButtonDefaults.LargeIconSize]. In order to correctly render when the Button is not enabled, |
| * the icon must set its alpha value to [LocalContentAlpha]. |
| * @param enabled Controls the enabled state of the button. When `false`, this button will not |
| * be clickable |
| * @param shape Defines the button's shape. It is strongly recommended to use the default as this |
| * shape is a key characteristic of the Wear Material3 Theme |
| * @param colors [ButtonColors] that will be used to resolve the background and content color for |
| * this button in different states. See [ButtonDefaults.filledTonalButtonColors]. |
| * @param border Optional [BorderStroke] that will be used to resolve the button border in |
| * different states. |
| * @param contentPadding The spacing values to apply internally between the container and the |
| * content |
| * @param interactionSource an optional hoisted [MutableInteractionSource] for observing and |
| * emitting [Interaction]s for this button. You can use this to change the button's appearance |
| * or preview the button in different states. Note that if `null` is provided, interactions will |
| * still happen internally. |
| * @param label A slot for providing the button's main label. The contents are expected to be text |
| * which is "start" aligned if there is an icon preset and "start" or "center" aligned if not. |
| */ |
| @Composable |
| fun FilledTonalButton( |
| onClick: () -> Unit, |
| modifier: Modifier = Modifier, |
| secondaryLabel: (@Composable RowScope.() -> Unit)? = null, |
| icon: (@Composable BoxScope.() -> Unit)? = null, |
| enabled: Boolean = true, |
| shape: Shape = FilledTonalButtonTokens.ContainerShape.value, |
| colors: ButtonColors = ButtonDefaults.filledTonalButtonColors(), |
| border: BorderStroke? = null, |
| contentPadding: PaddingValues = ButtonDefaults.ContentPadding, |
| interactionSource: MutableInteractionSource? = null, |
| label: @Composable RowScope.() -> Unit, |
| ) = ButtonImpl( |
| onClick = onClick, |
| modifier = modifier.buttonSizeModifier(), |
| secondaryLabel = secondaryLabel, |
| icon = icon, |
| enabled = enabled, |
| shape = shape, |
| labelFont = FilledTonalButtonTokens.LabelFont.value, |
| secondaryLabelFont = FilledTonalButtonTokens.SecondaryLabelFont.value, |
| colors = colors, |
| border = border, |
| contentPadding = contentPadding, |
| interactionSource = interactionSource, |
| label = label |
| ) |
| |
| /** |
| * Wear Material3 [OutlinedButton] that offers three slots and a specific layout for an |
| * icon, label and secondaryLabel. The icon and secondaryLabel are optional. |
| * The items are laid out with the icon, if provided, at the start of a row, with a column next |
| * containing the two label slots. |
| * |
| * The [OutlinedButton] is stadium-shaped by default and its standard height is designed to take |
| * 2 lines of text of [Typography.labelMedium] style - either a two-line label or both a single |
| * line label and a secondary label. |
| * With localisation and/or large font sizes, the [OutlinedButton] height adjusts to |
| * accommodate the contents. The label and secondary label should be consistently aligned. |
| * |
| * If a icon is provided then the labels should be "start" aligned, e.g. left aligned in ltr so that |
| * the text starts next to the icon. |
| * |
| * [OutlinedButton] takes the [ButtonDefaults.outlinedButtonColors] color scheme by default, |
| * with a transparent background and a thin border. This is a medium-emphasis button |
| * for important, non-primary actions that need attention. |
| * |
| * Other recommended buttons with [ButtonColors] for different levels of emphasis are: |
| * [Button] which defaults to [ButtonDefaults.filledButtonColors], |
| * [FilledTonalButton] which defaults to [ButtonDefaults.filledTonalButtonColors], |
| * [ChildButton] which defaults to [ButtonDefaults.childButtonColors]. |
| * Buttons can also take an image background using [ButtonDefaults.imageBackgroundButtonColors]. |
| * |
| * [OutlinedButton] can be enabled or disabled. A disabled button will not respond to click events. |
| * |
| * TODO(b/261838497) Add Material3 UX guidance links |
| * |
| * Example of an [OutlinedButton] with an icon and secondary label: |
| * @sample androidx.wear.compose.material3.samples.OutlinedButtonSample |
| * |
| * @param onClick Will be called when the user clicks the button |
| * @param modifier Modifier to be applied to the button |
| * @param secondaryLabel A slot for providing the button's secondary label. The contents are |
| * expected to be text which is "start" aligned if there is an icon preset and |
| * "start" or "center" aligned if not. |
| * label and secondaryLabel contents should be consistently aligned. |
| * @param icon A slot for providing the button's icon. The contents are expected to be a |
| * horizontally and vertically aligned icon of size [ButtonDefaults.IconSize] or |
| * [ButtonDefaults.LargeIconSize]. In order to correctly render when the Button is not enabled, |
| * the icon must set its alpha value to [LocalContentAlpha]. |
| * @param enabled Controls the enabled state of the button. When `false`, this button will not |
| * be clickable |
| * @param shape Defines the button's shape. It is strongly recommended to use the default as this |
| * shape is a key characteristic of the Wear Material3 Theme |
| * @param colors [ButtonColors] that will be used to resolve the background and content color for |
| * this button in different states. See [ButtonDefaults.outlinedButtonColors]. |
| * @param border Optional [BorderStroke] that will be used to resolve the button border in |
| * different states. See [ButtonDefaults.outlinedButtonBorder]. |
| * @param contentPadding The spacing values to apply internally between the container and the |
| * content |
| * @param interactionSource an optional hoisted [MutableInteractionSource] for observing and |
| * emitting [Interaction]s for this button. You can use this to change the button's appearance |
| * or preview the button in different states. Note that if `null` is provided, interactions will |
| * still happen internally. |
| * @param label A slot for providing the button's main label. The contents are expected to be text |
| * which is "start" aligned if there is an icon preset and "start" or "center" aligned if not. |
| */ |
| @Composable |
| fun OutlinedButton( |
| onClick: () -> Unit, |
| modifier: Modifier = Modifier, |
| secondaryLabel: (@Composable RowScope.() -> Unit)? = null, |
| icon: (@Composable BoxScope.() -> Unit)? = null, |
| enabled: Boolean = true, |
| shape: Shape = OutlinedButtonTokens.ContainerShape.value, |
| colors: ButtonColors = ButtonDefaults.outlinedButtonColors(), |
| border: BorderStroke? = ButtonDefaults.outlinedButtonBorder(enabled), |
| contentPadding: PaddingValues = ButtonDefaults.ContentPadding, |
| interactionSource: MutableInteractionSource? = null, |
| label: @Composable RowScope.() -> Unit, |
| ) = ButtonImpl( |
| onClick = onClick, |
| modifier = modifier.buttonSizeModifier(), |
| secondaryLabel = secondaryLabel, |
| icon = icon, |
| enabled = enabled, |
| shape = shape, |
| labelFont = OutlinedButtonTokens.LabelFont.value, |
| secondaryLabelFont = OutlinedButtonTokens.SecondaryLabelFont.value, |
| colors = colors, |
| border = border, |
| contentPadding = contentPadding, |
| interactionSource = interactionSource, |
| label = label |
| ) |
| |
| /** |
| * Wear Material3 [ChildButton] that offers three slots and a specific layout for an icon, label and |
| * secondaryLabel. The icon and secondaryLabel are optional. The items are laid out with the icon, |
| * if provided, at the start of a row, with a column next containing the two label slots. |
| * |
| * The [ChildButton] is stadium-shaped by default and its standard height is designed to take |
| * 2 lines of text of [Typography.labelMedium] style - either a two-line label or both a single |
| * line label and a secondary label. |
| * With localisation and/or large font sizes, the [ChildButton] height adjusts to |
| * accommodate the contents. The label and secondary label should be consistently aligned. |
| * |
| * If a icon is provided then the labels should be "start" aligned, e.g. left aligned in ltr so that |
| * the text starts next to the icon. |
| * |
| * [ChildButton] takes the [ButtonDefaults.childButtonColors] color scheme by default, |
| * with a transparent background and no border. This is a low-emphasis button for optional |
| * or supplementary actions with the least amount of prominence. |
| * |
| * Other recommended buttons with [ButtonColors] for different levels of emphasis are: |
| * [Button] which defaults to [ButtonDefaults.filledButtonColors], |
| * [FilledTonalButton] which defaults to [ButtonDefaults.filledTonalButtonColors], |
| * [OutlinedButton] which defaults to [ButtonDefaults.outlinedButtonColors]. |
| * Buttons can also take an image background using [ButtonDefaults.imageBackgroundButtonColors]. |
| * |
| * [Button] can be enabled or disabled. A disabled button will not respond to click events. |
| * |
| * TODO(b/261838497) Add Material3 UX guidance links |
| * |
| * Example of a [ChildButton] with an icon and secondary label: |
| * @sample androidx.wear.compose.material3.samples.ChildButtonSample |
| * |
| * @param onClick Will be called when the user clicks the button |
| * @param modifier Modifier to be applied to the button |
| * @param secondaryLabel A slot for providing the button's secondary label. The contents are |
| * expected to be text which is "start" aligned if there is an icon preset and |
| * "start" or "center" aligned if not. |
| * label and secondaryLabel contents should be consistently aligned. |
| * @param icon A slot for providing the button's icon. The contents are expected to be a |
| * horizontally and vertically aligned icon of size [ButtonDefaults.IconSize] or |
| * [ButtonDefaults.LargeIconSize]. In order to correctly render when the Button is not enabled, |
| * the icon must set its alpha value to [LocalContentAlpha]. |
| * @param enabled Controls the enabled state of the button. When `false`, this button will not |
| * be clickable |
| * @param shape Defines the button's shape. It is strongly recommended to use the default as this |
| * shape is a key characteristic of the Wear Material3 Theme |
| * @param colors [ButtonColors] that will be used to resolve the background and content color for |
| * this button in different states. See [ButtonDefaults.childButtonColors]. |
| * @param border Optional [BorderStroke] that will be used to resolve the button border in |
| * different states. |
| * @param contentPadding The spacing values to apply internally between the container and the |
| * content |
| * @param interactionSource an optional hoisted [MutableInteractionSource] for observing and |
| * emitting [Interaction]s for this button. You can use this to change the button's appearance |
| * or preview the button in different states. Note that if `null` is provided, interactions will |
| * still happen internally. |
| * @param label A slot for providing the button's main label. The contents are expected to be text |
| * which is "start" aligned if there is an icon preset and "start" or "center" aligned if not. |
| */ |
| @Composable |
| fun ChildButton( |
| onClick: () -> Unit, |
| modifier: Modifier = Modifier, |
| secondaryLabel: (@Composable RowScope.() -> Unit)? = null, |
| icon: (@Composable BoxScope.() -> Unit)? = null, |
| enabled: Boolean = true, |
| shape: Shape = ChildButtonTokens.ContainerShape.value, |
| colors: ButtonColors = ButtonDefaults.childButtonColors(), |
| border: BorderStroke? = null, |
| contentPadding: PaddingValues = ButtonDefaults.ContentPadding, |
| interactionSource: MutableInteractionSource? = null, |
| label: @Composable RowScope.() -> Unit, |
| ) = ButtonImpl( |
| onClick = onClick, |
| modifier = modifier.buttonSizeModifier(), |
| secondaryLabel = secondaryLabel, |
| icon = icon, |
| enabled = enabled, |
| shape = shape, |
| labelFont = ChildButtonTokens.LabelFont.value, |
| secondaryLabelFont = ChildButtonTokens.SecondaryLabelFont.value, |
| colors = colors, |
| border = border, |
| contentPadding = contentPadding, |
| interactionSource = interactionSource, |
| label = label |
| ) |
| |
| /** |
| * A Wear Material3 [CompactButton] that offers two slots and a specific layout for an |
| * icon and label. Both the icon and label are optional however it is expected that at least one |
| * will be provided. |
| * |
| * The [CompactButton] is Stadium shaped and has a max height designed to take no more |
| * than one line of text and/or one icon. The default max height |
| * is [ButtonDefaults.CompactButtonHeight]. This includes a visible button height of 32.dp |
| * and 8.dp of padding above and below the button in order to meet accessibility guidelines that |
| * request a minimum of 48.dp height and width of tappable area. |
| * |
| * If an icon is provided then the labels should be "start" aligned, e.g. left aligned in |
| * left-to-right mode so that the text starts next to the icon. |
| * |
| * The items are laid out as follows. |
| * |
| * 1. If a label is provided then the button will be laid out with the optional icon at the |
| * start of a row followed by the label with a default max height of |
| * [ButtonDefaults.CompactButtonHeight]. |
| * |
| * 2. If only an icon is provided it will be laid out vertically and horizontally centered with a |
| * default height of [ButtonDefaults.CompactButtonHeight] and the default width of |
| * [ButtonDefaults.IconOnlyCompactButtonWidth] |
| * |
| * If neither icon nor label is provided then the button will displayed like an icon only button but |
| * with no contents or background color. |
| * |
| * [CompactButton] takes the [ButtonDefaults.filledButtonColors] color scheme by default, |
| * with colored background, contrasting content color and no border. This is a high-emphasis button |
| * for the primary, most important or most common action on a screen. |
| * |
| * Other recommended [ButtonColors] for different levels of emphasis are: |
| * [ButtonDefaults.filledTonalButtonColors], [ButtonDefaults.outlinedButtonColors] and |
| * [ButtonDefaults.childButtonColors]. |
| * Buttons can also take an image background using [ButtonDefaults.imageBackgroundButtonColors]. |
| * |
| * [CompactButton] can be enabled or disabled. A disabled button will not respond |
| * to click events. |
| * |
| * TODO(b/261838497) Add Material3 samples and UX guidance links |
| * |
| * Example of a [CompactButton] with an icon and a label |
| * @sample androidx.wear.compose.material3.samples.CompactButtonSample |
| * |
| * Example of a [CompactButton] with an icon and label and with |
| * [ButtonDefaults.filledTonalButtonColors] |
| * @sample androidx.wear.compose.material3.samples.FilledTonalCompactButtonSample |
| * |
| * Example of a [CompactButton] with an icon and label and with |
| * [ButtonDefaults.outlinedButtonBorder] and [ButtonDefaults.outlinedButtonColors] |
| * @sample androidx.wear.compose.material3.samples.OutlinedCompactButtonSample |
| * |
| * @param onClick Will be called when the user clicks the button |
| * @param modifier Modifier to be applied to the button |
| * @param label A slot for providing the button's main label. The contents are expected to be text |
| * which is "start" aligned if there is an icon preset and "center" aligned if not. |
| * @param icon A slot for providing the button's icon. The contents are expected to be a |
| * horizontally and vertically aligned icon of size [ButtonDefaults.SmallIconSize] when used |
| * with a label or [ButtonDefaults.IconSize] when used as the only content in the button. In order |
| * to correctly render when the button is not enabled the icon must set its |
| * alpha value to [LocalContentAlpha]. |
| * @param colors [ButtonColors] that will be used to resolve the background and content color for |
| * this button in different states. See [ButtonDefaults.filledButtonColors]. |
| * @param enabled Controls the enabled state of the button. When `false`, this button will not |
| * be clickable |
| * @param interactionSource an optional hoisted [MutableInteractionSource] for observing and |
| * emitting [Interaction]s for this button. You can use this to change the button's appearance |
| * or preview the button in different states. Note that if `null` is provided, interactions will |
| * still happen internally. |
| * @param contentPadding The spacing values to apply internally between the container and the |
| * content |
| * @param shape Defines the button's shape. It is strongly recommended to use the default as this |
| * shape is a key characteristic of the Wear Material3 Theme |
| * @param border Optional [BorderStroke] that will be used to resolve the border for this |
| * button in different states. |
| */ |
| @Composable |
| fun CompactButton( |
| onClick: () -> Unit, |
| modifier: Modifier = Modifier, |
| icon: (@Composable BoxScope.() -> Unit)? = null, |
| enabled: Boolean = true, |
| shape: Shape = CircleShape, |
| colors: ButtonColors = ButtonDefaults.filledButtonColors(), |
| border: BorderStroke? = null, |
| contentPadding: PaddingValues = ButtonDefaults.CompactButtonContentPadding, |
| interactionSource: MutableInteractionSource? = null, |
| label: (@Composable RowScope.() -> Unit)? = null, |
| ) { |
| if (label != null) { |
| ButtonImpl( |
| onClick = onClick, |
| modifier = modifier.compactButtonModifier() |
| .padding(ButtonDefaults.CompactButtonTapTargetPadding), |
| secondaryLabel = null, |
| icon = icon, |
| enabled = enabled, |
| shape = shape, |
| labelFont = MaterialTheme.typography.labelSmall, |
| secondaryLabelFont = null, |
| colors = colors, |
| border = border, |
| contentPadding = contentPadding, |
| interactionSource = interactionSource, |
| label = label |
| ) |
| } else { |
| // Icon only compact chips have their own layout with a specific width and center aligned |
| // content. We use the base simple single slot Button under the covers. |
| ButtonImpl( |
| onClick = onClick, |
| modifier = modifier.compactButtonModifier() |
| .width(ButtonDefaults.IconOnlyCompactButtonWidth) |
| .padding(ButtonDefaults.CompactButtonTapTargetPadding), |
| enabled = enabled, |
| shape = shape, |
| labelFont = MaterialTheme.typography.labelSmall, |
| colors = colors, |
| border = border, |
| contentPadding = contentPadding, |
| interactionSource = interactionSource, |
| ) { |
| // Use a box to fill and center align the icon into the single slot of the |
| // Button |
| Box(modifier = Modifier |
| .fillMaxSize() |
| .wrapContentSize(align = Alignment.Center)) { |
| if (icon != null) { |
| icon() |
| } |
| } |
| } |
| } |
| } |
| |
| /** |
| * Contains the default values used by [Button] |
| */ |
| object ButtonDefaults { |
| /** |
| * Creates a [ButtonColors] with colored background and contrasting content color, |
| * the defaults for high emphasis buttons like [Button], for the primary, most important |
| * or most common action on a screen. If a button is disabled then the content will have |
| * an alpha([ContentAlpha.disabled]) value applied and container/border colors will be |
| * muted. |
| * |
| * @param containerColor The background color of this [Button] when enabled |
| * @param contentColor The content color of this [Button] when enabled |
| * @param secondaryContentColor The secondary content color of this [Button] when enabled, used |
| * for secondaryLabel content |
| * @param iconColor The icon color of this [Button] when enabled, used for icon content |
| * @param disabledContainerColor The background color of this [Button] when not enabled |
| * @param disabledContentColor The content color of this [Button] when not enabled |
| * @param disabledSecondaryContentColor The secondary content color of this [Button] when not |
| * enabled |
| * @param disabledIconColor The content color of this [Button] when not enabled |
| */ |
| @Composable |
| fun filledButtonColors( |
| containerColor: Color = FilledButtonTokens.ContainerColor.value, |
| contentColor: Color = FilledButtonTokens.LabelColor.value, |
| secondaryContentColor: Color = FilledButtonTokens.SecondaryLabelColor.value, |
| iconColor: Color = FilledButtonTokens.IconColor.value, |
| disabledContainerColor: Color = |
| FilledButtonTokens.DisabledContainerColor.value.toDisabledColor( |
| disabledAlpha = FilledButtonTokens.DisabledContainerOpacity |
| ), |
| disabledContentColor: Color = FilledButtonTokens.DisabledContentColor.value.toDisabledColor( |
| disabledAlpha = FilledButtonTokens.DisabledContentOpacity |
| ), |
| disabledSecondaryContentColor: Color = |
| FilledButtonTokens.DisabledContentColor.value.toDisabledColor( |
| disabledAlpha = FilledButtonTokens.DisabledContentOpacity |
| ), |
| disabledIconColor: Color = FilledButtonTokens.DisabledContentColor.value.toDisabledColor( |
| disabledAlpha = FilledButtonTokens.DisabledContentOpacity |
| ) |
| ): ButtonColors { |
| return buttonColors( |
| containerColor = containerColor, |
| contentColor = contentColor, |
| secondaryContentColor = secondaryContentColor, |
| iconColor = iconColor, |
| disabledContainerColor = disabledContainerColor, |
| disabledContentColor = disabledContentColor, |
| disabledSecondaryContentColor = disabledSecondaryContentColor, |
| disabledIconColor = disabledIconColor |
| ) |
| } |
| |
| /** |
| * Creates a [ButtonColors] with a muted background and contrasting content color, |
| * the defaults for medium emphasis buttons like [FilledTonalButton]. |
| * Use [filledTonalButtonColors] for important actions that don't distract from |
| * other onscreen elements, such as final or unblocking actions in a flow with less emphasis |
| * than [filledButtonColors]. |
| * |
| * If a button is disabled then the content will have an alpha([ContentAlpha.disabled]) |
| * value applied and container/border colors will be muted. |
| * |
| * @param containerColor The background color of this [Button] when enabled |
| * @param contentColor The content color of this [Button] when enabled |
| * @param secondaryContentColor The secondary content color of this [Button] when enabled, used |
| * for secondaryLabel content |
| * @param iconColor The icon color of this [Button] when enabled, used for icon content |
| * @param disabledContainerColor The background color of this [Button] when not enabled |
| * @param disabledContentColor The content color of this [Button] when not enabled |
| * @param disabledSecondaryContentColor The secondary content color of this [Button] when not |
| * enabled |
| * @param disabledIconColor The content color of this [Button] when not enabled |
| */ |
| @Composable |
| fun filledTonalButtonColors( |
| containerColor: Color = FilledTonalButtonTokens.ContainerColor.value, |
| contentColor: Color = FilledTonalButtonTokens.LabelColor.value, |
| secondaryContentColor: Color = FilledTonalButtonTokens.SecondaryLabelColor.value, |
| iconColor: Color = FilledTonalButtonTokens.IconColor.value, |
| disabledContainerColor: Color = |
| FilledTonalButtonTokens.DisabledContainerColor.value.toDisabledColor( |
| disabledAlpha = FilledTonalButtonTokens.DisabledContainerOpacity |
| ), |
| disabledContentColor: Color = |
| FilledTonalButtonTokens.DisabledContentColor.value.toDisabledColor( |
| disabledAlpha = FilledTonalButtonTokens.DisabledContentOpacity |
| ), |
| disabledSecondaryContentColor: Color = |
| FilledTonalButtonTokens.DisabledContentColor.value.toDisabledColor( |
| disabledAlpha = FilledTonalButtonTokens.DisabledContentOpacity |
| ), |
| disabledIconColor: Color = |
| FilledTonalButtonTokens.DisabledContentColor.value.toDisabledColor( |
| disabledAlpha = FilledTonalButtonTokens.DisabledContentOpacity |
| ) |
| ): ButtonColors { |
| return buttonColors( |
| containerColor = containerColor, |
| contentColor = contentColor, |
| secondaryContentColor = secondaryContentColor, |
| iconColor = iconColor, |
| disabledContainerColor = disabledContainerColor, |
| disabledContentColor = disabledContentColor, |
| disabledSecondaryContentColor = disabledSecondaryContentColor, |
| disabledIconColor = disabledIconColor |
| ) |
| } |
| |
| /** |
| * Creates a [ButtonColors] with a transparent background (typically paired with |
| * [ButtonDefaults.outlinedButtonBorder]), the defaults for medium emphasis buttons |
| * like [OutlinedButton], for important, non-primary actions that need attention. |
| * |
| * If a button is disabled then the content will have an alpha([ContentAlpha.disabled]) |
| * value applied and container/border colors will be muted. |
| * |
| * @param contentColor The content color of this [Button] when enabled |
| * @param secondaryContentColor The secondary content color of this [Button] when enabled, used |
| * for secondaryLabel content |
| * @param iconColor The icon color of this [Button] when enabled, used for icon content |
| * @param disabledContentColor The content color of this [Button] when not enabled |
| * @param disabledSecondaryContentColor The secondary content color of this [Button] when not |
| * enabled |
| * @param disabledIconColor The content color of this [Button] when not enabled |
| */ |
| @Composable |
| fun outlinedButtonColors( |
| contentColor: Color = OutlinedButtonTokens.LabelColor.value, |
| secondaryContentColor: Color = OutlinedButtonTokens.SecondaryLabelColor.value, |
| iconColor: Color = OutlinedButtonTokens.IconColor.value, |
| disabledContentColor: Color = |
| OutlinedButtonTokens.DisabledContentColor.value.toDisabledColor( |
| disabledAlpha = OutlinedButtonTokens.DisabledContentOpacity |
| ), |
| disabledSecondaryContentColor: Color = |
| OutlinedButtonTokens.DisabledContentColor.value.toDisabledColor( |
| disabledAlpha = OutlinedButtonTokens.DisabledContentOpacity |
| ), |
| disabledIconColor: Color = OutlinedButtonTokens.DisabledContentColor.value.toDisabledColor( |
| disabledAlpha = OutlinedButtonTokens.DisabledContentOpacity |
| ) |
| ): ButtonColors { |
| return buttonColors( |
| containerColor = Color.Transparent, |
| contentColor = contentColor, |
| secondaryContentColor = secondaryContentColor, |
| iconColor = iconColor, |
| disabledContainerColor = Color.Transparent, |
| disabledContentColor = disabledContentColor, |
| disabledSecondaryContentColor = disabledSecondaryContentColor, |
| disabledIconColor = disabledIconColor |
| ) |
| } |
| |
| /** |
| * Creates a [ButtonColors] with transparent background, the defaults for low emphasis |
| * buttons like [ChildButton]. Use [childButtonColors] for optional or supplementary |
| * actions with the least amount of prominence. |
| * |
| * If a button is disabled then the content will have an alpha([ContentAlpha.disabled]) |
| * value applied and container/border colors will be muted. |
| * |
| * @param contentColor The content color of this [Button] when enabled |
| * @param secondaryContentColor The secondary content color of this [Button] when enabled, used |
| * for secondaryLabel content |
| * @param iconColor The icon color of this [Button] when enabled, used for icon content |
| * @param disabledContentColor The content color of this [Button] when not enabled |
| * @param disabledSecondaryContentColor The secondary content color of this [Button] when not |
| * enabled |
| * @param disabledIconColor The content color of this [Button] when not enabled |
| */ |
| @Composable |
| fun childButtonColors( |
| contentColor: Color = ChildButtonTokens.LabelColor.value, |
| secondaryContentColor: Color = ChildButtonTokens.SecondaryLabelColor.value, |
| iconColor: Color = ChildButtonTokens.IconColor.value, |
| disabledContentColor: Color = ChildButtonTokens.DisabledContentColor.value.toDisabledColor( |
| disabledAlpha = ChildButtonTokens.DisabledContentOpacity |
| ), |
| disabledSecondaryContentColor: Color = |
| ChildButtonTokens.DisabledContentColor.value.toDisabledColor( |
| disabledAlpha = ChildButtonTokens.DisabledContentOpacity |
| ), |
| disabledIconColor: Color = ChildButtonTokens.DisabledContentColor.value.toDisabledColor( |
| disabledAlpha = ChildButtonTokens.DisabledContentOpacity |
| ), |
| ): ButtonColors { |
| return buttonColors( |
| containerColor = Color.Transparent, |
| contentColor = contentColor, |
| secondaryContentColor = secondaryContentColor, |
| iconColor = iconColor, |
| disabledContainerColor = Color.Transparent, |
| disabledContentColor = disabledContentColor, |
| disabledSecondaryContentColor = disabledSecondaryContentColor, |
| disabledIconColor = disabledIconColor |
| ) |
| } |
| |
| /** |
| * Creates a [ButtonColors] for a [Button] with an image background, typically with a scrim |
| * over the image to ensure that the content is visible. Uses a default content color |
| * of [ColorScheme.onSurface]. |
| * |
| * @param backgroundImagePainter The [Painter] to use to draw the background of the [Button] |
| * @param backgroundImageScrimBrush The [Brush] to use to paint a scrim over the background |
| * image to ensure that any text drawn over the image is legible |
| * @param contentColor The content color of this [Button] when enabled |
| * @param secondaryContentColor The secondary content color of this [Button] when enabled, used |
| * for secondaryLabel content |
| * @param iconColor The icon color of this [Button] when enabled, used for icon content |
| * @param disabledContentColor The content color of this [Button] when disabled |
| * @param disabledSecondaryContentColor The secondary content color of this [Button] when |
| * disabled, used for secondary label content |
| * @param disabledIconColor The icon color of this [Button] when disabled, used for icon content |
| */ |
| @Composable |
| fun imageBackgroundButtonColors( |
| backgroundImagePainter: Painter, |
| backgroundImageScrimBrush: Brush = Brush.linearGradient( |
| colors = listOf( |
| ImageButtonTokens.BackgroundImageGradientColor.value.copy( |
| alpha = ImageButtonTokens.GradientStartOpacity |
| ), |
| ImageButtonTokens.BackgroundImageGradientColor.value.copy( |
| alpha = ImageButtonTokens.GradientEndOpacity |
| ) |
| ) |
| ), |
| contentColor: Color = ImageButtonTokens.ContentColor.value, |
| secondaryContentColor: Color = ImageButtonTokens.SecondaryContentColor.value, |
| iconColor: Color = ImageButtonTokens.IconColor.value, |
| disabledContentColor: Color = ImageButtonTokens.DisabledContentColor.value.toDisabledColor( |
| disabledAlpha = ImageButtonTokens.DisabledContentOpacity |
| ), |
| disabledSecondaryContentColor: Color = ImageButtonTokens.DisabledContentColor.value |
| .toDisabledColor( |
| disabledAlpha = ImageButtonTokens.DisabledContentOpacity |
| ), |
| disabledIconColor: Color = ImageButtonTokens.DisabledContentColor.value.toDisabledColor( |
| disabledAlpha = ImageButtonTokens.DisabledContentOpacity |
| ) |
| ): ButtonColors { |
| val backgroundPainter = |
| remember(backgroundImagePainter, backgroundImageScrimBrush) { |
| androidx.wear.compose.materialcore.ImageWithScrimPainter( |
| imagePainter = backgroundImagePainter, |
| brush = backgroundImageScrimBrush |
| ) |
| } |
| |
| val disabledContentAlpha = ImageButtonTokens.DisabledContentOpacity |
| val disabledBackgroundPainter = |
| remember(backgroundImagePainter, backgroundImageScrimBrush, disabledContentAlpha) { |
| androidx.wear.compose.materialcore.ImageWithScrimPainter( |
| imagePainter = backgroundImagePainter, |
| brush = backgroundImageScrimBrush, |
| alpha = disabledContentAlpha, |
| ) |
| } |
| return ButtonColors( |
| containerPainter = backgroundPainter, |
| contentColor = contentColor, |
| secondaryContentColor = secondaryContentColor, |
| iconColor = iconColor, |
| disabledContainerPainter = disabledBackgroundPainter, |
| disabledContentColor = disabledContentColor, |
| disabledSecondaryContentColor = disabledSecondaryContentColor, |
| disabledIconColor = disabledIconColor, |
| ) |
| } |
| |
| /** |
| * Creates a [BorderStroke], such as for an [OutlinedButton] |
| * |
| * @param borderColor The color to use for the border for this outline when enabled |
| * @param disabledBorderColor The color to use for the border for this outline when |
| * disabled |
| * @param borderWidth The width to use for the border for this outline. It is strongly |
| * recommended to use the default width as this outline is a key characteristic |
| * of Wear Material3. |
| */ |
| @Composable |
| fun outlinedButtonBorder( |
| enabled: Boolean, |
| borderColor: Color = OutlinedButtonTokens.ContainerBorderColor.value, |
| disabledBorderColor: Color = |
| OutlinedButtonTokens.DisabledContainerBorderColor.value.toDisabledColor( |
| disabledAlpha = OutlinedButtonTokens.DisabledContainerBorderOpacity |
| ), |
| borderWidth: Dp = OutlinedButtonTokens.ContainerBorderWidth |
| ): BorderStroke { |
| return remember { |
| BorderStroke(borderWidth, if (enabled) borderColor else disabledBorderColor) |
| } |
| } |
| |
| /** |
| * Creates a [ButtonColors] that represents the default background and content colors used in |
| * a [Button]. |
| * |
| * @param containerColor The background color of this [Button] when enabled |
| * @param contentColor The content color of this [Button] when enabled |
| * @param secondaryContentColor The content color of this [Button] when enabled |
| * @param iconColor The content color of this [Button] when enabled |
| * @param disabledContainerColor The background color of this [Button] when not enabled |
| * @param disabledContentColor The content color of this [Button] when not enabled |
| * @param disabledSecondaryContentColor The content color of this [Button] when not enabled |
| * @param disabledIconColor The content color of this [Button] when not enabled |
| */ |
| @Composable |
| fun buttonColors( |
| containerColor: Color = FilledButtonTokens.ContainerColor.value, |
| contentColor: Color = FilledButtonTokens.LabelColor.value, |
| secondaryContentColor: Color = FilledButtonTokens.SecondaryLabelColor.value, |
| iconColor: Color = FilledButtonTokens.IconColor.value, |
| disabledContainerColor: Color = |
| FilledButtonTokens.DisabledContainerColor.value.toDisabledColor( |
| disabledAlpha = FilledButtonTokens.DisabledContainerOpacity |
| ), |
| disabledContentColor: Color = FilledButtonTokens.DisabledContentColor.value.toDisabledColor( |
| disabledAlpha = FilledButtonTokens.DisabledContentOpacity |
| ), |
| disabledSecondaryContentColor: Color = |
| FilledButtonTokens.DisabledContentColor.value.toDisabledColor( |
| disabledAlpha = FilledButtonTokens.DisabledContentOpacity |
| ), |
| disabledIconColor: Color = FilledButtonTokens.DisabledContentColor.value.toDisabledColor( |
| disabledAlpha = FilledButtonTokens.DisabledContentOpacity |
| ) |
| ): ButtonColors = ButtonColors( |
| containerColor = containerColor, |
| contentColor = contentColor, |
| secondaryContentColor = secondaryContentColor, |
| iconColor = iconColor, |
| disabledContainerColor = disabledContainerColor, |
| disabledContentColor = disabledContentColor, |
| disabledSecondaryContentColor = disabledSecondaryContentColor, |
| disabledIconColor = disabledIconColor |
| ) |
| |
| val ButtonHorizontalPadding = 14.dp |
| val ButtonVerticalPadding = 6.dp |
| |
| /** |
| * The default content padding used by [Button] |
| */ |
| val ContentPadding: PaddingValues = PaddingValues( |
| horizontal = ButtonHorizontalPadding, |
| vertical = ButtonVerticalPadding, |
| ) |
| |
| /** |
| * The default size of the icon when used inside a [Button]. |
| */ |
| val IconSize: Dp = FilledButtonTokens.IconSize |
| |
| /** |
| * The size of the icon when used inside a Large "Avatar" [Button]. |
| */ |
| val LargeIconSize: Dp = FilledButtonTokens.IconLargeSize |
| |
| /** |
| * The default height applied for the [Button]. |
| * Note that you can override it by applying Modifier.heightIn directly on [Button]. |
| */ |
| val Height = FilledButtonTokens.ContainerHeight |
| |
| val CompactButtonHorizontalPadding = 12.dp |
| val CompactButtonVerticalPadding = 0.dp |
| |
| /** |
| * The default content padding used by [CompactButton] |
| */ |
| val CompactButtonContentPadding: PaddingValues = PaddingValues( |
| start = CompactButtonHorizontalPadding, |
| top = CompactButtonVerticalPadding, |
| end = CompactButtonHorizontalPadding, |
| bottom = CompactButtonVerticalPadding |
| ) |
| |
| /** |
| * The height applied for the [CompactButton]. This includes a |
| * visible button height of 32.dp and 8.dp of padding above and below the button |
| * in order to meet accessibility guidelines that |
| * request a minimum of 48.dp height and width of tappable area. |
| * |
| * Note that you can override it by adjusting Modifier.height and Modifier.padding directly on |
| * [CompactButton]. |
| */ |
| val CompactButtonHeight = 48.dp |
| |
| /** |
| * The size of the icon when used inside a "[CompactButton]. |
| */ |
| val SmallIconSize: Dp = 20.dp |
| |
| /** |
| * The default padding to be provided around a [CompactButton] in order to ensure that its |
| * tappable area meets minimum UX guidance. |
| */ |
| val CompactButtonTapTargetPadding: PaddingValues = PaddingValues( |
| top = 8.dp, |
| bottom = 8.dp |
| ) |
| |
| /** |
| * The default width applied for the [CompactButton] when it has no label provided. |
| * Note that you can override it by applying Modifier.width directly on [CompactButton]. |
| */ |
| internal val IconOnlyCompactButtonWidth = 52.dp |
| |
| /** |
| * The default size of the spacing between an icon and a text when they are used inside a |
| * [Button]. |
| */ |
| internal val IconSpacing = 6.dp |
| } |
| |
| /** |
| * Represents the container and content colors used in buttons |
| * in different states. |
| * |
| * @param containerPainter [Painter] to use to draw the background of the [Button] when enabled. |
| * @param contentColor The content color of this [Button] when enabled. |
| * @param secondaryContentColor The content color of this [Button] when enabled. |
| * @param iconColor The content color of this [Button] when enabled. |
| * @param disabledContainerPainter [Painter] to use to draw the background of the [Button] when not enabled. |
| * @param disabledContentColor The content color of this [Button] when not enabled. |
| * @param disabledSecondaryContentColor The content color of this [Button] when not enabled. |
| * @param disabledIconColor The content color of this [Button] when not enabled. |
| */ |
| @Immutable |
| class ButtonColors constructor( |
| val containerPainter: Painter, |
| val contentColor: Color, |
| val secondaryContentColor: Color, |
| val iconColor: Color, |
| val disabledContainerPainter: Painter, |
| val disabledContentColor: Color, |
| val disabledSecondaryContentColor: Color, |
| val disabledIconColor: Color, |
| ) { |
| /** |
| * Creates a [ButtonColors] where all of the values are explicitly defined. |
| * |
| * @param containerColor The background color of this [Button] when enabled |
| * @param contentColor The content color of this [Button] when enabled |
| * @param secondaryContentColor The content color of this [Button] when enabled |
| * @param iconColor The content color of this [Button] when enabled |
| * @param disabledContainerColor The background color of this [Button] when not enabled |
| * @param disabledContentColor The content color of this [Button] when not enabled |
| * @param disabledSecondaryContentColor The content color of this [Button] when not enabled |
| * @param disabledIconColor The content color of this [Button] when not enabled |
| */ |
| constructor( |
| containerColor: Color, |
| contentColor: Color, |
| secondaryContentColor: Color, |
| iconColor: Color, |
| disabledContainerColor: Color, |
| disabledContentColor: Color, |
| disabledSecondaryContentColor: Color, |
| disabledIconColor: Color, |
| ) : this( |
| ColorPainter(containerColor), |
| contentColor, |
| secondaryContentColor, |
| iconColor, |
| ColorPainter(disabledContainerColor), |
| disabledContentColor, |
| disabledSecondaryContentColor, |
| disabledIconColor, |
| ) |
| |
| /** |
| * Represents the container color for this button, depending on [enabled]. |
| * |
| * @param enabled whether the button is enabled |
| */ |
| @Composable |
| internal fun containerPainter(enabled: Boolean): State<Painter> { |
| return rememberUpdatedState( |
| if (enabled) containerPainter else disabledContainerPainter |
| ) |
| } |
| |
| /** |
| * Represents the content color for this button, depending on [enabled]. |
| * |
| * @param enabled whether the button is enabled |
| */ |
| @Composable |
| internal fun contentColor(enabled: Boolean): State<Color> { |
| return rememberUpdatedState( |
| if (enabled) contentColor else disabledContentColor |
| ) |
| } |
| |
| /** |
| * Represents the secondary content color for this button, depending on [enabled]. |
| * |
| * @param enabled Whether the button is enabled |
| */ |
| @Composable |
| internal fun secondaryContentColor(enabled: Boolean): State<Color> { |
| return rememberUpdatedState( |
| if (enabled) secondaryContentColor else disabledSecondaryContentColor |
| ) |
| } |
| |
| /** |
| * Represents the icon color for this button, depending on [enabled]. |
| * |
| * @param enabled Whether the button is enabled |
| */ |
| @Composable |
| internal fun iconColor(enabled: Boolean): State<Color> { |
| return rememberUpdatedState(if (enabled) iconColor else disabledIconColor) |
| } |
| |
| override fun equals(other: Any?): Boolean { |
| if (this === other) return true |
| if (other == null || other !is ButtonColors) return false |
| |
| if (containerPainter != other.containerPainter) return false |
| if (contentColor != other.contentColor) return false |
| if (secondaryContentColor != other.secondaryContentColor) return false |
| if (iconColor != other.iconColor) return false |
| if (disabledContainerPainter != other.disabledContainerPainter) return false |
| if (disabledContentColor != other.disabledContentColor) return false |
| if (disabledSecondaryContentColor != other.disabledSecondaryContentColor) return false |
| if (disabledIconColor != other.disabledIconColor) return false |
| |
| return true |
| } |
| |
| override fun hashCode(): Int { |
| var result = containerPainter.hashCode() |
| result = 31 * result + contentColor.hashCode() |
| result = 31 * result + secondaryContentColor.hashCode() |
| result = 31 * result + iconColor.hashCode() |
| result = 31 * result + disabledContainerPainter.hashCode() |
| result = 31 * result + disabledContentColor.hashCode() |
| result = 31 * result + disabledSecondaryContentColor.hashCode() |
| result = 31 * result + disabledIconColor.hashCode() |
| return result |
| } |
| } |
| |
| @Composable |
| private fun Modifier.buttonSizeModifier(): Modifier = |
| this.defaultMinSize(minHeight = ButtonDefaults.Height) |
| .height(IntrinsicSize.Min) |
| |
| @Composable |
| private fun Modifier.compactButtonModifier(): Modifier = |
| this.height(ButtonDefaults.CompactButtonHeight) |
| |
| /** |
| * Button with label. This allows to use the token values for |
| * individual buttons instead of relying on common values. |
| */ |
| @Composable |
| private fun ButtonImpl( |
| onClick: () -> Unit, |
| modifier: Modifier, |
| enabled: Boolean, |
| shape: Shape, |
| labelFont: TextStyle, |
| colors: ButtonColors, |
| border: BorderStroke?, |
| contentPadding: PaddingValues, |
| interactionSource: MutableInteractionSource?, |
| content: @Composable RowScope.() -> Unit |
| ) { |
| val borderModifier = if (border != null) |
| modifier.border( |
| border = border, |
| shape = shape |
| ) else modifier |
| Row( |
| modifier = borderModifier |
| .clip(shape = shape) |
| .width(intrinsicSize = IntrinsicSize.Max) |
| .paint( |
| painter = colors.containerPainter(enabled = enabled).value, |
| contentScale = ContentScale.Crop |
| ) |
| .clickable( |
| enabled = enabled, |
| onClick = onClick, |
| role = Role.Button, |
| indication = rippleOrFallbackImplementation(), |
| interactionSource = interactionSource, |
| ) |
| .padding(contentPadding), |
| content = provideScopeContent( |
| colors.contentColor(enabled = enabled), |
| labelFont, |
| content |
| ) |
| ) |
| } |
| |
| /** |
| * Button with icon, label and secondary label. This allows to use the token values for |
| * individual buttons instead of relying on common values. |
| */ |
| @Composable |
| private fun ButtonImpl( |
| onClick: () -> Unit, |
| modifier: Modifier, |
| secondaryLabel: (@Composable RowScope.() -> Unit)?, |
| icon: (@Composable BoxScope.() -> Unit)?, |
| enabled: Boolean, |
| shape: Shape, |
| labelFont: TextStyle, |
| secondaryLabelFont: TextStyle?, |
| colors: ButtonColors, |
| border: BorderStroke?, |
| contentPadding: PaddingValues, |
| interactionSource: MutableInteractionSource?, |
| label: @Composable RowScope.() -> Unit |
| ) { |
| ButtonImpl( |
| onClick = onClick, |
| modifier = modifier, |
| enabled = enabled, |
| shape = shape, |
| labelFont = labelFont, |
| colors = colors, |
| border = border, |
| contentPadding = contentPadding, |
| interactionSource = interactionSource, |
| ) { |
| Row( |
| verticalAlignment = Alignment.CenterVertically, |
| // Fill the container height but not its width as chips have fixed size height but we |
| // want them to be able to fit their content |
| modifier = Modifier.fillMaxHeight() |
| ) { |
| if (icon != null) { |
| Box( |
| modifier = Modifier.wrapContentSize(align = Alignment.Center), |
| content = provideScopeContent(colors.iconColor(enabled), icon) |
| ) |
| Spacer(modifier = Modifier.size(ButtonDefaults.IconSpacing)) |
| } |
| Column { |
| Row( |
| content = provideScopeContent( |
| colors.contentColor(enabled), |
| labelFont, |
| label |
| ) |
| ) |
| if (secondaryLabel != null && secondaryLabelFont != null) { |
| Row( |
| content = provideScopeContent( |
| colors.secondaryContentColor(enabled), |
| secondaryLabelFont, |
| secondaryLabel |
| ) |
| ) |
| } |
| } |
| } |
| } |
| } |