1 /*
2  * Copyright 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package androidx.tv.material3
18 
19 import androidx.annotation.FloatRange
20 import androidx.compose.foundation.BorderStroke
21 import androidx.compose.foundation.interaction.Interaction
22 import androidx.compose.foundation.shape.CircleShape
23 import androidx.compose.runtime.Composable
24 import androidx.compose.runtime.ReadOnlyComposable
25 import androidx.compose.ui.graphics.Color
26 import androidx.compose.ui.graphics.Shape
27 import androidx.compose.ui.unit.dp
28 
29 object IconButtonDefaults {
30     private val ContainerShape = CircleShape
31 
32     /** The size of a small icon inside [IconButton] */
33     val SmallIconSize = 16.dp
34 
35     /** The size of a medium icon inside [IconButton] */
36     val MediumIconSize = 20.dp
37 
38     /** The size of a large icon inside [IconButton] */
39     val LargeIconSize = 28.dp
40 
41     /** The size of a small [IconButton] */
42     val SmallButtonSize = 28.dp
43 
44     /** The size of a medium [IconButton]. */
45     val MediumButtonSize = 40.dp
46 
47     /** The size of a large [IconButton]. */
48     val LargeButtonSize = 56.dp
49 
50     /**
51      * Creates a [ButtonShape] that represents the default container shapes used in a IconButton.
52      *
53      * @param shape the shape used when the Button is enabled, and has no other [Interaction]s.
54      * @param focusedShape the shape used when the Button is enabled and focused.
55      * @param pressedShape the shape used when the Button is enabled pressed.
56      * @param disabledShape the shape used when the Button is not enabled.
57      * @param focusedDisabledShape the shape used when the Button is not enabled and focused.
58      */
shapenull59     fun shape(
60         shape: Shape = ContainerShape,
61         focusedShape: Shape = shape,
62         pressedShape: Shape = shape,
63         disabledShape: Shape = shape,
64         focusedDisabledShape: Shape = disabledShape
65     ) =
66         ButtonShape(
67             shape = shape,
68             focusedShape = focusedShape,
69             pressedShape = pressedShape,
70             disabledShape = disabledShape,
71             focusedDisabledShape = focusedDisabledShape
72         )
73 
74     /**
75      * Creates a [ButtonColors] that represents the default colors used in a IconButton.
76      *
77      * @param containerColor the container color of this Button when enabled
78      * @param contentColor the content color of this Button when enabled
79      * @param focusedContainerColor the container color of this Button when enabled and focused
80      * @param focusedContentColor the content color of this Button when enabled and focused
81      * @param pressedContainerColor the container color of this Button when enabled and pressed
82      * @param pressedContentColor the content color of this Button when enabled and pressed
83      * @param disabledContainerColor the container color of this Button when not enabled
84      * @param disabledContentColor the content color of this Button when not enabled
85      */
86     @ReadOnlyComposable
87     @Composable
88     fun colors(
89         containerColor: Color = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.8f),
90         contentColor: Color = MaterialTheme.colorScheme.onSurface,
91         focusedContainerColor: Color = MaterialTheme.colorScheme.onSurface,
92         focusedContentColor: Color = MaterialTheme.colorScheme.inverseOnSurface,
93         pressedContainerColor: Color = focusedContainerColor,
94         pressedContentColor: Color = focusedContentColor,
95         disabledContainerColor: Color = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.4f),
96         disabledContentColor: Color = contentColor,
97     ) =
98         ButtonColors(
99             containerColor = containerColor,
100             contentColor = contentColor,
101             focusedContainerColor = focusedContainerColor,
102             focusedContentColor = focusedContentColor,
103             pressedContainerColor = pressedContainerColor,
104             pressedContentColor = pressedContentColor,
105             disabledContainerColor = disabledContainerColor,
106             disabledContentColor = disabledContentColor,
107         )
108 
109     /**
110      * Creates a [ButtonScale] that represents the default scales used in a IconButton. scales are
111      * used to modify the size of a composable in different [Interaction] states e.g. 1f (original)
112      * in default state, 1.2f (scaled up) in focused state, 0.8f (scaled down) in pressed state,
113      * etc.
114      *
115      * @param scale the scale to be used for this Button when enabled
116      * @param focusedScale the scale to be used for this Button when focused
117      * @param pressedScale the scale to be used for this Button when pressed
118      * @param disabledScale the scale to be used for this Button when disabled
119      * @param focusedDisabledScale the scale to be used for this Button when disabled and focused
120      */
121     fun scale(
122         @FloatRange(from = 0.0) scale: Float = 1f,
123         @FloatRange(from = 0.0) focusedScale: Float = 1.1f,
124         @FloatRange(from = 0.0) pressedScale: Float = scale,
125         @FloatRange(from = 0.0) disabledScale: Float = scale,
126         @FloatRange(from = 0.0) focusedDisabledScale: Float = disabledScale
127     ) =
128         ButtonScale(
129             scale = scale,
130             focusedScale = focusedScale,
131             pressedScale = pressedScale,
132             disabledScale = disabledScale,
133             focusedDisabledScale = focusedDisabledScale
134         )
135 
136     /**
137      * Creates a [ButtonBorder] that represents the default [Border]s applied on a IconButton in
138      * different [Interaction] states.
139      *
140      * @param border the [Border] to be used for this Button when enabled
141      * @param focusedBorder the [Border] to be used for this Button when focused
142      * @param pressedBorder the [Border] to be used for this Button when pressed
143      * @param disabledBorder the [Border] to be used for this Button when disabled
144      * @param focusedDisabledBorder the [Border] to be used for this Button when disabled and
145      *   focused
146      */
147     @ReadOnlyComposable
148     @Composable
149     fun border(
150         border: Border = Border.None,
151         focusedBorder: Border = border,
152         pressedBorder: Border = focusedBorder,
153         disabledBorder: Border = border,
154         focusedDisabledBorder: Border =
155             Border(
156                 border =
157                     BorderStroke(
158                         width = 2.dp,
159                         color = MaterialTheme.colorScheme.border.copy(alpha = 0.2f)
160                     ),
161                 shape = ContainerShape
162             )
163     ) =
164         ButtonBorder(
165             border = border,
166             focusedBorder = focusedBorder,
167             pressedBorder = pressedBorder,
168             disabledBorder = disabledBorder,
169             focusedDisabledBorder = focusedDisabledBorder
170         )
171 
172     /**
173      * Creates a [ButtonGlow] that represents the default [Glow]s used in a IconButton.
174      *
175      * @param glow the Glow behind this Button when enabled
176      * @param focusedGlow the Glow behind this Button when focused
177      * @param pressedGlow the Glow behind this Button when pressed
178      */
179     fun glow(glow: Glow = Glow.None, focusedGlow: Glow = glow, pressedGlow: Glow = glow) =
180         ButtonGlow(glow = glow, focusedGlow = focusedGlow, pressedGlow = pressedGlow)
181 }
182 
183 object OutlinedIconButtonDefaults {
184     private val ContainerShape = CircleShape
185 
186     val SmallIconSize = 16.dp
187     val MediumIconSize = 20.dp
188     val LargeIconSize = 28.dp
189 
190     /** The size of a small [OutlinedIconButton] */
191     val SmallButtonSize = 28.dp
192 
193     /** The size of a medium [OutlinedIconButton]. */
194     val MediumButtonSize = 40.dp
195 
196     /** The size of a large [OutlinedIconButton]. */
197     val LargeButtonSize = 56.dp
198 
199     /**
200      * Creates a [ButtonShape] that represents the default container shapes used in an
201      * OutlinedIconButton.
202      *
203      * @param shape the shape used when the Button is enabled, and has no other [Interaction]s.
204      * @param focusedShape the shape used when the Button is enabled and focused.
205      * @param pressedShape the shape used when the Button is enabled pressed.
206      * @param disabledShape the shape used when the Button is not enabled.
207      * @param focusedDisabledShape the shape used when the Button is not enabled and focused.
208      */
209     fun shape(
210         shape: Shape = ContainerShape,
211         focusedShape: Shape = shape,
212         pressedShape: Shape = shape,
213         disabledShape: Shape = shape,
214         focusedDisabledShape: Shape = disabledShape
215     ) =
216         ButtonShape(
217             shape = shape,
218             focusedShape = focusedShape,
219             pressedShape = pressedShape,
220             disabledShape = disabledShape,
221             focusedDisabledShape = focusedDisabledShape
222         )
223 
224     /**
225      * Creates a [ButtonColors] that represents the default colors used in a OutlinedIconButton.
226      *
227      * @param containerColor the container color of this Button when enabled
228      * @param contentColor the content color of this Button when enabled
229      * @param focusedContainerColor the container color of this Button when enabled and focused
230      * @param focusedContentColor the content color of this Button when enabled and focused
231      * @param pressedContainerColor the container color of this Button when enabled and pressed
232      * @param pressedContentColor the content color of this Button when enabled and pressed
233      * @param disabledContainerColor the container color of this Button when not enabled
234      * @param disabledContentColor the content color of this Button when not enabled
235      */
236     @ReadOnlyComposable
237     @Composable
238     fun colors(
239         containerColor: Color = Color.Transparent,
240         contentColor: Color = MaterialTheme.colorScheme.onSurface,
241         focusedContainerColor: Color = MaterialTheme.colorScheme.onSurface,
242         focusedContentColor: Color = MaterialTheme.colorScheme.inverseOnSurface,
243         pressedContainerColor: Color = focusedContainerColor,
244         pressedContentColor: Color = focusedContentColor,
245         disabledContainerColor: Color = containerColor,
246         disabledContentColor: Color = contentColor,
247     ) =
248         ButtonColors(
249             containerColor = containerColor,
250             contentColor = contentColor,
251             focusedContainerColor = focusedContainerColor,
252             focusedContentColor = focusedContentColor,
253             pressedContainerColor = pressedContainerColor,
254             pressedContentColor = pressedContentColor,
255             disabledContainerColor = disabledContainerColor,
256             disabledContentColor = disabledContentColor,
257         )
258 
259     /**
260      * Creates a [ButtonScale] that represents the default scales used in an OutlinedIconButton.
261      * scales are used to modify the size of a composable in different [Interaction] states e.g. 1f
262      * (original) in default state, 1.2f (scaled up) in focused state, 0.8f (scaled down) in pressed
263      * state, etc.
264      *
265      * @param scale the scale to be used for this Button when enabled
266      * @param focusedScale the scale to be used for this Button when focused
267      * @param pressedScale the scale to be used for this Button when pressed
268      * @param disabledScale the scale to be used for this Button when disabled
269      * @param focusedDisabledScale the scale to be used for this Button when disabled and focused
270      */
271     fun scale(
272         @FloatRange(from = 0.0) scale: Float = 1f,
273         @FloatRange(from = 0.0) focusedScale: Float = 1.1f,
274         @FloatRange(from = 0.0) pressedScale: Float = scale,
275         @FloatRange(from = 0.0) disabledScale: Float = scale,
276         @FloatRange(from = 0.0) focusedDisabledScale: Float = disabledScale
277     ) =
278         ButtonScale(
279             scale = scale,
280             focusedScale = focusedScale,
281             pressedScale = pressedScale,
282             disabledScale = disabledScale,
283             focusedDisabledScale = focusedDisabledScale
284         )
285 
286     /**
287      * Creates a [ButtonBorder] that represents the default [Border]s applied on an
288      * OutlinedIconButton in different [Interaction] states.
289      *
290      * @param border the [Border] to be used for this Button when enabled
291      * @param focusedBorder the [Border] to be used for this Button when focused
292      * @param pressedBorder the [Border] to be used for this Button when pressed
293      * @param disabledBorder the [Border] to be used for this Button when disabled
294      * @param focusedDisabledBorder the [Border] to be used for this Button when disabled and
295      *   focused
296      */
297     @ReadOnlyComposable
298     @Composable
299     fun border(
300         border: Border =
301             Border(
302                 border =
303                     BorderStroke(
304                         width = 2.dp,
305                         color = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.4f)
306                     ),
307                 shape = ContainerShape
308             ),
309         focusedBorder: Border =
310             Border(
311                 border = BorderStroke(width = 2.dp, color = MaterialTheme.colorScheme.onSurface),
312                 shape = ContainerShape
313             ),
314         pressedBorder: Border =
315             Border(
316                 border = BorderStroke(width = 2.dp, color = MaterialTheme.colorScheme.onSurface),
317                 shape = ContainerShape
318             ),
319         disabledBorder: Border =
320             Border(
321                 border =
322                     BorderStroke(
323                         width = 2.dp,
324                         color = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.2f)
325                     ),
326                 shape = ContainerShape
327             ),
328         focusedDisabledBorder: Border = disabledBorder
329     ) =
330         ButtonBorder(
331             border = border,
332             focusedBorder = focusedBorder,
333             pressedBorder = pressedBorder,
334             disabledBorder = disabledBorder,
335             focusedDisabledBorder = focusedDisabledBorder
336         )
337 
338     /**
339      * Creates a [ButtonGlow] that represents the default [Glow]s used in an OutlinedIconButton.
340      *
341      * @param glow the Glow behind this Button when enabled
342      * @param focusedGlow the Glow behind this Button when focused
343      * @param pressedGlow the Glow behind this Button when pressed
344      */
345     fun glow(glow: Glow = Glow.None, focusedGlow: Glow = glow, pressedGlow: Glow = glow) =
346         ButtonGlow(glow = glow, focusedGlow = focusedGlow, pressedGlow = pressedGlow)
347 }
348