1 /* 2 * Copyright 2025 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.compose.material3 18 19 import androidx.compose.foundation.BorderStroke 20 import androidx.compose.foundation.shape.CornerBasedShape 21 import androidx.compose.material3.tokens.FilledIconButtonTokens 22 import androidx.compose.material3.tokens.FilledTonalIconButtonTokens 23 import androidx.compose.material3.tokens.LargeIconButtonTokens 24 import androidx.compose.material3.tokens.MediumIconButtonTokens 25 import androidx.compose.material3.tokens.OutlinedIconButtonTokens 26 import androidx.compose.material3.tokens.SmallIconButtonTokens 27 import androidx.compose.material3.tokens.StandardIconButtonTokens 28 import androidx.compose.material3.tokens.XLargeIconButtonTokens 29 import androidx.compose.material3.tokens.XSmallIconButtonTokens 30 import androidx.compose.runtime.Composable 31 import androidx.compose.runtime.remember 32 import androidx.compose.ui.graphics.Color 33 import androidx.compose.ui.graphics.Shape 34 import androidx.compose.ui.unit.Dp 35 import androidx.compose.ui.unit.DpSize 36 import androidx.compose.ui.unit.dp 37 import kotlin.jvm.JvmInline 38 39 /** Contains the default values for all four icon and icon toggle button types. */ 40 object IconButtonDefaults { 41 /** 42 * Contains the default values used by [IconButton]. [LocalContentColor] will be applied to the 43 * icon and down the UI tree. 44 * 45 * See [iconButtonVibrantColors] for default values that applies the recommended high contrast 46 * colors. 47 */ 48 @Composable iconButtonColorsnull49 fun iconButtonColors(): IconButtonColors { 50 val contentColor = LocalContentColor.current 51 val colors = MaterialTheme.colorScheme.defaultIconButtonColors(contentColor) 52 return if (colors.contentColor == contentColor) { 53 colors 54 } else { 55 colors.copy( 56 contentColor = contentColor, 57 disabledContentColor = 58 contentColor.copy(alpha = StandardIconButtonTokens.DisabledOpacity) 59 ) 60 } 61 } 62 63 /** 64 * Creates a [IconButtonColors] that represents the default colors used in a [IconButton]. 65 * [LocalContentColor] will be applied to the icon and down the UI tree unless a custom 66 * [contentColor] is provided. 67 * 68 * See [iconButtonVibrantColors] for default values that applies the recommended high contrast 69 * colors. 70 * 71 * @param containerColor the container color of this icon button when enabled. 72 * @param contentColor the content color of this icon button when enabled. By default, this will 73 * use the current LocalContentColor value. 74 * @param disabledContainerColor the container color of this icon button when not enabled. 75 * @param disabledContentColor the content color of this icon button when not enabled. 76 */ 77 @Composable iconButtonColorsnull78 fun iconButtonColors( 79 containerColor: Color = Color.Unspecified, 80 contentColor: Color = LocalContentColor.current, 81 disabledContainerColor: Color = Color.Unspecified, 82 disabledContentColor: Color = 83 contentColor.copy(alpha = StandardIconButtonTokens.DisabledOpacity) 84 ): IconButtonColors = 85 MaterialTheme.colorScheme 86 .defaultIconButtonColors(LocalContentColor.current) 87 .copy( 88 containerColor = containerColor, 89 contentColor = contentColor, 90 disabledContainerColor = disabledContainerColor, 91 disabledContentColor = disabledContentColor, 92 ) 93 94 internal fun ColorScheme.defaultIconButtonColors(localContentColor: Color): IconButtonColors { 95 return defaultIconButtonColorsCached 96 ?: run { 97 IconButtonColors( 98 containerColor = Color.Transparent, 99 contentColor = localContentColor, 100 disabledContainerColor = Color.Transparent, 101 disabledContentColor = 102 localContentColor.copy(alpha = StandardIconButtonTokens.DisabledOpacity) 103 ) 104 .also { defaultIconButtonColorsCached = it } 105 } 106 } 107 108 /** 109 * Creates a [IconButtonColors] that represents the recommended high contrast colors used in an 110 * [IconButton]. 111 * 112 * See [iconButtonColors] for default values that applies [LocalContentColor] to the icon and 113 * down the UI tree. 114 */ 115 @Composable iconButtonVibrantColorsnull116 fun iconButtonVibrantColors(): IconButtonColors = 117 MaterialTheme.colorScheme.defaultIconButtonVibrantColors() 118 119 /** 120 * Creates a [IconButtonColors] that represents the recommended high contrast colors used in an 121 * [IconButton]. 122 * 123 * See [iconButtonColors] for default values that applies [LocalContentColor] to the icon and 124 * down the UI tree. 125 * 126 * @param containerColor the container color of this icon button when enabled. 127 * @param contentColor the content color of this icon button when enabled. 128 * @param disabledContainerColor the container color of this icon button when not enabled. 129 * @param disabledContentColor the content color of this icon button when not enabled. 130 */ 131 @Composable 132 fun iconButtonVibrantColors( 133 containerColor: Color = Color.Unspecified, 134 contentColor: Color = Color.Unspecified, 135 disabledContainerColor: Color = Color.Unspecified, 136 disabledContentColor: Color = 137 contentColor.copy(alpha = StandardIconButtonTokens.DisabledOpacity) 138 ): IconButtonColors = 139 MaterialTheme.colorScheme 140 .defaultIconButtonVibrantColors() 141 .copy( 142 containerColor = containerColor, 143 contentColor = contentColor, 144 disabledContainerColor = disabledContainerColor, 145 disabledContentColor = disabledContentColor, 146 ) 147 148 internal fun ColorScheme.defaultIconButtonVibrantColors(): IconButtonColors { 149 return defaultIconButtonVibrantColorsCached 150 ?: run { 151 IconButtonColors( 152 containerColor = Color.Transparent, 153 contentColor = fromToken(StandardIconButtonTokens.Color), 154 disabledContainerColor = Color.Transparent, 155 disabledContentColor = 156 fromToken(StandardIconButtonTokens.DisabledColor) 157 .copy(alpha = StandardIconButtonTokens.DisabledOpacity) 158 ) 159 .also { defaultIconButtonVibrantColorsCached = it } 160 } 161 } 162 163 /** 164 * Creates a [IconToggleButtonColors] that represents the default colors used in a 165 * [IconToggleButton]. [LocalContentColor] will be applied to the icon and down the UI tree. 166 * 167 * See [iconToggleButtonVibrantColors] for default values that applies the recommended high 168 * contrast colors. 169 */ 170 @Composable iconToggleButtonColorsnull171 fun iconToggleButtonColors(): IconToggleButtonColors { 172 val contentColor = LocalContentColor.current 173 val colors = MaterialTheme.colorScheme.defaultIconToggleButtonColors(contentColor) 174 if (colors.contentColor == contentColor) { 175 return colors 176 } else { 177 return colors.copy( 178 contentColor = contentColor, 179 disabledContentColor = 180 contentColor.copy(alpha = StandardIconButtonTokens.DisabledOpacity) 181 ) 182 } 183 } 184 185 /** 186 * Creates a [IconToggleButtonColors] that represents the default colors used in a 187 * [IconToggleButton]. [LocalContentColor] will be applied to the icon and down the UI tree 188 * unless a custom [contentColor] is provided. 189 * 190 * See [iconToggleButtonVibrantColors] for default values that applies the recommended high 191 * contrast colors. 192 * 193 * @param containerColor the container color of this icon button when enabled. 194 * @param contentColor the content color of this icon button when enabled. 195 * @param disabledContainerColor the container color of this icon button when not enabled. 196 * @param disabledContentColor the content color of this icon button when not enabled. 197 * @param checkedContainerColor the container color of this icon button when checked. 198 * @param checkedContentColor the content color of this icon button when checked. 199 */ 200 @Composable iconToggleButtonColorsnull201 fun iconToggleButtonColors( 202 containerColor: Color = Color.Unspecified, 203 contentColor: Color = LocalContentColor.current, 204 disabledContainerColor: Color = Color.Unspecified, 205 disabledContentColor: Color = 206 contentColor.copy(alpha = StandardIconButtonTokens.DisabledOpacity), 207 checkedContainerColor: Color = Color.Unspecified, 208 checkedContentColor: Color = Color.Unspecified 209 ): IconToggleButtonColors = 210 MaterialTheme.colorScheme 211 .defaultIconToggleButtonColors(LocalContentColor.current) 212 .copy( 213 containerColor = containerColor, 214 contentColor = contentColor, 215 disabledContainerColor = disabledContainerColor, 216 disabledContentColor = disabledContentColor, 217 checkedContainerColor = checkedContainerColor, 218 checkedContentColor = checkedContentColor, 219 ) 220 221 internal fun ColorScheme.defaultIconToggleButtonColors( 222 localContentColor: Color 223 ): IconToggleButtonColors { 224 return defaultIconToggleButtonColorsCached 225 ?: run { 226 IconToggleButtonColors( 227 containerColor = Color.Transparent, 228 contentColor = localContentColor, 229 disabledContainerColor = Color.Transparent, 230 disabledContentColor = 231 localContentColor.copy( 232 alpha = StandardIconButtonTokens.DisabledOpacity 233 ), 234 checkedContainerColor = Color.Transparent, 235 checkedContentColor = fromToken(StandardIconButtonTokens.SelectedColor) 236 ) 237 .also { defaultIconToggleButtonColorsCached = it } 238 } 239 } 240 241 /** 242 * Creates a [IconToggleButtonColors] that represents the recommended high contrast colors used 243 * in a [IconToggleButton]. See [iconToggleButtonColors] for default values that applies 244 * [LocalContentColor] to the icon and down the UI tree. 245 */ 246 @Composable iconToggleButtonVibrantColorsnull247 fun iconToggleButtonVibrantColors(): IconToggleButtonColors = 248 MaterialTheme.colorScheme.defaultIconToggleButtonVibrantColors() 249 250 /** 251 * Creates a [IconToggleButtonColors] that represents the recommended high contrast colors used 252 * in a [IconToggleButton]. 253 * 254 * See [iconToggleButtonColors] for default values that applies [LocalContentColor] to the icon 255 * and down the UI tree. 256 * 257 * @param containerColor the container color of this icon button when enabled. 258 * @param contentColor the content color of this icon button when enabled. 259 * @param disabledContainerColor the container color of this icon button when not enabled. 260 * @param disabledContentColor the content color of this icon button when not enabled. 261 * @param checkedContainerColor the container color of this icon button when checked. 262 * @param checkedContentColor the content color of this icon button when checked. 263 */ 264 @Composable 265 fun iconToggleButtonVibrantColors( 266 containerColor: Color = Color.Unspecified, 267 contentColor: Color = Color.Unspecified, 268 disabledContainerColor: Color = Color.Unspecified, 269 disabledContentColor: Color = 270 contentColor.copy(alpha = StandardIconButtonTokens.DisabledOpacity), 271 checkedContainerColor: Color = Color.Unspecified, 272 checkedContentColor: Color = Color.Unspecified 273 ): IconToggleButtonColors = 274 MaterialTheme.colorScheme 275 .defaultIconToggleButtonVibrantColors() 276 .copy( 277 containerColor = containerColor, 278 contentColor = contentColor, 279 disabledContainerColor = disabledContainerColor, 280 disabledContentColor = disabledContentColor, 281 checkedContainerColor = checkedContainerColor, 282 checkedContentColor = checkedContentColor, 283 ) 284 285 internal fun ColorScheme.defaultIconToggleButtonVibrantColors(): IconToggleButtonColors { 286 return defaultIconToggleButtonVibrantColorsCached 287 ?: run { 288 IconToggleButtonColors( 289 containerColor = Color.Transparent, 290 contentColor = fromToken(StandardIconButtonTokens.UnselectedColor), 291 disabledContainerColor = Color.Transparent, 292 disabledContentColor = 293 fromToken(StandardIconButtonTokens.DisabledColor) 294 .copy(alpha = StandardIconButtonTokens.DisabledOpacity), 295 checkedContainerColor = Color.Transparent, 296 checkedContentColor = fromToken(StandardIconButtonTokens.SelectedColor) 297 ) 298 .also { defaultIconToggleButtonVibrantColorsCached = it } 299 } 300 } 301 302 /** 303 * Creates a [IconButtonColors] that represents the default colors used in a [FilledIconButton]. 304 */ 305 @Composable filledIconButtonColorsnull306 fun filledIconButtonColors(): IconButtonColors = 307 MaterialTheme.colorScheme.defaultFilledIconButtonColors 308 309 /** 310 * Creates a [IconButtonColors] that represents the default colors used in a [FilledIconButton]. 311 * 312 * @param containerColor the container color of this icon button when enabled. 313 * @param contentColor the content color of this icon button when enabled. 314 * @param disabledContainerColor the container color of this icon button when not enabled. 315 * @param disabledContentColor the content color of this icon button when not enabled. 316 */ 317 @Composable 318 fun filledIconButtonColors( 319 containerColor: Color = Color.Unspecified, 320 contentColor: Color = contentColorFor(containerColor), 321 disabledContainerColor: Color = Color.Unspecified, 322 disabledContentColor: Color = Color.Unspecified 323 ): IconButtonColors = 324 MaterialTheme.colorScheme.defaultFilledIconButtonColors.copy( 325 containerColor = containerColor, 326 contentColor = contentColor, 327 disabledContainerColor = disabledContainerColor, 328 disabledContentColor = disabledContentColor, 329 ) 330 331 internal val ColorScheme.defaultFilledIconButtonColors: IconButtonColors 332 get() { 333 return defaultFilledIconButtonColorsCached 334 ?: IconButtonColors( 335 containerColor = fromToken(FilledIconButtonTokens.ContainerColor), 336 contentColor = fromToken(FilledIconButtonTokens.Color), 337 disabledContainerColor = 338 fromToken(FilledIconButtonTokens.DisabledContainerColor) 339 .copy(alpha = FilledIconButtonTokens.DisabledContainerOpacity), 340 disabledContentColor = 341 fromToken(FilledIconButtonTokens.DisabledColor) 342 .copy(alpha = FilledIconButtonTokens.DisabledOpacity) 343 ) 344 .also { defaultFilledIconButtonColorsCached = it } 345 } 346 347 /** 348 * Creates a [IconToggleButtonColors] that represents the default colors used in a 349 * [FilledIconToggleButton]. 350 */ 351 @Composable filledIconToggleButtonColorsnull352 fun filledIconToggleButtonColors(): IconToggleButtonColors = 353 MaterialTheme.colorScheme.defaultFilledIconToggleButtonColors 354 355 /** 356 * Creates a [IconToggleButtonColors] that represents the default colors used in a 357 * [FilledIconToggleButton]. 358 * 359 * @param containerColor the container color of this icon button when enabled. 360 * @param contentColor the content color of this icon button when enabled. 361 * @param disabledContainerColor the container color of this icon button when not enabled. 362 * @param disabledContentColor the content color of this icon button when not enabled. 363 * @param checkedContainerColor the container color of this icon button when checked. 364 * @param checkedContentColor the content color of this icon button when checked. 365 */ 366 @Composable 367 fun filledIconToggleButtonColors( 368 containerColor: Color = Color.Unspecified, 369 // TODO(b/228455081): Using contentColorFor here will return OnSurfaceVariant, 370 // while the token value is Primary. 371 contentColor: Color = Color.Unspecified, 372 disabledContainerColor: Color = Color.Unspecified, 373 disabledContentColor: Color = Color.Unspecified, 374 checkedContainerColor: Color = Color.Unspecified, 375 checkedContentColor: Color = contentColorFor(checkedContainerColor) 376 ): IconToggleButtonColors = 377 MaterialTheme.colorScheme.defaultFilledIconToggleButtonColors.copy( 378 containerColor = containerColor, 379 contentColor = contentColor, 380 disabledContainerColor = disabledContainerColor, 381 disabledContentColor = disabledContentColor, 382 checkedContainerColor = checkedContainerColor, 383 checkedContentColor = checkedContentColor, 384 ) 385 386 internal val ColorScheme.defaultFilledIconToggleButtonColors: IconToggleButtonColors 387 get() { 388 return defaultFilledIconToggleButtonColorsCached 389 ?: IconToggleButtonColors( 390 containerColor = fromToken(FilledIconButtonTokens.UnselectedContainerColor), 391 // TODO(b/228455081): Using contentColorFor here will return 392 // OnSurfaceVariant, 393 // while the token value is Primary. 394 contentColor = fromToken(FilledIconButtonTokens.UnselectedColor), 395 disabledContainerColor = 396 fromToken(FilledIconButtonTokens.DisabledContainerColor) 397 .copy(alpha = FilledIconButtonTokens.DisabledContainerOpacity), 398 disabledContentColor = 399 fromToken(FilledIconButtonTokens.DisabledColor) 400 .copy(alpha = FilledIconButtonTokens.DisabledOpacity), 401 checkedContainerColor = 402 fromToken(FilledIconButtonTokens.SelectedContainerColor), 403 checkedContentColor = fromToken(FilledIconButtonTokens.SelectedColor) 404 ) 405 .also { defaultFilledIconToggleButtonColorsCached = it } 406 } 407 408 /** 409 * Creates a [IconButtonColors] that represents the default colors used in a 410 * [FilledTonalIconButton]. 411 */ 412 @Composable filledTonalIconButtonColorsnull413 fun filledTonalIconButtonColors(): IconButtonColors = 414 MaterialTheme.colorScheme.defaultFilledTonalIconButtonColors 415 416 /** 417 * Creates a [IconButtonColors] that represents the default colors used in a 418 * [FilledTonalIconButton]. 419 * 420 * @param containerColor the container color of this icon button when enabled. 421 * @param contentColor the content color of this icon button when enabled. 422 * @param disabledContainerColor the container color of this icon button when not enabled. 423 * @param disabledContentColor the content color of this icon button when not enabled. 424 */ 425 @Composable 426 fun filledTonalIconButtonColors( 427 containerColor: Color = Color.Unspecified, 428 contentColor: Color = contentColorFor(containerColor), 429 disabledContainerColor: Color = Color.Unspecified, 430 disabledContentColor: Color = Color.Unspecified 431 ): IconButtonColors = 432 MaterialTheme.colorScheme.defaultFilledTonalIconButtonColors.copy( 433 containerColor = containerColor, 434 contentColor = contentColor, 435 disabledContainerColor = disabledContainerColor, 436 disabledContentColor = disabledContentColor, 437 ) 438 439 internal val ColorScheme.defaultFilledTonalIconButtonColors: IconButtonColors 440 get() { 441 return defaultFilledTonalIconButtonColorsCached 442 ?: IconButtonColors( 443 containerColor = fromToken(FilledTonalIconButtonTokens.ContainerColor), 444 contentColor = fromToken(FilledTonalIconButtonTokens.Color), 445 disabledContainerColor = 446 fromToken(FilledTonalIconButtonTokens.DisabledContainerColor) 447 .copy(alpha = FilledTonalIconButtonTokens.DisabledContainerOpacity), 448 disabledContentColor = 449 fromToken(FilledTonalIconButtonTokens.DisabledColor) 450 .copy(alpha = FilledTonalIconButtonTokens.DisabledOpacity) 451 ) 452 .also { defaultFilledTonalIconButtonColorsCached = it } 453 } 454 455 /** 456 * Creates a [IconToggleButtonColors] that represents the default colors used in a 457 * [FilledTonalIconToggleButton]. 458 */ 459 @Composable filledTonalIconToggleButtonColorsnull460 fun filledTonalIconToggleButtonColors(): IconToggleButtonColors = 461 MaterialTheme.colorScheme.defaultFilledTonalIconToggleButtonColors 462 463 /** 464 * Creates a [IconToggleButtonColors] that represents the default colors used in a 465 * [FilledTonalIconToggleButton]. 466 * 467 * @param containerColor the container color of this icon button when enabled. 468 * @param contentColor the content color of this icon button when enabled. 469 * @param disabledContainerColor the container color of this icon button when not enabled. 470 * @param disabledContentColor the content color of this icon button when not enabled. 471 * @param checkedContainerColor the container color of this icon button when checked. 472 * @param checkedContentColor the content color of this icon button when checked. 473 */ 474 @Composable 475 fun filledTonalIconToggleButtonColors( 476 containerColor: Color = Color.Unspecified, 477 contentColor: Color = contentColorFor(containerColor), 478 disabledContainerColor: Color = Color.Unspecified, 479 disabledContentColor: Color = Color.Unspecified, 480 checkedContainerColor: Color = Color.Unspecified, 481 checkedContentColor: Color = contentColorFor(checkedContainerColor) 482 ): IconToggleButtonColors = 483 MaterialTheme.colorScheme.defaultFilledTonalIconToggleButtonColors.copy( 484 containerColor = containerColor, 485 contentColor = contentColor, 486 disabledContainerColor = disabledContainerColor, 487 disabledContentColor = disabledContentColor, 488 checkedContainerColor = checkedContainerColor, 489 checkedContentColor = checkedContentColor, 490 ) 491 492 internal val ColorScheme.defaultFilledTonalIconToggleButtonColors: IconToggleButtonColors 493 get() { 494 return defaultFilledTonalIconToggleButtonColorsCached 495 ?: IconToggleButtonColors( 496 containerColor = 497 fromToken(FilledTonalIconButtonTokens.UnselectedContainerColor), 498 contentColor = fromToken(FilledTonalIconButtonTokens.UnselectedColor), 499 disabledContainerColor = 500 fromToken(FilledTonalIconButtonTokens.DisabledContainerColor) 501 .copy(alpha = FilledTonalIconButtonTokens.DisabledContainerOpacity), 502 disabledContentColor = 503 fromToken(FilledTonalIconButtonTokens.DisabledColor) 504 .copy(alpha = FilledTonalIconButtonTokens.DisabledOpacity), 505 checkedContainerColor = 506 fromToken(FilledTonalIconButtonTokens.SelectedContainerColor), 507 checkedContentColor = fromToken(FilledTonalIconButtonTokens.SelectedColor) 508 ) 509 .also { defaultFilledTonalIconToggleButtonColorsCached = it } 510 } 511 512 /** 513 * Creates a [IconButtonColors] that represents the default colors used in a 514 * [OutlinedIconButton]. [LocalContentColor] will be applied to the icon and down the UI tree. 515 * 516 * See [outlinedIconButtonVibrantColors] for default values that applies the recommended high 517 * contrast colors. 518 */ 519 @Composable outlinedIconButtonColorsnull520 fun outlinedIconButtonColors(): IconButtonColors { 521 val contentColor = LocalContentColor.current 522 val colors = MaterialTheme.colorScheme.defaultOutlinedIconButtonColors(contentColor) 523 if (colors.contentColor == contentColor) { 524 return colors 525 } else { 526 return colors.copy( 527 contentColor = contentColor, 528 disabledContentColor = 529 contentColor.copy(alpha = OutlinedIconButtonTokens.DisabledOpacity) 530 ) 531 } 532 } 533 534 /** 535 * Creates a [IconButtonColors] that represents the default colors used in a 536 * [OutlinedIconButton]. 537 * 538 * See [outlinedIconButtonVibrantColors] for default values that applies the recommended high 539 * contrast colors. 540 * 541 * @param containerColor the container color of this icon button when enabled. 542 * @param contentColor the content color of this icon button when enabled. 543 * @param disabledContainerColor the container color of this icon button when not enabled. 544 * @param disabledContentColor the content color of this icon button when not enabled. 545 */ 546 @Composable outlinedIconButtonColorsnull547 fun outlinedIconButtonColors( 548 containerColor: Color = Color.Unspecified, 549 contentColor: Color = LocalContentColor.current, 550 disabledContainerColor: Color = Color.Unspecified, 551 disabledContentColor: Color = 552 contentColor.copy(alpha = OutlinedIconButtonTokens.DisabledOpacity) 553 ): IconButtonColors = 554 MaterialTheme.colorScheme 555 .defaultOutlinedIconButtonColors(LocalContentColor.current) 556 .copy( 557 containerColor = containerColor, 558 contentColor = contentColor, 559 disabledContainerColor = disabledContainerColor, 560 disabledContentColor = disabledContentColor, 561 ) 562 563 internal fun ColorScheme.defaultOutlinedIconButtonColors( 564 localContentColor: Color 565 ): IconButtonColors { 566 return defaultOutlinedIconButtonColorsCached 567 ?: run { 568 IconButtonColors( 569 containerColor = Color.Transparent, 570 contentColor = localContentColor, 571 disabledContainerColor = Color.Transparent, 572 disabledContentColor = 573 localContentColor.copy(alpha = OutlinedIconButtonTokens.DisabledOpacity) 574 ) 575 .also { defaultOutlinedIconButtonColorsCached = it } 576 } 577 } 578 579 /** 580 * Creates a [IconButtonColors] that represents the default colors used in a 581 * [OutlinedIconButton]. 582 * 583 * See [outlinedIconButtonColors] for default values that applies [LocalContentColor] to the 584 * icon and down the UI tree. 585 */ 586 @Composable outlinedIconButtonVibrantColorsnull587 fun outlinedIconButtonVibrantColors(): IconButtonColors = 588 MaterialTheme.colorScheme.defaultOutlinedIconButtonVibrantColors() 589 590 /** 591 * Creates a [IconButtonColors] that represents the default colors used in a 592 * [OutlinedIconButton]. 593 * 594 * See [outlinedIconButtonColors] for default values that applies [LocalContentColor] to the 595 * icon and down the UI tree. 596 * 597 * @param containerColor the container color of this icon button when enabled. 598 * @param contentColor the content color of this icon button when enabled. 599 * @param disabledContainerColor the container color of this icon button when not enabled. 600 * @param disabledContentColor the content color of this icon button when not enabled. 601 */ 602 @Composable 603 fun outlinedIconButtonVibrantColors( 604 containerColor: Color = Color.Unspecified, 605 contentColor: Color = Color.Unspecified, 606 disabledContainerColor: Color = Color.Unspecified, 607 disabledContentColor: Color = 608 contentColor.copy(alpha = OutlinedIconButtonTokens.DisabledOpacity) 609 ): IconButtonColors = 610 MaterialTheme.colorScheme 611 .defaultOutlinedIconButtonVibrantColors() 612 .copy( 613 containerColor = containerColor, 614 contentColor = contentColor, 615 disabledContainerColor = disabledContainerColor, 616 disabledContentColor = disabledContentColor, 617 ) 618 619 internal fun ColorScheme.defaultOutlinedIconButtonVibrantColors(): IconButtonColors { 620 return defaultOutlinedIconButtonVibrantColorsCached 621 ?: run { 622 IconButtonColors( 623 containerColor = Color.Transparent, 624 contentColor = fromToken(OutlinedIconButtonTokens.Color), 625 disabledContainerColor = Color.Transparent, 626 disabledContentColor = 627 fromToken(OutlinedIconButtonTokens.DisabledColor) 628 .copy(alpha = OutlinedIconButtonTokens.DisabledOpacity) 629 ) 630 .also { defaultOutlinedIconButtonVibrantColorsCached = it } 631 } 632 } 633 634 /** 635 * Creates a [IconToggleButtonColors] that represents the default colors used in a 636 * [OutlinedIconToggleButton]. [LocalContentColor] will be applied to the icon and down the UI 637 * tree. 638 * 639 * See [outlinedIconButtonVibrantColors] for default values that applies the recommended high 640 * contrast colors. 641 */ 642 @Composable outlinedIconToggleButtonColorsnull643 fun outlinedIconToggleButtonColors(): IconToggleButtonColors { 644 val contentColor = LocalContentColor.current 645 val colors = MaterialTheme.colorScheme.defaultOutlinedIconToggleButtonColors(contentColor) 646 if (colors.contentColor == contentColor) { 647 return colors 648 } else { 649 return colors.copy( 650 contentColor = contentColor, 651 disabledContentColor = 652 contentColor.copy(alpha = OutlinedIconButtonTokens.DisabledOpacity) 653 ) 654 } 655 } 656 657 /** 658 * Creates a [IconToggleButtonColors] that represents the default colors used in a 659 * [OutlinedIconToggleButton]. [LocalContentColor] will be applied to the icon and down the UI 660 * tree. 661 * 662 * See [outlinedIconButtonVibrantColors] for default values that applies the recommended high 663 * contrast colors. 664 * 665 * @param containerColor the container color of this icon button when enabled. 666 * @param contentColor the content color of this icon button when enabled. 667 * @param disabledContainerColor the container color of this icon button when not enabled. 668 * @param disabledContentColor the content color of this icon button when not enabled. 669 * @param checkedContainerColor the container color of this icon button when checked. 670 * @param checkedContentColor the content color of this icon button when checked. 671 */ 672 @Composable outlinedIconToggleButtonColorsnull673 fun outlinedIconToggleButtonColors( 674 containerColor: Color = Color.Unspecified, 675 contentColor: Color = LocalContentColor.current, 676 disabledContainerColor: Color = Color.Unspecified, 677 disabledContentColor: Color = 678 contentColor.copy(alpha = OutlinedIconButtonTokens.DisabledOpacity), 679 checkedContainerColor: Color = Color.Unspecified, 680 checkedContentColor: Color = contentColorFor(checkedContainerColor) 681 ): IconToggleButtonColors = 682 MaterialTheme.colorScheme 683 .defaultOutlinedIconToggleButtonColors(LocalContentColor.current) 684 .copy( 685 containerColor = containerColor, 686 contentColor = contentColor, 687 disabledContainerColor = disabledContainerColor, 688 disabledContentColor = disabledContentColor, 689 checkedContainerColor = checkedContainerColor, 690 checkedContentColor = checkedContentColor, 691 ) 692 693 internal fun ColorScheme.defaultOutlinedIconToggleButtonColors( 694 localContentColor: Color 695 ): IconToggleButtonColors { 696 return defaultIconToggleButtonColorsCached 697 ?: run { 698 IconToggleButtonColors( 699 containerColor = Color.Transparent, 700 contentColor = localContentColor, 701 disabledContainerColor = Color.Transparent, 702 disabledContentColor = 703 localContentColor.copy( 704 alpha = OutlinedIconButtonTokens.DisabledOpacity 705 ), 706 checkedContainerColor = 707 fromToken(OutlinedIconButtonTokens.SelectedContainerColor), 708 checkedContentColor = 709 contentColorFor( 710 fromToken(OutlinedIconButtonTokens.SelectedContainerColor) 711 ) 712 ) 713 .also { defaultOutlinedIconToggleButtonColorsCached = it } 714 } 715 } 716 717 /** 718 * Creates a [IconToggleButtonColors] that represents the default colors used in a 719 * [OutlinedIconToggleButton]. 720 * 721 * See [outlinedIconToggleButtonColors] for default values that applies [LocalContentColor] to 722 * the icon and down the UI tree. 723 */ 724 @Composable outlinedIconToggleButtonVibrantColorsnull725 fun outlinedIconToggleButtonVibrantColors(): IconToggleButtonColors = 726 MaterialTheme.colorScheme.defaultOutlinedIconToggleButtonVibrantColors() 727 728 /** 729 * Creates a [IconToggleButtonColors] that represents the default colors used in a 730 * [OutlinedIconToggleButton]. 731 * 732 * See [outlinedIconToggleButtonColors] for default values that applies [LocalContentColor] to 733 * the icon and down the UI tree. 734 * 735 * @param containerColor the container color of this icon button when enabled. 736 * @param contentColor the content color of this icon button when enabled. 737 * @param disabledContainerColor the container color of this icon button when not enabled. 738 * @param disabledContentColor the content color of this icon button when not enabled. 739 * @param checkedContainerColor the container color of this icon button when checked. 740 * @param checkedContentColor the content color of this icon button when checked. 741 */ 742 @Composable 743 fun outlinedIconToggleButtonVibrantColors( 744 containerColor: Color = Color.Unspecified, 745 contentColor: Color = Color.Unspecified, 746 disabledContainerColor: Color = Color.Unspecified, 747 disabledContentColor: Color = 748 contentColor.copy(alpha = OutlinedIconButtonTokens.DisabledOpacity), 749 checkedContainerColor: Color = Color.Unspecified, 750 checkedContentColor: Color = contentColorFor(checkedContainerColor) 751 ): IconToggleButtonColors = 752 MaterialTheme.colorScheme 753 .defaultOutlinedIconToggleButtonVibrantColors() 754 .copy( 755 containerColor = containerColor, 756 contentColor = contentColor, 757 disabledContainerColor = disabledContainerColor, 758 disabledContentColor = disabledContentColor, 759 checkedContainerColor = checkedContainerColor, 760 checkedContentColor = checkedContentColor, 761 ) 762 763 internal fun ColorScheme.defaultOutlinedIconToggleButtonVibrantColors(): 764 IconToggleButtonColors { 765 return defaultOutlinedIconToggleButtonVibrantColorsCached 766 ?: run { 767 IconToggleButtonColors( 768 containerColor = Color.Transparent, 769 contentColor = fromToken(OutlinedIconButtonTokens.UnselectedColor), 770 disabledContainerColor = Color.Transparent, 771 disabledContentColor = 772 fromToken(OutlinedIconButtonTokens.DisabledColor) 773 .copy(alpha = OutlinedIconButtonTokens.DisabledOpacity), 774 checkedContainerColor = 775 fromToken(OutlinedIconButtonTokens.SelectedContainerColor), 776 checkedContentColor = fromToken(OutlinedIconButtonTokens.SelectedColor) 777 ) 778 .also { defaultOutlinedIconToggleButtonColorsCached = it } 779 } 780 } 781 782 /** 783 * Represents the [BorderStroke] for an [OutlinedIconButton], depending on its [enabled] and 784 * [checked] state. [LocalContentColor] will be used as the border color. 785 * 786 * See [outlinedIconToggleButtonVibrantBorder] for a [BorderStroke] that uses the spec 787 * recommended color as the border color. 788 * 789 * @param enabled whether the icon button is enabled 790 * @param checked whether the icon button is checked 791 */ 792 @Composable outlinedIconToggleButtonBordernull793 fun outlinedIconToggleButtonBorder(enabled: Boolean, checked: Boolean): BorderStroke? { 794 if (checked) { 795 return null 796 } 797 return outlinedIconButtonBorder(enabled) 798 } 799 800 /** 801 * Represents the [BorderStroke] for an [OutlinedIconButton], depending on its [enabled] and 802 * [checked] state. The spec recommended color will be used as the border color. 803 * 804 * @param enabled whether the icon button is enabled 805 * @param checked whether the icon button is checked 806 */ 807 @Composable outlinedIconToggleButtonVibrantBordernull808 fun outlinedIconToggleButtonVibrantBorder(enabled: Boolean, checked: Boolean): BorderStroke? { 809 if (checked) { 810 return null 811 } 812 return outlinedIconButtonVibrantBorder(enabled) 813 } 814 815 /** 816 * Represents the [BorderStroke] for an [OutlinedIconButton], depending on its [enabled] state. 817 * [LocalContentColor] will be used as the border color. 818 * 819 * See [outlinedIconToggleButtonVibrantBorder] for a [BorderStroke] that uses the spec 820 * recommended color as the border color. 821 * 822 * @param enabled whether the icon button is enabled 823 */ 824 @Composable outlinedIconButtonBordernull825 fun outlinedIconButtonBorder(enabled: Boolean): BorderStroke { 826 val outlineColor = LocalContentColor.current 827 val color: Color = 828 if (enabled) { 829 outlineColor 830 } else { 831 outlineColor.copy(alpha = OutlinedIconButtonTokens.DisabledOpacity) 832 } 833 return remember(color) { BorderStroke(SmallIconButtonTokens.OutlinedOutlineWidth, color) } 834 } 835 836 /** 837 * Represents the [BorderStroke] for an [OutlinedIconButton], depending on its [enabled] state. 838 * The spec recommended color will be used as the border color. 839 * 840 * @param enabled whether the icon button is enabled 841 */ 842 @Composable outlinedIconButtonVibrantBordernull843 fun outlinedIconButtonVibrantBorder(enabled: Boolean): BorderStroke { 844 val outlineColor = OutlinedIconButtonTokens.OutlineColor.value 845 val color: Color = 846 if (enabled) { 847 outlineColor 848 } else { 849 outlineColor.copy(alpha = OutlinedIconButtonTokens.DisabledOpacity) 850 } 851 return remember(color) { BorderStroke(SmallIconButtonTokens.OutlinedOutlineWidth, color) } 852 } 853 854 /** Default ripple shape for a standard icon button. */ 855 val standardShape: Shape 856 @Composable get() = SmallIconButtonTokens.ContainerShapeRound.value 857 858 /** Default shape for a filled icon button. */ 859 val filledShape: Shape 860 @Composable get() = SmallIconButtonTokens.ContainerShapeRound.value 861 862 /** Default shape for an outlined icon button. */ 863 val outlinedShape: Shape 864 @Composable get() = SmallIconButtonTokens.ContainerShapeRound.value 865 866 @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET") 867 @get:ExperimentalMaterial3ExpressiveApi 868 @ExperimentalMaterial3ExpressiveApi 869 /** Default round shape for any extra small icon button. */ 870 val extraSmallRoundShape: Shape 871 @Composable get() = XSmallIconButtonTokens.ContainerShapeRound.value 872 873 @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET") 874 @get:ExperimentalMaterial3ExpressiveApi 875 @ExperimentalMaterial3ExpressiveApi 876 /** Default square shape for any extra small icon button. */ 877 val extraSmallSquareShape: Shape 878 @Composable get() = XSmallIconButtonTokens.ContainerShapeSquare.value 879 880 @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET") 881 @get:ExperimentalMaterial3ExpressiveApi 882 @ExperimentalMaterial3ExpressiveApi 883 /** Default pressed shape for any extra small icon button. */ 884 val extraSmallPressedShape: Shape 885 @Composable get() = XSmallIconButtonTokens.PressedContainerShape.value 886 887 @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET") 888 @get:ExperimentalMaterial3ExpressiveApi 889 @ExperimentalMaterial3ExpressiveApi 890 /** Default selected shape for any extra small icon button. */ 891 val extraSmallSelectedRoundShape: Shape 892 @Composable get() = XSmallIconButtonTokens.SelectedContainerShapeRound.value 893 894 @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET") 895 @get:ExperimentalMaterial3ExpressiveApi 896 @ExperimentalMaterial3ExpressiveApi 897 /** Default selected shape for any extra small, square icon button. */ 898 val extraSmallSelectedSquareShape: Shape 899 @Composable get() = XSmallIconButtonTokens.SelectedContainerShapeSquare.value 900 901 @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET") 902 @get:ExperimentalMaterial3ExpressiveApi 903 @ExperimentalMaterial3ExpressiveApi 904 /** Default shape for any small icon button. */ 905 val smallRoundShape: Shape 906 @Composable get() = SmallIconButtonTokens.ContainerShapeRound.value 907 908 @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET") 909 @get:ExperimentalMaterial3ExpressiveApi 910 @ExperimentalMaterial3ExpressiveApi 911 /** Default square shape for any small icon button. */ 912 val smallSquareShape: Shape 913 @Composable get() = SmallIconButtonTokens.ContainerShapeSquare.value 914 915 @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET") 916 @get:ExperimentalMaterial3ExpressiveApi 917 @ExperimentalMaterial3ExpressiveApi 918 /** Default pressed shape for any small icon button. */ 919 val smallPressedShape: Shape 920 @Composable get() = SmallIconButtonTokens.PressedContainerShape.value 921 922 @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET") 923 @get:ExperimentalMaterial3ExpressiveApi 924 @ExperimentalMaterial3ExpressiveApi 925 /** Default selected shape for any small icon button. */ 926 val smallSelectedRoundShape: Shape 927 @Composable get() = SmallIconButtonTokens.SelectedContainerShapeRound.value 928 929 @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET") 930 @get:ExperimentalMaterial3ExpressiveApi 931 @ExperimentalMaterial3ExpressiveApi 932 /** Default selected shape for any small, square icon button. */ 933 val SmallSelectedSquareShape: Shape 934 @Composable get() = SmallIconButtonTokens.SelectedContainerShapeSquare.value 935 936 @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET") 937 @get:ExperimentalMaterial3ExpressiveApi 938 @ExperimentalMaterial3ExpressiveApi 939 /** Default shape for any medium icon button. */ 940 val mediumRoundShape: Shape 941 @Composable get() = MediumIconButtonTokens.ContainerShapeRound.value 942 943 @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET") 944 @get:ExperimentalMaterial3ExpressiveApi 945 @ExperimentalMaterial3ExpressiveApi 946 /** Default shape for any medium icon button. */ 947 val mediumSquareShape: Shape 948 @Composable get() = MediumIconButtonTokens.ContainerShapeSquare.value 949 950 @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET") 951 @get:ExperimentalMaterial3ExpressiveApi 952 @ExperimentalMaterial3ExpressiveApi 953 /** Default pressed shape for any medium icon button. */ 954 val mediumPressedShape: Shape 955 @Composable get() = MediumIconButtonTokens.PressedContainerShape.value 956 957 @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET") 958 @get:ExperimentalMaterial3ExpressiveApi 959 @ExperimentalMaterial3ExpressiveApi 960 /** Default selected shape for any medium icon button. */ 961 val mediumSelectedRoundShape: Shape 962 @Composable get() = MediumIconButtonTokens.SelectedContainerShapeRound.value 963 964 @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET") 965 @get:ExperimentalMaterial3ExpressiveApi 966 @ExperimentalMaterial3ExpressiveApi 967 /** Default selected shape for any medium, square icon button. */ 968 val mediumSelectedSquareShape: Shape 969 @Composable get() = MediumIconButtonTokens.SelectedContainerShapeSquare.value 970 971 @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET") 972 @get:ExperimentalMaterial3ExpressiveApi 973 @ExperimentalMaterial3ExpressiveApi 974 /** Default shape for any large icon button. */ 975 val largeRoundShape: Shape 976 @Composable get() = LargeIconButtonTokens.ContainerShapeRound.value 977 978 @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET") 979 @get:ExperimentalMaterial3ExpressiveApi 980 @ExperimentalMaterial3ExpressiveApi 981 /** Default shape for any large icon button. */ 982 val largeSquareShape: Shape 983 @Composable get() = LargeIconButtonTokens.ContainerShapeSquare.value 984 985 @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET") 986 @get:ExperimentalMaterial3ExpressiveApi 987 @ExperimentalMaterial3ExpressiveApi 988 /** Default pressed shape for any large icon button. */ 989 val largePressedShape: Shape 990 @Composable get() = LargeIconButtonTokens.PressedContainerShape.value 991 992 @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET") 993 @get:ExperimentalMaterial3ExpressiveApi 994 @ExperimentalMaterial3ExpressiveApi 995 /** Default selected shape for any large icon button. */ 996 val largeSelectedRoundShape: Shape 997 @Composable get() = LargeIconButtonTokens.SelectedContainerShapeRound.value 998 999 @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET") 1000 @get:ExperimentalMaterial3ExpressiveApi 1001 @ExperimentalMaterial3ExpressiveApi 1002 /** Default selected shape for any large, square icon button. */ 1003 val largeSelectedSquareShape: Shape 1004 @Composable get() = LargeIconButtonTokens.SelectedContainerShapeSquare.value 1005 1006 @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET") 1007 @get:ExperimentalMaterial3ExpressiveApi 1008 @ExperimentalMaterial3ExpressiveApi 1009 /** Default shape for any extra large icon button. */ 1010 val extraLargeRoundShape: Shape 1011 @Composable get() = XLargeIconButtonTokens.ContainerShapeRound.value 1012 1013 @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET") 1014 @get:ExperimentalMaterial3ExpressiveApi 1015 @ExperimentalMaterial3ExpressiveApi 1016 /** Default shape for any extra large icon button. */ 1017 val extraLargeSquareShape: Shape 1018 @Composable get() = XLargeIconButtonTokens.ContainerShapeSquare.value 1019 1020 @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET") 1021 @get:ExperimentalMaterial3ExpressiveApi 1022 @ExperimentalMaterial3ExpressiveApi 1023 /** Default pressed shape for any extra large icon button. */ 1024 val extraLargePressedShape: Shape 1025 @Composable get() = XLargeIconButtonTokens.PressedContainerShape.value 1026 1027 @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET") 1028 @get:ExperimentalMaterial3ExpressiveApi 1029 @ExperimentalMaterial3ExpressiveApi 1030 /** Default selected shape for any extra large icon button. */ 1031 val extraLargeSelectedRoundShape: Shape 1032 @Composable get() = XLargeIconButtonTokens.SelectedContainerShapeRound.value 1033 1034 @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET") 1035 @get:ExperimentalMaterial3ExpressiveApi 1036 @ExperimentalMaterial3ExpressiveApi 1037 /** Default selected shape for any extra large, square icon button. */ 1038 val extraLargeSelectedSquareShape: Shape 1039 @Composable get() = XLargeIconButtonTokens.SelectedContainerShapeSquare.value 1040 1041 /** 1042 * Creates a [IconButtonShapes] that correspond to the shapes in the default or pressed states. 1043 * Icon button will morph between these shapes as long as the shapes are all 1044 * [CornerBasedShape]s. 1045 * 1046 * @param shape the unchecked shape for [ButtonShapes] 1047 * @param pressedShape the unchecked shape for [ButtonShapes] 1048 */ 1049 @ExperimentalMaterial3ExpressiveApi 1050 @Composable shapesnull1051 fun shapes(shape: Shape? = null, pressedShape: Shape? = null): IconButtonShapes = 1052 MaterialTheme.shapes.defaultIconButtonShapes.copy( 1053 shape = shape, 1054 pressedShape = pressedShape, 1055 ) 1056 1057 /** 1058 * Creates a [IconButtonShapes] that correspond to a default [IconButton] in the active and 1059 * pressed states. [IconButton] will morph between these shapes as long as the shapes are all 1060 * [CornerBasedShape]s. 1061 */ 1062 @ExperimentalMaterial3ExpressiveApi 1063 @Composable 1064 fun shapes(): IconButtonShapes = MaterialTheme.shapes.defaultIconButtonShapes 1065 1066 @OptIn(ExperimentalMaterial3ExpressiveApi::class) 1067 internal val Shapes.defaultIconButtonShapes: IconButtonShapes 1068 get() { 1069 return defaultIconButtonShapesCached 1070 ?: IconButtonShapes( 1071 shape = fromToken(SmallIconButtonTokens.ContainerShapeRound), 1072 pressedShape = fromToken(SmallIconButtonTokens.PressedContainerShape), 1073 ) 1074 .also { defaultIconButtonShapesCached = it } 1075 } 1076 1077 /** 1078 * Creates a [IconToggleButtonShapes] that correspond to the shapes in the default, pressed, and 1079 * checked states. Icon button will morph between these shapes as long as the shapes are all 1080 * [CornerBasedShape]s. 1081 * 1082 * @param shape the active shape for [IconToggleButtonShapes] 1083 * @param pressedShape the pressed shape for [IconToggleButtonShapes] 1084 * @param checkedShape the checked shape for [IconToggleButtonShapes] 1085 */ 1086 @ExperimentalMaterial3ExpressiveApi 1087 @Composable toggleableShapesnull1088 fun toggleableShapes( 1089 shape: Shape? = null, 1090 pressedShape: Shape? = null, 1091 checkedShape: Shape? = null 1092 ): IconToggleButtonShapes = 1093 MaterialTheme.shapes.defaultIconToggleButtonShapes.copy( 1094 shape = shape, 1095 pressedShape = pressedShape, 1096 checkedShape = checkedShape 1097 ) 1098 1099 /** 1100 * Creates a [ButtonShapes] that correspond to a default [IconToggleButton] in the active, 1101 * pressed and selected states. [IconToggleButton] will morph between these shapes as long as 1102 * the shapes are all [CornerBasedShape]s. 1103 */ 1104 @ExperimentalMaterial3ExpressiveApi 1105 @Composable 1106 fun toggleableShapes(): IconToggleButtonShapes = 1107 MaterialTheme.shapes.defaultIconToggleButtonShapes 1108 1109 @OptIn(ExperimentalMaterial3ExpressiveApi::class) 1110 internal val Shapes.defaultIconToggleButtonShapes: IconToggleButtonShapes 1111 get() { 1112 return defaultIconToggleButtonShapesCached 1113 ?: IconToggleButtonShapes( 1114 shape = fromToken(SmallIconButtonTokens.ContainerShapeRound), 1115 pressedShape = fromToken(SmallIconButtonTokens.PressedContainerShape), 1116 checkedShape = fromToken(SmallIconButtonTokens.SelectedContainerShapeRound) 1117 ) 1118 .also { defaultIconToggleButtonShapesCached = it } 1119 } 1120 1121 @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET") 1122 @get:ExperimentalMaterial3ExpressiveApi 1123 @ExperimentalMaterial3ExpressiveApi 1124 /** Default container for any extra small icon button. */ 1125 val extraSmallIconSize: Dp = XSmallIconButtonTokens.IconSize 1126 1127 @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET") 1128 @get:ExperimentalMaterial3ExpressiveApi 1129 @ExperimentalMaterial3ExpressiveApi 1130 /** Default size for any small icon button. */ 1131 val smallIconSize: Dp = SmallIconButtonTokens.IconSize 1132 1133 @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET") 1134 @get:ExperimentalMaterial3ExpressiveApi 1135 @ExperimentalMaterial3ExpressiveApi 1136 /** Default container size for any medium icon button. */ 1137 val mediumIconSize: Dp = MediumIconButtonTokens.IconSize 1138 1139 @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET") 1140 @get:ExperimentalMaterial3ExpressiveApi 1141 @ExperimentalMaterial3ExpressiveApi 1142 /** Default size for any large icon button. */ 1143 val largeIconSize: Dp = LargeIconButtonTokens.IconSize 1144 1145 /** Default size for any xlarge icon button. */ 1146 @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET") 1147 @get:ExperimentalMaterial3ExpressiveApi 1148 @ExperimentalMaterial3ExpressiveApi 1149 val extraLargeIconSize: Dp = XLargeIconButtonTokens.IconSize 1150 1151 /** 1152 * Default container size for any extra small icon button. 1153 * 1154 * @param widthOption the width of the container 1155 */ 1156 @ExperimentalMaterial3ExpressiveApi extraSmallContainerSizenull1157 fun extraSmallContainerSize( 1158 widthOption: IconButtonWidthOption = IconButtonWidthOption.Uniform 1159 ): DpSize { 1160 val horizontalSpace = 1161 when (widthOption) { 1162 IconButtonWidthOption.Narrow -> 1163 XSmallIconButtonTokens.NarrowLeadingSpace + 1164 XSmallIconButtonTokens.NarrowTrailingSpace 1165 IconButtonWidthOption.Uniform -> 1166 XSmallIconButtonTokens.DefaultLeadingSpace + 1167 XSmallIconButtonTokens.DefaultLeadingSpace 1168 IconButtonWidthOption.Wide -> 1169 XSmallIconButtonTokens.WideLeadingSpace + 1170 XSmallIconButtonTokens.WideTrailingSpace 1171 else -> 0.dp 1172 } 1173 return DpSize( 1174 XSmallIconButtonTokens.IconSize + horizontalSpace, 1175 XSmallIconButtonTokens.ContainerHeight 1176 ) 1177 } 1178 1179 /** 1180 * Default container size for any small icon button. 1181 * 1182 * @param widthOption the width of the container 1183 */ 1184 @ExperimentalMaterial3ExpressiveApi smallContainerSizenull1185 fun smallContainerSize( 1186 widthOption: IconButtonWidthOption = IconButtonWidthOption.Uniform 1187 ): DpSize { 1188 val horizontalSpace = 1189 when (widthOption) { 1190 IconButtonWidthOption.Narrow -> 1191 SmallIconButtonTokens.NarrowLeadingSpace + 1192 SmallIconButtonTokens.NarrowTrailingSpace 1193 IconButtonWidthOption.Uniform -> 1194 SmallIconButtonTokens.DefaultLeadingSpace + 1195 SmallIconButtonTokens.DefaultLeadingSpace 1196 IconButtonWidthOption.Wide -> 1197 SmallIconButtonTokens.WideLeadingSpace + SmallIconButtonTokens.WideTrailingSpace 1198 else -> 0.dp 1199 } 1200 return DpSize( 1201 SmallIconButtonTokens.IconSize + horizontalSpace, 1202 SmallIconButtonTokens.ContainerHeight 1203 ) 1204 } 1205 1206 /** 1207 * Default container size for any medium icon button. 1208 * 1209 * @param widthOption the width of the container 1210 */ 1211 @ExperimentalMaterial3ExpressiveApi mediumContainerSizenull1212 fun mediumContainerSize( 1213 widthOption: IconButtonWidthOption = IconButtonWidthOption.Uniform 1214 ): DpSize { 1215 val horizontalSpace = 1216 when (widthOption) { 1217 IconButtonWidthOption.Narrow -> 1218 MediumIconButtonTokens.NarrowLeadingSpace + 1219 MediumIconButtonTokens.NarrowTrailingSpace 1220 IconButtonWidthOption.Uniform -> 1221 MediumIconButtonTokens.DefaultLeadingSpace + 1222 MediumIconButtonTokens.DefaultLeadingSpace 1223 IconButtonWidthOption.Wide -> 1224 MediumIconButtonTokens.WideLeadingSpace + 1225 MediumIconButtonTokens.WideTrailingSpace 1226 else -> 0.dp 1227 } 1228 return DpSize( 1229 MediumIconButtonTokens.IconSize + horizontalSpace, 1230 MediumIconButtonTokens.ContainerHeight 1231 ) 1232 } 1233 1234 /** 1235 * Default container size for any large icon button. 1236 * 1237 * @param widthOption the width of the container 1238 */ 1239 @ExperimentalMaterial3ExpressiveApi largeContainerSizenull1240 fun largeContainerSize( 1241 widthOption: IconButtonWidthOption = IconButtonWidthOption.Uniform 1242 ): DpSize { 1243 val horizontalSpace = 1244 when (widthOption) { 1245 IconButtonWidthOption.Narrow -> 1246 LargeIconButtonTokens.NarrowLeadingSpace + 1247 LargeIconButtonTokens.NarrowTrailingSpace 1248 IconButtonWidthOption.Uniform -> 1249 LargeIconButtonTokens.UniformLeadingSpace + 1250 LargeIconButtonTokens.UniformLeadingSpace 1251 IconButtonWidthOption.Wide -> 1252 LargeIconButtonTokens.WideLeadingSpace + LargeIconButtonTokens.WideTrailingSpace 1253 else -> 0.dp 1254 } 1255 return DpSize( 1256 LargeIconButtonTokens.IconSize + horizontalSpace, 1257 LargeIconButtonTokens.ContainerHeight 1258 ) 1259 } 1260 1261 /** 1262 * Default container size for any extra large icon button. 1263 * 1264 * @param widthOption the width of the container 1265 */ 1266 @ExperimentalMaterial3ExpressiveApi extraLargeContainerSizenull1267 fun extraLargeContainerSize( 1268 widthOption: IconButtonWidthOption = IconButtonWidthOption.Uniform 1269 ): DpSize { 1270 val horizontalSpace = 1271 when (widthOption) { 1272 IconButtonWidthOption.Narrow -> 1273 XLargeIconButtonTokens.NarrowLeadingSpace + 1274 XLargeIconButtonTokens.NarrowTrailingSpace 1275 IconButtonWidthOption.Uniform -> 1276 XLargeIconButtonTokens.DefaultLeadingSpace + 1277 XLargeIconButtonTokens.DefaultLeadingSpace 1278 IconButtonWidthOption.Wide -> 1279 XLargeIconButtonTokens.WideLeadingSpace + 1280 XLargeIconButtonTokens.WideTrailingSpace 1281 else -> 0.dp 1282 } 1283 return DpSize( 1284 XLargeIconButtonTokens.IconSize + horizontalSpace, 1285 XLargeIconButtonTokens.ContainerHeight 1286 ) 1287 } 1288 1289 /** Class that describes the different supported widths of the [IconButton]. */ 1290 @JvmInline 1291 value class IconButtonWidthOption private constructor(private val value: Int) { 1292 companion object { 1293 // TODO(b/342666275): update this kdoc with spec guidance 1294 /* 1295 * This configuration is recommended for small screens. 1296 */ 1297 val Narrow = IconButtonWidthOption(0) 1298 1299 /* 1300 * This configuration is recommended for medium width screens. 1301 */ 1302 val Uniform = IconButtonWidthOption(1) 1303 1304 /* 1305 * This configuration is recommended for wide screens. 1306 */ 1307 val Wide = IconButtonWidthOption(2) 1308 } 1309 toStringnull1310 override fun toString() = 1311 when (this) { 1312 Narrow -> "Narrow" 1313 Uniform -> "Uniform" 1314 Wide -> "Wide" 1315 else -> "Unknown" 1316 } 1317 } 1318 } 1319