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.runtime.Composable 23 import androidx.compose.runtime.ReadOnlyComposable 24 import androidx.compose.ui.graphics.Color 25 import androidx.compose.ui.graphics.RectangleShape 26 import androidx.compose.ui.graphics.Shape 27 import androidx.compose.ui.unit.dp 28 29 /** Contains the default values used by a non-interactive [Surface] */ 30 object SurfaceDefaults { 31 /** Represents the default shape used by a non-interactive [Surface] */ 32 val shape: Shape 33 @ReadOnlyComposable @Composable get() = RectangleShape 34 35 /** 36 * Creates a [SurfaceColors] that represents the default container & content colors used by a 37 * non-interactive [Surface]. 38 * 39 * @param containerColor the container color of this Surface 40 * @param contentColor the content color of this Surface 41 */ 42 @ReadOnlyComposable 43 @Composable colorsnull44 fun colors( 45 containerColor: Color = MaterialTheme.colorScheme.surface, 46 contentColor: Color = contentColorFor(containerColor) 47 ) = SurfaceColors(containerColor = containerColor, contentColor = contentColor) 48 49 /** Represents the default border used by a non-interactive [Surface] */ 50 internal val border: Border = Border.None 51 52 /** Represents the default glow used by a non-interactive [Surface] */ 53 internal val glow: Glow = Glow.None 54 } 55 56 /** Contains the default values used by clickable Surface. */ 57 object ClickableSurfaceDefaults { 58 /** 59 * Creates a [ClickableSurfaceShape] that represents the default container shapes used in a 60 * Surface. 61 * 62 * @param shape the shape used when the Surface is enabled, and has no other [Interaction]s. 63 * @param focusedShape the shape used when the Surface is enabled and focused. 64 * @param pressedShape the shape used when the Surface is enabled pressed. 65 * @param disabledShape the shape used when the Surface is not enabled. 66 * @param focusedDisabledShape the shape used when the Surface is not enabled and focused. 67 */ 68 @ReadOnlyComposable 69 @Composable 70 fun shape( 71 shape: Shape = MaterialTheme.shapes.medium, 72 focusedShape: Shape = shape, 73 pressedShape: Shape = shape, 74 disabledShape: Shape = shape, 75 focusedDisabledShape: Shape = disabledShape 76 ) = 77 ClickableSurfaceShape( 78 shape = shape, 79 focusedShape = focusedShape, 80 pressedShape = pressedShape, 81 disabledShape = disabledShape, 82 focusedDisabledShape = focusedDisabledShape 83 ) 84 85 /** 86 * Creates a [ClickableSurfaceColors] that represents the default container & content colors 87 * used in a Surface. 88 * 89 * @param containerColor the container color of this Surface when enabled 90 * @param contentColor the content color of this Surface when enabled 91 * @param focusedContainerColor the container color of this Surface when enabled and focused 92 * @param focusedContentColor the content color of this Surface when enabled and focused 93 * @param pressedContainerColor the container color of this Surface when enabled and pressed 94 * @param pressedContentColor the content color of this Surface when enabled and pressed 95 * @param disabledContainerColor the container color of this Surface when not enabled 96 * @param disabledContentColor the content color of this Surface when not enabled 97 */ 98 @ReadOnlyComposable 99 @Composable 100 fun colors( 101 containerColor: Color = MaterialTheme.colorScheme.surface, 102 contentColor: Color = contentColorFor(containerColor), 103 focusedContainerColor: Color = MaterialTheme.colorScheme.inverseSurface, 104 focusedContentColor: Color = contentColorFor(focusedContainerColor), 105 pressedContainerColor: Color = focusedContainerColor, 106 pressedContentColor: Color = contentColorFor(pressedContainerColor), 107 disabledContainerColor: Color = 108 MaterialTheme.colorScheme.surfaceVariant.copy(alpha = DisabledContainerAlpha), 109 disabledContentColor: Color = MaterialTheme.colorScheme.onSurface 110 ) = 111 ClickableSurfaceColors( 112 containerColor = containerColor, 113 contentColor = contentColor, 114 focusedContainerColor = focusedContainerColor, 115 focusedContentColor = focusedContentColor, 116 pressedContainerColor = pressedContainerColor, 117 pressedContentColor = pressedContentColor, 118 disabledContainerColor = disabledContainerColor, 119 disabledContentColor = disabledContentColor 120 ) 121 122 /** 123 * Creates a [ClickableSurfaceScale] that represents the default scales used in a Surface. 124 * scales are used to modify the size of a composable in different [Interaction] states e.g. 1f 125 * (original) in default state, 1.2f (scaled up) in focused state, 0.8f (scaled down) in pressed 126 * state, etc. 127 * 128 * @param scale the scale to be used for this Surface when enabled 129 * @param focusedScale the scale to be used for this Surface when focused 130 * @param pressedScale the scale to be used for this Surface when pressed 131 * @param disabledScale the scale to be used for this Surface when disabled 132 * @param focusedDisabledScale the scale to be used for this Surface when disabled and focused 133 */ 134 fun scale( 135 @FloatRange(from = 0.0) scale: Float = 1f, 136 @FloatRange(from = 0.0) focusedScale: Float = 1.1f, 137 @FloatRange(from = 0.0) pressedScale: Float = scale, 138 @FloatRange(from = 0.0) disabledScale: Float = scale, 139 @FloatRange(from = 0.0) focusedDisabledScale: Float = disabledScale 140 ) = 141 ClickableSurfaceScale( 142 scale = scale, 143 focusedScale = focusedScale, 144 pressedScale = pressedScale, 145 disabledScale = disabledScale, 146 focusedDisabledScale = focusedDisabledScale 147 ) 148 149 /** 150 * Creates a [ClickableSurfaceBorder] that represents the default [Border]s applied on a Surface 151 * in different [Interaction] states. 152 * 153 * @param border the [Border] to be used for this Surface when enabled 154 * @param focusedBorder the [Border] to be used for this Surface when focused 155 * @param pressedBorder the [Border] to be used for this Surface when pressed 156 * @param disabledBorder the [Border] to be used for this Surface when disabled 157 * @param focusedDisabledBorder the [Border] to be used for this Surface when disabled and 158 * focused 159 */ 160 @ReadOnlyComposable 161 @Composable 162 fun border( 163 border: Border = Border.None, 164 focusedBorder: Border = border, 165 pressedBorder: Border = focusedBorder, 166 disabledBorder: Border = border, 167 focusedDisabledBorder: Border = 168 Border( 169 border = BorderStroke(width = 2.dp, color = MaterialTheme.colorScheme.border), 170 inset = 0.dp, 171 shape = ShapeDefaults.Small 172 ) 173 ) = 174 ClickableSurfaceBorder( 175 border = border, 176 focusedBorder = focusedBorder, 177 pressedBorder = pressedBorder, 178 disabledBorder = disabledBorder, 179 focusedDisabledBorder = focusedDisabledBorder 180 ) 181 182 /** 183 * Creates a [ClickableSurfaceGlow] that represents the default [Glow]s used in a Surface. 184 * 185 * @param glow the Glow behind this Surface when enabled 186 * @param focusedGlow the Glow behind this Surface when focused 187 * @param pressedGlow the Glow behind this Surface when pressed 188 */ 189 fun glow(glow: Glow = Glow.None, focusedGlow: Glow = glow, pressedGlow: Glow = glow) = 190 ClickableSurfaceGlow(glow = glow, focusedGlow = focusedGlow, pressedGlow = pressedGlow) 191 } 192 193 /** Contains the default values used by Selectable Surface. */ 194 object SelectableSurfaceDefaults { 195 /** 196 * Creates a [SelectableSurfaceShape] that represents the default container shapes used in a 197 * selectable Surface. 198 * 199 * @param shape the shape used when the Surface is enabled, and has no other [Interaction]s. 200 * @param focusedShape the shape used when the Surface is enabled and focused. 201 * @param pressedShape the shape used when the Surface is enabled and pressed. 202 * @param selectedShape the shape used when the Surface is enabled and selected. 203 * @param disabledShape the shape used when the Surface is not enabled. 204 * @param focusedSelectedShape the shape used when the Surface is enabled, focused and selected. 205 * @param focusedDisabledShape the shape used when the Surface is not enabled and focused. 206 * @param pressedSelectedShape the shape used when the Surface is enabled, pressed and selected. 207 * @param selectedDisabledShape the shape used when the Surface is not enabled and selected. 208 * @param focusedSelectedDisabledShape the shape used when the Surface is not enabled, focused 209 * and selected. 210 */ 211 @ReadOnlyComposable 212 @Composable shapenull213 fun shape( 214 shape: Shape = MaterialTheme.shapes.medium, 215 focusedShape: Shape = shape, 216 pressedShape: Shape = shape, 217 selectedShape: Shape = shape, 218 disabledShape: Shape = shape, 219 focusedSelectedShape: Shape = shape, 220 focusedDisabledShape: Shape = disabledShape, 221 pressedSelectedShape: Shape = shape, 222 selectedDisabledShape: Shape = disabledShape, 223 focusedSelectedDisabledShape: Shape = disabledShape 224 ) = 225 SelectableSurfaceShape( 226 shape = shape, 227 focusedShape = focusedShape, 228 pressedShape = pressedShape, 229 selectedShape = selectedShape, 230 disabledShape = disabledShape, 231 focusedSelectedShape = focusedSelectedShape, 232 focusedDisabledShape = focusedDisabledShape, 233 pressedSelectedShape = pressedSelectedShape, 234 selectedDisabledShape = selectedDisabledShape, 235 focusedSelectedDisabledShape = focusedSelectedDisabledShape 236 ) 237 238 /** 239 * Creates a [SelectableSurfaceColors] that represents the default container & content colors 240 * used in a selectable Surface. 241 * 242 * @param containerColor the container color used when the Surface is enabled, and has no other 243 * [Interaction]s. 244 * @param contentColor the content color used when the Surface is enabled, and has no other 245 * [Interaction]s. 246 * @param focusedContainerColor the container color used when the Surface is enabled and 247 * focused. 248 * @param focusedContentColor the content color used when the Surface is enabled and focused. 249 * @param pressedContainerColor the container color used when the Surface is enabled and 250 * pressed. 251 * @param pressedContentColor the content color used when the Surface is enabled and pressed. 252 * @param selectedContainerColor the container color used when the Surface is enabled and 253 * selected. 254 * @param selectedContentColor the content color used when the Surface is enabled and selected. 255 * @param disabledContainerColor the container color used when the Surface is not enabled. 256 * @param disabledContentColor the content color used when the Surface is not enabled. 257 * @param focusedSelectedContainerColor the container color used when the Surface is enabled, 258 * focused and selected. 259 * @param focusedSelectedContentColor the content color used when the Surface is enabled, 260 * focused and selected. 261 * @param pressedSelectedContainerColor the container color used when the Surface is enabled, 262 * pressed and selected. 263 * @param pressedSelectedContentColor the content color used when the Surface is enabled, 264 * pressed and selected. 265 */ 266 @ReadOnlyComposable 267 @Composable 268 fun colors( 269 containerColor: Color = MaterialTheme.colorScheme.surface, 270 contentColor: Color = contentColorFor(containerColor), 271 focusedContainerColor: Color = MaterialTheme.colorScheme.inverseSurface, 272 focusedContentColor: Color = contentColorFor(focusedContainerColor), 273 pressedContainerColor: Color = focusedContainerColor, 274 pressedContentColor: Color = contentColorFor(pressedContainerColor), 275 selectedContainerColor: Color = 276 MaterialTheme.colorScheme.inverseSurface.copy(alpha = SelectedContainerAlpha), 277 selectedContentColor: Color = MaterialTheme.colorScheme.inverseOnSurface, 278 disabledContainerColor: Color = 279 MaterialTheme.colorScheme.surfaceVariant.copy(alpha = DisabledContainerAlpha), 280 disabledContentColor: Color = MaterialTheme.colorScheme.onSurface, 281 focusedSelectedContainerColor: Color = 282 MaterialTheme.colorScheme.inverseSurface.copy(alpha = SelectedContainerAlpha), 283 focusedSelectedContentColor: Color = MaterialTheme.colorScheme.inverseOnSurface, 284 pressedSelectedContainerColor: Color = focusedSelectedContainerColor, 285 pressedSelectedContentColor: Color = focusedSelectedContentColor 286 ) = 287 SelectableSurfaceColors( 288 containerColor = containerColor, 289 contentColor = contentColor, 290 focusedContainerColor = focusedContainerColor, 291 focusedContentColor = focusedContentColor, 292 pressedContainerColor = pressedContainerColor, 293 pressedContentColor = pressedContentColor, 294 selectedContainerColor = selectedContainerColor, 295 selectedContentColor = selectedContentColor, 296 disabledContainerColor = disabledContainerColor, 297 disabledContentColor = disabledContentColor, 298 focusedSelectedContainerColor = focusedSelectedContainerColor, 299 focusedSelectedContentColor = focusedSelectedContentColor, 300 pressedSelectedContainerColor = pressedSelectedContainerColor, 301 pressedSelectedContentColor = pressedSelectedContentColor 302 ) 303 304 /** 305 * Creates a [SelectableSurfaceScale] that represents the default scales used in a selectable 306 * Surface. scales are used to modify the size of a composable in different [Interaction] states 307 * e.g. 1f (original) in default state, 1.2f (scaled up) in focused state, 0.8f (scaled down) in 308 * pressed state, etc. 309 * 310 * @param scale the scale used when the Surface is enabled, and has no other [Interaction]s. 311 * @param focusedScale the scale used when the Surface is enabled and focused. 312 * @param pressedScale the scale used when the Surface is enabled and pressed. 313 * @param selectedScale the scale used when the Surface is enabled and selected. 314 * @param disabledScale the scale used when the Surface is not enabled. 315 * @param focusedSelectedScale the scale used when the Surface is enabled, focused and selected. 316 * @param focusedDisabledScale the scale used when the Surface is not enabled and focused. 317 * @param pressedSelectedScale the scale used when the Surface is enabled, pressed and selected. 318 * @param selectedDisabledScale the scale used when the Surface is not enabled and selected. 319 * @param focusedSelectedDisabledScale the scale used when the Surface is not enabled, focused 320 * and selected. 321 */ 322 fun scale( 323 scale: Float = 1f, 324 focusedScale: Float = 1.1f, 325 pressedScale: Float = scale, 326 selectedScale: Float = scale, 327 disabledScale: Float = scale, 328 focusedSelectedScale: Float = focusedScale, 329 focusedDisabledScale: Float = disabledScale, 330 pressedSelectedScale: Float = scale, 331 selectedDisabledScale: Float = disabledScale, 332 focusedSelectedDisabledScale: Float = disabledScale 333 ) = 334 SelectableSurfaceScale( 335 scale = scale, 336 focusedScale = focusedScale, 337 pressedScale = pressedScale, 338 selectedScale = selectedScale, 339 disabledScale = disabledScale, 340 focusedSelectedScale = focusedSelectedScale, 341 focusedDisabledScale = focusedDisabledScale, 342 pressedSelectedScale = pressedSelectedScale, 343 selectedDisabledScale = selectedDisabledScale, 344 focusedSelectedDisabledScale = focusedSelectedDisabledScale 345 ) 346 347 /** 348 * Creates a [SelectableSurfaceBorder] that represents the default [Border]s applied on a 349 * selectable Surface in different [Interaction] states. 350 * 351 * @param border the [Border] used when the Surface is enabled, and has no other [Interaction]s. 352 * @param focusedBorder the [Border] used when the Surface is enabled and focused. 353 * @param pressedBorder the [Border] used when the Surface is enabled and pressed. 354 * @param selectedBorder the [Border] used when the Surface is enabled and selected. 355 * @param disabledBorder the [Border] used when the Surface is not enabled. 356 * @param focusedSelectedBorder the [Border] used when the Surface is enabled, focused and 357 * selected. 358 * @param focusedDisabledBorder the [Border] used when the Surface is not enabled and focused. 359 * @param pressedSelectedBorder the [Border] used when the Surface is enabled, pressed and 360 * selected. 361 * @param selectedDisabledBorder the [Border] used when the Surface is not enabled and selected. 362 * @param focusedSelectedDisabledBorder the [Border] used when the Surface is not enabled, 363 * focused and selected. 364 */ 365 fun border( 366 border: Border = Border.None, 367 focusedBorder: Border = border, 368 pressedBorder: Border = focusedBorder, 369 selectedBorder: Border = border, 370 disabledBorder: Border = border, 371 focusedSelectedBorder: Border = focusedBorder, 372 focusedDisabledBorder: Border = disabledBorder, 373 pressedSelectedBorder: Border = border, 374 selectedDisabledBorder: Border = disabledBorder, 375 focusedSelectedDisabledBorder: Border = disabledBorder 376 ) = 377 SelectableSurfaceBorder( 378 border = border, 379 focusedBorder = focusedBorder, 380 pressedBorder = pressedBorder, 381 selectedBorder = selectedBorder, 382 disabledBorder = disabledBorder, 383 focusedSelectedBorder = focusedSelectedBorder, 384 focusedDisabledBorder = focusedDisabledBorder, 385 pressedSelectedBorder = pressedSelectedBorder, 386 selectedDisabledBorder = selectedDisabledBorder, 387 focusedSelectedDisabledBorder = focusedSelectedDisabledBorder 388 ) 389 390 /** 391 * Creates a [SelectableSurfaceGlow] that represents the default [Glow]s used in a selectable 392 * Surface. 393 * 394 * @param glow the [Glow] used when the Surface is enabled, and has no other [Interaction]s. 395 * @param focusedGlow the [Glow] used when the Surface is enabled and focused. 396 * @param pressedGlow the [Glow] used when the Surface is enabled and pressed. 397 * @param selectedGlow the [Glow] used when the Surface is enabled and selected. 398 * @param focusedSelectedGlow the [Glow] used when the Surface is enabled, focused and selected. 399 * @param pressedSelectedGlow the [Glow] used when the Surface is enabled, pressed and selected. 400 */ 401 fun glow( 402 glow: Glow = Glow.None, 403 focusedGlow: Glow = glow, 404 pressedGlow: Glow = glow, 405 selectedGlow: Glow = glow, 406 focusedSelectedGlow: Glow = focusedGlow, 407 pressedSelectedGlow: Glow = glow 408 ) = 409 SelectableSurfaceGlow( 410 glow = glow, 411 focusedGlow = focusedGlow, 412 pressedGlow = pressedGlow, 413 selectedGlow = selectedGlow, 414 focusedSelectedGlow = focusedSelectedGlow, 415 pressedSelectedGlow = pressedSelectedGlow 416 ) 417 } 418 419 private const val DisabledContainerAlpha = 0.4f 420 private const val SelectedContainerAlpha = 0.5f 421