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.wear.compose.material
17 
18 import androidx.compose.foundation.BorderStroke
19 import androidx.compose.foundation.border
20 import androidx.compose.foundation.clickable
21 import androidx.compose.foundation.interaction.Interaction
22 import androidx.compose.foundation.interaction.MutableInteractionSource
23 import androidx.compose.foundation.layout.Box
24 import androidx.compose.foundation.layout.BoxScope
25 import androidx.compose.foundation.layout.Column
26 import androidx.compose.foundation.layout.IntrinsicSize
27 import androidx.compose.foundation.layout.PaddingValues
28 import androidx.compose.foundation.layout.Row
29 import androidx.compose.foundation.layout.RowScope
30 import androidx.compose.foundation.layout.Spacer
31 import androidx.compose.foundation.layout.defaultMinSize
32 import androidx.compose.foundation.layout.fillMaxHeight
33 import androidx.compose.foundation.layout.fillMaxSize
34 import androidx.compose.foundation.layout.height
35 import androidx.compose.foundation.layout.padding
36 import androidx.compose.foundation.layout.size
37 import androidx.compose.foundation.layout.width
38 import androidx.compose.foundation.layout.wrapContentSize
39 import androidx.compose.runtime.Composable
40 import androidx.compose.runtime.Immutable
41 import androidx.compose.runtime.Stable
42 import androidx.compose.runtime.State
43 import androidx.compose.runtime.remember
44 import androidx.compose.runtime.rememberUpdatedState
45 import androidx.compose.ui.Alignment
46 import androidx.compose.ui.Modifier
47 import androidx.compose.ui.draw.clip
48 import androidx.compose.ui.draw.paint
49 import androidx.compose.ui.graphics.Brush
50 import androidx.compose.ui.graphics.Color
51 import androidx.compose.ui.graphics.Shape
52 import androidx.compose.ui.graphics.compositeOver
53 import androidx.compose.ui.graphics.painter.BrushPainter
54 import androidx.compose.ui.graphics.painter.ColorPainter
55 import androidx.compose.ui.graphics.painter.Painter
56 import androidx.compose.ui.layout.ContentScale
57 import androidx.compose.ui.platform.LocalLayoutDirection
58 import androidx.compose.ui.semantics.Role
59 import androidx.compose.ui.text.TextStyle
60 import androidx.compose.ui.unit.Dp
61 import androidx.compose.ui.unit.LayoutDirection
62 import androidx.compose.ui.unit.dp
63 import androidx.wear.compose.materialcore.ImageWithScrimPainter
64 
65 /**
66  * Base level Wear Material [Chip] that offers a single slot to take any content.
67  *
68  * Is used as the container for more opinionated [Chip] components that take specific content such
69  * as icons and labels.
70  *
71  * The [Chip] is Stadium shaped and has a max height designed to take no more than two lines of text
72  * of [Typography.button] style. The [Chip] can have an icon or image horizontally parallel to the
73  * two lines of text. With localisation and/or large font sizes, the [Chip] height adjusts to
74  * accommodate the contents.
75  *
76  * The [Chip] can have different styles with configurable content colors, background colors
77  * including gradients, these are provided by [ChipColors] implementations.
78  *
79  * The recommended set of [ChipColors] styles can be obtained from [ChipDefaults], e.g.
80  * [ChipDefaults.primaryChipColors] to get a color scheme for a primary [Chip] which by default will
81  * have a solid background of [Colors.primary] and content color of [Colors.onPrimary].
82  *
83  * Chips can be enabled or disabled. A disabled chip will not respond to click events.
84  *
85  * For more information, see the
86  * [Chips](https://developer.android.com/training/wearables/components/chips) guide.
87  *
88  * @param onClick Will be called when the user clicks the chip
89  * @param colors [ChipColors] that will be used to resolve the background and content color for this
90  *   chip in different states. See [ChipDefaults.chipColors].
91  * @param modifier Modifier to be applied to the chip
92  * @param enabled Controls the enabled state of the chip. When `false`, this chip will not be
93  *   clickable
94  * @param contentPadding The spacing values to apply internally between the container and the
95  *   content
96  * @param shape Defines the chip's shape. It is strongly recommended to use the default as this
97  *   shape is a key characteristic of the Wear Material Theme
98  * @param interactionSource The [MutableInteractionSource] representing the stream of [Interaction]s
99  *   for this Chip. You can create and pass in your own remembered [MutableInteractionSource] if you
100  *   want to observe [Interaction]s and customize the appearance / behavior of this Chip in
101  *   different [Interaction]s.
102  * @param role The type of user interface element. Accessibility services might use this to describe
103  *   the element or do customizations
104  */
105 @Deprecated(
106     "This overload is provided for backwards compatibility with Compose for Wear OS 1.0." +
107         "A newer overload is available with an additional border parameter.",
108     level = DeprecationLevel.HIDDEN
109 )
110 @Composable
Chipnull111 public fun Chip(
112     onClick: () -> Unit,
113     colors: ChipColors,
114     modifier: Modifier = Modifier,
115     enabled: Boolean = true,
116     contentPadding: PaddingValues = ChipDefaults.ContentPadding,
117     shape: Shape = MaterialTheme.shapes.large,
118     interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
119     role: Role? = Role.Button,
120     content: @Composable RowScope.() -> Unit,
121 ): Unit =
122     Chip(
123         onClick = onClick,
124         colors = colors,
125         border = ChipDefaults.chipBorder(),
126         modifier = modifier,
127         enabled = enabled,
128         contentPadding = contentPadding,
129         shape = shape,
130         interactionSource = interactionSource,
131         role = role,
132         content = content
133     )
134 
135 /**
136  * Base level Wear Material [Chip] that offers a single slot to take any content.
137  *
138  * Is used as the container for more opinionated [Chip] components that take specific content such
139  * as icons and labels.
140  *
141  * The [Chip] is Stadium shaped and has a max height designed to take no more than two lines of text
142  * of [Typography.button] style. The [Chip] can have an icon or image horizontally parallel to the
143  * two lines of text. With localisation and/or large font sizes, the [Chip] height adjusts to
144  * accommodate the contents.
145  *
146  * The [Chip] can have different styles with configurable content colors, background colors
147  * including gradients, these are provided by [ChipColors] implementations.
148  *
149  * The recommended set of [ChipColors] styles can be obtained from [ChipDefaults], e.g.
150  * [ChipDefaults.primaryChipColors] to get a color scheme for a primary [Chip] which by default will
151  * have a solid background of [Colors.primary] and content color of [Colors.onPrimary].
152  *
153  * Chips can be enabled or disabled. A disabled chip will not respond to click events.
154  *
155  * For more information, see the
156  * [Chips](https://developer.android.com/training/wearables/components/chips) guide.
157  *
158  * @param onClick Will be called when the user clicks the chip
159  * @param colors [ChipColors] that will be used to resolve the background and content color for this
160  *   chip in different states. See [ChipDefaults.chipColors].
161  * @param border [ChipBorder] that will be used to resolve the border for this chip in different
162  *   states. See [ChipDefaults.chipBorder].
163  * @param modifier Modifier to be applied to the chip
164  * @param enabled Controls the enabled state of the chip. When `false`, this chip will not be
165  *   clickable
166  * @param contentPadding The spacing values to apply internally between the container and the
167  *   content
168  * @param shape Defines the chip's shape. It is strongly recommended to use the default as this
169  *   shape is a key characteristic of the Wear Material Theme
170  * @param interactionSource an optional hoisted [MutableInteractionSource] for observing and
171  *   emitting [Interaction]s for this chip. You can use this to change the chip's appearance or
172  *   preview the chip in different states. Note that if `null` is provided, interactions will still
173  *   happen internally.
174  * @param role The type of user interface element. Accessibility services might use this to describe
175  *   the element or do customizations
176  * @param content Slot for composable body content displayed on the Chip
177  */
178 @Composable
Chipnull179 public fun Chip(
180     onClick: () -> Unit,
181     colors: ChipColors,
182     border: ChipBorder,
183     modifier: Modifier = Modifier,
184     enabled: Boolean = true,
185     contentPadding: PaddingValues = ChipDefaults.ContentPadding,
186     shape: Shape = MaterialTheme.shapes.large,
187     interactionSource: MutableInteractionSource? = null,
188     role: Role? = Role.Button,
189     content: @Composable RowScope.() -> Unit,
190 ) {
191     ChipImpl(
192         onClick = onClick,
193         colors = colors,
194         border = border,
195         modifier = modifier.chipSizeModifier(),
196         enabled = enabled,
197         contentPadding = contentPadding,
198         shape = shape,
199         interactionSource = interactionSource,
200         role = role,
201         content = content
202     )
203 }
204 
205 /**
206  * Wear Material [Chip] that offers three slots and a specific layout for an icon, label and
207  * secondaryLabel. The icon and secondaryLabel are optional. The items are laid out with the icon,
208  * if provided, at the start of a row, with a column next containing the two label slots.
209  *
210  * The [Chip] is Stadium shaped and has a max height designed to take no more than two lines of text
211  * of [Typography.button] style. If no secondary label is provided then the label can be two lines
212  * of text. The label and secondary label should be consistently aligned. With localisation and/or
213  * large font sizes, the [Chip] height adjusts to accommodate the contents.
214  *
215  * If a icon is provided then the labels should be "start" aligned, e.g. left aligned in ltr so that
216  * the text starts next to the icon.
217  *
218  * The [Chip] can have different styles with configurable content colors, background colors
219  * including gradients, these are provided by [ChipColors] implementations.
220  *
221  * The recommended set of [ChipColors] styles can be obtained from [ChipDefaults], e.g.
222  * [ChipDefaults.primaryChipColors] to get a color scheme for a primary [Chip] which by default will
223  * have a solid background of [Colors.primary] and content color of [Colors.onPrimary].
224  *
225  * Chips can be enabled or disabled. A disabled chip will not respond to click events.
226  *
227  * Example of a [Chip] with icon and a label only with longer text:
228  *
229  * @sample androidx.wear.compose.material.samples.ChipWithIconAndLabel
230  *
231  * Example of a [Chip] with icon, label and secondary label:
232  *
233  * @sample androidx.wear.compose.material.samples.ChipWithIconAndLabels
234  *
235  * For more information, see the
236  * [Chips](https://developer.android.com/training/wearables/components/chips) guide.
237  *
238  * @param label A slot for providing the chip's main label. The contents are expected to be text
239  *   which is "start" aligned if there is an icon preset and "start" or "center" aligned if not.
240  * @param onClick Will be called when the user clicks the chip
241  * @param modifier Modifier to be applied to the chip
242  * @param secondaryLabel A slot for providing the chip's secondary label. The contents are expected
243  *   to be text which is "start" aligned if there is an icon preset and "start" or "center" aligned
244  *   if not. label and secondaryLabel contents should be consistently aligned.
245  * @param icon A slot for providing the chip's icon. The contents are expected to be a horizontally
246  *   and vertically aligned icon of size [ChipDefaults.IconSize] or [ChipDefaults.LargeIconSize]. In
247  *   order to correctly render when the Chip is not enabled the icon must set its alpha value to
248  *   [LocalContentAlpha].
249  * @param colors [ChipColors] that will be used to resolve the background and content color for this
250  *   chip in different states. See [ChipDefaults.chipColors]. Defaults to
251  *   [ChipDefaults.primaryChipColors]
252  * @param enabled Controls the enabled state of the chip. When `false`, this chip will not be
253  *   clickable
254  * @param interactionSource The [MutableInteractionSource] representing the stream of [Interaction]s
255  *   for this Chip. You can create and pass in your own remembered [MutableInteractionSource] if you
256  *   want to observe [Interaction]s and customize the appearance / behavior of this Chip in
257  *   different [Interaction]s.
258  * @param contentPadding The spacing values to apply internally between the container and the
259  *   content
260  */
261 @Deprecated(
262     "This overload is provided for backwards compatibility with Compose for Wear OS 1.0." +
263         "A newer overload is available with an additional shape parameter.",
264     level = DeprecationLevel.HIDDEN
265 )
266 @Composable
Chipnull267 public fun Chip(
268     label: @Composable RowScope.() -> Unit,
269     onClick: () -> Unit,
270     modifier: Modifier = Modifier,
271     secondaryLabel: (@Composable RowScope.() -> Unit)? = null,
272     icon: (@Composable BoxScope.() -> Unit)? = null,
273     colors: ChipColors = ChipDefaults.primaryChipColors(),
274     enabled: Boolean = true,
275     interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
276     contentPadding: PaddingValues = ChipDefaults.ContentPadding,
277 ): Unit =
278     Chip(
279         label,
280         onClick,
281         modifier,
282         secondaryLabel,
283         icon,
284         colors,
285         enabled,
286         interactionSource,
287         contentPadding,
288         MaterialTheme.shapes.small
289     )
290 
291 /**
292  * Wear Material [Chip] that offers three slots and a specific layout for an icon, label and
293  * secondaryLabel. The icon and secondaryLabel are optional. The items are laid out with the icon,
294  * if provided, at the start of a row, with a column next containing the two label slots.
295  *
296  * The [Chip] is Stadium shaped and has a max height designed to take no more than two lines of text
297  * of [Typography.button] style. If no secondary label is provided then the label can be two lines
298  * of text. The label and secondary label should be consistently aligned. With localisation and/or
299  * large font sizes, the [Chip] height adjusts to accommodate the contents.
300  *
301  * If a icon is provided then the labels should be "start" aligned, e.g. left aligned in ltr so that
302  * the text starts next to the icon.
303  *
304  * The [Chip] can have different styles with configurable content colors, background colors
305  * including gradients, these are provided by [ChipColors] implementations.
306  *
307  * The recommended set of [ChipColors] styles can be obtained from [ChipDefaults], e.g.
308  * [ChipDefaults.primaryChipColors] to get a color scheme for a primary [Chip] which by default will
309  * have a solid background of [Colors.primary] and content color of [Colors.onPrimary].
310  *
311  * Chips can be enabled or disabled. A disabled chip will not respond to click events.
312  *
313  * Example of a [Chip] with icon and a label only with longer text:
314  *
315  * @sample androidx.wear.compose.material.samples.ChipWithIconAndLabel
316  *
317  * Example of a [Chip] with icon, label and secondary label:
318  *
319  * @sample androidx.wear.compose.material.samples.ChipWithIconAndLabels
320  *
321  * For more information, see the
322  * [Chips](https://developer.android.com/training/wearables/components/chips) guide.
323  *
324  * @param label A slot for providing the chip's main label. The contents are expected to be text
325  *   which is "start" aligned if there is an icon preset and "start" or "center" aligned if not.
326  * @param onClick Will be called when the user clicks the chip
327  * @param modifier Modifier to be applied to the chip
328  * @param secondaryLabel A slot for providing the chip's secondary label. The contents are expected
329  *   to be text which is "start" aligned if there is an icon preset and "start" or "center" aligned
330  *   if not. label and secondaryLabel contents should be consistently aligned.
331  * @param icon A slot for providing the chip's icon. The contents are expected to be a horizontally
332  *   and vertically aligned icon of size [ChipDefaults.IconSize] or [ChipDefaults.LargeIconSize]. In
333  *   order to correctly render when the Chip is not enabled the icon must set its alpha value to
334  *   [LocalContentAlpha].
335  * @param colors [ChipColors] that will be used to resolve the background and content color for this
336  *   chip in different states. See [ChipDefaults.chipColors]. Defaults to
337  *   [ChipDefaults.primaryChipColors]
338  * @param enabled Controls the enabled state of the chip. When `false`, this chip will not be
339  *   clickable
340  * @param interactionSource an optional hoisted [MutableInteractionSource] for observing and
341  *   emitting [Interaction]s for this chip. You can use this to change the chip's appearance or
342  *   preview the chip in different states. Note that if `null` is provided, interactions will still
343  *   happen internally.
344  * @param contentPadding The spacing values to apply internally between the container and the
345  *   content
346  * @param shape Defines the chip's shape. It is strongly recommended to use the default as this
347  *   shape is a key characteristic of the Wear Material Theme
348  * @param border [ChipBorder] that will be used to resolve the chip border in different states. See
349  *   [ChipDefaults.chipBorder].
350  */
351 @Composable
Chipnull352 public fun Chip(
353     label: @Composable RowScope.() -> Unit,
354     onClick: () -> Unit,
355     modifier: Modifier = Modifier,
356     secondaryLabel: (@Composable RowScope.() -> Unit)? = null,
357     icon: (@Composable BoxScope.() -> Unit)? = null,
358     colors: ChipColors = ChipDefaults.primaryChipColors(),
359     enabled: Boolean = true,
360     interactionSource: MutableInteractionSource? = null,
361     contentPadding: PaddingValues = ChipDefaults.ContentPadding,
362     shape: Shape = MaterialTheme.shapes.large,
363     border: ChipBorder = ChipDefaults.chipBorder()
364 ) {
365     ChipImpl(
366         onClick = onClick,
367         label = label,
368         labelTypography = MaterialTheme.typography.button,
369         modifier = modifier.chipSizeModifier(),
370         secondaryLabel = secondaryLabel,
371         icon = icon,
372         colors = colors,
373         enabled = enabled,
374         interactionSource = interactionSource,
375         contentPadding = contentPadding,
376         shape = shape,
377         border = border,
378         defaultIconSpacing = ChipDefaults.IconSpacing
379     )
380 }
381 
382 /**
383  * Wear Material [OutlinedChip] that offers three slots and a specific layout for an icon, label and
384  * secondaryLabel. The icon and secondaryLabel are optional. The items are laid out with the icon,
385  * if provided, at the start of a row, with a column next containing the two label slots.
386  *
387  * The [OutlinedChip] is Stadium shaped and has a max height designed to take no more than two lines
388  * of text of [Typography.button] style. If no secondary label is provided then the label can be two
389  * lines of text. The label and secondary label should be consistently aligned. With localisation
390  * and/or large font sizes, the [OutlinedChip] height adjusts to accommodate the contents.
391  *
392  * If a icon is provided then the labels should be "start" aligned, e.g. left aligned in ltr so that
393  * the text starts next to the icon.
394  *
395  * the [OutlinedChip] has a transparent background, a thin border and contents which are colored
396  * with the theme primary color. Colors can be obtained and customized using
397  * [ChipDefaults.outlinedChipColors()].
398  *
399  * Chips can be enabled or disabled. A disabled chip will not respond to click events.
400  *
401  * Example of a [OutlinedChip] with icon and a label only with longer text:
402  *
403  * @sample androidx.wear.compose.material.samples.OutlinedChipWithIconAndLabel
404  *
405  * For more information, see the
406  * [Chips](https://developer.android.com/training/wearables/components/chips) guide.
407  *
408  * @param label A slot for providing the chip's main label. The contents are expected to be text
409  *   which is "start" aligned if there is an icon preset and "start" or "center" aligned if not.
410  * @param onClick Will be called when the user clicks the chip
411  * @param modifier Modifier to be applied to the chip
412  * @param secondaryLabel A slot for providing the chip's secondary label. The contents are expected
413  *   to be text which is "start" aligned if there is an icon preset and "start" or "center" aligned
414  *   if not. label and secondaryLabel contents should be consistently aligned.
415  * @param icon A slot for providing the chip's icon. The contents are expected to be a horizontally
416  *   and vertically aligned icon of size [ChipDefaults.IconSize] or [ChipDefaults.LargeIconSize]. In
417  *   order to correctly render when the Chip is not enabled the icon must set its alpha value to
418  *   [LocalContentAlpha].
419  * @param colors [ChipColors] that will be used to resolve the background and content color for this
420  *   chip in different states.
421  * @param enabled Controls the enabled state of the chip. When `false`, this chip will not be
422  *   clickable
423  * @param interactionSource an optional hoisted [MutableInteractionSource] for observing and
424  *   emitting [Interaction]s for this chip. You can use this to change the chip's appearance or
425  *   preview the chip in different states. Note that if `null` is provided, interactions will still
426  *   happen internally.
427  * @param contentPadding The spacing values to apply internally between the container and the
428  *   content
429  * @param shape Defines the chip's shape. It is strongly recommended to use the default as this
430  *   shape is a key characteristic of the Wear Material Theme
431  * @param border [ChipBorder] that will be used to resolve the chip border in different states.
432  */
433 @Composable
OutlinedChipnull434 public fun OutlinedChip(
435     label: @Composable RowScope.() -> Unit,
436     onClick: () -> Unit,
437     modifier: Modifier = Modifier,
438     secondaryLabel: (@Composable RowScope.() -> Unit)? = null,
439     icon: (@Composable BoxScope.() -> Unit)? = null,
440     colors: ChipColors = ChipDefaults.outlinedChipColors(),
441     enabled: Boolean = true,
442     interactionSource: MutableInteractionSource? = null,
443     contentPadding: PaddingValues = ChipDefaults.ContentPadding,
444     shape: Shape = MaterialTheme.shapes.large,
445     border: ChipBorder = ChipDefaults.outlinedChipBorder()
446 ): Unit =
447     Chip(
448         label = label,
449         onClick = onClick,
450         modifier = modifier,
451         secondaryLabel = secondaryLabel,
452         icon = icon,
453         colors = colors,
454         enabled = enabled,
455         interactionSource = interactionSource,
456         contentPadding = contentPadding,
457         shape = shape,
458         border = border
459     )
460 
461 /**
462  * A compact Wear Material Chip that offers two slots and a specific layout for an icon and label.
463  * Both the icon and label are optional however it is expected that at least one will be provided.
464  *
465  * The [CompactChip] is Stadium shaped and has a max height designed to take no more than one line
466  * of text of [Typography.caption1] style and/or one icon. The default max height is
467  * [ChipDefaults.CompactChipHeight]. This includes a visible chip height of 32.dp and 8.dp of
468  * padding above and below the chip in order to meet accessibility guidelines that request a minimum
469  * of 48.dp height and width of tappable area.
470  *
471  * If a icon is provided then the labels should be "start" aligned, e.g. left aligned in ltr so that
472  * the text starts next to the icon.
473  *
474  * The items are laid out as follows.
475  * 1. If a label is provided then the chip will be laid out with the optional icon at the start of a
476  *    row followed by the label with a default max height of [ChipDefaults.CompactChipHeight].
477  * 2. If only an icon is provided it will be laid out vertically and horizontally centered with a
478  *    default height of [ChipDefaults.CompactChipHeight] and the default width of
479  *    [ChipDefaults.IconOnlyCompactChipWidth]
480  *
481  * If neither icon nor label is provided then the chip will displayed like an icon only chip but
482  * with no contents and [ChipColors.background()] color.
483  *
484  * The [CompactChip] can have different styles with configurable content colors, background colors
485  * including gradients, these are provided by [ChipColors] implementations.
486  *
487  * The recommended set of [ChipColors] styles can be obtained from [ChipDefaults], e.g.
488  * [ChipDefaults.primaryChipColors] to get a color scheme for a primary [Chip] which by default will
489  * have a solid background of [Colors.primary] and content color of [Colors.onPrimary].
490  *
491  * Chips can be enabled or disabled. A disabled chip will not respond to click events.
492  *
493  * Example of a [CompactChip] with icon and single line of label text:
494  *
495  * @sample androidx.wear.compose.material.samples.CompactChipWithIconAndLabel
496  *
497  * Example of a [CompactChip] with a label, note that the text is center aligned:
498  *
499  * @sample androidx.wear.compose.material.samples.CompactChipWithLabel
500  *
501  * Example of a [CompactChip] with an icon only, note that the recommended icon size is 24x24 when
502  * only an icon is displayed:
503  *
504  * @sample androidx.wear.compose.material.samples.CompactChipWithIcon
505  *
506  * For more information, see the
507  * [Chips](https://developer.android.com/training/wearables/components/chips) guide.
508  *
509  * @param onClick Will be called when the user clicks the chip
510  * @param modifier Modifier to be applied to the chip
511  * @param label A slot for providing the chip's main label. The contents are expected to be text
512  *   which is "start" aligned if there is an icon preset and "center" aligned if not.
513  * @param icon A slot for providing the chip's icon. The contents are expected to be a horizontally
514  *   and vertically aligned icon of size [ChipDefaults.SmallIconSize] when used with a label or
515  *   [ChipDefaults.IconSize] when used as the only content in the CompactChip. In order to correctly
516  *   render when the Chip is not enabled the icon must set its alpha value to [LocalContentAlpha].
517  * @param colors [ChipColors] that will be used to resolve the background and content color for this
518  *   chip in different states. See [ChipDefaults.chipColors]. Defaults to
519  *   [ChipDefaults.primaryChipColors]
520  * @param enabled Controls the enabled state of the chip. When `false`, this chip will not be
521  *   clickable
522  * @param interactionSource The [MutableInteractionSource] representing the stream of [Interaction]s
523  *   for this Chip. You can create and pass in your own remembered [MutableInteractionSource] if you
524  *   want to observe [Interaction]s and customize the appearance / behavior of this Chip in
525  *   different [Interaction]s.
526  * @param contentPadding The spacing values to apply internally between the container and the
527  *   content
528  */
529 @Deprecated(
530     "This overload is provided for backwards compatibility with Compose for Wear OS 1.0." +
531         "A newer overload is available with an additional shape parameter.",
532     level = DeprecationLevel.HIDDEN
533 )
534 @Composable
535 public fun CompactChip(
536     onClick: () -> Unit,
537     modifier: Modifier = Modifier,
538     label: (@Composable RowScope.() -> Unit)? = null,
539     icon: (@Composable BoxScope.() -> Unit)? = null,
540     colors: ChipColors = ChipDefaults.primaryChipColors(),
541     enabled: Boolean = true,
542     interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
543     contentPadding: PaddingValues = ChipDefaults.CompactChipContentPadding,
544 ): Unit =
545     CompactChip(
546         onClick,
547         modifier,
548         label,
549         icon,
550         colors,
551         enabled,
552         interactionSource,
553         contentPadding,
554         MaterialTheme.shapes.small,
555         ChipDefaults.chipBorder()
556     )
557 
558 /**
559  * A compact Wear Material Chip that offers two slots and a specific layout for an icon and label.
560  * Both the icon and label are optional however it is expected that at least one will be provided.
561  *
562  * The [CompactChip] is Stadium shaped and has a max height designed to take no more than one line
563  * of text of [Typography.caption1] style and/or one icon. The default max height is
564  * [ChipDefaults.CompactChipHeight]. This includes a visible chip height of 32.dp and 8.dp of
565  * padding above and below the chip in order to meet accessibility guidelines that request a minimum
566  * of 48.dp height and width of tappable area.
567  *
568  * If a icon is provided then the labels should be "start" aligned, e.g. left aligned in ltr so that
569  * the text starts next to the icon.
570  *
571  * The items are laid out as follows.
572  * 1. If a label is provided then the chip will be laid out with the optional icon at the start of a
573  *    row followed by the label with a default max height of [ChipDefaults.CompactChipHeight].
574  * 2. If only an icon is provided it will be laid out vertically and horizontally centered with a
575  *    default height of [ChipDefaults.CompactChipHeight] and the default width of
576  *    [ChipDefaults.IconOnlyCompactChipWidth]
577  *
578  * If neither icon nor label is provided then the chip will displayed like an icon only chip but
579  * with no contents and [ChipColors.background()] color.
580  *
581  * The [CompactChip] can have different styles with configurable content colors, background colors
582  * including gradients, these are provided by [ChipColors] implementations.
583  *
584  * The recommended set of [ChipColors] styles can be obtained from [ChipDefaults], e.g.
585  * [ChipDefaults.primaryChipColors] to get a color scheme for a primary [Chip] which by default will
586  * have a solid background of [Colors.primary] and content color of [Colors.onPrimary].
587  *
588  * Chips can be enabled or disabled. A disabled chip will not respond to click events.
589  *
590  * Example of a [CompactChip] with icon and single line of label text:
591  *
592  * @sample androidx.wear.compose.material.samples.CompactChipWithIconAndLabel
593  *
594  * Example of a [CompactChip] with a label, note that the text is center aligned:
595  *
596  * @sample androidx.wear.compose.material.samples.CompactChipWithLabel
597  *
598  * Example of a [CompactChip] with an icon only, note that the recommended icon size is 24x24 when
599  * only an icon is displayed:
600  *
601  * @sample androidx.wear.compose.material.samples.CompactChipWithIcon
602  *
603  * For more information, see the
604  * [Chips](https://developer.android.com/training/wearables/components/chips) guide.
605  *
606  * @param onClick Will be called when the user clicks the chip
607  * @param modifier Modifier to be applied to the chip
608  * @param label A slot for providing the chip's main label. The contents are expected to be text
609  *   which is "start" aligned if there is an icon preset and "center" aligned if not.
610  * @param icon A slot for providing the chip's icon. The contents are expected to be a horizontally
611  *   and vertically aligned icon of size [ChipDefaults.SmallIconSize] when used with a label or
612  *   [ChipDefaults.IconSize] when used as the only content in the CompactChip. In order to correctly
613  *   render when the Chip is not enabled the icon must set its alpha value to [LocalContentAlpha].
614  * @param colors [ChipColors] that will be used to resolve the background and content color for this
615  *   chip in different states. See [ChipDefaults.chipColors]. Defaults to
616  *   [ChipDefaults.primaryChipColors]
617  * @param enabled Controls the enabled state of the chip. When `false`, this chip will not be
618  *   clickable
619  * @param interactionSource an optional hoisted [MutableInteractionSource] for observing and
620  *   emitting [Interaction]s for this chip. You can use this to change the chip's appearance or
621  *   preview the chip in different states. Note that if `null` is provided, interactions will still
622  *   happen internally.
623  * @param contentPadding The spacing values to apply internally between the container and the
624  *   content
625  * @param shape Defines the chip's shape. It is strongly recommended to use the default as this
626  *   shape is a key characteristic of the Wear Material Theme
627  * @param border [ChipBorder] that will be used to resolve the border for this chip in different
628  *   states. See [ChipDefaults.chipBorder].
629  */
630 @Composable
CompactChipnull631 public fun CompactChip(
632     onClick: () -> Unit,
633     modifier: Modifier = Modifier,
634     label: (@Composable RowScope.() -> Unit)? = null,
635     icon: (@Composable BoxScope.() -> Unit)? = null,
636     colors: ChipColors = ChipDefaults.primaryChipColors(),
637     enabled: Boolean = true,
638     interactionSource: MutableInteractionSource? = null,
639     contentPadding: PaddingValues = ChipDefaults.CompactChipContentPadding,
640     shape: Shape = MaterialTheme.shapes.large,
641     border: ChipBorder = ChipDefaults.chipBorder()
642 ) {
643     if (label != null) {
644         ChipImpl(
645             modifier =
646                 modifier.compactChipModifier().padding(ChipDefaults.CompactChipTapTargetPadding),
647             label = label,
648             labelTypography = MaterialTheme.typography.caption1,
649             onClick = onClick,
650             colors = colors,
651             secondaryLabel = null,
652             icon = icon,
653             enabled = enabled,
654             interactionSource = interactionSource,
655             contentPadding = contentPadding,
656             shape = shape,
657             border = border,
658             defaultIconSpacing = ChipDefaults.IconSpacing,
659         )
660     } else {
661         // Icon only compact chips have their own layout with a specific width and center aligned
662         // content. We use the base simple single slot Chip under the covers.
663         ChipImpl(
664             modifier =
665                 modifier
666                     .compactChipModifier()
667                     .width(ChipDefaults.IconOnlyCompactChipWidth)
668                     .padding(ChipDefaults.CompactChipTapTargetPadding),
669             onClick = onClick,
670             colors = colors,
671             border = border,
672             enabled = enabled,
673             contentPadding = contentPadding,
674             shape = shape,
675             interactionSource = interactionSource,
676         ) {
677             // Use a box to fill and center align the icon into the single slot of the Chip
678             Box(modifier = Modifier.fillMaxSize().wrapContentSize(align = Alignment.Center)) {
679                 if (icon != null) {
680                     icon()
681                 }
682             }
683         }
684     }
685 }
686 
687 /**
688  * A compact Outlined Wear Material Chip that offers two slots and a specific layout for an icon and
689  * label. Both the icon and label are optional however it is expected that at least one will be
690  * provided.
691  *
692  * The [CompactChip] is Stadium shaped and has a max height designed to take no more than one line
693  * of text of [Typography.caption1] style and/or one icon. The default max height is
694  * [ChipDefaults.CompactChipHeight]. This includes a visible chip height of 32.dp and 8.dp of
695  * padding above and below the chip in order to meet accessibility guidelines that request a minimum
696  * of 48.dp height and width of tappable area.
697  *
698  * If a icon is provided then the labels should be "start" aligned, e.g. left aligned in ltr so that
699  * the text starts next to the icon.
700  *
701  * The items are laid out as follows.
702  * 1. If a label is provided then the chip will be laid out with the optional icon at the start of a
703  *    row followed by the label with a default max height of [ChipDefaults.CompactChipHeight].
704  * 2. If only an icon is provided it will be laid out vertically and horizontally centered with a
705  *    default height of [ChipDefaults.CompactChipHeight] and the default width of
706  *    [ChipDefaults.IconOnlyCompactChipWidth]
707  *
708  * If neither icon nor label is provided then the chip will displayed like an icon only chip but
709  * with no contents and [ChipColors.background()] color.
710  *
711  * the [OutlinedCompactChip] has a transparent background, a thin border and contents which are
712  * colored with the theme primary color. Colors can be obtained and customized using
713  * [ChipDefaults.outlinedChipColors()].
714  *
715  * Chips can be enabled or disabled. A disabled chip will not respond to click events.
716  *
717  * Example of a [OutlinedCompactChip] with icon and single line of label text:
718  *
719  * @sample androidx.wear.compose.material.samples.OutlinedCompactChipWithIconAndLabel
720  *
721  * For more information, see the
722  * [Chips](https://developer.android.com/training/wearables/components/chips) guide.
723  *
724  * @param onClick Will be called when the user clicks the chip
725  * @param modifier Modifier to be applied to the chip
726  * @param label A slot for providing the chip's main label. The contents are expected to be text
727  *   which is "start" aligned if there is an icon preset and "center" aligned if not.
728  * @param icon A slot for providing the chip's icon. The contents are expected to be a horizontally
729  *   and vertically aligned icon of size [ChipDefaults.SmallIconSize] when used with a label or
730  *   [ChipDefaults.IconSize] when used as the only content in the CompactChip. In order to correctly
731  *   render when the Chip is not enabled the icon must set its alpha value to [LocalContentAlpha].
732  * @param colors [ChipColors] that will be used to resolve the background and content color for this
733  *   chip in different states. See [ChipDefaults.outlinedChipColors]. Defaults to
734  *   [ChipDefaults.primaryChipColors]
735  * @param enabled Controls the enabled state of the chip. When `false`, this chip will not be
736  *   clickable
737  * @param interactionSource an optional hoisted [MutableInteractionSource] for observing and
738  *   emitting [Interaction]s for this chip. You can use this to change the chip's appearance or
739  *   preview the chip in different states. Note that if `null` is provided, interactions will still
740  *   happen internally.
741  * @param contentPadding The spacing values to apply internally between the container and the
742  *   content
743  * @param shape Defines the chip's shape. It is strongly recommended to use the default as this
744  *   shape is a key characteristic of the Wear Material Theme
745  * @param border [ChipBorder] that will be used to resolve the border for this chip in different
746  *   states. See [ChipDefaults.outlinedChipBorder].
747  */
748 @Composable
OutlinedCompactChipnull749 public fun OutlinedCompactChip(
750     onClick: () -> Unit,
751     modifier: Modifier = Modifier,
752     label: (@Composable RowScope.() -> Unit)? = null,
753     icon: (@Composable BoxScope.() -> Unit)? = null,
754     colors: ChipColors = ChipDefaults.outlinedChipColors(),
755     enabled: Boolean = true,
756     interactionSource: MutableInteractionSource? = null,
757     contentPadding: PaddingValues = ChipDefaults.CompactChipContentPadding,
758     shape: Shape = MaterialTheme.shapes.large,
759     border: ChipBorder = ChipDefaults.outlinedChipBorder()
760 ): Unit =
761     CompactChip(
762         onClick = onClick,
763         modifier = modifier,
764         label = label,
765         icon = icon,
766         colors = colors,
767         enabled = enabled,
768         interactionSource = interactionSource,
769         contentPadding = contentPadding,
770         shape = shape,
771         border = border
772     )
773 
774 /**
775  * Represents the background and content colors used in a chip in different states.
776  *
777  * See [ChipDefaults.primaryChipColors] for the default colors used in a primary styled [Chip]. See
778  * [ChipDefaults.secondaryChipColors] for the default colors used in a secondary styled [Chip].
779  */
780 @Stable
781 public interface ChipColors {
782     /**
783      * Represents the background treatment for this chip, depending on [enabled]. Backgrounds can be
784      * solid, transparent or have a gradient applied.
785      *
786      * @param enabled Whether the chip is enabled
787      */
788     @Composable public fun background(enabled: Boolean): State<Painter>
789 
790     /**
791      * Represents the content color for this chip, depending on [enabled].
792      *
793      * @param enabled Whether the chip is enabled
794      */
795     @Composable public fun contentColor(enabled: Boolean): State<Color>
796 
797     /**
798      * Represents the secondary content color for this chip, depending on [enabled].
799      *
800      * @param enabled Whether the chip is enabled
801      */
802     @Composable public fun secondaryContentColor(enabled: Boolean): State<Color>
803 
804     /**
805      * Represents the icon color for this chip, depending on [enabled].
806      *
807      * @param enabled Whether the chip is enabled
808      */
809     @Composable public fun iconColor(enabled: Boolean): State<Color>
810 }
811 
812 /** Represents the border stroke used in a [Chip] in different states. */
813 @Stable
814 public interface ChipBorder {
815     @Composable
816     /**
817      * Represents the border stroke for this chip, depending on [enabled] or null if no border
818      *
819      * @param enabled Whether the chip is enabled
820      */
borderStrokenull821     public fun borderStroke(enabled: Boolean): State<BorderStroke?>
822 }
823 
824 /** Contains the default values used by [Chip] */
825 public object ChipDefaults {
826 
827     /**
828      * Creates a [ChipColors] that represents the default background and content colors for a
829      * primary [Chip]. Primary chips have a colored background with a contrasting content color. If
830      * a chip is disabled then the colors will have an alpha([ContentAlpha.disabled]) value applied.
831      *
832      * @param backgroundColor The background color of this [Chip] when enabled
833      * @param contentColor The content color of this [Chip] when enabled
834      * @param secondaryContentColor The secondary content color of this [Chip] when enabled, used
835      *   for secondaryLabel content
836      * @param iconColor The icon color of this [Chip] when enabled, used for icon content
837      */
838     @Composable
839     public fun primaryChipColors(
840         backgroundColor: Color = MaterialTheme.colors.primary,
841         contentColor: Color = contentColorFor(backgroundColor),
842         secondaryContentColor: Color = contentColor,
843         iconColor: Color = contentColor
844     ): ChipColors {
845         // For light background colors, the default disabled content colors do not provide
846         // sufficient contrast. Instead, we default to using background for disabled content.
847         // See b/254025377
848         return chipColors(
849             backgroundColor = backgroundColor,
850             contentColor = contentColor,
851             secondaryContentColor = secondaryContentColor,
852             iconColor = iconColor,
853             disabledContentColor = MaterialTheme.colors.background,
854             disabledSecondaryContentColor = MaterialTheme.colors.background,
855             disabledIconColor = MaterialTheme.colors.background,
856         )
857     }
858 
859     /**
860      * Creates a [ChipColors] that represents the background and content colors for a primary [Chip]
861      * with a linear gradient for a background. The gradient will be between startBackgroundColor
862      * and endBackgroundColor. Gradient backgrounds are typically used for chips showing an on-going
863      * activity, such as a music track that is playing.
864      *
865      * Gradient background chips should have a content color that contrasts with the background
866      * gradient. If a chip is disabled then the colors will have an alpha([ContentAlpha.disabled])
867      * value applied.
868      *
869      * @param startBackgroundColor The background color used at the start of the gradient of this
870      *   [Chip] when enabled
871      * @param endBackgroundColor The background color used at the end of the gradient of this [Chip]
872      *   when enabled
873      * @param contentColor The content color of this [Chip] when enabled
874      * @param secondaryContentColor The secondary content color of this [Chip] when enabled, used
875      *   for secondaryLabel content
876      * @param iconColor The icon color of this [Chip] when enabled, used for icon content
877      * @param gradientDirection Whether the chips gradient should be start to end (indicated by
878      *   [LayoutDirection.Ltr]) or end to start (indicated by [LayoutDirection.Rtl]).
879      */
880     @Composable
881     public fun gradientBackgroundChipColors(
882         startBackgroundColor: Color =
883             MaterialTheme.colors.primary
884                 .copy(alpha = 0.5f)
885                 .compositeOver(MaterialTheme.colors.surface),
886         endBackgroundColor: Color =
887             MaterialTheme.colors.surface
888                 .copy(alpha = 0f)
889                 .compositeOver(MaterialTheme.colors.surface),
890         contentColor: Color = contentColorFor(endBackgroundColor),
891         secondaryContentColor: Color = contentColor,
892         iconColor: Color = contentColor,
893         gradientDirection: LayoutDirection = LocalLayoutDirection.current
894     ): ChipColors {
895         val backgroundColors: List<Color>
896         val disabledBackgroundColors: List<Color>
897         if (gradientDirection == LayoutDirection.Ltr) {
898             backgroundColors = listOf(startBackgroundColor, endBackgroundColor)
899             disabledBackgroundColors =
900                 listOf(
901                     startBackgroundColor.copy(alpha = ContentAlpha.disabled),
902                     endBackgroundColor.copy(alpha = ContentAlpha.disabled)
903                 )
904         } else {
905             backgroundColors = listOf(endBackgroundColor, startBackgroundColor)
906             disabledBackgroundColors =
907                 listOf(
908                     endBackgroundColor.copy(alpha = ContentAlpha.disabled),
909                     startBackgroundColor.copy(alpha = ContentAlpha.disabled),
910                 )
911         }
912         return DefaultChipColors(
913             backgroundPainter = BrushPainter(Brush.linearGradient(backgroundColors)),
914             contentColor = contentColor,
915             secondaryContentColor = secondaryContentColor,
916             iconColor = iconColor,
917             disabledBackgroundPainter =
918                 BrushPainter(Brush.linearGradient(disabledBackgroundColors)),
919             disabledContentColor = contentColor.copy(alpha = ContentAlpha.disabled),
920             disabledSecondaryContentColor =
921                 secondaryContentColor.copy(alpha = ContentAlpha.disabled),
922             disabledIconColor = iconColor.copy(alpha = ContentAlpha.disabled),
923         )
924     }
925 
926     /**
927      * Creates a [ChipColors] that represents the default background and content colors for a
928      * secondary [Chip]. Secondary chips have a muted background with a contrasting content color.
929      * If a chip is disabled then the colors will have an alpha([ContentAlpha.disabled]) value
930      * applied.
931      *
932      * @param backgroundColor The background color of this [Chip] when enabled
933      * @param contentColor The content color of this [Chip] when enabled
934      * @param secondaryContentColor The secondary content color of this [Chip] when enabled, used
935      *   for secondaryLabel content
936      * @param iconColor The icon color of this [Chip] when enabled, used for icon content
937      */
938     @Composable
939     public fun secondaryChipColors(
940         backgroundColor: Color = MaterialTheme.colors.surface,
941         contentColor: Color = contentColorFor(backgroundColor),
942         secondaryContentColor: Color = contentColor,
943         iconColor: Color = contentColor
944     ): ChipColors {
945         return chipColors(
946             backgroundColor = backgroundColor,
947             contentColor = contentColor,
948             secondaryContentColor = secondaryContentColor,
949             iconColor = iconColor
950         )
951     }
952 
953     /**
954      * Creates a [ChipColors] that represents the default background (transparent) and content
955      * colors for a child [Chip]. Child chips have a transparent background and use a default
956      * content color of [Colors.onSurface].
957      *
958      * If a chip is disabled then the colors will have an alpha([ContentAlpha.disabled]) value
959      * applied.
960      *
961      * @param contentColor The content color of this [Chip] when enabled
962      * @param secondaryContentColor The secondary content color of this [Chip] when enabled, used
963      *   for secondaryLabel content
964      * @param iconColor The icon color of this [Chip] when enabled, used for icon content
965      */
966     @Composable
967     public fun childChipColors(
968         contentColor: Color = MaterialTheme.colors.onSurface,
969         secondaryContentColor: Color = contentColor,
970         iconColor: Color = contentColor
971     ): ChipColors {
972         return chipColors(
973             backgroundColor = Color.Transparent,
974             contentColor = contentColor,
975             secondaryContentColor = secondaryContentColor,
976             iconColor = iconColor,
977             disabledBackgroundColor = Color.Transparent
978         )
979     }
980 
981     /**
982      * Creates a [ChipColors] for an image background [Chip]. Image background chips have an image
983      * as the background of the chip typically with a scrim over the image to ensure that the
984      * content is visible, and use a default content color of [Colors.onBackground].
985      *
986      * @param backgroundImagePainter The [Painter] to use to draw the background of the [Chip]
987      * @param backgroundImageScrimBrush The [Brush] to use to paint a scrim over the background
988      *   image to ensure that any text drawn over the image is legible
989      * @param contentColor The content color of this [Chip] when enabled
990      * @param secondaryContentColor The secondary content color of this [Chip] when enabled, used
991      *   for secondaryLabel content
992      * @param iconColor The icon color of this [Chip] when enabled, used for icon content
993      */
994     @Composable
995     public fun imageBackgroundChipColors(
996         backgroundImagePainter: Painter,
997         backgroundImageScrimBrush: Brush =
998             Brush.linearGradient(
999                 colors =
1000                     listOf(
1001                         MaterialTheme.colors.surface.copy(alpha = 1.0f),
1002                         MaterialTheme.colors.surface.copy(alpha = 0f)
1003                     )
1004             ),
1005         contentColor: Color = MaterialTheme.colors.onBackground,
1006         secondaryContentColor: Color = contentColor,
1007         iconColor: Color = contentColor,
1008     ): ChipColors {
1009         val backgroundPainter =
1010             remember(backgroundImagePainter, backgroundImageScrimBrush) {
1011                 ImageWithScrimPainter(
1012                     imagePainter = backgroundImagePainter,
1013                     brush = backgroundImageScrimBrush
1014                 )
1015             }
1016 
1017         val disabledContentAlpha = ContentAlpha.disabled
1018         val disabledBackgroundPainter =
1019             remember(backgroundImagePainter, backgroundImageScrimBrush, disabledContentAlpha) {
1020                 ImageWithScrimPainter(
1021                     imagePainter = backgroundImagePainter,
1022                     brush = backgroundImageScrimBrush,
1023                     alpha = disabledContentAlpha,
1024                 )
1025             }
1026         return DefaultChipColors(
1027             backgroundPainter = backgroundPainter,
1028             contentColor = contentColor,
1029             secondaryContentColor = secondaryContentColor,
1030             iconColor = iconColor,
1031             disabledBackgroundPainter = disabledBackgroundPainter,
1032             disabledContentColor = contentColor.copy(alpha = ContentAlpha.disabled),
1033             disabledSecondaryContentColor =
1034                 secondaryContentColor.copy(alpha = ContentAlpha.disabled),
1035             disabledIconColor = iconColor.copy(alpha = ContentAlpha.disabled),
1036         )
1037     }
1038 
1039     /**
1040      * Creates a [ChipColors] for an outline [Chip]. Outline chips have a transparent background
1041      * with a thin border.
1042      *
1043      * If a chip is disabled then the colors will have an alpha([ContentAlpha.disabled]) value
1044      * applied.
1045      *
1046      * @param contentColor The content color of this [Chip] when enabled
1047      * @param secondaryContentColor The secondary content color of this [Chip] when enabled, used
1048      *   for secondaryLabel content
1049      * @param iconColor The icon color of this [Chip] when enabled, used for icon content
1050      */
1051     @Composable
1052     public fun outlinedChipColors(
1053         contentColor: Color = MaterialTheme.colors.primary,
1054         secondaryContentColor: Color = contentColor,
1055         iconColor: Color = contentColor,
1056     ): ChipColors {
1057         return chipColors(
1058             backgroundColor = Color.Transparent,
1059             contentColor = contentColor,
1060             secondaryContentColor = secondaryContentColor,
1061             iconColor = iconColor,
1062             disabledBackgroundColor = Color.Transparent,
1063         )
1064     }
1065 
1066     /**
1067      * Creates a default (no border) [ChipBorder] for a [Chip]
1068      *
1069      * @param borderStroke The border for this [Chip] when enabled
1070      * @param disabledBorderStroke The border to use for this [Chip] when disabled
1071      */
1072     @Composable
1073     public fun chipBorder(
1074         borderStroke: BorderStroke? = null,
1075         disabledBorderStroke: BorderStroke? = null
1076     ): ChipBorder {
1077         return DefaultChipBorder(
1078             borderStroke = borderStroke,
1079             disabledBorderStroke = disabledBorderStroke
1080         )
1081     }
1082 
1083     /**
1084      * Creates a [ChipBorder] for an [OutlinedChip]
1085      *
1086      * @param borderColor The color to use for the border for this [OutlinedChip] when enabled
1087      * @param disabledBorderColor The color to use for the border for this [OutlinedChip] when
1088      *   disabled
1089      * @param borderWidth The width to use for the border for this [OutlinedChip]
1090      */
1091     @Composable
1092     public fun outlinedChipBorder(
1093         borderColor: Color = MaterialTheme.colors.primaryVariant.copy(alpha = 0.6f),
1094         disabledBorderColor: Color = borderColor.copy(alpha = ContentAlpha.disabled),
1095         borderWidth: Dp = 1.dp
1096     ): ChipBorder {
1097         return DefaultChipBorder(
1098             borderStroke = BorderStroke(borderWidth, borderColor),
1099             disabledBorderStroke = BorderStroke(borderWidth, disabledBorderColor)
1100         )
1101     }
1102 
1103     public val ChipHorizontalPadding: Dp = 14.dp
1104     public val ChipVerticalPadding: Dp = 6.dp
1105 
1106     /** The default content padding used by [Chip] */
1107     public val ContentPadding: PaddingValues =
1108         PaddingValues(
1109             start = ChipHorizontalPadding,
1110             top = ChipVerticalPadding,
1111             end = ChipHorizontalPadding,
1112             bottom = ChipVerticalPadding
1113         )
1114 
1115     public val CompactChipHorizontalPadding: Dp = 12.dp
1116     public val CompactChipVerticalPadding: Dp = 0.dp
1117 
1118     /** The default content padding used by [CompactChip] */
1119     public val CompactChipContentPadding: PaddingValues =
1120         PaddingValues(
1121             start = CompactChipHorizontalPadding,
1122             top = CompactChipVerticalPadding,
1123             end = CompactChipHorizontalPadding,
1124             bottom = CompactChipVerticalPadding
1125         )
1126 
1127     /**
1128      * The default height applied for the [Chip]. Note that you can override it by applying
1129      * Modifier.heightIn directly on [Chip].
1130      */
1131     public val Height: Dp = 52.dp
1132 
1133     /**
1134      * The height applied for the [CompactChip]. This includes a visible chip height of 32.dp and
1135      * 8.dp of padding above and below the chip in order to meet accessibility guidelines that
1136      * request a minimum of 48.dp height and width of tappable area.
1137      *
1138      * Note that you can override it by adjusting Modifier.height and Modifier.padding directly on
1139      * [CompactChip].
1140      */
1141     public val CompactChipHeight: Dp = 48.dp
1142 
1143     /**
1144      * The default padding to be provided around a [CompactChip] in order to ensure that its
1145      * tappable area meets minimum UX guidance.
1146      */
1147     public val CompactChipTapTargetPadding: PaddingValues = PaddingValues(top = 8.dp, bottom = 8.dp)
1148 
1149     /**
1150      * The default width applied for the [CompactChip] when it has no label provided. Note that you
1151      * can override it by applying Modifier.width directly on [CompactChip].
1152      */
1153     internal val IconOnlyCompactChipWidth = 52.dp
1154 
1155     /** The default size of the icon when used inside a [Chip]. */
1156     public val IconSize: Dp = 24.dp
1157 
1158     /** The size of the icon when used inside a Large "Avatar" [Chip]. */
1159     public val LargeIconSize: Dp = 32.dp
1160 
1161     /** The size of the icon when used inside a "Compact" [Chip]. */
1162     public val SmallIconSize: Dp = 20.dp
1163 
1164     /**
1165      * The default size of the spacing between an icon and a text when they are used inside a
1166      * [Chip].
1167      */
1168     internal val IconSpacing = 6.dp
1169 
1170     /**
1171      * Creates a [ChipColors] that represents the default background and content colors used in a
1172      * [Chip].
1173      *
1174      * @param backgroundColor The background color of this [Chip] when enabled
1175      * @param contentColor The content color of this [Chip] when enabled
1176      * @param secondaryContentColor The content color of this [Chip] when enabled
1177      * @param iconColor The content color of this [Chip] when enabled
1178      * @param disabledBackgroundColor The background color of this [Chip] when not enabled
1179      * @param disabledContentColor The content color of this [Chip] when not enabled
1180      * @param disabledSecondaryContentColor The content color of this [Chip] when not enabled
1181      * @param disabledIconColor The content color of this [Chip] when not enabled
1182      */
1183     @Composable
1184     public fun chipColors(
1185         backgroundColor: Color = MaterialTheme.colors.primary,
1186         contentColor: Color = contentColorFor(backgroundColor),
1187         secondaryContentColor: Color = contentColor,
1188         iconColor: Color = contentColor,
1189         disabledBackgroundColor: Color = backgroundColor.copy(alpha = ContentAlpha.disabled),
1190         disabledContentColor: Color = contentColor.copy(alpha = ContentAlpha.disabled),
1191         disabledSecondaryContentColor: Color =
1192             secondaryContentColor.copy(alpha = ContentAlpha.disabled),
1193         disabledIconColor: Color = iconColor.copy(alpha = ContentAlpha.disabled),
1194     ): ChipColors =
1195         DefaultChipColors(
1196             backgroundColor = backgroundColor,
1197             contentColor = contentColor,
1198             secondaryContentColor = secondaryContentColor,
1199             iconColor = iconColor,
1200             disabledBackgroundColor = disabledBackgroundColor,
1201             disabledContentColor = disabledContentColor,
1202             disabledSecondaryContentColor = disabledSecondaryContentColor,
1203             disabledIconColor = disabledIconColor
1204         )
1205 
1206     /**
1207      * Creates a [ChipColors] where all of the values are explicitly defined.
1208      *
1209      * @param backgroundPainter The background painter of this [Chip] when enabled
1210      * @param contentColor The content color of this [Chip] when enabled
1211      * @param secondaryContentColor The content color of this [Chip] when enabled
1212      * @param iconColor The content color of this [Chip] when enabled
1213      * @param disabledBackgroundPainter The background painter of this [Chip] when not enabled
1214      * @param disabledContentColor The content color of this [Chip] when not enabled
1215      * @param disabledSecondaryContentColor The content color of this [Chip] when not enabled
1216      * @param disabledIconColor The content color of this [Chip] when not enabled
1217      */
1218     @ExperimentalWearMaterialApi
1219     public fun chipColors(
1220         backgroundPainter: Painter,
1221         contentColor: Color,
1222         secondaryContentColor: Color,
1223         iconColor: Color,
1224         disabledBackgroundPainter: Painter,
1225         disabledContentColor: Color,
1226         disabledSecondaryContentColor: Color,
1227         disabledIconColor: Color,
1228     ): ChipColors =
1229         DefaultChipColors(
1230             backgroundPainter = backgroundPainter,
1231             contentColor = contentColor,
1232             secondaryContentColor = secondaryContentColor,
1233             iconColor = iconColor,
1234             disabledBackgroundPainter = disabledBackgroundPainter,
1235             disabledContentColor = disabledContentColor,
1236             disabledSecondaryContentColor = disabledSecondaryContentColor,
1237             disabledIconColor = disabledIconColor
1238         )
1239 }
1240 
1241 /** Default [ChipColors] implementation. */
1242 @Immutable
1243 internal class DefaultChipColors(
1244     private val backgroundPainter: Painter,
1245     private val contentColor: Color,
1246     private val secondaryContentColor: Color,
1247     private val iconColor: Color,
1248     private val disabledBackgroundPainter: Painter,
1249     private val disabledContentColor: Color,
1250     private val disabledSecondaryContentColor: Color,
1251     private val disabledIconColor: Color
1252 ) : ChipColors {
1253 
1254     constructor(
1255         backgroundColor: Color,
1256         contentColor: Color,
1257         secondaryContentColor: Color,
1258         iconColor: Color,
1259         disabledBackgroundColor: Color,
1260         disabledContentColor: Color,
1261         disabledSecondaryContentColor: Color,
1262         disabledIconColor: Color
1263     ) : this(
1264         ColorPainter(backgroundColor),
1265         contentColor,
1266         secondaryContentColor,
1267         iconColor,
1268         ColorPainter(disabledBackgroundColor),
1269         disabledContentColor,
1270         disabledSecondaryContentColor,
1271         disabledIconColor
1272     )
1273 
1274     @Composable
backgroundnull1275     override fun background(enabled: Boolean): State<Painter> {
1276         return rememberUpdatedState(if (enabled) backgroundPainter else disabledBackgroundPainter)
1277     }
1278 
1279     @Composable
contentColornull1280     override fun contentColor(enabled: Boolean): State<Color> {
1281         return rememberUpdatedState(if (enabled) contentColor else disabledContentColor)
1282     }
1283 
1284     @Composable
secondaryContentColornull1285     override fun secondaryContentColor(enabled: Boolean): State<Color> {
1286         return rememberUpdatedState(
1287             if (enabled) secondaryContentColor else disabledSecondaryContentColor
1288         )
1289     }
1290 
1291     @Composable
iconColornull1292     override fun iconColor(enabled: Boolean): State<Color> {
1293         return rememberUpdatedState(if (enabled) iconColor else disabledIconColor)
1294     }
1295 
equalsnull1296     override fun equals(other: Any?): Boolean {
1297         if (this === other) return true
1298         if (other == null) return false
1299         if (this::class != other::class) return false
1300 
1301         other as DefaultChipColors
1302 
1303         if (backgroundPainter != other.backgroundPainter) return false
1304         if (contentColor != other.contentColor) return false
1305         if (secondaryContentColor != other.secondaryContentColor) return false
1306         if (iconColor != other.iconColor) return false
1307         if (disabledBackgroundPainter != other.disabledBackgroundPainter) return false
1308         if (disabledContentColor != other.disabledContentColor) return false
1309         if (disabledSecondaryContentColor != other.disabledSecondaryContentColor) return false
1310         if (disabledIconColor != other.disabledIconColor) return false
1311 
1312         return true
1313     }
1314 
hashCodenull1315     override fun hashCode(): Int {
1316         var result = backgroundPainter.hashCode()
1317         result = 31 * result + contentColor.hashCode()
1318         result = 31 * result + secondaryContentColor.hashCode()
1319         result = 31 * result + iconColor.hashCode()
1320         result = 31 * result + disabledBackgroundPainter.hashCode()
1321         result = 31 * result + disabledContentColor.hashCode()
1322         result = 31 * result + disabledSecondaryContentColor.hashCode()
1323         result = 31 * result + disabledIconColor.hashCode()
1324         return result
1325     }
1326 }
1327 
1328 /** Default [ChipBorder] implementation. */
1329 @Immutable
1330 private class DefaultChipBorder(
1331     private val borderStroke: BorderStroke? = null,
1332     private val disabledBorderStroke: BorderStroke? = null
1333 ) : ChipBorder {
1334     @Composable
borderStrokenull1335     override fun borderStroke(enabled: Boolean): State<BorderStroke?> {
1336         return rememberUpdatedState(if (enabled) borderStroke else disabledBorderStroke)
1337     }
1338 
equalsnull1339     override fun equals(other: Any?): Boolean {
1340         if (this === other) return true
1341         if (other == null) return false
1342         if (this::class != other::class) return false
1343 
1344         other as DefaultChipBorder
1345 
1346         if (borderStroke != other.borderStroke) return false
1347         if (disabledBorderStroke != other.disabledBorderStroke) return false
1348 
1349         return true
1350     }
1351 
hashCodenull1352     override fun hashCode(): Int {
1353         var result = borderStroke.hashCode()
1354         result = 31 * result + disabledBorderStroke.hashCode()
1355         return result
1356     }
1357 }
1358 
1359 @Composable
chipSizeModifiernull1360 private fun Modifier.chipSizeModifier() =
1361     this.defaultMinSize(minHeight = ChipDefaults.Height).height(IntrinsicSize.Min)
1362 
1363 @Composable private fun Modifier.compactChipModifier() = this.height(ChipDefaults.CompactChipHeight)
1364 
1365 @Composable
1366 private fun ChipImpl(
1367     onClick: () -> Unit,
1368     colors: ChipColors,
1369     border: ChipBorder?,
1370     modifier: Modifier,
1371     enabled: Boolean,
1372     contentPadding: PaddingValues,
1373     shape: Shape,
1374     interactionSource: MutableInteractionSource?,
1375     role: Role? = Role.Button,
1376     content: @Composable RowScope.() -> Unit,
1377 ) {
1378     val borderStroke = border?.borderStroke(enabled)?.value
1379     val borderModifier =
1380         if (borderStroke != null) modifier.border(border = borderStroke, shape = shape)
1381         else modifier
1382     Row(
1383         modifier =
1384             borderModifier
1385                 .clip(shape = shape)
1386                 .width(intrinsicSize = IntrinsicSize.Max)
1387                 .paint(painter = colors.background(enabled).value, contentScale = ContentScale.Crop)
1388                 .clickable(
1389                     enabled = enabled,
1390                     onClick = onClick,
1391                     role = role,
1392                     indication = ripple(),
1393                     interactionSource = interactionSource,
1394                 )
1395                 .padding(contentPadding),
1396         content =
1397             provideScopeContent(
1398                 colors.contentColor(enabled = enabled),
1399                 MaterialTheme.typography.button,
1400                 content
1401             )
1402     )
1403 }
1404 
1405 @Composable
ChipImplnull1406 private fun ChipImpl(
1407     label: @Composable RowScope.() -> Unit,
1408     labelTypography: TextStyle,
1409     onClick: () -> Unit,
1410     modifier: Modifier,
1411     secondaryLabel: (@Composable RowScope.() -> Unit)?,
1412     icon: (@Composable BoxScope.() -> Unit)?,
1413     colors: ChipColors,
1414     enabled: Boolean,
1415     interactionSource: MutableInteractionSource?,
1416     contentPadding: PaddingValues,
1417     shape: Shape,
1418     border: ChipBorder?,
1419     defaultIconSpacing: Dp
1420 ) {
1421     ChipImpl(
1422         onClick = onClick,
1423         modifier = modifier,
1424         colors = colors,
1425         border = border,
1426         enabled = enabled,
1427         contentPadding = contentPadding,
1428         shape = shape,
1429         interactionSource = interactionSource,
1430     ) {
1431         Row(
1432             verticalAlignment = Alignment.CenterVertically,
1433             // Fill the container height but not its width as chips have fixed size height but we
1434             // want them to be able to fit their content
1435             modifier = Modifier.fillMaxHeight()
1436         ) {
1437             if (icon != null) {
1438                 Box(
1439                     modifier = Modifier.wrapContentSize(align = Alignment.Center),
1440                     content = provideIcon(colors.iconColor(enabled), icon)
1441                 )
1442                 Spacer(modifier = Modifier.size(defaultIconSpacing))
1443             }
1444             Column {
1445                 Row(
1446                     content =
1447                         provideScopeContent(colors.contentColor(enabled), labelTypography, label)
1448                 )
1449                 secondaryLabel?.let {
1450                     Row(
1451                         content =
1452                             provideScopeContent(
1453                                 colors.secondaryContentColor(enabled),
1454                                 MaterialTheme.typography.caption2,
1455                                 secondaryLabel
1456                             )
1457                     )
1458                 }
1459             }
1460         }
1461     }
1462 }
1463