1 /*
<lambda>null2  * 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.wear.compose.material
17 
18 import androidx.compose.foundation.interaction.Interaction
19 import androidx.compose.foundation.interaction.MutableInteractionSource
20 import androidx.compose.foundation.layout.BoxScope
21 import androidx.compose.foundation.layout.IntrinsicSize
22 import androidx.compose.foundation.layout.PaddingValues
23 import androidx.compose.foundation.layout.RowScope
24 import androidx.compose.foundation.layout.defaultMinSize
25 import androidx.compose.foundation.layout.height
26 import androidx.compose.material.icons.materialIcon
27 import androidx.compose.material.icons.materialPath
28 import androidx.compose.runtime.Composable
29 import androidx.compose.runtime.Immutable
30 import androidx.compose.runtime.Stable
31 import androidx.compose.runtime.State
32 import androidx.compose.runtime.rememberUpdatedState
33 import androidx.compose.ui.Modifier
34 import androidx.compose.ui.draw.paint
35 import androidx.compose.ui.graphics.Brush
36 import androidx.compose.ui.graphics.Color
37 import androidx.compose.ui.graphics.PathFillType
38 import androidx.compose.ui.graphics.Shape
39 import androidx.compose.ui.graphics.compositeOver
40 import androidx.compose.ui.graphics.painter.BrushPainter
41 import androidx.compose.ui.graphics.painter.Painter
42 import androidx.compose.ui.graphics.vector.ImageVector
43 import androidx.compose.ui.layout.ContentScale
44 import androidx.compose.ui.platform.LocalLayoutDirection
45 import androidx.compose.ui.unit.Dp
46 import androidx.compose.ui.unit.LayoutDirection
47 import androidx.compose.ui.unit.dp
48 
49 /**
50  * A [ToggleChip] is a specialized type of [Chip] that includes a slot for a bi-state toggle control
51  * such as a toggle or checkbox. This overload provides suitable accessibility semantics for a
52  * toggleable control like [Checkbox] and [Switch]. For selectable controls like [RadioButton], use
53  * [SelectableChip] in order to provide the correct semantics for accessibility.
54  *
55  * The Wear Material [ToggleChip] offers four slots and a specific layout for an application icon, a
56  * label, a secondaryLabel and toggle control. The application icon and secondaryLabel are optional.
57  * The items are laid out in a row with the optional icon at the start, a column containing the two
58  * label slots in the middle and a slot for the toggle control at the end.
59  *
60  * The [ToggleChip] is Stadium shaped and has a max height designed to take no more than two lines
61  * of text of [Typography.button] style. With localisation and/or large font sizes, the [ToggleChip]
62  * height adjusts to accommodate the contents. The label and secondary label should be consistently
63  * aligned.
64  *
65  * The recommended set of [ToggleChipColors] can be obtained from [ToggleChipDefaults], e.g.
66  * [ToggleChipDefaults.toggleChipColors].
67  *
68  * Chips can be enabled or disabled. A disabled chip will not respond to click events.
69  *
70  * Example of a [ToggleChip] with an icon, label and secondary label (defaults to switch toggle):
71  *
72  * @sample androidx.wear.compose.material.samples.ToggleChipWithSwitch
73  *
74  * For more information, see the
75  * [Toggle Chips](https://developer.android.com/training/wearables/components/toggle-chips) guide.
76  *
77  * @param checked Boolean flag indicating whether this button is currently checked.
78  * @param onCheckedChange Callback to be invoked when this button's checked status changes
79  * @param label A slot for providing the chip's main label. The contents are expected to be text
80  *   which is "start" aligned.
81  * @param toggleControl A slot for providing the chip's toggle control. Two built-in types of toggle
82  *   control are supported - [Checkbox] and [Switch]. For [RadioButton], use [SelectableChip], in
83  *   order to provide the correct semantics for accessibility.
84  * @param modifier Modifier to be applied to the chip
85  * @param appIcon An optional slot for providing an icon to indicate the purpose of the chip. The
86  *   contents are expected to be a horizontally and vertically centre aligned icon of size
87  *   [ToggleChipDefaults.IconSize]. In order to correctly render when the Chip is not enabled the
88  *   icon must set its alpha value to [LocalContentAlpha].
89  * @param secondaryLabel A slot for providing the chip's secondary label. The contents are expected
90  *   to be text which is "start" aligned if there is an icon preset and "start" or "center" aligned
91  *   if not. label and secondaryLabel contents should be consistently aligned.
92  * @param colors [ToggleChipColors] that will be used to resolve the background and content color
93  *   for this chip in different states, see [ToggleChipDefaults.toggleChipColors].
94  * @param enabled Controls the enabled state of the chip. When `false`, this chip will not be
95  *   clickable
96  * @param interactionSource an optional hoisted [MutableInteractionSource] for observing and
97  *   emitting [Interaction]s for this chip's "toggleable" tap area. You can use this to change the
98  *   chip's appearance or preview the chip in different states. Note that if `null` is provided,
99  *   interactions will still happen internally.
100  * @param contentPadding The spacing values to apply internally between the container and the
101  *   content
102  * @param shape Defines the chip's shape. It is strongly recommended to use the default as this
103  *   shape is a key characteristic of the Wear Material Theme
104  */
105 @Composable
106 public fun ToggleChip(
107     checked: Boolean,
108     onCheckedChange: (Boolean) -> Unit,
109     label: @Composable RowScope.() -> Unit,
110     toggleControl: @Composable () -> Unit,
111     modifier: Modifier = Modifier,
112     appIcon: @Composable (BoxScope.() -> Unit)? = null,
113     secondaryLabel: @Composable (RowScope.() -> Unit)? = null,
114     colors: ToggleChipColors = ToggleChipDefaults.toggleChipColors(),
115     enabled: Boolean = true,
116     interactionSource: MutableInteractionSource? = null,
117     contentPadding: PaddingValues = ToggleChipDefaults.ContentPadding,
118     shape: Shape = MaterialTheme.shapes.large,
119 ): Unit =
120     androidx.wear.compose.materialcore.ToggleButton(
121         checked = checked,
122         onCheckedChange = onCheckedChange,
123         label =
124             provideScopeContent(
125                 contentColor = colors.contentColor(enabled = enabled, checked),
126                 textStyle = MaterialTheme.typography.button,
127                 content = label
128             ),
129         toggleControl =
130             provideContent(
131                 contentColor = colors.toggleControlColor(enabled, checked),
132                 content = toggleControl
133             ),
134         selectionControl = null,
135         modifier =
136             modifier
137                 .defaultMinSize(minHeight = ToggleChipDefaults.Height)
138                 .height(IntrinsicSize.Min),
139         icon =
140             provideNullableScopeContent(
141                 contentColor = colors.contentColor(enabled = enabled, checked = checked),
142                 content = appIcon
143             ),
144         secondaryLabel =
145             provideNullableScopeContent(
146                 contentColor = colors.secondaryContentColor(enabled = enabled, checked),
147                 textStyle = MaterialTheme.typography.caption2,
148                 content = secondaryLabel
149             ),
150         background = { isEnabled, isChecked ->
151             val painter = colors.background(enabled = isEnabled, checked = isChecked).value
152 
153             Modifier.paint(painter = painter, contentScale = ContentScale.Crop)
154         },
155         enabled = enabled,
156         interactionSource = interactionSource,
157         contentPadding = contentPadding,
158         shape = shape,
159         toggleControlHeight = TOGGLE_CONTROL_HEIGHT,
160         toggleControlWidth = TOGGLE_CONTROL_WIDTH,
161         labelSpacerSize = 0.dp,
162         toggleControlSpacing = TOGGLE_CONTROL_SPACING,
163         iconSpacing = ICON_SPACING,
164         ripple = ripple()
165     )
166 
167 /**
168  * A [SplitToggleChip] is a specialized type of [Chip] that includes a slot for a toggle control,
169  * such as a toggle or checkbox. The [SplitToggleChip] differs from the [ToggleChip] by having two
170  * "tappable" areas, one clickable and one toggleable.
171  *
172  * This overload provides suitable accessibility semantics for a toggleable control like [Checkbox]
173  * and [Switch]. For selectable controls like [RadioButton], use [SelectableChip] instead.
174  *
175  * The Wear Material [SplitToggleChip] offers three slots and a specific layout for a label,
176  * secondaryLabel and toggle control. The secondaryLabel is optional. The items are laid out with a
177  * column containing the two label slots and a slot for the toggle control at the end.
178  *
179  * A [SplitToggleChip] has two tappable areas, one tap area for the labels and another for the
180  * toggle control. The [onClick] listener will be associated with the main body of the split toggle
181  * chip with the [onCheckedChange] listener associated with the toggle control area only.
182  *
183  * For a split toggle chip the background of the tappable background area behind the toggle control
184  * will have a visual effect applied to provide a "divider" between the two tappable areas.
185  *
186  * The [SplitToggleChip] is Stadium shaped and has a max height designed to take no more than two
187  * lines of text of [Typography.button] style. With localisation and/or large font sizes, the
188  * [SplitToggleChip] height adjusts to accommodate the contents. The label and secondary label
189  * should be consistently aligned.
190  *
191  * The recommended set of [SplitToggleChipColors] can be obtained from [ToggleChipDefaults], e.g.
192  * [ToggleChipDefaults.splitToggleChipColors].
193  *
194  * Chips can be enabled or disabled. A disabled chip will not respond to click events.
195  *
196  * Example of a [SplitToggleChip] with a label and the toggle control changed to checkbox:
197  *
198  * @sample androidx.wear.compose.material.samples.SplitToggleChipWithCheckbox
199  *
200  * For more information, see the
201  * [Toggle Chips](https://developer.android.com/training/wearables/components/toggle-chips) guide.
202  *
203  * @param checked Boolean flag indicating whether this button is currently checked.
204  * @param onCheckedChange Callback to be invoked when this buttons checked status is changed.
205  * @param label A slot for providing the chip's main label. The contents are expected to be text
206  *   which is "start" aligned.
207  * @param onClick Click listener called when the user clicks the main body of the chip, the area
208  *   behind the labels.
209  * @param toggleControl A slot for providing the chip's toggle controls(s). Two built-in types of
210  *   toggle control are supported, see [Checkbox] and [Switch]. For [RadioButton], use
211  *   [SelectableChip] instead. [ImageVector]s can be obtained from [ToggleChipDefaults.switchIcon],
212  *   [ToggleChipDefaults.radioIcon] and [ToggleChipDefaults.checkboxIcon]. In order to correctly
213  *   render when the Chip is not enabled the icon must set its alpha value to [LocalContentAlpha].
214  * @param modifier Modifier to be applied to the chip
215  * @param secondaryLabel A slot for providing the chip's secondary label. The contents are expected
216  *   to be "start" or "center" aligned. label and secondaryLabel contents should be consistently
217  *   aligned.
218  * @param colors [SplitToggleChipColors] that will be used to resolve the background and content
219  *   color for this chip in different states, see [ToggleChipDefaults.splitToggleChipColors].
220  * @param enabled Controls the enabled state of the chip. When `false`, this chip will not be
221  *   clickable
222  * @param checkedInteractionSource an optional hoisted [MutableInteractionSource] for observing and
223  *   emitting [Interaction]s for this chip's "toggleable" tap area. You can use this to change the
224  *   chip's appearance or preview the chip in different states. Note that if `null` is provided,
225  *   interactions will still happen internally.
226  * @param clickInteractionSource an optional hoisted [MutableInteractionSource] for observing and
227  *   emitting [Interaction]s for this chip's "clickable" tap area. You can use this to change the
228  *   chip's appearance or preview the chip in different states. Note that if `null` is provided,
229  *   interactions will still happen internally.
230  * @param contentPadding The spacing values to apply internally between the container and the
231  *   content
232  * @param shape Defines the chip's shape. It is strongly recommended to use the default as this
233  *   shape is a key characteristic of the Wear Material Theme
234  */
235 @Composable
SplitToggleChipnull236 public fun SplitToggleChip(
237     checked: Boolean,
238     onCheckedChange: (Boolean) -> Unit,
239     label: @Composable RowScope.() -> Unit,
240     onClick: () -> Unit,
241     toggleControl: @Composable BoxScope.() -> Unit,
242     modifier: Modifier = Modifier,
243     secondaryLabel: @Composable (RowScope.() -> Unit)? = null,
244     colors: SplitToggleChipColors = ToggleChipDefaults.splitToggleChipColors(),
245     enabled: Boolean = true,
246     checkedInteractionSource: MutableInteractionSource? = null,
247     clickInteractionSource: MutableInteractionSource? = null,
248     contentPadding: PaddingValues = ToggleChipDefaults.ContentPadding,
249     shape: Shape = MaterialTheme.shapes.large,
250 ): Unit =
251     androidx.wear.compose.materialcore.SplitToggleButton(
252         checked = checked,
253         onCheckedChange = onCheckedChange,
254         label =
255             provideScopeContent(
256                 contentColor = colors.contentColor(enabled = enabled),
257                 textStyle = MaterialTheme.typography.button,
258                 content = label
259             ),
260         onClick = onClick,
261         toggleControl =
262             provideScopeContent(
263                 contentColor = colors.toggleControlColor(enabled = enabled, checked = checked),
264                 content = toggleControl
265             ),
266         selectionControl = null,
267         modifier =
268             modifier
269                 .defaultMinSize(minHeight = ToggleChipDefaults.Height)
270                 .height(IntrinsicSize.Min),
271         secondaryLabel =
272             provideNullableScopeContent(
273                 contentColor = colors.secondaryContentColor(enabled = enabled),
274                 textStyle = MaterialTheme.typography.caption2,
275                 content = secondaryLabel
276             ),
277         backgroundColor = { isEnabled, _ -> colors.backgroundColor(enabled = isEnabled) },
isEnablednull278         splitBackgroundColor = { isEnabled, isChecked ->
279             colors.splitBackgroundOverlay(enabled = isEnabled, checked = isChecked)
280         },
281         enabled = enabled,
282         checkedInteractionSource = checkedInteractionSource,
283         clickInteractionSource = clickInteractionSource,
284         onClickLabel = null,
285         contentPadding = contentPadding,
286         shape = shape,
287         labelSpacerSize = 0.dp,
288         ripple = ripple()
289     )
290 
291 /** Represents the background and content colors used in [ToggleChip]s in different states. */
292 @Stable
293 public interface ToggleChipColors {
294     /**
295      * Represents the background treatment for this chip, depending on the [enabled] and [checked]
296      * properties. Backgrounds are typically a linear gradient when the chip is checked and solid
297      * when it is not.
298      *
299      * @param enabled Whether the chip is enabled
300      * @param checked Whether the chip is currently checked or unchecked
301      */
backgroundnull302     @Composable public fun background(enabled: Boolean, checked: Boolean): State<Painter>
303 
304     /**
305      * Represents the content color for this chip, depending on the [enabled] and [checked]
306      * properties.
307      *
308      * @param enabled Whether the chip is enabled
309      * @param checked Whether the chip is currently checked or unchecked
310      */
311     @Composable public fun contentColor(enabled: Boolean, checked: Boolean): State<Color>
312 
313     /**
314      * Represents the secondary content color for this chip, depending on the [enabled] and
315      * [checked] properties.
316      *
317      * @param enabled Whether the chip is enabled
318      * @param checked Whether the chip is currently checked or unchecked
319      */
320     @Composable public fun secondaryContentColor(enabled: Boolean, checked: Boolean): State<Color>
321 
322     /**
323      * Represents the color for the toggle control content for this chip, depending on the [enabled]
324      * and [checked] properties.
325      *
326      * @param enabled Whether the chip is enabled
327      * @param checked Whether the chip is currently checked or unchecked
328      */
329     @Composable public fun toggleControlColor(enabled: Boolean, checked: Boolean): State<Color>
330 }
331 
332 /** Represents the background and content colors used in [SplitToggleChip]s in different states. */
333 @Stable
334 public interface SplitToggleChipColors {
335     /**
336      * Represents the background color for this chip, depending on whether it is [enabled].
337      *
338      * @param enabled Whether the chip is enabled
339      */
340     @Composable public fun backgroundColor(enabled: Boolean): State<Color>
341 
342     /**
343      * Represents the content color for this chip, depending on whether it is [enabled]
344      *
345      * @param enabled Whether the chip is enabled
346      */
347     @Composable public fun contentColor(enabled: Boolean): State<Color>
348 
349     /**
350      * Represents the secondary content color for this chip, depending on whether it is [enabled]
351      *
352      * @param enabled Whether the chip is enabled
353      */
354     @Composable public fun secondaryContentColor(enabled: Boolean): State<Color>
355 
356     /**
357      * Represents the color for the toggle control content for this chip, depending on the [enabled]
358      * and [checked] properties.
359      *
360      * @param enabled Whether the chip is enabled
361      * @param checked Whether the chip is currently checked or unchecked
362      */
363     @Composable public fun toggleControlColor(enabled: Boolean, checked: Boolean): State<Color>
364 
365     /**
366      * Represents the overlay to apply to a split background SplitToggleChip to distinguish between
367      * the two tappable areas. The overlay will be applied to "lighten" the background of area under
368      * the toggle control, depending on the [enabled] and [checked] properties.
369      *
370      * @param enabled Whether the chip is enabled
371      * @param checked Whether the chip is currently checked or unchecked
372      */
373     @Composable public fun splitBackgroundOverlay(enabled: Boolean, checked: Boolean): State<Color>
374 }
375 
376 /** Contains the default values used by [ToggleChip]s and [SplitToggleChip]s */
377 public object ToggleChipDefaults {
378 
379     /**
380      * Creates a [ToggleChipColors] for use in a [ToggleChip]. [ToggleChip]s are expected to have a
381      * linear gradient background when checked, similar to a
382      * [ChipDefaults.gradientBackgroundChipColors] and a solid neutral background when not checked
383      * (similar to a [ChipDefaults.secondaryChipColors])
384      *
385      * @param checkedStartBackgroundColor The background color used at the start of the gradient of
386      *   a [ToggleChip] when enabled and checked.
387      * @param checkedEndBackgroundColor The background color used at the end of the gradient of a
388      *   [ToggleChip] when enabled and checked.
389      * @param checkedContentColor The content color of a [ToggleChip] when enabled and checked.
390      * @param checkedSecondaryContentColor The secondary content color of this [ToggleChip] when
391      *   enabled and checked, used for secondaryLabel content
392      * @param checkedToggleControlColor The toggle control color of this [ToggleChip] when enabled
393      *   and checked, used for toggleControl content
394      * @param uncheckedStartBackgroundColor The background color used at the start of the gradient
395      *   of a [ToggleChip] when enabled and unchecked.
396      * @param uncheckedEndBackgroundColor The background color used at the end of the gradient of a
397      *   [ToggleChip] when enabled and unchecked.
398      * @param uncheckedContentColor The content color of a [ToggleChip] when enabled and checked.
399      * @param uncheckedSecondaryContentColor The secondary content color of this [ToggleChip] when
400      *   enabled and unchecked, used for secondaryLabel content
401      * @param uncheckedToggleControlColor The toggle control color of this [ToggleChip] when enabled
402      *   and unchecked.
403      * @param gradientDirection Whether the chips gradient should be start to end (indicated by
404      *   [LayoutDirection.Ltr]) or end to start (indicated by [LayoutDirection.Rtl]).
405      */
406     @Composable
toggleChipColorsnull407     public fun toggleChipColors(
408         checkedStartBackgroundColor: Color =
409             MaterialTheme.colors.surface
410                 .copy(alpha = 0f)
411                 .compositeOver(MaterialTheme.colors.surface),
412         checkedEndBackgroundColor: Color =
413             MaterialTheme.colors.primary
414                 .copy(alpha = 0.5f)
415                 .compositeOver(MaterialTheme.colors.surface),
416         checkedContentColor: Color = MaterialTheme.colors.onSurface,
417         checkedSecondaryContentColor: Color = MaterialTheme.colors.onSurfaceVariant,
418         checkedToggleControlColor: Color = MaterialTheme.colors.secondary,
419         uncheckedStartBackgroundColor: Color = MaterialTheme.colors.surface,
420         uncheckedEndBackgroundColor: Color = uncheckedStartBackgroundColor,
421         uncheckedContentColor: Color = contentColorFor(checkedEndBackgroundColor),
422         uncheckedSecondaryContentColor: Color = uncheckedContentColor,
423         uncheckedToggleControlColor: Color = uncheckedContentColor,
424         gradientDirection: LayoutDirection = LocalLayoutDirection.current
425     ): ToggleChipColors {
426         val checkedBackgroundColors: List<Color>
427         val disabledCheckedBackgroundColors: List<Color>
428         if (gradientDirection == LayoutDirection.Ltr) {
429             checkedBackgroundColors = listOf(checkedStartBackgroundColor, checkedEndBackgroundColor)
430             disabledCheckedBackgroundColors =
431                 listOf(
432                     checkedStartBackgroundColor.copy(alpha = ContentAlpha.disabled),
433                     checkedEndBackgroundColor.copy(alpha = ContentAlpha.disabled)
434                 )
435         } else {
436             checkedBackgroundColors = listOf(checkedEndBackgroundColor, checkedStartBackgroundColor)
437             disabledCheckedBackgroundColors =
438                 listOf(
439                     checkedEndBackgroundColor.copy(alpha = ContentAlpha.disabled),
440                     checkedStartBackgroundColor.copy(alpha = ContentAlpha.disabled),
441                 )
442         }
443         val uncheckedBackgroundColors: List<Color>
444         val disabledUncheckedBackgroundColors: List<Color>
445         if (gradientDirection == LayoutDirection.Ltr) {
446             uncheckedBackgroundColors =
447                 listOf(uncheckedStartBackgroundColor, uncheckedEndBackgroundColor)
448             disabledUncheckedBackgroundColors =
449                 listOf(
450                     uncheckedStartBackgroundColor.copy(alpha = ContentAlpha.disabled),
451                     uncheckedEndBackgroundColor.copy(alpha = ContentAlpha.disabled)
452                 )
453         } else {
454             uncheckedBackgroundColors =
455                 listOf(uncheckedEndBackgroundColor, uncheckedStartBackgroundColor)
456             disabledUncheckedBackgroundColors =
457                 listOf(
458                     uncheckedEndBackgroundColor.copy(alpha = ContentAlpha.disabled),
459                     uncheckedStartBackgroundColor.copy(alpha = ContentAlpha.disabled),
460                 )
461         }
462 
463         return DefaultToggleChipColors(
464             checkedBackgroundPainter = BrushPainter(Brush.linearGradient(checkedBackgroundColors)),
465             checkedContentColor = checkedContentColor,
466             checkedSecondaryContentColor = checkedSecondaryContentColor,
467             checkedIconColor = checkedToggleControlColor,
468             uncheckedBackgroundPainter =
469                 BrushPainter(Brush.linearGradient(uncheckedBackgroundColors)),
470             uncheckedContentColor = uncheckedContentColor,
471             uncheckedSecondaryContentColor = uncheckedSecondaryContentColor,
472             uncheckedIconColor = uncheckedToggleControlColor,
473             disabledCheckedBackgroundPainter =
474                 BrushPainter(Brush.linearGradient(disabledCheckedBackgroundColors)),
475             disabledCheckedContentColor = checkedContentColor.copy(alpha = ContentAlpha.disabled),
476             disabledCheckedSecondaryContentColor =
477                 checkedSecondaryContentColor.copy(alpha = ContentAlpha.disabled),
478             disabledCheckedIconColor =
479                 checkedToggleControlColor.copy(alpha = ContentAlpha.disabled),
480             disabledUncheckedBackgroundPainter =
481                 BrushPainter(Brush.linearGradient(disabledUncheckedBackgroundColors)),
482             disabledUncheckedContentColor =
483                 uncheckedContentColor.copy(alpha = ContentAlpha.disabled),
484             disabledUncheckedSecondaryContentColor =
485                 uncheckedSecondaryContentColor.copy(alpha = ContentAlpha.disabled),
486             disabledUncheckedIconColor =
487                 uncheckedToggleControlColor.copy(alpha = ContentAlpha.disabled),
488         )
489     }
490 
491     /**
492      * Creates a [SplitToggleChipColors] for use in a [SplitToggleChip].
493      *
494      * @param backgroundColor The background color of this [SplitToggleChip] when enabled
495      * @param contentColor The content color of this [SplitToggleChip] when enabled.
496      * @param secondaryContentColor The secondary content color of this[SplitToggleChip] when
497      *   enabled
498      * @param checkedToggleControlColor The toggle control content color of this [SplitToggleChip]
499      *   when enabled.
500      * @param uncheckedToggleControlColor The toggle control content color of this [SplitToggleChip]
501      *   when enabled.
502      * @param splitBackgroundOverlayColor The color to use to lighten/distinguish the background
503      *   behind the ToggleControl for a split background chip. A split background chip has two
504      *   tappable areas, one for the main body of the chip and one for area around the toggle
505      *   control icon.
506      */
507     @Composable
splitToggleChipColorsnull508     public fun splitToggleChipColors(
509         backgroundColor: Color = MaterialTheme.colors.surface,
510         contentColor: Color = MaterialTheme.colors.onSurface,
511         secondaryContentColor: Color = MaterialTheme.colors.onSurfaceVariant,
512         checkedToggleControlColor: Color = MaterialTheme.colors.secondary,
513         uncheckedToggleControlColor: Color = contentColor,
514         splitBackgroundOverlayColor: Color = Color.White.copy(alpha = 0.05f),
515     ): SplitToggleChipColors {
516         return DefaultSplitToggleChipColors(
517             backgroundColor = backgroundColor,
518             contentColor = contentColor,
519             secondaryContentColor = secondaryContentColor,
520             checkedIconColor = checkedToggleControlColor,
521             checkedSplitBackgroundOverlay = splitBackgroundOverlayColor,
522             uncheckedIconColor = uncheckedToggleControlColor,
523             uncheckedSplitBackgroundOverlay = splitBackgroundOverlayColor,
524             disabledBackgroundColor = backgroundColor.copy(alpha = ContentAlpha.disabled),
525             disabledContentColor = contentColor.copy(alpha = ContentAlpha.disabled),
526             disabledSecondaryContentColor =
527                 secondaryContentColor.copy(alpha = ContentAlpha.disabled),
528             disabledCheckedIconColor =
529                 checkedToggleControlColor.copy(alpha = ContentAlpha.disabled),
530             disabledCheckedSplitBackgroundOverlay = splitBackgroundOverlayColor,
531             disabledUncheckedIconColor =
532                 uncheckedToggleControlColor.copy(alpha = ContentAlpha.disabled),
533             disabledUncheckedSplitBackgroundOverlay = splitBackgroundOverlayColor,
534         )
535     }
536 
537     /** The Wear Material UX recommended color to use for an unchecked switch icon. */
538     public val SwitchUncheckedIconColor: Color
539         @Composable get() = MaterialTheme.colors.onSurface.copy(0.6f)
540 
541     private val ChipHorizontalPadding = 14.dp
542     private val ChipVerticalPadding = 6.dp
543 
544     /** The default content padding used by [ToggleChip] and [SplitToggleChip] */
545     public val ContentPadding: PaddingValues =
546         PaddingValues(
547             start = ChipHorizontalPadding,
548             top = ChipVerticalPadding,
549             end = ChipHorizontalPadding,
550             bottom = ChipVerticalPadding
551         )
552 
553     /**
554      * Creates switch style toggle [ImageVector]s for use in the toggleControl slot of a
555      * [ToggleChip] or [SplitToggleChip]. Depending on [checked] will return either an 'on'
556      * (checked) or 'off' (unchecked) switch icon.
557      *
558      * @param checked whether the [ToggleChip] or [SplitToggleChip] is currently 'on' (checked/true)
559      *   or 'off' (unchecked/false)
560      */
switchIconnull561     public fun switchIcon(
562         checked: Boolean,
563     ): ImageVector = if (checked) SwitchOn else SwitchOff
564 
565     /**
566      * Creates a radio button style toggle [ImageVector]s for use in the toggleControl slot of a
567      * [ToggleChip] or [SplitToggleChip]. Depending on [checked] will return either an 'on'
568      * (checked) or 'off' (unchecked) radio button icon.
569      *
570      * @param checked whether the [ToggleChip] or [SplitToggleChip] is currently 'on' (checked/true)
571      *   or 'off' (unchecked/false)
572      */
573     public fun radioIcon(
574         checked: Boolean,
575     ): ImageVector = if (checked) RadioOn else RadioOff
576 
577     /**
578      * Creates checkbox style toggle [ImageVector]s for use in the toggleControl slot of a
579      * [ToggleChip] or [SplitToggleChip]. Depending on [checked] will return either an 'on'
580      * (ticked/checked) or 'off' (unticked/unchecked) checkbox image.
581      *
582      * @param checked whether the [ToggleChip] or [SplitToggleChip] is currently 'on' (checked/true)
583      *   or 'off' (unchecked/false)
584      */
585     public fun checkboxIcon(
586         checked: Boolean,
587     ): ImageVector = if (checked) CheckboxOn else CheckboxOff
588 
589     /**
590      * The default height applied for the [ToggleChip] or [SplitToggleChip]. Note that you can
591      * override it by applying Modifier.heightIn directly on [ToggleChip] or [SplitToggleChip].
592      */
593     public val Height: Dp = 52.dp
594 
595     /**
596      * The default size of app icons or toggle controls when used inside a [ToggleChip] or
597      * [SplitToggleChip].
598      */
599     public val IconSize: Dp = 24.dp
600 
601     private val SwitchOn: ImageVector
602         get() {
603             if (_switchOn != null) {
604                 return _switchOn!!
605             }
606             _switchOn =
607                 materialIcon(name = "SwitchOn") {
608                     materialPath(fillAlpha = 0.38f, strokeAlpha = 0.38f) {
609                         moveTo(5.0f, 7.0f)
610                         lineTo(19.0f, 7.0f)
611                         arcTo(5.0f, 5.0f, 0.0f, false, true, 24.0f, 12.0f)
612                         lineTo(24.0f, 12.0f)
613                         arcTo(5.0f, 5.0f, 0.0f, false, true, 19.0f, 17.0f)
614                         lineTo(5.0f, 17.0f)
615                         arcTo(5.0f, 5.0f, 0.0f, false, true, 0.0f, 12.0f)
616                         lineTo(0.0f, 12.0f)
617                         arcTo(5.0f, 5.0f, 0.0f, false, true, 5.0f, 7.0f)
618                         close()
619                     }
620                     materialPath(pathFillType = PathFillType.EvenOdd) {
621                         moveTo(17.0f, 19.0f)
622                         curveTo(20.866f, 19.0f, 24.0f, 15.866f, 24.0f, 12.0f)
623                         curveTo(24.0f, 8.134f, 20.866f, 5.0f, 17.0f, 5.0f)
624                         curveTo(13.134f, 5.0f, 10.0f, 8.134f, 10.0f, 12.0f)
625                         curveTo(10.0f, 15.866f, 13.134f, 19.0f, 17.0f, 19.0f)
626                         close()
627                     }
628                 }
629             return _switchOn!!
630         }
631 
632     private var _switchOn: ImageVector? = null
633 
634     private val SwitchOff: ImageVector
635         get() {
636             if (_switchOff != null) {
637                 return _switchOff!!
638             }
639             _switchOff =
<lambda>null640                 materialIcon(name = "SwitchOff") {
641                     materialPath(fillAlpha = 0.38f, strokeAlpha = 0.38f) {
642                         moveTo(5.0f, 7.0f)
643                         lineTo(19.0f, 7.0f)
644                         arcTo(5.0f, 5.0f, 0.0f, false, true, 24.0f, 12.0f)
645                         lineTo(24.0f, 12.0f)
646                         arcTo(5.0f, 5.0f, 0.0f, false, true, 19.0f, 17.0f)
647                         lineTo(5.0f, 17.0f)
648                         arcTo(5.0f, 5.0f, 0.0f, false, true, 0.0f, 12.0f)
649                         lineTo(0.0f, 12.0f)
650                         arcTo(5.0f, 5.0f, 0.0f, false, true, 5.0f, 7.0f)
651                         close()
652                     }
653                     materialPath(pathFillType = PathFillType.EvenOdd) {
654                         moveTo(7.0f, 19.0f)
655                         curveTo(10.866f, 19.0f, 14.0f, 15.866f, 14.0f, 12.0f)
656                         curveTo(14.0f, 8.134f, 10.866f, 5.0f, 7.0f, 5.0f)
657                         curveTo(3.134f, 5.0f, 0.0f, 8.134f, 0.0f, 12.0f)
658                         curveTo(0.0f, 15.866f, 3.134f, 19.0f, 7.0f, 19.0f)
659                         close()
660                     }
661                 }
662             return _switchOff!!
663         }
664 
665     private var _switchOff: ImageVector? = null
666 
667     public val RadioOn: ImageVector
668         get() {
669             if (_radioOn != null) {
670                 return _radioOn!!
671             }
672             _radioOn =
<lambda>null673                 materialIcon(name = "RadioOn") {
674                     materialPath {
675                         moveTo(12.0f, 2.0f)
676                         curveTo(6.48f, 2.0f, 2.0f, 6.48f, 2.0f, 12.0f)
677                         curveTo(2.0f, 17.52f, 6.48f, 22.0f, 12.0f, 22.0f)
678                         curveTo(17.52f, 22.0f, 22.0f, 17.52f, 22.0f, 12.0f)
679                         curveTo(22.0f, 6.48f, 17.52f, 2.0f, 12.0f, 2.0f)
680                         close()
681                         moveTo(12.0f, 20.0f)
682                         curveTo(7.58f, 20.0f, 4.0f, 16.42f, 4.0f, 12.0f)
683                         curveTo(4.0f, 7.58f, 7.58f, 4.0f, 12.0f, 4.0f)
684                         curveTo(16.42f, 4.0f, 20.0f, 7.58f, 20.0f, 12.0f)
685                         curveTo(20.0f, 16.42f, 16.42f, 20.0f, 12.0f, 20.0f)
686                         close()
687                     }
688                     materialPath {
689                         moveTo(12.0f, 12.0f)
690                         moveToRelative(-5.0f, 0.0f)
691                         arcToRelative(5.0f, 5.0f, 0.0f, true, true, 10.0f, 0.0f)
692                         arcToRelative(5.0f, 5.0f, 0.0f, true, true, -10.0f, 0.0f)
693                     }
694                 }
695             return _radioOn!!
696         }
697 
698     private var _radioOn: ImageVector? = null
699 
700     public val RadioOff: ImageVector
701         get() {
702             if (_radioOff != null) {
703                 return _radioOff!!
704             }
705             _radioOff =
<lambda>null706                 materialIcon(name = "RadioOff") {
707                     materialPath {
708                         moveTo(12.0f, 2.0f)
709                         curveTo(6.48f, 2.0f, 2.0f, 6.48f, 2.0f, 12.0f)
710                         curveTo(2.0f, 17.52f, 6.48f, 22.0f, 12.0f, 22.0f)
711                         curveTo(17.52f, 22.0f, 22.0f, 17.52f, 22.0f, 12.0f)
712                         curveTo(22.0f, 6.48f, 17.52f, 2.0f, 12.0f, 2.0f)
713                         close()
714                         moveTo(12.0f, 20.0f)
715                         curveTo(7.58f, 20.0f, 4.0f, 16.42f, 4.0f, 12.0f)
716                         curveTo(4.0f, 7.58f, 7.58f, 4.0f, 12.0f, 4.0f)
717                         curveTo(16.42f, 4.0f, 20.0f, 7.58f, 20.0f, 12.0f)
718                         curveTo(20.0f, 16.42f, 16.42f, 20.0f, 12.0f, 20.0f)
719                         close()
720                     }
721                 }
722             return _radioOff!!
723         }
724 
725     private var _radioOff: ImageVector? = null
726 
727     public val CheckboxOn: ImageVector
728         get() {
729             if (_checkboxOn != null) {
730                 return _checkboxOn!!
731             }
732             _checkboxOn =
<lambda>null733                 materialIcon(name = "CheckboxOn") {
734                     materialPath {
735                         moveTo(19.0f, 3.0f)
736                         horizontalLineTo(5.0f)
737                         curveTo(3.9f, 3.0f, 3.0f, 3.9f, 3.0f, 5.0f)
738                         verticalLineTo(19.0f)
739                         curveTo(3.0f, 20.1f, 3.9f, 21.0f, 5.0f, 21.0f)
740                         horizontalLineTo(19.0f)
741                         curveTo(20.1f, 21.0f, 21.0f, 20.1f, 21.0f, 19.0f)
742                         verticalLineTo(5.0f)
743                         curveTo(21.0f, 3.9f, 20.1f, 3.0f, 19.0f, 3.0f)
744                         close()
745                         moveTo(19.0f, 19.0f)
746                         horizontalLineTo(5.0f)
747                         verticalLineTo(5.0f)
748                         horizontalLineTo(19.0f)
749                         verticalLineTo(19.0f)
750                         close()
751                         moveTo(18.0f, 9.0f)
752                         lineTo(16.6f, 7.6f)
753                         lineTo(13.3f, 10.9f)
754                         lineTo(10.0f, 14.2f)
755                         lineTo(7.4f, 11.6f)
756                         lineTo(6.0f, 13.0f)
757                         lineTo(10.0f, 17.0f)
758                         lineTo(18.0f, 9.0f)
759                         close()
760                     }
761                 }
762             return _checkboxOn!!
763         }
764 
765     private var _checkboxOn: ImageVector? = null
766 
767     private val CheckboxOff: ImageVector
768         get() {
769             if (_checkboxOff != null) {
770                 return _checkboxOff!!
771             }
772             _checkboxOff =
<lambda>null773                 materialIcon(name = "CheckboxOff") {
774                     materialPath {
775                         moveTo(19.0f, 5.0f)
776                         verticalLineTo(19.0f)
777                         horizontalLineTo(5.0f)
778                         verticalLineTo(5.0f)
779                         horizontalLineTo(19.0f)
780                         close()
781                         moveTo(19.0f, 3.0f)
782                         horizontalLineTo(5.0f)
783                         curveTo(3.9f, 3.0f, 3.0f, 3.9f, 3.0f, 5.0f)
784                         verticalLineTo(19.0f)
785                         curveTo(3.0f, 20.1f, 3.9f, 21.0f, 5.0f, 21.0f)
786                         horizontalLineTo(19.0f)
787                         curveTo(20.1f, 21.0f, 21.0f, 20.1f, 21.0f, 19.0f)
788                         verticalLineTo(5.0f)
789                         curveTo(21.0f, 3.9f, 20.1f, 3.0f, 19.0f, 3.0f)
790                         close()
791                     }
792                 }
793             return _checkboxOff!!
794         }
795 
796     private var _checkboxOff: ImageVector? = null
797 }
798 
799 /** Default [ToggleChipColors] implementation. */
800 @Immutable
801 private class DefaultToggleChipColors(
802     private val checkedBackgroundPainter: Painter,
803     private val checkedContentColor: Color,
804     private val checkedSecondaryContentColor: Color,
805     private val checkedIconColor: Color,
806     private val disabledCheckedBackgroundPainter: Painter,
807     private val disabledCheckedContentColor: Color,
808     private val disabledCheckedSecondaryContentColor: Color,
809     private val disabledCheckedIconColor: Color,
810     private val uncheckedBackgroundPainter: Painter,
811     private val uncheckedContentColor: Color,
812     private val uncheckedSecondaryContentColor: Color,
813     private val uncheckedIconColor: Color,
814     private val disabledUncheckedBackgroundPainter: Painter,
815     private val disabledUncheckedContentColor: Color,
816     private val disabledUncheckedSecondaryContentColor: Color,
817     private val disabledUncheckedIconColor: Color,
818 ) : ToggleChipColors {
819 
820     @Composable
backgroundnull821     override fun background(enabled: Boolean, checked: Boolean): State<Painter> {
822         return rememberUpdatedState(
823             if (enabled) {
824                 if (checked) checkedBackgroundPainter else uncheckedBackgroundPainter
825             } else {
826                 if (checked) disabledCheckedBackgroundPainter
827                 else disabledUncheckedBackgroundPainter
828             }
829         )
830     }
831 
832     @Composable
contentColornull833     override fun contentColor(enabled: Boolean, checked: Boolean): State<Color> {
834         return rememberUpdatedState(
835             if (enabled) {
836                 if (checked) checkedContentColor else uncheckedContentColor
837             } else {
838                 if (checked) disabledCheckedContentColor else disabledUncheckedContentColor
839             }
840         )
841     }
842 
843     @Composable
secondaryContentColornull844     override fun secondaryContentColor(enabled: Boolean, checked: Boolean): State<Color> {
845         return rememberUpdatedState(
846             if (enabled) {
847                 if (checked) checkedSecondaryContentColor else uncheckedSecondaryContentColor
848             } else {
849                 if (checked) disabledCheckedSecondaryContentColor
850                 else disabledUncheckedSecondaryContentColor
851             }
852         )
853     }
854 
855     @Composable
toggleControlColornull856     override fun toggleControlColor(enabled: Boolean, checked: Boolean): State<Color> {
857         return rememberUpdatedState(
858             if (enabled) {
859                 if (checked) checkedIconColor else uncheckedIconColor
860             } else {
861                 if (checked) disabledCheckedIconColor else disabledUncheckedIconColor
862             }
863         )
864     }
865 
equalsnull866     override fun equals(other: Any?): Boolean {
867         if (this === other) return true
868         if (other == null) return false
869         if (this::class != other::class) return false
870 
871         other as DefaultToggleChipColors
872 
873         if (checkedBackgroundPainter != other.checkedBackgroundPainter) return false
874         if (checkedContentColor != other.checkedContentColor) return false
875         if (checkedIconColor != other.checkedIconColor) return false
876         if (checkedSecondaryContentColor != other.checkedSecondaryContentColor) return false
877         if (uncheckedBackgroundPainter != other.uncheckedBackgroundPainter) return false
878         if (uncheckedContentColor != other.uncheckedContentColor) return false
879         if (uncheckedIconColor != other.uncheckedIconColor) return false
880         if (uncheckedSecondaryContentColor != other.uncheckedSecondaryContentColor) return false
881         if (disabledCheckedBackgroundPainter != other.disabledCheckedBackgroundPainter) return false
882         if (disabledCheckedContentColor != other.disabledCheckedContentColor) return false
883         if (disabledCheckedIconColor != other.disabledCheckedIconColor) return false
884         if (disabledCheckedSecondaryContentColor != other.disabledCheckedSecondaryContentColor)
885             return false
886         if (disabledUncheckedBackgroundPainter != other.disabledUncheckedBackgroundPainter)
887             return false
888         if (disabledUncheckedContentColor != other.disabledUncheckedContentColor) return false
889         if (disabledUncheckedIconColor != other.disabledUncheckedIconColor) return false
890         if (disabledUncheckedSecondaryContentColor != other.disabledUncheckedSecondaryContentColor)
891             return false
892 
893         return true
894     }
895 
hashCodenull896     override fun hashCode(): Int {
897         var result = checkedBackgroundPainter.hashCode()
898         result = 31 * result + checkedContentColor.hashCode()
899         result = 31 * result + checkedSecondaryContentColor.hashCode()
900         result = 31 * result + checkedIconColor.hashCode()
901         result = 31 * result + uncheckedBackgroundPainter.hashCode()
902         result = 31 * result + uncheckedContentColor.hashCode()
903         result = 31 * result + uncheckedSecondaryContentColor.hashCode()
904         result = 31 * result + uncheckedIconColor.hashCode()
905         result = 31 * result + disabledCheckedBackgroundPainter.hashCode()
906         result = 31 * result + disabledCheckedContentColor.hashCode()
907         result = 31 * result + disabledCheckedSecondaryContentColor.hashCode()
908         result = 31 * result + disabledCheckedIconColor.hashCode()
909         result = 31 * result + disabledUncheckedBackgroundPainter.hashCode()
910         result = 31 * result + disabledUncheckedContentColor.hashCode()
911         result = 31 * result + disabledUncheckedSecondaryContentColor.hashCode()
912         result = 31 * result + disabledUncheckedIconColor.hashCode()
913         return result
914     }
915 }
916 
917 /** Default [SplitToggleChipColors] implementation. */
918 @Immutable
919 private class DefaultSplitToggleChipColors(
920     private val backgroundColor: Color,
921     private val contentColor: Color,
922     private val secondaryContentColor: Color,
923     private val checkedIconColor: Color,
924     private val checkedSplitBackgroundOverlay: Color,
925     private val disabledBackgroundColor: Color,
926     private val disabledContentColor: Color,
927     private val disabledSecondaryContentColor: Color,
928     private val disabledCheckedIconColor: Color,
929     private val disabledCheckedSplitBackgroundOverlay: Color,
930     private val uncheckedIconColor: Color,
931     private val uncheckedSplitBackgroundOverlay: Color,
932     private val disabledUncheckedIconColor: Color,
933     private val disabledUncheckedSplitBackgroundOverlay: Color,
934 ) : SplitToggleChipColors {
935 
936     @Composable
backgroundColornull937     override fun backgroundColor(enabled: Boolean): State<Color> {
938         return rememberUpdatedState(if (enabled) backgroundColor else disabledBackgroundColor)
939     }
940 
941     @Composable
contentColornull942     override fun contentColor(enabled: Boolean): State<Color> {
943         return rememberUpdatedState(if (enabled) contentColor else disabledContentColor)
944     }
945 
946     @Composable
secondaryContentColornull947     override fun secondaryContentColor(enabled: Boolean): State<Color> {
948         return rememberUpdatedState(
949             if (enabled) secondaryContentColor else disabledSecondaryContentColor
950         )
951     }
952 
953     @Composable
toggleControlColornull954     override fun toggleControlColor(enabled: Boolean, checked: Boolean): State<Color> {
955         return rememberUpdatedState(
956             if (enabled) {
957                 if (checked) checkedIconColor else uncheckedIconColor
958             } else {
959                 if (checked) disabledCheckedIconColor else disabledUncheckedIconColor
960             }
961         )
962     }
963 
964     @Composable
splitBackgroundOverlaynull965     override fun splitBackgroundOverlay(enabled: Boolean, checked: Boolean): State<Color> {
966         return rememberUpdatedState(
967             if (enabled) {
968                 if (checked) checkedSplitBackgroundOverlay else uncheckedSplitBackgroundOverlay
969             } else {
970                 if (checked) disabledCheckedSplitBackgroundOverlay
971                 else disabledUncheckedSplitBackgroundOverlay
972             }
973         )
974     }
975 
equalsnull976     override fun equals(other: Any?): Boolean {
977         if (this === other) return true
978         if (other == null) return false
979         if (this::class != other::class) return false
980 
981         other as DefaultSplitToggleChipColors
982 
983         if (backgroundColor != other.backgroundColor) return false
984         if (contentColor != other.contentColor) return false
985         if (checkedIconColor != other.checkedIconColor) return false
986         if (checkedSplitBackgroundOverlay != other.checkedSplitBackgroundOverlay) return false
987         if (uncheckedIconColor != other.uncheckedIconColor) return false
988         if (uncheckedSplitBackgroundOverlay != other.uncheckedSplitBackgroundOverlay) return false
989         if (disabledBackgroundColor != other.disabledBackgroundColor) return false
990         if (disabledContentColor != other.disabledContentColor) return false
991         if (disabledCheckedIconColor != other.disabledCheckedIconColor) return false
992         if (disabledSecondaryContentColor != other.disabledSecondaryContentColor) return false
993         if (disabledCheckedSplitBackgroundOverlay != other.disabledCheckedSplitBackgroundOverlay)
994             return false
995         if (disabledUncheckedIconColor != other.disabledUncheckedIconColor) return false
996         if (
997             disabledUncheckedSplitBackgroundOverlay != other.disabledUncheckedSplitBackgroundOverlay
998         )
999             return false
1000 
1001         return true
1002     }
1003 
hashCodenull1004     override fun hashCode(): Int {
1005         var result = backgroundColor.hashCode()
1006         result = 31 * result + contentColor.hashCode()
1007         result = 31 * result + secondaryContentColor.hashCode()
1008         result = 31 * result + checkedIconColor.hashCode()
1009         result = 31 * result + checkedSplitBackgroundOverlay.hashCode()
1010         result = 31 * result + uncheckedIconColor.hashCode()
1011         result = 31 * result + uncheckedSplitBackgroundOverlay.hashCode()
1012         result = 31 * result + disabledBackgroundColor.hashCode()
1013         result = 31 * result + disabledContentColor.hashCode()
1014         result = 31 * result + disabledSecondaryContentColor.hashCode()
1015         result = 31 * result + disabledCheckedIconColor.hashCode()
1016         result = 31 * result + disabledCheckedSplitBackgroundOverlay.hashCode()
1017         result = 31 * result + disabledUncheckedIconColor.hashCode()
1018         result = 31 * result + disabledUncheckedSplitBackgroundOverlay.hashCode()
1019         return result
1020     }
1021 }
1022 
1023 private val TOGGLE_CONTROL_HEIGHT = 24.dp
1024 private val TOGGLE_CONTROL_WIDTH = 24.dp
1025 private val TOGGLE_CONTROL_SPACING = 4.dp
1026 private val ICON_SPACING = 6.dp
1027