1 /*
2  * Copyright 2021 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 package androidx.compose.material3
17 
18 import androidx.compose.animation.core.FiniteAnimationSpec
19 import androidx.compose.foundation.BorderStroke
20 import androidx.compose.foundation.background
21 import androidx.compose.foundation.clickable
22 import androidx.compose.foundation.interaction.Interaction
23 import androidx.compose.foundation.interaction.MutableInteractionSource
24 import androidx.compose.foundation.interaction.collectIsPressedAsState
25 import androidx.compose.foundation.layout.Box
26 import androidx.compose.foundation.layout.size
27 import androidx.compose.foundation.selection.toggleable
28 import androidx.compose.foundation.shape.CornerBasedShape
29 import androidx.compose.foundation.shape.RoundedCornerShape
30 import androidx.compose.material3.internal.childSemantics
31 import androidx.compose.material3.internal.rememberAnimatedShape
32 import androidx.compose.material3.tokens.MotionSchemeKeyTokens
33 import androidx.compose.runtime.Composable
34 import androidx.compose.runtime.CompositionLocalProvider
35 import androidx.compose.runtime.Immutable
36 import androidx.compose.runtime.Stable
37 import androidx.compose.runtime.State
38 import androidx.compose.runtime.getValue
39 import androidx.compose.runtime.key
40 import androidx.compose.runtime.remember
41 import androidx.compose.runtime.rememberUpdatedState
42 import androidx.compose.ui.Alignment
43 import androidx.compose.ui.Modifier
44 import androidx.compose.ui.draw.clip
45 import androidx.compose.ui.graphics.Color
46 import androidx.compose.ui.graphics.Shape
47 import androidx.compose.ui.graphics.takeOrElse
48 import androidx.compose.ui.semantics.Role
49 import androidx.compose.ui.semantics.role
50 import androidx.compose.ui.semantics.semantics
51 
52 /**
53  * [Material Design standard icon button](https://m3.material.io/components/icon-button/overview)
54  *
55  * Icon buttons help people take supplementary actions with a single tap. They’re used when a
56  * compact button is required, such as in a toolbar or image list.
57  *
58  * ![Standard icon button
59  * image](https://developer.android.com/images/reference/androidx/compose/material3/standard-icon-button.png)
60  *
61  * [content] should typically be an [Icon] (see [androidx.compose.material.icons.Icons]). If using a
62  * custom icon, note that the typical size for the internal icon is 24 x 24 dp. This icon button has
63  * an overall minimum touch target size of 48 x 48dp, to meet accessibility guidelines.
64  *
65  * Simple Usage
66  *
67  * @sample androidx.compose.material3.samples.IconButtonSample
68  *
69  * IconButton with a color tint
70  *
71  * @sample androidx.compose.material3.samples.TintedIconButtonSample
72  * @param onClick called when this icon button is clicked
73  * @param modifier the [Modifier] to be applied to this icon button
74  * @param enabled controls the enabled state of this icon button. When `false`, this component will
75  *   not respond to user input, and it will appear visually disabled and disabled to accessibility
76  *   services.
77  * @param colors [IconButtonColors] that will be used to resolve the colors used for this icon
78  *   button in different states. See [IconButtonDefaults.iconButtonVibrantColors].
79  * @param interactionSource an optional hoisted [MutableInteractionSource] for observing and
80  *   emitting [Interaction]s for this icon button. You can use this to change the icon button's
81  *   appearance or preview the icon button in different states. Note that if `null` is provided,
82  *   interactions will still happen internally.
83  * @param content the content of this icon button, typically an [Icon]
84  */
85 @Deprecated(
86     message = "Use overload with `shape`",
87     replaceWith =
88         ReplaceWith(
89             "IconButton(onClick, modifier, enabled, colors, interactionSource, shape, content)"
90         ),
91     level = DeprecationLevel.HIDDEN
92 )
93 @Composable
IconButtonnull94 fun IconButton(
95     onClick: () -> Unit,
96     modifier: Modifier = Modifier,
97     enabled: Boolean = true,
98     colors: IconButtonColors = IconButtonDefaults.iconButtonColors(),
99     interactionSource: MutableInteractionSource? = null,
100     content: @Composable () -> Unit
101 ) {
102     IconButton(
103         onClick,
104         modifier,
105         enabled,
106         colors,
107         interactionSource,
108         IconButtonDefaults.standardShape,
109         content
110     )
111 }
112 
113 /**
114  * [Material Design standard icon button](https://m3.material.io/components/icon-button/overview)
115  *
116  * Icon buttons help people take supplementary actions with a single tap. They’re used when a
117  * compact button is required, such as in a toolbar or image list.
118  *
119  * ![Standard icon button
120  * image](https://developer.android.com/images/reference/androidx/compose/material3/standard-icon-button.png)
121  *
122  * [content] should typically be an [Icon] (see [androidx.compose.material.icons.Icons]). If using a
123  * custom icon, note that the typical size for the internal icon is 24 x 24 dp. This icon button has
124  * an overall minimum touch target size of 48 x 48dp, to meet accessibility guidelines.
125  *
126  * Simple Usage
127  *
128  * @sample androidx.compose.material3.samples.IconButtonSample
129  *
130  * IconButton with a color tint
131  *
132  * @sample androidx.compose.material3.samples.TintedIconButtonSample
133  *
134  * Small-sized narrow round shape IconButton
135  *
136  * @sample androidx.compose.material3.samples.ExtraSmallNarrowSquareIconButtonsSample
137  *
138  * Medium / default size round-shaped icon button
139  *
140  * @sample androidx.compose.material3.samples.MediumRoundWideIconButtonSample
141  * @param onClick called when this icon button is clicked
142  * @param modifier the [Modifier] to be applied to this icon button
143  * @param enabled controls the enabled state of this icon button. When `false`, this component will
144  *   not respond to user input, and it will appear visually disabled and disabled to accessibility
145  *   services.
146  * @param colors [IconButtonColors] that will be used to resolve the colors used for this icon
147  *   button in different states. See [IconButtonDefaults.iconButtonVibrantColors] and
148  *   [IconButtonDefaults.iconButtonColors] .
149  * @param interactionSource an optional hoisted [MutableInteractionSource] for observing and
150  *   emitting [Interaction]s for this icon button. You can use this to change the icon button's
151  *   appearance or preview the icon button in different states. Note that if `null` is provided,
152  *   interactions will still happen internally.
153  * @param shape the [Shape] of this icon button.
154  * @param content the content of this icon button, typically an [Icon]
155  */
156 @OptIn(ExperimentalMaterial3ExpressiveApi::class)
157 @Composable
IconButtonnull158 fun IconButton(
159     onClick: () -> Unit,
160     modifier: Modifier = Modifier,
161     enabled: Boolean = true,
162     colors: IconButtonColors = IconButtonDefaults.iconButtonColors(),
163     interactionSource: MutableInteractionSource? = null,
164     shape: Shape = IconButtonDefaults.standardShape,
165     content: @Composable () -> Unit
166 ) =
167     IconButtonImpl(
168         onClick = onClick,
169         modifier = modifier,
170         enabled = enabled,
171         colors = colors,
172         interactionSource = interactionSource,
173         shape = shape,
174         content = content
175     )
176 
177 /**
178  * [Material Design standard icon button](https://m3.material.io/components/icon-button/overview)
179  *
180  * Icon buttons help people take supplementary actions with a single tap. They’re used when a
181  * compact button is required, such as in a toolbar or image list.
182  *
183  * ![Standard icon button
184  * image](https://developer.android.com/images/reference/androidx/compose/material3/small_icon_button_round_enabled_pressed.png)
185  *
186  * [content] should typically be an [Icon] (see [androidx.compose.material.icons.Icons]). If using a
187  * custom icon, note that the typical size for the internal icon is 24 x 24 dp. This icon button has
188  * an overall minimum touch target size of 48 x 48dp, to meet accessibility guidelines.
189  *
190  * Simple Usage
191  *
192  * @sample androidx.compose.material3.samples.IconButtonWithAnimatedShapeSample
193  * @param onClick called when this icon button is clicked
194  * @param shapes the [IconButtonShapes] that the icon button will morph between depending on the
195  *   user's interaction with the icon button.
196  * @param modifier the [Modifier] to be applied to this icon button
197  * @param enabled controls the enabled state of this icon button. When `false`, this component will
198  *   not respond to user input, and it will appear visually disabled and disabled to accessibility
199  *   services.
200  * @param colors [IconButtonColors] that will be used to resolve the colors used for this icon
201  *   button in different states. See [IconButtonDefaults.iconButtonVibrantColors] and
202  *   [IconButtonDefaults.iconButtonColors] .
203  * @param interactionSource an optional hoisted [MutableInteractionSource] for observing and
204  *   emitting [Interaction]s for this icon button. You can use this to change the icon button's
205  *   appearance or preview the icon button in different states. Note that if `null` is provided,
206  *   interactions will still happen internally.
207  * @param content the content of this icon button, typically an [Icon]
208  */
209 @ExperimentalMaterial3ExpressiveApi
210 @Composable
211 fun IconButton(
212     onClick: () -> Unit,
213     shapes: IconButtonShapes,
214     modifier: Modifier = Modifier,
215     enabled: Boolean = true,
216     colors: IconButtonColors = IconButtonDefaults.iconButtonColors(),
217     interactionSource: MutableInteractionSource? = null,
218     content: @Composable () -> Unit
219 ) {
220     @Suppress("NAME_SHADOWING")
221     val interactionSource = interactionSource ?: remember { MutableInteractionSource() }
222     IconButtonImpl(
223         modifier,
224         onClick = onClick,
225         enabled = enabled,
226         shape = shapeForInteraction(shapes, interactionSource),
227         colors = colors,
228         interactionSource = interactionSource,
229         content = content
230     )
231 }
232 
233 @ExperimentalMaterial3ExpressiveApi
234 @Composable
IconButtonImplnull235 private fun IconButtonImpl(
236     modifier: Modifier,
237     onClick: () -> Unit,
238     enabled: Boolean,
239     shape: Shape,
240     colors: IconButtonColors,
241     interactionSource: MutableInteractionSource?,
242     content: @Composable () -> Unit
243 ) {
244     @Suppress("NAME_SHADOWING")
245     val interactionSource = interactionSource ?: remember { MutableInteractionSource() }
246     Box(
247         modifier =
248             modifier
249                 .minimumInteractiveComponentSize()
250                 .size(IconButtonDefaults.smallContainerSize())
251                 .clip(shape)
252                 .background(color = colors.containerColor(enabled), shape = shape)
253                 .clickable(
254                     onClick = onClick,
255                     enabled = enabled,
256                     role = Role.Button,
257                     interactionSource = interactionSource,
258                     indication = ripple()
259                 )
260                 .childSemantics(),
261         contentAlignment = Alignment.Center
262     ) {
263         val contentColor = colors.contentColor(enabled)
264         CompositionLocalProvider(LocalContentColor provides contentColor, content = content)
265     }
266 }
267 
268 /**
269  * [Material Design standard icon toggle
270  * button](https://m3.material.io/components/icon-button/overview)
271  *
272  * Icon buttons help people take supplementary actions with a single tap. They’re used when a
273  * compact button is required, such as in a toolbar or image list.
274  *
275  * ![Standard icon toggle button
276  * image](https://developer.android.com/images/reference/androidx/compose/material3/standard-icon-toggle-button.png)
277  *
278  * [content] should typically be an [Icon] (see [androidx.compose.material.icons.Icons]). If using a
279  * custom icon, note that the typical size for the internal icon is 24 x 24 dp. This icon button has
280  * an overall minimum touch target size of 48 x 48dp, to meet accessibility guidelines.
281  *
282  * @sample androidx.compose.material3.samples.IconToggleButtonSample
283  * @param checked whether this icon button is toggled on or off
284  * @param onCheckedChange called when this icon button is clicked
285  * @param modifier the [Modifier] to be applied to this icon button
286  * @param enabled controls the enabled state of this icon button. When `false`, this component will
287  *   not respond to user input, and it will appear visually disabled and disabled to accessibility
288  *   services.
289  * @param colors [IconToggleButtonColors] that will be used to resolve the colors used for this icon
290  *   button in different states. See [IconButtonDefaults.iconToggleButtonVibrantColors].
291  * @param interactionSource an optional hoisted [MutableInteractionSource] for observing and
292  *   emitting [Interaction]s for this icon button. You can use this to change the icon button's
293  *   appearance or preview the icon button in different states. Note that if `null` is provided,
294  *   interactions will still happen internally.
295  * @param content the content of this icon button, typically an [Icon]
296  */
297 @Deprecated(
298     message = "Use overload with `shape`",
299     replaceWith =
300         ReplaceWith(
301             "IconToggleButton(checked, onCheckedChange, modifier, enabled, colors," +
302                 " interactionSource, shape, content)"
303         ),
304     level = DeprecationLevel.HIDDEN
305 )
306 @Composable
IconToggleButtonnull307 fun IconToggleButton(
308     checked: Boolean,
309     onCheckedChange: (Boolean) -> Unit,
310     modifier: Modifier = Modifier,
311     enabled: Boolean = true,
312     colors: IconToggleButtonColors = IconButtonDefaults.iconToggleButtonColors(),
313     interactionSource: MutableInteractionSource? = null,
314     content: @Composable () -> Unit
315 ) {
316     IconToggleButton(
317         checked,
318         onCheckedChange,
319         modifier,
320         enabled,
321         colors,
322         interactionSource,
323         IconButtonDefaults.standardShape,
324         content
325     )
326 }
327 
328 /**
329  * [Material Design standard icon toggle
330  * button](https://m3.material.io/components/icon-button/overview)
331  *
332  * Icon buttons help people take supplementary actions with a single tap. They’re used when a
333  * compact button is required, such as in a toolbar or image list.
334  *
335  * ![Standard icon toggle button
336  * image](https://developer.android.com/images/reference/androidx/compose/material3/standard-icon-toggle-button.png)
337  *
338  * [content] should typically be an [Icon] (see [androidx.compose.material.icons.Icons]). If using a
339  * custom icon, note that the typical size for the internal icon is 24 x 24 dp. This icon button has
340  * an overall minimum touch target size of 48 x 48dp, to meet accessibility guidelines.
341  *
342  * @sample androidx.compose.material3.samples.IconToggleButtonSample
343  * @param checked whether this icon button is toggled on or off
344  * @param onCheckedChange called when this icon button is clicked
345  * @param modifier the [Modifier] to be applied to this icon button
346  * @param enabled controls the enabled state of this icon button. When `false`, this component will
347  *   not respond to user input, and it will appear visually disabled and disabled to accessibility
348  *   services.
349  * @param colors [IconToggleButtonColors] that will be used to resolve the colors used for this icon
350  *   button in different states. See [IconButtonDefaults.iconToggleButtonVibrantColors] and
351  *   [IconButtonDefaults.iconToggleButtonColors].
352  * @param interactionSource an optional hoisted [MutableInteractionSource] for observing and
353  *   emitting [Interaction]s for this icon button. You can use this to change the icon button's
354  *   appearance or preview the icon button in different states. Note that if `null` is provided,
355  *   interactions will still happen internally.
356  * @param shape the [Shape] of this icon button.
357  * @param content the content of this icon button, typically an [Icon]
358  */
359 @OptIn(ExperimentalMaterial3ExpressiveApi::class)
360 @Composable
IconToggleButtonnull361 fun IconToggleButton(
362     checked: Boolean,
363     onCheckedChange: (Boolean) -> Unit,
364     modifier: Modifier = Modifier,
365     enabled: Boolean = true,
366     colors: IconToggleButtonColors = IconButtonDefaults.iconToggleButtonColors(),
367     interactionSource: MutableInteractionSource? = null,
368     shape: Shape = IconButtonDefaults.standardShape,
369     content: @Composable () -> Unit
370 ) =
371     IconToggleButtonImpl(
372         checked = checked,
373         onCheckedChange = onCheckedChange,
374         modifier = modifier,
375         enabled = enabled,
376         colors = colors,
377         interactionSource = interactionSource,
378         shape = shape,
379         content = content
380     )
381 
382 /**
383  * [Material Design standard icon toggle
384  * button](https://m3.material.io/components/icon-button/overview)
385  *
386  * Icon buttons help people take supplementary actions with a single tap. They’re used when a
387  * compact button is required, such as in a toolbar or image list.
388  *
389  * ![Standard icon toggle button
390  * image](https://developer.android.com/images/reference/androidx/compose/material3/small_icon_button_round_unselected_select.png)
391  *
392  * [content] should typically be an [Icon] (see [androidx.compose.material.icons.Icons]). If using a
393  * custom icon, note that the typical size for the internal icon is 24 x 24 dp. This icon button has
394  * an overall minimum touch target size of 48 x 48dp, to meet accessibility guidelines.
395  *
396  * @sample androidx.compose.material3.samples.IconToggleButtonWithAnimatedShapeSample
397  * @param checked whether this button is toggled on or off
398  * @param onCheckedChange called when this icon button is clicked
399  * @param shapes the [IconToggleButtonShapes] that the icon toggle button will morph between
400  *   depending on the user's interaction with this button.
401  * @param modifier the [Modifier] to be applied to this icon button
402  * @param enabled controls the enabled state of this icon button. When `false`, this component will
403  *   not respond to user input, and it will appear visually disabled and disabled to accessibility
404  *   services.
405  * @param colors [IconToggleButtonColors] that will be used to resolve the colors used for this icon
406  *   button in different states. See [IconButtonDefaults.iconToggleButtonVibrantColors].
407  * @param interactionSource an optional hoisted [MutableInteractionSource] for observing and
408  *   emitting [Interaction]s for this icon button. You can use this to change the icon button's
409  *   appearance or preview the icon button in different states. Note that if `null` is provided,
410  *   interactions will still happen internally.
411  * @param content the content of this icon button, typically an [Icon]
412  */
413 @ExperimentalMaterial3ExpressiveApi
414 @Composable
415 fun IconToggleButton(
416     checked: Boolean,
417     onCheckedChange: (Boolean) -> Unit,
418     shapes: IconToggleButtonShapes,
419     modifier: Modifier = Modifier,
420     enabled: Boolean = true,
421     colors: IconToggleButtonColors = IconButtonDefaults.iconToggleButtonVibrantColors(),
422     interactionSource: MutableInteractionSource? = null,
423     content: @Composable () -> Unit
424 ) {
425     @Suppress("NAME_SHADOWING")
426     val interactionSource = interactionSource ?: remember { MutableInteractionSource() }
427     IconToggleButtonImpl(
428         checked = checked,
429         onCheckedChange = onCheckedChange,
430         modifier = modifier,
431         enabled = enabled,
432         shape = shapeForInteraction(checked, shapes, interactionSource),
433         colors = colors,
434         interactionSource = interactionSource,
435         content = content
436     )
437 }
438 
439 @ExperimentalMaterial3ExpressiveApi
440 @Composable
IconToggleButtonImplnull441 private fun IconToggleButtonImpl(
442     checked: Boolean,
443     onCheckedChange: (Boolean) -> Unit,
444     modifier: Modifier = Modifier,
445     enabled: Boolean = true,
446     colors: IconToggleButtonColors = IconButtonDefaults.iconToggleButtonVibrantColors(),
447     interactionSource: MutableInteractionSource? = null,
448     shape: Shape = IconButtonDefaults.standardShape,
449     content: @Composable () -> Unit
450 ) {
451     @Suppress("NAME_SHADOWING")
452     val interactionSource = interactionSource ?: remember { MutableInteractionSource() }
453     Box(
454         modifier =
455             modifier
456                 .minimumInteractiveComponentSize()
457                 .size(IconButtonDefaults.smallContainerSize())
458                 .clip(shape)
459                 .background(color = colors.containerColor(enabled, checked).value)
460                 .toggleable(
461                     value = checked,
462                     onValueChange = onCheckedChange,
463                     enabled = enabled,
464                     role = Role.Checkbox,
465                     interactionSource = interactionSource,
466                     indication = ripple()
467                 ),
468         contentAlignment = Alignment.Center
469     ) {
470         val contentColor = colors.contentColor(enabled, checked).value
471         CompositionLocalProvider(LocalContentColor provides contentColor, content = content)
472     }
473 }
474 
475 /**
476  * [Material Design filled icon button](https://m3.material.io/components/icon-button/overview)
477  *
478  * Icon buttons help people take supplementary actions with a single tap. They’re used when a
479  * compact button is required, such as in a toolbar or image list.
480  *
481  * ![Filled icon button
482  * image](https://developer.android.com/images/reference/androidx/compose/material3/filled-icon-button.png)
483  *
484  * [content] should typically be an [Icon] (see [androidx.compose.material.icons.Icons]). If using a
485  * custom icon, note that the typical size for the internal icon is 24 x 24 dp. This icon button has
486  * an overall minimum touch target size of 48 x 48dp, to meet accessibility guidelines.
487  *
488  * Filled icon button sample:
489  *
490  * @sample androidx.compose.material3.samples.FilledIconButtonSample
491  * @param onClick called when this icon button is clicked
492  * @param modifier the [Modifier] to be applied to this icon button
493  * @param enabled controls the enabled state of this icon button. When `false`, this component will
494  *   not respond to user input, and it will appear visually disabled and disabled to accessibility
495  *   services.
496  * @param shape defines the shape of this icon button's container
497  * @param colors [IconButtonColors] that will be used to resolve the colors used for this icon
498  *   button in different states. See [IconButtonDefaults.filledIconButtonColors].
499  * @param interactionSource an optional hoisted [MutableInteractionSource] for observing and
500  *   emitting [Interaction]s for this icon button. You can use this to change the icon button's
501  *   appearance or preview the icon button in different states. Note that if `null` is provided,
502  *   interactions will still happen internally.
503  * @param content the content of this icon button, typically an [Icon]
504  */
505 @Composable
FilledIconButtonnull506 fun FilledIconButton(
507     onClick: () -> Unit,
508     modifier: Modifier = Modifier,
509     enabled: Boolean = true,
510     shape: Shape = IconButtonDefaults.filledShape,
511     colors: IconButtonColors = IconButtonDefaults.filledIconButtonColors(),
512     interactionSource: MutableInteractionSource? = null,
513     content: @Composable () -> Unit
514 ) =
515     SurfaceIconButton(
516         onClick = onClick,
517         modifier = modifier,
518         enabled = enabled,
519         shape = shape,
520         colors = colors,
521         border = null,
522         interactionSource = interactionSource,
523         content = content
524     )
525 
526 /**
527  * [Material Design filled icon button](https://m3.material.io/components/icon-button/overview)
528  *
529  * Icon buttons help people take supplementary actions with a single tap. They’re used when a
530  * compact button is required, such as in a toolbar or image list.
531  *
532  * ![Filled icon button
533  * image](https://developer.android.com/images/reference/androidx/compose/material3/small_filled_icon_button_round_enabled_pressed.png)
534  *
535  * [content] should typically be an [Icon] (see [androidx.compose.material.icons.Icons]). If using a
536  * custom icon, note that the typical size for the internal icon is 24 x 24 dp. This icon button has
537  * an overall minimum touch target size of 48 x 48dp, to meet accessibility guidelines.
538  *
539  * Filled icon button sample:
540  *
541  * @sample androidx.compose.material3.samples.FilledIconButtonWithAnimatedShapeSample
542  * @param onClick called when this icon button is clicked
543  * @param modifier the [Modifier] to be applied to this icon button
544  * @param enabled controls the enabled state of this icon button. When `false`, this component will
545  *   not respond to user input, and it will appear visually disabled and disabled to accessibility
546  *   services.
547  * @param shapes the [IconButtonShapes] that the icon button will morph between depending on the
548  *   user's interaction with the icon button.
549  * @param colors [IconButtonColors] that will be used to resolve the colors used for this icon
550  *   button in different states. See [IconButtonDefaults.filledIconButtonColors].
551  * @param interactionSource an optional hoisted [MutableInteractionSource] for observing and
552  *   emitting [Interaction]s for this icon button. You can use this to change the icon button's
553  *   appearance or preview the icon button in different states. Note that if `null` is provided,
554  *   interactions will still happen internally.
555  * @param content the content of this icon button, typically an [Icon]
556  */
557 @ExperimentalMaterial3ExpressiveApi
558 @Composable
559 fun FilledIconButton(
560     onClick: () -> Unit,
561     shapes: IconButtonShapes,
562     modifier: Modifier = Modifier,
563     enabled: Boolean = true,
564     colors: IconButtonColors = IconButtonDefaults.filledIconButtonColors(),
565     interactionSource: MutableInteractionSource? = null,
566     content: @Composable () -> Unit
567 ) =
568     SurfaceIconButton(
569         onClick = onClick,
570         modifier = modifier,
571         enabled = enabled,
572         shapes = shapes,
573         colors = colors,
574         border = null,
575         interactionSource = interactionSource,
576         content = content
577     )
578 
579 /**
580  * [Material Design filled icon button](https://m3.material.io/components/icon-button/overview)
581  *
582  * Icon buttons help people take supplementary actions with a single tap. They’re used when a
583  * compact button is required, such as in a toolbar or image list.
584  *
585  * ![Filled icon toggle button
586  * image](https://developer.android.com/images/reference/androidx/compose/material3/filled-icon-toggle-button.png)
587  *
588  * [content] should typically be an [Icon] (see [androidx.compose.material.icons.Icons]). If using a
589  * custom icon, note that the typical size for the internal icon is 24 x 24 dp. This icon button has
590  * an overall minimum touch target size of 48 x 48dp, to meet accessibility guidelines.
591  *
592  * Toggleable filled icon button sample:
593  *
594  * @sample androidx.compose.material3.samples.FilledIconToggleButtonSample
595  * @param checked whether this icon button is toggled on or off
596  * @param onCheckedChange called when this icon button is clicked
597  * @param modifier the [Modifier] to be applied to this icon button
598  * @param enabled controls the enabled state of this icon button. When `false`, this component will
599  *   not respond to user input, and it will appear visually disabled and disabled to accessibility
600  *   services.
601  * @param shape defines the shape of this icon button's container
602  * @param colors [IconToggleButtonColors] that will be used to resolve the colors used for this icon
603  *   button in different states. See [IconButtonDefaults.filledIconToggleButtonColors].
604  * @param interactionSource an optional hoisted [MutableInteractionSource] for observing and
605  *   emitting [Interaction]s for this icon button. You can use this to change the icon button's
606  *   appearance or preview the icon button in different states. Note that if `null` is provided,
607  *   interactions will still happen internally.
608  * @param content the content of this icon button, typically an [Icon]
609  */
610 @Composable
611 fun FilledIconToggleButton(
612     checked: Boolean,
613     onCheckedChange: (Boolean) -> Unit,
614     modifier: Modifier = Modifier,
615     enabled: Boolean = true,
616     shape: Shape = IconButtonDefaults.filledShape,
617     colors: IconToggleButtonColors = IconButtonDefaults.filledIconToggleButtonColors(),
618     interactionSource: MutableInteractionSource? = null,
619     content: @Composable () -> Unit
620 ) =
621     SurfaceIconToggleButton(
622         checked = checked,
623         onCheckedChange = onCheckedChange,
624         modifier = modifier.semantics { role = Role.Checkbox },
625         enabled = enabled,
626         shape = shape,
627         colors = colors,
628         border = null,
629         interactionSource = interactionSource,
630         content = content
631     )
632 
633 /**
634  * [Material Design filled icon toggle
635  * button](https://m3.material.io/components/icon-button/overview)
636  *
637  * Icon buttons help people take supplementary actions with a single tap. They’re used when a
638  * compact button is required, such as in a toolbar or image list.
639  *
640  * ![Filled icon toggle button
641  * image](https://developer.android.com/images/reference/androidx/compose/material3/small_filled_icon_button_round_unselected_select.png)
642  *
643  * [content] should typically be an [Icon] (see [androidx.compose.material.icons.Icons]). If using a
644  * custom icon, note that the typical size for the internal icon is 24 x 24 dp. This icon button has
645  * an overall minimum touch target size of 48 x 48dp, to meet accessibility guidelines.
646  *
647  * Toggleable filled icon button sample:
648  *
649  * @sample androidx.compose.material3.samples.FilledIconToggleButtonWithAnimatedShapeSample
650  * @param checked whether this icon button is toggled on or off
651  * @param onCheckedChange called when this icon button is clicked
652  * @param shapes the [IconButtonShapes] that the icon button will morph between depending on the
653  *   user's interaction with the icon button.
654  * @param modifier the [Modifier] to be applied to this icon button
655  * @param enabled controls the enabled state of this icon button. When `false`, this component will
656  *   not respond to user input, and it will appear visually disabled and disabled to accessibility
657  *   services.
658  * @param colors [IconToggleButtonColors] that will be used to resolve the colors used for this icon
659  *   button in different states. See [IconButtonDefaults.filledIconToggleButtonColors].
660  * @param interactionSource an optional hoisted [MutableInteractionSource] for observing and
661  *   emitting [Interaction]s for this icon button. You can use this to change the icon button's
662  *   appearance or preview the icon button in different states. Note that if `null` is provided,
663  *   interactions will still happen internally.
664  * @param content the content of this icon button, typically an [Icon]
665  */
666 @ExperimentalMaterial3ExpressiveApi
667 @Composable
FilledIconToggleButtonnull668 fun FilledIconToggleButton(
669     checked: Boolean,
670     onCheckedChange: (Boolean) -> Unit,
671     shapes: IconToggleButtonShapes,
672     modifier: Modifier = Modifier,
673     enabled: Boolean = true,
674     colors: IconToggleButtonColors = IconButtonDefaults.filledIconToggleButtonColors(),
675     interactionSource: MutableInteractionSource? = null,
676     content: @Composable () -> Unit
677 ) =
678     SurfaceIconToggleButton(
679         checked = checked,
680         onCheckedChange = onCheckedChange,
681         modifier = modifier.semantics { role = Role.Checkbox },
682         enabled = enabled,
683         shapes = shapes,
684         colors = colors,
685         border = null,
686         interactionSource = interactionSource,
687         content = content
688     )
689 
690 /**
691  * [Material Design filled tonal icon
692  * button](https://m3.material.io/components/icon-button/overview)
693  *
694  * Icon buttons help people take supplementary actions with a single tap. They’re used when a
695  * compact button is required, such as in a toolbar or image list.
696  *
697  * ![Filled tonal icon button
698  * image](https://developer.android.com/images/reference/androidx/compose/material3/filled-tonal-icon-button.png)
699  *
700  * A filled tonal icon button is a medium-emphasis icon button that is an alternative middle ground
701  * between the default [FilledIconButton] and [OutlinedIconButton]. They can be used in contexts
702  * where the lower-priority icon button requires slightly more emphasis than an outline would give.
703  *
704  * [content] should typically be an [Icon] (see [androidx.compose.material.icons.Icons]). If using a
705  * custom icon, note that the typical size for the internal icon is 24 x 24 dp. This icon button has
706  * an overall minimum touch target size of 48 x 48dp, to meet accessibility guidelines.
707  *
708  * Filled tonal icon button sample:
709  *
710  * @sample androidx.compose.material3.samples.FilledTonalIconButtonSample
711  * @param onClick called when this icon button is clicked
712  * @param modifier the [Modifier] to be applied to this icon button
713  * @param enabled controls the enabled state of this icon button. When `false`, this component will
714  *   not respond to user input, and it will appear visually disabled and disabled to accessibility
715  *   services.
716  * @param shape defines the shape of this icon button's container
717  * @param colors [IconButtonColors] that will be used to resolve the colors used for this icon
718  *   button in different states. See [IconButtonDefaults.filledIconButtonColors].
719  * @param interactionSource an optional hoisted [MutableInteractionSource] for observing and
720  *   emitting [Interaction]s for this icon button. You can use this to change the icon button's
721  *   appearance or preview the icon button in different states. Note that if `null` is provided,
722  *   interactions will still happen internally.
723  * @param content the content of this icon button, typically an [Icon]
724  */
725 @Composable
FilledTonalIconButtonnull726 fun FilledTonalIconButton(
727     onClick: () -> Unit,
728     modifier: Modifier = Modifier,
729     enabled: Boolean = true,
730     shape: Shape = IconButtonDefaults.filledShape,
731     colors: IconButtonColors = IconButtonDefaults.filledTonalIconButtonColors(),
732     interactionSource: MutableInteractionSource? = null,
733     content: @Composable () -> Unit
734 ) =
735     SurfaceIconButton(
736         onClick = onClick,
737         modifier = modifier,
738         enabled = enabled,
739         shape = shape,
740         colors = colors,
741         border = null,
742         interactionSource = interactionSource,
743         content = content
744     )
745 
746 /**
747  * [Material Design filled tonal icon
748  * button](https://m3.material.io/components/icon-button/overview)
749  *
750  * Icon buttons help people take supplementary actions with a single tap. They’re used when a
751  * compact button is required, such as in a toolbar or image list.
752  *
753  * ![Filled tonal icon button
754  * image](https://developer.android.com/images/reference/androidx/compose/material3/small_tonal_filled_icon_button_round_enabled_pressed.png)
755  *
756  * A filled tonal icon button is a medium-emphasis icon button that is an alternative middle ground
757  * between the default [FilledIconButton] and [OutlinedIconButton]. They can be used in contexts
758  * where the lower-priority icon button requires slightly more emphasis than an outline would give.
759  *
760  * [content] should typically be an [Icon] (see [androidx.compose.material.icons.Icons]). If using a
761  * custom icon, note that the typical size for the internal icon is 24 x 24 dp. This icon button has
762  * an overall minimum touch target size of 48 x 48dp, to meet accessibility guidelines.
763  *
764  * Filled tonal icon button sample:
765  *
766  * @sample androidx.compose.material3.samples.FilledTonalIconButtonWithAnimatedShapeSample
767  * @param onClick called when this icon button is clicked
768  * @param shapes the [IconButtonShapes] that the icon button will morph between depending on the
769  *   user's interaction with the icon button.
770  * @param modifier the [Modifier] to be applied to this icon button
771  * @param enabled controls the enabled state of this icon button. When `false`, this component will
772  *   not respond to user input, and it will appear visually disabled and disabled to accessibility
773  *   services.
774  * @param colors [IconButtonColors] that will be used to resolve the colors used for this icon
775  *   button in different states. See [IconButtonDefaults.filledIconButtonColors].
776  * @param interactionSource an optional hoisted [MutableInteractionSource] for observing and
777  *   emitting [Interaction]s for this icon button. You can use this to change the icon button's
778  *   appearance or preview the icon button in different states. Note that if `null` is provided,
779  *   interactions will still happen internally.
780  * @param content the content of this icon button, typically an [Icon]
781  */
782 @ExperimentalMaterial3ExpressiveApi
783 @Composable
784 fun FilledTonalIconButton(
785     onClick: () -> Unit,
786     shapes: IconButtonShapes,
787     modifier: Modifier = Modifier,
788     enabled: Boolean = true,
789     colors: IconButtonColors = IconButtonDefaults.filledTonalIconButtonColors(),
790     interactionSource: MutableInteractionSource? = null,
791     content: @Composable () -> Unit
792 ) =
793     SurfaceIconButton(
794         onClick = onClick,
795         modifier = modifier,
796         enabled = enabled,
797         shapes = shapes,
798         colors = colors,
799         border = null,
800         interactionSource = interactionSource,
801         content = content
802     )
803 
804 /**
805  * [Material Design filled tonal icon toggle
806  * button](https://m3.material.io/components/icon-button/overview)
807  *
808  * Icon buttons help people take supplementary actions with a single tap. They’re used when a
809  * compact button is required, such as in a toolbar or image list.
810  *
811  * ![Filled tonal icon toggle button
812  * image](https://developer.android.com/images/reference/androidx/compose/material3/filled-tonal-icon-toggle-button.png)
813  *
814  * A filled tonal toggle icon button is a medium-emphasis icon button that is an alternative middle
815  * ground between the default [FilledIconToggleButton] and [OutlinedIconToggleButton]. They can be
816  * used in contexts where the lower-priority icon button requires slightly more emphasis than an
817  * outline would give.
818  *
819  * [content] should typically be an [Icon] (see [androidx.compose.material.icons.Icons]). If using a
820  * custom icon, note that the typical size for the internal icon is 24 x 24 dp. This icon button has
821  * an overall minimum touch target size of 48 x 48dp, to meet accessibility guidelines.
822  *
823  * Toggleable filled tonal icon button sample:
824  *
825  * @sample androidx.compose.material3.samples.FilledTonalIconToggleButtonSample
826  * @param checked whether this icon button is toggled on or off
827  * @param onCheckedChange called when this icon button is clicked
828  * @param modifier the [Modifier] to be applied to this icon button
829  * @param enabled controls the enabled state of this icon button. When `false`, this component will
830  *   not respond to user input, and it will appear visually disabled and disabled to accessibility
831  *   services.
832  * @param shape defines the shape of this icon button's container
833  * @param colors [IconToggleButtonColors] that will be used to resolve the colors used for this icon
834  *   button in different states. See [IconButtonDefaults.filledIconToggleButtonColors].
835  * @param interactionSource an optional hoisted [MutableInteractionSource] for observing and
836  *   emitting [Interaction]s for this icon button. You can use this to change the icon button's
837  *   appearance or preview the icon button in different states. Note that if `null` is provided,
838  *   interactions will still happen internally.
839  * @param content the content of this icon button, typically an [Icon]
840  */
841 @Composable
842 fun FilledTonalIconToggleButton(
843     checked: Boolean,
844     onCheckedChange: (Boolean) -> Unit,
845     modifier: Modifier = Modifier,
846     enabled: Boolean = true,
847     shape: Shape = IconButtonDefaults.filledShape,
848     colors: IconToggleButtonColors = IconButtonDefaults.filledTonalIconToggleButtonColors(),
849     interactionSource: MutableInteractionSource? = null,
850     content: @Composable () -> Unit
851 ) =
852     SurfaceIconToggleButton(
853         checked = checked,
854         onCheckedChange = onCheckedChange,
855         modifier = modifier.semantics { role = Role.Checkbox },
856         enabled = enabled,
857         shape = shape,
858         colors = colors,
859         border = null,
860         interactionSource = interactionSource,
861         content = content
862     )
863 
864 /**
865  * [Material Design filled tonal icon toggle
866  * button](https://m3.material.io/components/icon-button/overview)
867  *
868  * Icon buttons help people take supplementary actions with a single tap. They’re used when a
869  * compact button is required, such as in a toolbar or image list.
870  *
871  * ![Filled tonal icon toggle button
872  * image](https://developer.android.com/images/reference/androidx/compose/material3/small_tonal_filled_icon_button_round_unselected_select.png)
873  *
874  * A filled tonal toggle icon button is a medium-emphasis icon button that is an alternative middle
875  * ground between the default [FilledIconToggleButton] and [OutlinedIconToggleButton]. They can be
876  * used in contexts where the lower-priority icon button requires slightly more emphasis than an
877  * outline would give.
878  *
879  * [content] should typically be an [Icon] (see [androidx.compose.material.icons.Icons]). If using a
880  * custom icon, note that the typical size for the internal icon is 24 x 24 dp. This icon button has
881  * an overall minimum touch target size of 48 x 48dp, to meet accessibility guidelines.
882  *
883  * Toggleable filled tonal icon button with animatable shape sample:
884  *
885  * @sample androidx.compose.material3.samples.FilledTonalIconToggleButtonWithAnimatedShapeSample
886  * @param checked whether this icon button is toggled on or off
887  * @param onCheckedChange called when this icon button is clicked
888  * @param shapes the [IconButtonShapes] that the icon button will morph between depending on the
889  *   user's interaction with the icon button.
890  * @param modifier the [Modifier] to be applied to this icon button
891  * @param enabled controls the enabled state of this icon button. When `false`, this component will
892  *   not respond to user input, and it will appear visually disabled and disabled to accessibility
893  *   services.
894  * @param colors [IconToggleButtonColors] that will be used to resolve the colors used for this icon
895  *   button in different states. See [IconButtonDefaults.filledIconToggleButtonColors].
896  * @param interactionSource an optional hoisted [MutableInteractionSource] for observing and
897  *   emitting [Interaction]s for this icon button. You can use this to change the icon button's
898  *   appearance or preview the icon button in different states. Note that if `null` is provided,
899  *   interactions will still happen internally.
900  * @param content the content of this icon button, typically an [Icon]
901  */
902 @ExperimentalMaterial3ExpressiveApi
903 @Composable
FilledTonalIconToggleButtonnull904 fun FilledTonalIconToggleButton(
905     checked: Boolean,
906     onCheckedChange: (Boolean) -> Unit,
907     shapes: IconToggleButtonShapes,
908     modifier: Modifier = Modifier,
909     enabled: Boolean = true,
910     colors: IconToggleButtonColors = IconButtonDefaults.filledTonalIconToggleButtonColors(),
911     interactionSource: MutableInteractionSource? = null,
912     content: @Composable () -> Unit
913 ) =
914     SurfaceIconToggleButton(
915         checked = checked,
916         onCheckedChange = onCheckedChange,
917         modifier = modifier.semantics { role = Role.Checkbox },
918         enabled = enabled,
919         shapes = shapes,
920         colors = colors,
921         border = null,
922         interactionSource = interactionSource,
923         content = content
924     )
925 
926 /**
927  * [Material Design outlined icon button](https://m3.material.io/components/icon-button/overview)
928  *
929  * Icon buttons help people take supplementary actions with a single tap. They’re used when a
930  * compact button is required, such as in a toolbar or image list.
931  *
932  * ![Outlined icon button
933  * image](https://developer.android.com/images/reference/androidx/compose/material3/outlined-icon-button.png)
934  *
935  * Icon buttons help people take supplementary actions with a single tap. They’re used when a
936  * compact button is required, such as in a toolbar or image list.
937  *
938  * Use this "contained" icon button when the component requires more visual separation from the
939  * background.
940  *
941  * [content] should typically be an [Icon] (see [androidx.compose.material.icons.Icons]). If using a
942  * custom icon, note that the typical size for the internal icon is 24 x 24 dp. The outlined icon
943  * button has an overall minimum touch target size of 48 x 48dp, to meet accessibility guidelines.
944  *
945  * @sample androidx.compose.material3.samples.OutlinedIconButtonSample
946  *
947  * Large-sized uniform rounded shape
948  *
949  * @sample androidx.compose.material3.samples.LargeRoundUniformOutlinedIconButtonSample
950  * @param onClick called when this icon button is clicked
951  * @param modifier the [Modifier] to be applied to this icon button
952  * @param enabled controls the enabled state of this icon button. When `false`, this component will
953  *   not respond to user input, and it will appear visually disabled and disabled to accessibility
954  *   services.
955  * @param shape defines the shape of this icon button's container and border (when [border] is not
956  *   null)
957  * @param colors [IconButtonColors] that will be used to resolve the colors used for this icon
958  *   button in different states. See [IconButtonDefaults.outlinedIconButtonVibrantColors] and
959  *   [IconButtonDefaults.outlinedIconButtonColors].
960  * @param border the border to draw around the container of this icon button. Pass `null` for no
961  *   border. See [IconButtonDefaults.outlinedIconButtonBorder] and
962  *   [IconButtonDefaults.outlinedIconButtonBorder].
963  * @param interactionSource an optional hoisted [MutableInteractionSource] for observing and
964  *   emitting [Interaction]s for this icon button. You can use this to change the icon button's
965  *   appearance or preview the icon button in different states. Note that if `null` is provided,
966  *   interactions will still happen internally.
967  * @param content the content of this icon button, typically an [Icon]
968  */
969 @Composable
OutlinedIconButtonnull970 fun OutlinedIconButton(
971     onClick: () -> Unit,
972     modifier: Modifier = Modifier,
973     enabled: Boolean = true,
974     shape: Shape = IconButtonDefaults.outlinedShape,
975     colors: IconButtonColors = IconButtonDefaults.outlinedIconButtonColors(),
976     border: BorderStroke? = IconButtonDefaults.outlinedIconButtonBorder(enabled),
977     interactionSource: MutableInteractionSource? = null,
978     content: @Composable () -> Unit
979 ) =
980     SurfaceIconButton(
981         onClick = onClick,
982         modifier = modifier,
983         enabled = enabled,
984         shape = shape,
985         colors = colors,
986         border = border,
987         interactionSource = interactionSource,
988         content = content
989     )
990 
991 /**
992  * [Material Design outlined icon button](https://m3.material.io/components/icon-button/overview)
993  *
994  * Icon buttons help people take supplementary actions with a single tap. They’re used when a
995  * compact button is required, such as in a toolbar or image list.
996  *
997  * ![Outlined icon button
998  * image](https://developer.android.com/images/reference/androidx/compose/material3/small_outlined_icon_button_round_enabled_pressed.png)
999  *
1000  * Icon buttons help people take supplementary actions with a single tap. They’re used when a
1001  * compact button is required, such as in a toolbar or image list.
1002  *
1003  * Use this "contained" icon button when the component requires more visual separation from the
1004  * background.
1005  *
1006  * [content] should typically be an [Icon] (see [androidx.compose.material.icons.Icons]). If using a
1007  * custom icon, note that the typical size for the internal icon is 24 x 24 dp. The outlined icon
1008  * button has an overall minimum touch target size of 48 x 48dp, to meet accessibility guidelines.
1009  *
1010  * Toggleable filled tonal icon button with animatable shape sample:
1011  *
1012  * @sample androidx.compose.material3.samples.OutlinedIconButtonWithAnimatedShapeSample
1013  * @param shapes the [IconButtonShapes] that the icon button will morph between depending on the
1014  *   user's interaction with the icon button.
1015  * @param onClick called when this icon button is clicked
1016  * @param modifier the [Modifier] to be applied to this icon button
1017  * @param enabled controls the enabled state of this icon button. When `false`, this component will
1018  *   not respond to user input, and it will appear visually disabled and disabled to accessibility
1019  *   services.
1020  * @param colors [IconButtonColors] that will be used to resolve the colors used for this icon
1021  *   button in different states. See [IconButtonDefaults.outlinedIconButtonVibrantColors] and
1022  *   [IconButtonDefaults.outlinedIconButtonColors].
1023  * @param border the border to draw around the container of this icon button. Pass `null` for no
1024  *   border. See [IconButtonDefaults.outlinedIconButtonBorder] and
1025  *   [IconButtonDefaults.outlinedIconButtonBorder].
1026  * @param interactionSource an optional hoisted [MutableInteractionSource] for observing and
1027  *   emitting [Interaction]s for this icon button. You can use this to change the icon button's
1028  *   appearance or preview the icon button in different states. Note that if `null` is provided,
1029  *   interactions will still happen internally.
1030  * @param content the content of this icon button, typically an [Icon]
1031  */
1032 @ExperimentalMaterial3ExpressiveApi
1033 @Composable
1034 fun OutlinedIconButton(
1035     onClick: () -> Unit,
1036     shapes: IconButtonShapes,
1037     modifier: Modifier = Modifier,
1038     enabled: Boolean = true,
1039     colors: IconButtonColors = IconButtonDefaults.outlinedIconButtonColors(),
1040     border: BorderStroke? = IconButtonDefaults.outlinedIconButtonBorder(enabled),
1041     interactionSource: MutableInteractionSource? = null,
1042     content: @Composable () -> Unit
1043 ) =
1044     SurfaceIconButton(
1045         onClick = onClick,
1046         modifier = modifier,
1047         enabled = enabled,
1048         shapes = shapes,
1049         colors = colors,
1050         border = border,
1051         interactionSource = interactionSource,
1052         content = content
1053     )
1054 
1055 /**
1056  * [Material Design outlined icon toggle
1057  * button](https://m3.material.io/components/icon-button/overview)
1058  *
1059  * Icon buttons help people take supplementary actions with a single tap. They’re used when a
1060  * compact button is required, such as in a toolbar or image list.
1061  *
1062  * ![Outlined icon toggle button
1063  * image](https://developer.android.com/images/reference/androidx/compose/material3/outlined-icon-toggle-button.png)
1064  *
1065  * [content] should typically be an [Icon] (see [androidx.compose.material.icons.Icons]). If using a
1066  * custom icon, note that the typical size for the internal icon is 24 x 24 dp. This icon button has
1067  * an overall minimum touch target size of 48 x 48dp, to meet accessibility guidelines.
1068  *
1069  * @sample androidx.compose.material3.samples.OutlinedIconToggleButtonSample
1070  * @param checked whether this icon button is toggled on or off
1071  * @param onCheckedChange called when this icon button is clicked
1072  * @param modifier the [Modifier] to be applied to this icon button
1073  * @param enabled controls the enabled state of this icon button. When `false`, this component will
1074  *   not respond to user input, and it will appear visually disabled and disabled to accessibility
1075  *   services.
1076  * @param shape defines the shape of this icon button's container and border (when [border] is not
1077  *   null)
1078  * @param colors [IconToggleButtonColors] that will be used to resolve the colors used for this icon
1079  *   button in different states. See [IconButtonDefaults.outlinedIconToggleButtonVibrantColors] and
1080  *   [IconButtonDefaults.outlinedIconToggleButtonColors].
1081  * @param border the border to draw around the container of this icon button. Pass `null` for no
1082  *   border. See [IconButtonDefaults.outlinedIconToggleButtonVibrantBorder] and
1083  *   [IconButtonDefaults.outlinedIconToggleButtonBorder].
1084  * @param interactionSource an optional hoisted [MutableInteractionSource] for observing and
1085  *   emitting [Interaction]s for this icon button. You can use this to change the icon button's
1086  *   appearance or preview the icon button in different states. Note that if `null` is provided,
1087  *   interactions will still happen internally.
1088  * @param content the content of this icon button, typically an [Icon]
1089  */
1090 @Composable
1091 fun OutlinedIconToggleButton(
1092     checked: Boolean,
1093     onCheckedChange: (Boolean) -> Unit,
1094     modifier: Modifier = Modifier,
1095     enabled: Boolean = true,
1096     shape: Shape = IconButtonDefaults.outlinedShape,
1097     colors: IconToggleButtonColors = IconButtonDefaults.outlinedIconToggleButtonColors(),
1098     border: BorderStroke? = IconButtonDefaults.outlinedIconToggleButtonBorder(enabled, checked),
1099     interactionSource: MutableInteractionSource? = null,
1100     content: @Composable () -> Unit
1101 ) =
1102     SurfaceIconToggleButton(
1103         checked = checked,
1104         onCheckedChange = onCheckedChange,
1105         modifier = modifier.semantics { role = Role.Checkbox },
1106         enabled = enabled,
1107         shape = shape,
1108         colors = colors,
1109         border = border,
1110         interactionSource = interactionSource,
1111         content = content
1112     )
1113 
1114 /**
1115  * [Material Design outlined icon toggle
1116  * button](https://m3.material.io/components/icon-button/overview)
1117  *
1118  * Icon buttons help people take supplementary actions with a single tap. They’re used when a
1119  * compact button is required, such as in a toolbar or image list.
1120  *
1121  * ![Outlined icon toggle button
1122  * image](https://developer.android.com/images/reference/androidx/compose/material3/small_outlined_icon_button_round_unselected_select.png)
1123  *
1124  * [content] should typically be an [Icon] (see [androidx.compose.material.icons.Icons]). If using a
1125  * custom icon, note that the typical size for the internal icon is 24 x 24 dp. This icon button has
1126  * an overall minimum touch target size of 48 x 48dp, to meet accessibility guidelines.
1127  *
1128  * @sample androidx.compose.material3.samples.OutlinedIconToggleButtonWithAnimatedShapeSample
1129  * @param checked whether this icon button is toggled on or off
1130  * @param onCheckedChange called when this icon button is clicked
1131  * @param shapes the [IconButtonShapes] that the icon button will morph between depending on the
1132  *   user's interaction with the icon button.
1133  * @param modifier the [Modifier] to be applied to this icon button
1134  * @param enabled controls the enabled state of this icon button. When `false`, this component will
1135  *   not respond to user input, and it will appear visually disabled and disabled to accessibility
1136  *   services.
1137  * @param colors [IconToggleButtonColors] that will be used to resolve the colors used for this icon
1138  *   button in different states. See [IconButtonDefaults.outlinedIconToggleButtonVibrantColors].
1139  * @param border the border to draw around the container of this icon button. Pass `null` for no
1140  *   border. See [IconButtonDefaults.outlinedIconToggleButtonVibrantBorder].
1141  * @param interactionSource an optional hoisted [MutableInteractionSource] for observing and
1142  *   emitting [Interaction]s for this icon button. You can use this to change the icon button's
1143  *   appearance or preview the icon button in different states. Note that if `null` is provided,
1144  *   interactions will still happen internally.
1145  * @param content the content of this icon button, typically an [Icon]
1146  */
1147 @ExperimentalMaterial3ExpressiveApi
1148 @Composable
OutlinedIconToggleButtonnull1149 fun OutlinedIconToggleButton(
1150     checked: Boolean,
1151     onCheckedChange: (Boolean) -> Unit,
1152     shapes: IconToggleButtonShapes,
1153     modifier: Modifier = Modifier,
1154     enabled: Boolean = true,
1155     colors: IconToggleButtonColors = IconButtonDefaults.outlinedIconToggleButtonVibrantColors(),
1156     border: BorderStroke? =
1157         IconButtonDefaults.outlinedIconToggleButtonVibrantBorder(enabled, checked),
1158     interactionSource: MutableInteractionSource? = null,
1159     content: @Composable () -> Unit
1160 ) =
1161     SurfaceIconToggleButton(
1162         checked = checked,
1163         onCheckedChange = onCheckedChange,
1164         modifier = modifier.semantics { role = Role.Checkbox },
1165         enabled = enabled,
1166         shapes = shapes,
1167         colors = colors,
1168         border = border,
1169         interactionSource = interactionSource,
1170         content = content
1171     )
1172 
1173 @OptIn(ExperimentalMaterial3ExpressiveApi::class)
1174 @Composable
SurfaceIconButtonnull1175 private fun SurfaceIconButton(
1176     onClick: () -> Unit,
1177     modifier: Modifier,
1178     enabled: Boolean,
1179     shape: Shape,
1180     colors: IconButtonColors,
1181     border: BorderStroke?,
1182     interactionSource: MutableInteractionSource?,
1183     content: @Composable () -> Unit
1184 ) =
1185     Surface(
1186         onClick = onClick,
1187         modifier = modifier.semantics { role = Role.Button },
1188         enabled = enabled,
1189         shape = shape,
1190         color = colors.containerColor(enabled),
1191         contentColor = colors.contentColor(enabled),
1192         border = border,
1193         interactionSource = interactionSource
<lambda>null1194     ) {
1195         Box(
1196             modifier = Modifier.size(IconButtonDefaults.smallContainerSize()),
1197             contentAlignment = Alignment.Center
1198         ) {
1199             content()
1200         }
1201     }
1202 
1203 @ExperimentalMaterial3ExpressiveApi
1204 @Composable
SurfaceIconButtonnull1205 private fun SurfaceIconButton(
1206     onClick: () -> Unit,
1207     modifier: Modifier,
1208     enabled: Boolean,
1209     shapes: IconButtonShapes,
1210     colors: IconButtonColors,
1211     border: BorderStroke?,
1212     interactionSource: MutableInteractionSource?,
1213     content: @Composable () -> Unit
1214 ) {
1215 
1216     @Suppress("NAME_SHADOWING")
1217     val interactionSource = interactionSource ?: remember { MutableInteractionSource() }
1218 
1219     SurfaceIconButton(
1220         onClick = onClick,
1221         modifier = modifier,
1222         enabled = enabled,
1223         shape = shapeForInteraction(shapes, interactionSource),
1224         colors = colors,
1225         border = border,
1226         interactionSource = interactionSource,
1227         content = content
1228     )
1229 }
1230 
1231 @OptIn(ExperimentalMaterial3ExpressiveApi::class)
1232 @Composable
SurfaceIconToggleButtonnull1233 private fun SurfaceIconToggleButton(
1234     checked: Boolean,
1235     onCheckedChange: (Boolean) -> Unit,
1236     modifier: Modifier,
1237     enabled: Boolean,
1238     shape: Shape,
1239     colors: IconToggleButtonColors,
1240     border: BorderStroke?,
1241     interactionSource: MutableInteractionSource?,
1242     content: @Composable () -> Unit
1243 ) {
1244     Surface(
1245         checked = checked,
1246         onCheckedChange = onCheckedChange,
1247         modifier = modifier.semantics { role = Role.Checkbox },
1248         enabled = enabled,
1249         shape = shape,
1250         color = colors.containerColor(enabled, checked).value,
1251         contentColor = colors.contentColor(enabled, checked).value,
1252         border = border,
1253         interactionSource = interactionSource
1254     ) {
1255         Box(
1256             modifier =
1257                 Modifier.size(
1258                     IconButtonDefaults.smallContainerSize(),
1259                 ),
1260             contentAlignment = Alignment.Center
1261         ) {
1262             content()
1263         }
1264     }
1265 }
1266 
1267 @ExperimentalMaterial3ExpressiveApi
1268 @Composable
SurfaceIconToggleButtonnull1269 private fun SurfaceIconToggleButton(
1270     checked: Boolean,
1271     onCheckedChange: (Boolean) -> Unit,
1272     modifier: Modifier,
1273     enabled: Boolean,
1274     shapes: IconToggleButtonShapes,
1275     colors: IconToggleButtonColors,
1276     border: BorderStroke?,
1277     interactionSource: MutableInteractionSource?,
1278     content: @Composable () -> Unit
1279 ) {
1280 
1281     @Suppress("NAME_SHADOWING")
1282     val interactionSource = interactionSource ?: remember { MutableInteractionSource() }
1283 
1284     SurfaceIconToggleButton(
1285         checked = checked,
1286         onCheckedChange = onCheckedChange,
1287         modifier = modifier,
1288         enabled = enabled,
1289         shape = shapeForInteraction(checked, shapes, interactionSource),
1290         colors = colors,
1291         border = border,
1292         interactionSource = interactionSource,
1293         content = content
1294     )
1295 }
1296 
1297 /**
1298  * Represents the container and content colors used in an icon button in different states.
1299  *
1300  * @param containerColor the container color of this icon button when enabled.
1301  * @param contentColor the content color of this icon button when enabled.
1302  * @param disabledContainerColor the container color of this icon button when not enabled.
1303  * @param disabledContentColor the content color of this icon button when not enabled.
1304  * @constructor create an instance with arbitrary colors.
1305  * - See [IconButtonDefaults.filledIconButtonColors] and
1306  *   [IconButtonDefaults.filledTonalIconButtonColors] for the default colors used in a
1307  *   [FilledIconButton].
1308  * - See [IconButtonDefaults.outlinedIconButtonVibrantColors] for the default colors used in an
1309  *   [OutlinedIconButton].
1310  */
1311 @Immutable
1312 class IconButtonColors(
1313     val containerColor: Color,
1314     val contentColor: Color,
1315     val disabledContainerColor: Color,
1316     val disabledContentColor: Color,
1317 ) {
1318 
1319     /**
1320      * Returns a copy of this IconButtonColors, optionally overriding some of the values. This uses
1321      * the Color.Unspecified to mean “use the value from the source”
1322      */
copynull1323     fun copy(
1324         containerColor: Color = this.containerColor,
1325         contentColor: Color = this.contentColor,
1326         disabledContainerColor: Color = this.disabledContainerColor,
1327         disabledContentColor: Color = this.disabledContentColor,
1328     ) =
1329         IconButtonColors(
1330             containerColor.takeOrElse { this.containerColor },
<lambda>null1331             contentColor.takeOrElse { this.contentColor },
<lambda>null1332             disabledContainerColor.takeOrElse { this.disabledContainerColor },
<lambda>null1333             disabledContentColor.takeOrElse { this.disabledContentColor },
1334         )
1335 
1336     /**
1337      * Represents the container color for this icon button, depending on [enabled].
1338      *
1339      * @param enabled whether the icon button is enabled
1340      */
1341     @Stable
containerColornull1342     internal fun containerColor(enabled: Boolean): Color =
1343         if (enabled) containerColor else disabledContainerColor
1344 
1345     /**
1346      * Represents the content color for this icon button, depending on [enabled].
1347      *
1348      * @param enabled whether the icon button is enabled
1349      */
1350     @Stable
1351     internal fun contentColor(enabled: Boolean): Color =
1352         if (enabled) contentColor else disabledContentColor
1353 
1354     override fun equals(other: Any?): Boolean {
1355         if (this === other) return true
1356         if (other == null || other !is IconButtonColors) return false
1357 
1358         if (containerColor != other.containerColor) return false
1359         if (contentColor != other.contentColor) return false
1360         if (disabledContainerColor != other.disabledContainerColor) return false
1361         if (disabledContentColor != other.disabledContentColor) return false
1362 
1363         return true
1364     }
1365 
hashCodenull1366     override fun hashCode(): Int {
1367         var result = containerColor.hashCode()
1368         result = 31 * result + contentColor.hashCode()
1369         result = 31 * result + disabledContainerColor.hashCode()
1370         result = 31 * result + disabledContentColor.hashCode()
1371 
1372         return result
1373     }
1374 }
1375 
1376 /**
1377  * Represents the container and content colors used in a toggleable icon button in different states.
1378  *
1379  * @param containerColor the container color of this icon button when enabled.
1380  * @param contentColor the content color of this icon button when enabled.
1381  * @param disabledContainerColor the container color of this icon button when not enabled.
1382  * @param disabledContentColor the content color of this icon button when not enabled.
1383  * @param checkedContainerColor the container color of this icon button when checked.
1384  * @param checkedContentColor the content color of this icon button when checked.
1385  * @constructor create an instance with arbitrary colors.
1386  * - See [IconButtonDefaults.filledIconToggleButtonColors] and
1387  *   [IconButtonDefaults.filledTonalIconToggleButtonColors] for the default colors used in a
1388  *   [FilledIconButton].
1389  * - See [IconButtonDefaults.outlinedIconToggleButtonVibrantColors] for the default colors used in a
1390  *   toggleable [OutlinedIconButton].
1391  */
1392 @Immutable
1393 class IconToggleButtonColors(
1394     val containerColor: Color,
1395     val contentColor: Color,
1396     val disabledContainerColor: Color,
1397     val disabledContentColor: Color,
1398     val checkedContainerColor: Color,
1399     val checkedContentColor: Color,
1400 ) {
1401 
1402     /**
1403      * Returns a copy of this IconToggleButtonColors, optionally overriding some of the values. This
1404      * uses the Color.Unspecified to mean “use the value from the source”
1405      */
copynull1406     fun copy(
1407         containerColor: Color = this.containerColor,
1408         contentColor: Color = this.contentColor,
1409         disabledContainerColor: Color = this.disabledContainerColor,
1410         disabledContentColor: Color = this.disabledContentColor,
1411         checkedContainerColor: Color = this.checkedContainerColor,
1412         checkedContentColor: Color = this.checkedContentColor
1413     ) =
1414         IconToggleButtonColors(
1415             containerColor.takeOrElse { this.containerColor },
<lambda>null1416             contentColor.takeOrElse { this.contentColor },
<lambda>null1417             disabledContainerColor.takeOrElse { this.disabledContainerColor },
<lambda>null1418             disabledContentColor.takeOrElse { this.disabledContentColor },
<lambda>null1419             checkedContainerColor.takeOrElse { this.checkedContainerColor },
<lambda>null1420             checkedContentColor.takeOrElse { this.checkedContentColor }
1421         )
1422 
1423     /**
1424      * Represents the container color for this icon button, depending on [enabled] and [checked].
1425      *
1426      * @param enabled whether the icon button is enabled
1427      * @param checked whether the icon button is checked
1428      */
1429     @Composable
containerColornull1430     internal fun containerColor(enabled: Boolean, checked: Boolean): State<Color> {
1431         val target =
1432             when {
1433                 !enabled -> disabledContainerColor
1434                 !checked -> containerColor
1435                 else -> checkedContainerColor
1436             }
1437         return rememberUpdatedState(target)
1438     }
1439 
1440     /**
1441      * Represents the content color for this icon button, depending on [enabled] and [checked].
1442      *
1443      * @param enabled whether the icon button is enabled
1444      * @param checked whether the icon button is checked
1445      */
1446     @Composable
contentColornull1447     internal fun contentColor(enabled: Boolean, checked: Boolean): State<Color> {
1448         val target =
1449             when {
1450                 !enabled -> disabledContentColor
1451                 !checked -> contentColor
1452                 else -> checkedContentColor
1453             }
1454         return rememberUpdatedState(target)
1455     }
1456 
equalsnull1457     override fun equals(other: Any?): Boolean {
1458         if (this === other) return true
1459         if (other == null || other !is IconToggleButtonColors) return false
1460 
1461         if (containerColor != other.containerColor) return false
1462         if (contentColor != other.contentColor) return false
1463         if (disabledContainerColor != other.disabledContainerColor) return false
1464         if (disabledContentColor != other.disabledContentColor) return false
1465         if (checkedContainerColor != other.checkedContainerColor) return false
1466         if (checkedContentColor != other.checkedContentColor) return false
1467 
1468         return true
1469     }
1470 
hashCodenull1471     override fun hashCode(): Int {
1472         var result = containerColor.hashCode()
1473         result = 31 * result + contentColor.hashCode()
1474         result = 31 * result + disabledContainerColor.hashCode()
1475         result = 31 * result + disabledContentColor.hashCode()
1476         result = 31 * result + checkedContainerColor.hashCode()
1477         result = 31 * result + checkedContentColor.hashCode()
1478 
1479         return result
1480     }
1481 }
1482 
1483 /**
1484  * The shapes that will be used in icon buttons. Icon button will morph between these shapes
1485  * depending on the interaction of the icon button, assuming all of the shapes are
1486  * [CornerBasedShape]s.
1487  *
1488  * @property shape is the unchecked shape.
1489  * @property pressedShape is the pressed shape.
1490  */
1491 @ExperimentalMaterial3ExpressiveApi
1492 class IconButtonShapes(val shape: Shape, val pressedShape: Shape = shape) {
1493 
1494     /** Returns a copy of this IconButtonShapes, optionally overriding some of the values. */
copynull1495     fun copy(
1496         shape: Shape? = this.shape,
1497         pressedShape: Shape? = this.pressedShape,
1498     ) =
1499         IconButtonShapes(
1500             shape = shape.takeOrElse { this.shape },
<lambda>null1501             pressedShape = pressedShape.takeOrElse { this.pressedShape },
1502         )
1503 
takeOrElsenull1504     internal fun Shape?.takeOrElse(block: () -> Shape): Shape = this ?: block()
1505 
1506     override fun equals(other: Any?): Boolean {
1507         if (this === other) return true
1508         if (other == null || other !is IconButtonShapes) return false
1509 
1510         if (shape != other.shape) return false
1511         if (pressedShape != other.pressedShape) return false
1512 
1513         return true
1514     }
1515 
hashCodenull1516     override fun hashCode(): Int {
1517         var result = shape.hashCode()
1518         result = 31 * result + pressedShape.hashCode()
1519 
1520         return result
1521     }
1522 }
1523 
1524 /**
1525  * The shapes that will be used in toggle buttons. Toggle button will morph between these three
1526  * shapes depending on the interaction of the toggle button, assuming all of the shapes are
1527  * [CornerBasedShape]s.
1528  *
1529  * @property shape is the unchecked shape.
1530  * @property pressedShape is the pressed shape.
1531  * @property checkedShape is the checked shape.
1532  */
1533 @ExperimentalMaterial3ExpressiveApi
1534 class IconToggleButtonShapes(
1535     val shape: Shape,
1536     val pressedShape: Shape = shape,
1537     val checkedShape: Shape = shape
1538 ) {
1539 
1540     /** Returns a copy of this IconButtonShapes, optionally overriding some of the values. */
copynull1541     fun copy(
1542         shape: Shape? = this.shape,
1543         pressedShape: Shape? = this.pressedShape,
1544         checkedShape: Shape? = this.checkedShape
1545     ) =
1546         IconToggleButtonShapes(
1547             shape = shape.takeOrElse { this.shape },
<lambda>null1548             pressedShape = pressedShape.takeOrElse { this.pressedShape },
<lambda>null1549             checkedShape = checkedShape.takeOrElse { this.checkedShape }
1550         )
1551 
takeOrElsenull1552     internal fun Shape?.takeOrElse(block: () -> Shape): Shape = this ?: block()
1553 
1554     override fun equals(other: Any?): Boolean {
1555         if (this === other) return true
1556         if (other == null || other !is IconToggleButtonShapes) return false
1557 
1558         if (shape != other.shape) return false
1559         if (pressedShape != other.pressedShape) return false
1560         if (checkedShape != other.checkedShape) return false
1561 
1562         return true
1563     }
1564 
hashCodenull1565     override fun hashCode(): Int {
1566         var result = shape.hashCode()
1567         result = 31 * result + pressedShape.hashCode()
1568         result = 31 * result + checkedShape.hashCode()
1569 
1570         return result
1571     }
1572 }
1573 
1574 @ExperimentalMaterial3ExpressiveApi
1575 @Composable
shapeForInteractionnull1576 private fun shapeForInteraction(
1577     shapes: IconButtonShapes,
1578     interactionSource: MutableInteractionSource,
1579 ): Shape {
1580     if (shapes.isStatic) {
1581         return shapes.shape
1582     }
1583     // TODO Load the motionScheme tokens from the component tokens file
1584     // MotionSchemeKeyTokens.DefaultEffects is intentional here to prevent
1585     // any bounce in this component.
1586     val defaultAnimationSpec = MotionSchemeKeyTokens.DefaultEffects.value<Float>()
1587     val pressed by interactionSource.collectIsPressedAsState()
1588 
1589     return shapeByInteraction(shapes, pressed, defaultAnimationSpec)
1590 }
1591 
1592 @ExperimentalMaterial3ExpressiveApi
1593 @Composable
shapeForInteractionnull1594 private fun shapeForInteraction(
1595     checked: Boolean,
1596     shapes: IconToggleButtonShapes,
1597     interactionSource: MutableInteractionSource,
1598 ): Shape {
1599     if (shapes.isStatic) {
1600         return shapes.shape
1601     }
1602     // TODO Load the motionScheme tokens from the component tokens file
1603     // MotionSchemeKeyTokens.DefaultEffects is intentional here to prevent
1604     // any bounce in this component.
1605     val defaultAnimationSpec = MotionSchemeKeyTokens.DefaultEffects.value<Float>()
1606     val pressed by interactionSource.collectIsPressedAsState()
1607 
1608     return shapeByInteraction(shapes, pressed, checked, defaultAnimationSpec)
1609 }
1610 
1611 @OptIn(ExperimentalMaterial3ExpressiveApi::class)
1612 internal val IconButtonShapes.isCornerBasedShape: Boolean
1613     get() = shape is RoundedCornerShape && pressedShape is CornerBasedShape
1614 
1615 @OptIn(ExperimentalMaterial3ExpressiveApi::class)
1616 internal val IconButtonShapes.isStatic: Boolean
1617     get() = shape === pressedShape
1618 
1619 @OptIn(ExperimentalMaterial3ExpressiveApi::class)
1620 internal val IconToggleButtonShapes.isCornerBasedShape: Boolean
1621     get() =
1622         shape is RoundedCornerShape &&
1623             pressedShape is CornerBasedShape &&
1624             checkedShape is CornerBasedShape
1625 
1626 @OptIn(ExperimentalMaterial3ExpressiveApi::class)
1627 internal val IconToggleButtonShapes.isStatic: Boolean
1628     get() = shape === pressedShape && shape === checkedShape
1629 
1630 @ExperimentalMaterial3ExpressiveApi
1631 @Composable
shapeByInteractionnull1632 private fun shapeByInteraction(
1633     shapes: IconButtonShapes,
1634     pressed: Boolean,
1635     animationSpec: FiniteAnimationSpec<Float>
1636 ): Shape {
1637     val shape =
1638         if (pressed) {
1639             shapes.pressedShape
1640         } else shapes.shape
1641 
1642     if (shapes.isCornerBasedShape) {
1643         return key(shapes) { rememberAnimatedShape(shape as RoundedCornerShape, animationSpec) }
1644     }
1645     return shape
1646 }
1647 
1648 @ExperimentalMaterial3ExpressiveApi
1649 @Composable
shapeByInteractionnull1650 private fun shapeByInteraction(
1651     shapes: IconToggleButtonShapes,
1652     pressed: Boolean,
1653     checked: Boolean,
1654     animationSpec: FiniteAnimationSpec<Float>
1655 ): Shape {
1656     val shape =
1657         if (pressed) {
1658             shapes.pressedShape
1659         } else if (checked) {
1660             shapes.checkedShape
1661         } else shapes.shape
1662 
1663     if (shapes.isCornerBasedShape) {
1664         return key(shapes) { rememberAnimatedShape(shape as RoundedCornerShape, animationSpec) }
1665     }
1666     return shape
1667 }
1668