1 /* 2 * Copyright 2023 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package androidx.tv.material3 18 19 import androidx.annotation.FloatRange 20 import androidx.compose.foundation.BorderStroke 21 import androidx.compose.foundation.interaction.Interaction 22 import androidx.compose.foundation.layout.PaddingValues 23 import androidx.compose.foundation.shape.CircleShape 24 import androidx.compose.runtime.Composable 25 import androidx.compose.runtime.ReadOnlyComposable 26 import androidx.compose.ui.graphics.Color 27 import androidx.compose.ui.graphics.Shape 28 import androidx.compose.ui.unit.dp 29 30 internal object BaseButtonDefaults { 31 val MinWidth = 58.dp 32 val MinHeight = 40.dp 33 } 34 35 object ButtonDefaults { 36 private val ContainerShape = CircleShape 37 private val ButtonHorizontalPadding = 16.dp 38 private val ButtonVerticalPadding = 10.dp 39 private val ButtonWithIconHorizontalStartPadding = 12.dp 40 41 val ContentPadding = 42 PaddingValues( 43 start = ButtonHorizontalPadding, 44 top = ButtonVerticalPadding, 45 end = ButtonHorizontalPadding, 46 bottom = ButtonVerticalPadding 47 ) 48 49 val ButtonWithIconContentPadding = 50 PaddingValues( 51 start = ButtonWithIconHorizontalStartPadding, 52 top = ButtonVerticalPadding, 53 end = ButtonHorizontalPadding, 54 bottom = ButtonVerticalPadding 55 ) 56 57 /** The default size of the icon when used inside any button. */ 58 val IconSize = 20.dp 59 60 /** 61 * The default size of the spacing between an icon and a text when they used inside any button. 62 */ 63 val IconSpacing = 8.dp 64 65 /** 66 * Creates a [ButtonShape] that represents the default container shapes used in a FilledButton. 67 * 68 * @param shape the shape used when the Button is enabled, and has no other [Interaction]s. 69 * @param focusedShape the shape used when the Button is enabled and focused. 70 * @param pressedShape the shape used when the Button is enabled pressed. 71 * @param disabledShape the shape used when the Button is not enabled. 72 * @param focusedDisabledShape the shape used when the Button is not enabled and focused. 73 */ shapenull74 fun shape( 75 shape: Shape = ContainerShape, 76 focusedShape: Shape = shape, 77 pressedShape: Shape = shape, 78 disabledShape: Shape = shape, 79 focusedDisabledShape: Shape = disabledShape 80 ) = 81 ButtonShape( 82 shape = shape, 83 focusedShape = focusedShape, 84 pressedShape = pressedShape, 85 disabledShape = disabledShape, 86 focusedDisabledShape = focusedDisabledShape 87 ) 88 89 /** 90 * Creates a [ButtonColors] that represents the default colors used in a FilledButton. 91 * 92 * @param containerColor the container color of this Button when enabled 93 * @param contentColor the content color of this Button when enabled 94 * @param focusedContainerColor the container color of this Button when enabled and focused 95 * @param focusedContentColor the content color of this Button when enabled and focused 96 * @param pressedContainerColor the container color of this Button when enabled and pressed 97 * @param pressedContentColor the content color of this Button when enabled and pressed 98 * @param disabledContainerColor the container color of this Button when not enabled 99 * @param disabledContentColor the content color of this Button when not enabled 100 */ 101 @ReadOnlyComposable 102 @Composable 103 fun colors( 104 containerColor: Color = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.8f), 105 contentColor: Color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.8f), 106 focusedContainerColor: Color = MaterialTheme.colorScheme.onSurface, 107 focusedContentColor: Color = MaterialTheme.colorScheme.inverseOnSurface, 108 pressedContainerColor: Color = focusedContainerColor, 109 pressedContentColor: Color = focusedContentColor, 110 disabledContainerColor: Color = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.4f), 111 disabledContentColor: Color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.4f), 112 ) = 113 ButtonColors( 114 containerColor = containerColor, 115 contentColor = contentColor, 116 focusedContainerColor = focusedContainerColor, 117 focusedContentColor = focusedContentColor, 118 pressedContainerColor = pressedContainerColor, 119 pressedContentColor = pressedContentColor, 120 disabledContainerColor = disabledContainerColor, 121 disabledContentColor = disabledContentColor, 122 ) 123 124 /** 125 * Creates a [ButtonScale] that represents the default scales used in a FilledButton. scales are 126 * used to modify the size of a composable in different [Interaction] states e.g. 1f (original) 127 * in default state, 1.2f (scaled up) in focused state, 0.8f (scaled down) in pressed state, 128 * etc. 129 * 130 * @param scale the scale to be used for this Button when enabled 131 * @param focusedScale the scale to be used for this Button when focused 132 * @param pressedScale the scale to be used for this Button when pressed 133 * @param disabledScale the scale to be used for this Button when disabled 134 * @param focusedDisabledScale the scale to be used for this Button when disabled and focused 135 */ 136 fun scale( 137 @FloatRange(from = 0.0) scale: Float = 1f, 138 @FloatRange(from = 0.0) focusedScale: Float = 1.1f, 139 @FloatRange(from = 0.0) pressedScale: Float = scale, 140 @FloatRange(from = 0.0) disabledScale: Float = scale, 141 @FloatRange(from = 0.0) focusedDisabledScale: Float = disabledScale 142 ) = 143 ButtonScale( 144 scale = scale, 145 focusedScale = focusedScale, 146 pressedScale = pressedScale, 147 disabledScale = disabledScale, 148 focusedDisabledScale = focusedDisabledScale 149 ) 150 151 /** 152 * Creates a [ButtonBorder] that represents the default [Border]s applied on a FilledButton in 153 * different [Interaction] states. 154 * 155 * @param border the [Border] to be used for this Button when enabled 156 * @param focusedBorder the [Border] to be used for this Button when focused 157 * @param pressedBorder the [Border] to be used for this Button when pressed 158 * @param disabledBorder the [Border] to be used for this Button when disabled 159 * @param focusedDisabledBorder the [Border] to be used for this Button when disabled and 160 * focused 161 */ 162 @ReadOnlyComposable 163 @Composable 164 fun border( 165 border: Border = Border.None, 166 focusedBorder: Border = border, 167 pressedBorder: Border = focusedBorder, 168 disabledBorder: Border = border, 169 focusedDisabledBorder: Border = 170 Border( 171 border = 172 BorderStroke( 173 width = 1.5.dp, 174 color = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.2f) 175 ), 176 shape = ContainerShape 177 ) 178 ) = 179 ButtonBorder( 180 border = border, 181 focusedBorder = focusedBorder, 182 pressedBorder = pressedBorder, 183 disabledBorder = disabledBorder, 184 focusedDisabledBorder = focusedDisabledBorder 185 ) 186 187 /** 188 * Creates a [ButtonGlow] that represents the default [Glow]s used in a FilledButton. 189 * 190 * @param glow the Glow behind this Button when enabled 191 * @param focusedGlow the Glow behind this Button when focused 192 * @param pressedGlow the Glow behind this Button when pressed 193 */ 194 fun glow(glow: Glow = Glow.None, focusedGlow: Glow = glow, pressedGlow: Glow = glow) = 195 ButtonGlow(glow = glow, focusedGlow = focusedGlow, pressedGlow = pressedGlow) 196 } 197 198 object OutlinedButtonDefaults { 199 private val ContainerShape = CircleShape 200 private val ButtonHorizontalPadding = 16.dp 201 private val ButtonVerticalPadding = 10.dp 202 private val ButtonWithIconHorizontalStartPadding = 12.dp 203 204 val ContentPadding = 205 PaddingValues( 206 start = ButtonHorizontalPadding, 207 top = ButtonVerticalPadding, 208 end = ButtonHorizontalPadding, 209 bottom = ButtonVerticalPadding 210 ) 211 212 /** The default size of the icon when used inside any button. */ 213 val IconSize = 20.dp 214 215 /** 216 * The default size of the spacing between an icon and a text when they used inside any button. 217 */ 218 val IconSpacing = 8.dp 219 220 /** The default content padding used by [OutlinedButton] that contains an [Icon]. */ 221 val ButtonWithIconContentPadding = 222 PaddingValues( 223 start = ButtonWithIconHorizontalStartPadding, 224 top = ButtonVerticalPadding, 225 end = ButtonHorizontalPadding, 226 bottom = ButtonVerticalPadding 227 ) 228 229 /** 230 * Creates a [ButtonShape] that represents the default container shapes used in an 231 * OutlinedButton. 232 * 233 * @param shape the shape used when the Button is enabled, and has no other [Interaction]s. 234 * @param focusedShape the shape used when the Button is enabled and focused. 235 * @param pressedShape the shape used when the Button is enabled pressed. 236 * @param disabledShape the shape used when the Button is not enabled. 237 * @param focusedDisabledShape the shape used when the Button is not enabled and focused. 238 */ 239 fun shape( 240 shape: Shape = ContainerShape, 241 focusedShape: Shape = shape, 242 pressedShape: Shape = shape, 243 disabledShape: Shape = shape, 244 focusedDisabledShape: Shape = disabledShape 245 ) = 246 ButtonShape( 247 shape = shape, 248 focusedShape = focusedShape, 249 pressedShape = pressedShape, 250 disabledShape = disabledShape, 251 focusedDisabledShape = focusedDisabledShape 252 ) 253 254 /** 255 * Creates a [ButtonColors] that represents the default colors used in a OutlinedButton. 256 * 257 * @param containerColor the container color of this Button when enabled 258 * @param contentColor the content color of this Button when enabled 259 * @param focusedContainerColor the container color of this Button when enabled and focused 260 * @param focusedContentColor the content color of this Button when enabled and focused 261 * @param pressedContainerColor the container color of this Button when enabled and pressed 262 * @param pressedContentColor the content color of this Button when enabled and pressed 263 * @param disabledContainerColor the container color of this Button when not enabled 264 * @param disabledContentColor the content color of this Button when not enabled 265 */ 266 @ReadOnlyComposable 267 @Composable 268 fun colors( 269 containerColor: Color = Color.Transparent, 270 contentColor: Color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.8f), 271 focusedContainerColor: Color = MaterialTheme.colorScheme.onSurface, 272 focusedContentColor: Color = MaterialTheme.colorScheme.inverseOnSurface, 273 pressedContainerColor: Color = focusedContainerColor, 274 pressedContentColor: Color = focusedContentColor, 275 disabledContainerColor: Color = containerColor, 276 disabledContentColor: Color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.4f), 277 ) = 278 ButtonColors( 279 containerColor = containerColor, 280 contentColor = contentColor, 281 focusedContainerColor = focusedContainerColor, 282 focusedContentColor = focusedContentColor, 283 pressedContainerColor = pressedContainerColor, 284 pressedContentColor = pressedContentColor, 285 disabledContainerColor = disabledContainerColor, 286 disabledContentColor = disabledContentColor, 287 ) 288 289 /** 290 * Creates a [ButtonScale] that represents the default scales used in an OutlinedButton. scales 291 * are used to modify the size of a composable in different [Interaction] states e.g. 1f 292 * (original) in default state, 1.2f (scaled up) in focused state, 0.8f (scaled down) in pressed 293 * state, etc. 294 * 295 * @param scale the scale to be used for this Button when enabled 296 * @param focusedScale the scale to be used for this Button when focused 297 * @param pressedScale the scale to be used for this Button when pressed 298 * @param disabledScale the scale to be used for this Button when disabled 299 * @param focusedDisabledScale the scale to be used for this Button when disabled and focused 300 */ 301 fun scale( 302 @FloatRange(from = 0.0) scale: Float = 1f, 303 @FloatRange(from = 0.0) focusedScale: Float = 1.1f, 304 @FloatRange(from = 0.0) pressedScale: Float = scale, 305 @FloatRange(from = 0.0) disabledScale: Float = scale, 306 @FloatRange(from = 0.0) focusedDisabledScale: Float = disabledScale 307 ) = 308 ButtonScale( 309 scale = scale, 310 focusedScale = focusedScale, 311 pressedScale = pressedScale, 312 disabledScale = disabledScale, 313 focusedDisabledScale = focusedDisabledScale 314 ) 315 316 /** 317 * Creates a [ButtonBorder] that represents the default [Border]s applied on an OutlinedButton 318 * in different [Interaction] states. 319 * 320 * @param border the [Border] to be used for this Button when enabled 321 * @param focusedBorder the [Border] to be used for this Button when focused 322 * @param pressedBorder the [Border] to be used for this Button when pressed 323 * @param disabledBorder the [Border] to be used for this Button when disabled 324 * @param focusedDisabledBorder the [Border] to be used for this Button when disabled and 325 * focused 326 */ 327 @ReadOnlyComposable 328 @Composable 329 fun border( 330 border: Border = 331 Border( 332 border = 333 BorderStroke( 334 width = 1.5.dp, 335 color = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.4f) 336 ), 337 shape = ContainerShape 338 ), 339 focusedBorder: Border = 340 Border( 341 border = 342 BorderStroke( 343 width = 1.65.dp, 344 color = MaterialTheme.colorScheme.onSurfaceVariant 345 ), 346 shape = ContainerShape 347 ), 348 pressedBorder: Border = 349 Border( 350 border = 351 BorderStroke( 352 width = 1.5.dp, 353 color = MaterialTheme.colorScheme.onSurfaceVariant 354 ), 355 shape = ContainerShape 356 ), 357 disabledBorder: Border = 358 Border( 359 border = 360 BorderStroke( 361 width = 1.5.dp, 362 color = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.2f) 363 ), 364 shape = ContainerShape 365 ), 366 focusedDisabledBorder: Border = disabledBorder 367 ) = 368 ButtonBorder( 369 border = border, 370 focusedBorder = focusedBorder, 371 pressedBorder = pressedBorder, 372 disabledBorder = disabledBorder, 373 focusedDisabledBorder = focusedDisabledBorder 374 ) 375 376 /** 377 * Creates a [ButtonGlow] that represents the default [Glow]s used in an OutlinedButton. 378 * 379 * @param glow the Glow behind this Button when enabled 380 * @param focusedGlow the Glow behind this Button when focused 381 * @param pressedGlow the Glow behind this Button when pressed 382 */ 383 fun glow(glow: Glow = Glow.None, focusedGlow: Glow = glow, pressedGlow: Glow = glow) = 384 ButtonGlow(glow = glow, focusedGlow = focusedGlow, pressedGlow = pressedGlow) 385 } 386