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.animation.fadeIn
21 import androidx.compose.animation.fadeOut
22 import androidx.compose.animation.slideIn
23 import androidx.compose.animation.slideOut
24 import androidx.compose.foundation.BorderStroke
25 import androidx.compose.foundation.background
26 import androidx.compose.foundation.interaction.Interaction
27 import androidx.compose.foundation.layout.Box
28 import androidx.compose.foundation.layout.PaddingValues
29 import androidx.compose.foundation.layout.padding
30 import androidx.compose.foundation.shape.RoundedCornerShape
31 import androidx.compose.runtime.Composable
32 import androidx.compose.runtime.ReadOnlyComposable
33 import androidx.compose.ui.Modifier
34 import androidx.compose.ui.graphics.Color
35 import androidx.compose.ui.graphics.Shape
36 import androidx.compose.ui.unit.IntOffset
37 import androidx.compose.ui.unit.dp
38 import androidx.tv.material3.tokens.Elevation
39 
40 /** Contains the default values used by selectable [NavigationDrawerItem] */
41 object NavigationDrawerItemDefaults {
42     /** The default Icon size used by [NavigationDrawerItem] */
43     val IconSize = 24.dp
44 
45     /** The size of the [NavigationDrawerItem] when the drawer is collapsed */
46     val CollapsedDrawerItemWidth = 56.dp
47 
48     /** The size of the [NavigationDrawerItem] when the drawer is expanded */
49     val ExpandedDrawerItemWidth = 256.dp
50 
51     /**
52      * The default content padding [PaddingValues] used by [NavigationDrawerItem] with 1 line when
53      * the drawer is expanded
54      */
55     val ContainerHeightOneLine = 48.dp
56 
57     /**
58      * The default content padding [PaddingValues] used by [NavigationDrawerItem] with 2 lines when
59      * the drawer is expanded
60      */
61     val ContainerHeightTwoLine = 56.dp
62 
63     /** The default elevation used by [NavigationDrawerItem] */
64     val NavigationDrawerItemElevation = Elevation.Level0
65 
66     /** Animation enter default for inner content */
<lambda>null67     val ContentAnimationEnter = fadeIn() + slideIn { IntOffset(-it.width, 0) }
68 
69     /** Animation exit default for inner content */
<lambda>null70     val ContentAnimationExit = fadeOut() + slideOut { IntOffset(0, 0) }
71 
72     /** Default border used by [NavigationDrawerItem] */
73     val DefaultBorder
74         @ReadOnlyComposable
75         @Composable
76         get() =
77             Border(
78                 border = BorderStroke(width = 2.dp, color = MaterialTheme.colorScheme.border),
79             )
80 
81     /** The default container color used by [NavigationDrawerItem]'s trailing badge */
82     val TrailingBadgeContainerColor
83         @ReadOnlyComposable @Composable get() = MaterialTheme.colorScheme.tertiary
84 
85     /** The default text style used by [NavigationDrawerItem]'s trailing badge */
86     val TrailingBadgeTextStyle
87         @ReadOnlyComposable @Composable get() = MaterialTheme.typography.labelSmall
88 
89     /** The default content color used by [NavigationDrawerItem]'s trailing badge */
90     val TrailingBadgeContentColor
91         @ReadOnlyComposable @Composable get() = MaterialTheme.colorScheme.onTertiary
92 
93     /** Creates a trailing badge for [NavigationDrawerItem] */
94     @Composable
95     @OptIn(
96         ExperimentalTvMaterial3Api::class
97     ) // TODO: This will be removed once Text API is marked as stable
TrailingBadgenull98     fun TrailingBadge(
99         text: String,
100         containerColor: Color = TrailingBadgeContainerColor,
101         contentColor: Color = TrailingBadgeContentColor
102     ) {
103         Box(
104             modifier =
105                 Modifier.background(containerColor, RoundedCornerShape(50)).padding(10.dp, 2.dp)
106         ) {
107             ProvideTextStyle(value = TrailingBadgeTextStyle) {
108                 Text(
109                     text = text,
110                     color = contentColor,
111                 )
112             }
113         }
114     }
115 
116     /**
117      * Creates a [NavigationDrawerItemShape] that represents the default container shapes used in a
118      * selectable [NavigationDrawerItem]
119      *
120      * @param shape the default shape used when the [NavigationDrawerItem] is enabled
121      * @param focusedShape the shape used when the [NavigationDrawerItem] is enabled and focused
122      * @param pressedShape the shape used when the [NavigationDrawerItem] is enabled and pressed
123      * @param selectedShape the shape used when the [NavigationDrawerItem] is enabled and selected
124      * @param disabledShape the shape used when the [NavigationDrawerItem] is not enabled
125      * @param focusedSelectedShape the shape used when the [NavigationDrawerItem] is enabled,
126      *   focused and selected
127      * @param focusedDisabledShape the shape used when the [NavigationDrawerItem] is not enabled and
128      *   focused
129      * @param pressedSelectedShape the shape used when the [NavigationDrawerItem] is enabled,
130      *   pressed and selected
131      */
shapenull132     fun shape(
133         shape: Shape = RoundedCornerShape(50),
134         focusedShape: Shape = shape,
135         pressedShape: Shape = shape,
136         selectedShape: Shape = shape,
137         disabledShape: Shape = shape,
138         focusedSelectedShape: Shape = shape,
139         focusedDisabledShape: Shape = disabledShape,
140         pressedSelectedShape: Shape = shape
141     ) =
142         NavigationDrawerItemShape(
143             shape = shape,
144             focusedShape = focusedShape,
145             pressedShape = pressedShape,
146             selectedShape = selectedShape,
147             disabledShape = disabledShape,
148             focusedSelectedShape = focusedSelectedShape,
149             focusedDisabledShape = focusedDisabledShape,
150             pressedSelectedShape = pressedSelectedShape
151         )
152 
153     /**
154      * Creates a [NavigationDrawerItemColors] that represents the default container & content colors
155      * used in a selectable [NavigationDrawerItem]
156      *
157      * @param containerColor the default container color used when the [NavigationDrawerItem] is
158      *   enabled
159      * @param contentColor the default content color used when the [NavigationDrawerItem] is enabled
160      * @param inactiveContentColor the content color used when none of the navigation items have
161      *   focus
162      * @param focusedContainerColor the container color used when the [NavigationDrawerItem] is
163      *   enabled and focused
164      * @param focusedContentColor the content color used when the [NavigationDrawerItem] is enabled
165      *   and focused
166      * @param pressedContainerColor the container color used when the [NavigationDrawerItem] is
167      *   enabled and pressed
168      * @param pressedContentColor the content color used when the [NavigationDrawerItem] is enabled
169      *   and pressed
170      * @param selectedContainerColor the container color used when the [NavigationDrawerItem] is
171      *   enabled and selected
172      * @param selectedContentColor the content color used when the [NavigationDrawerItem] is enabled
173      *   and selected
174      * @param disabledContainerColor the container color used when the [NavigationDrawerItem] is not
175      *   enabled
176      * @param disabledContentColor the content color used when the [NavigationDrawerItem] is not
177      *   enabled
178      * @param disabledInactiveContentColor the content color used when none of the navigation items
179      *   have focus and this item is disabled
180      * @param focusedSelectedContainerColor the container color used when the NavigationDrawerItem
181      *   is enabled, focused and selected
182      * @param focusedSelectedContentColor the content color used when the [NavigationDrawerItem] is
183      *   enabled, focused and selected
184      * @param pressedSelectedContainerColor the container color used when the [NavigationDrawerItem]
185      *   is enabled, pressed and selected
186      * @param pressedSelectedContentColor the content color used when the [NavigationDrawerItem] is
187      *   enabled, pressed and selected
188      */
189     @ReadOnlyComposable
190     @Composable
191     fun colors(
192         containerColor: Color = Color.Transparent,
193         contentColor: Color = MaterialTheme.colorScheme.onSurface,
194         inactiveContentColor: Color = contentColor.copy(alpha = 0.4f),
195         focusedContainerColor: Color = MaterialTheme.colorScheme.inverseSurface,
196         focusedContentColor: Color = contentColorFor(focusedContainerColor),
197         pressedContainerColor: Color = focusedContainerColor,
198         pressedContentColor: Color = contentColorFor(focusedContainerColor),
199         selectedContainerColor: Color =
200             MaterialTheme.colorScheme.secondaryContainer.copy(alpha = 0.4f),
201         selectedContentColor: Color = MaterialTheme.colorScheme.onSecondaryContainer,
202         disabledContainerColor: Color = Color.Transparent,
203         disabledContentColor: Color = MaterialTheme.colorScheme.onSurface,
204         disabledInactiveContentColor: Color = disabledContentColor.copy(alpha = 0.4f),
205         focusedSelectedContainerColor: Color = focusedContainerColor,
206         focusedSelectedContentColor: Color = focusedContentColor,
207         pressedSelectedContainerColor: Color = pressedContainerColor,
208         pressedSelectedContentColor: Color = pressedContentColor
209     ) =
210         NavigationDrawerItemColors(
211             containerColor = containerColor,
212             contentColor = contentColor,
213             inactiveContentColor = inactiveContentColor,
214             focusedContainerColor = focusedContainerColor,
215             focusedContentColor = focusedContentColor,
216             pressedContainerColor = pressedContainerColor,
217             pressedContentColor = pressedContentColor,
218             selectedContainerColor = selectedContainerColor,
219             selectedContentColor = selectedContentColor,
220             disabledContainerColor = disabledContainerColor,
221             disabledContentColor = disabledContentColor,
222             disabledInactiveContentColor = disabledInactiveContentColor,
223             focusedSelectedContainerColor = focusedSelectedContainerColor,
224             focusedSelectedContentColor = focusedSelectedContentColor,
225             pressedSelectedContainerColor = pressedSelectedContainerColor,
226             pressedSelectedContentColor = pressedSelectedContentColor
227         )
228 
229     /**
230      * Creates a [NavigationDrawerItemScale] that represents the default scales used in a selectable
231      * [NavigationDrawerItem]
232      *
233      * scales are used to modify the size of a composable in different [Interaction] states e.g.
234      * `1f` (original) in default state, `1.2f` (scaled up) in focused state, `0.8f` (scaled down)
235      * in pressed state, etc.
236      *
237      * @param scale the scale used when the [NavigationDrawerItem] is enabled
238      * @param focusedScale the scale used when the [NavigationDrawerItem] is enabled and focused
239      * @param pressedScale the scale used when the [NavigationDrawerItem] is enabled and pressed
240      * @param selectedScale the scale used when the [NavigationDrawerItem] is enabled and selected
241      * @param disabledScale the scale used when the [NavigationDrawerItem] is not enabled
242      * @param focusedSelectedScale the scale used when the [NavigationDrawerItem] is enabled,
243      *   focused and selected
244      * @param focusedDisabledScale the scale used when the [NavigationDrawerItem] is not enabled and
245      *   focused
246      * @param pressedSelectedScale the scale used when the [NavigationDrawerItem] is enabled,
247      *   pressed and selected
248      */
249     fun scale(
250         @FloatRange(from = 0.0) scale: Float = 1f,
251         @FloatRange(from = 0.0) focusedScale: Float = 1.05f,
252         @FloatRange(from = 0.0) pressedScale: Float = scale,
253         @FloatRange(from = 0.0) selectedScale: Float = scale,
254         @FloatRange(from = 0.0) disabledScale: Float = scale,
255         @FloatRange(from = 0.0) focusedSelectedScale: Float = focusedScale,
256         @FloatRange(from = 0.0) focusedDisabledScale: Float = disabledScale,
257         @FloatRange(from = 0.0) pressedSelectedScale: Float = scale
258     ) =
259         NavigationDrawerItemScale(
260             scale = scale,
261             focusedScale = focusedScale,
262             pressedScale = pressedScale,
263             selectedScale = selectedScale,
264             disabledScale = disabledScale,
265             focusedSelectedScale = focusedSelectedScale,
266             focusedDisabledScale = focusedDisabledScale,
267             pressedSelectedScale = pressedSelectedScale
268         )
269 
270     /**
271      * Creates a [NavigationDrawerItemBorder] that represents the default [Border]s applied on a
272      * selectable [NavigationDrawerItem] in different [Interaction] states
273      *
274      * @param border the default [Border] used when the [NavigationDrawerItem] is enabled
275      * @param focusedBorder the [Border] used when the [NavigationDrawerItem] is enabled and focused
276      * @param pressedBorder the [Border] used when the [NavigationDrawerItem] is enabled and pressed
277      * @param selectedBorder the [Border] used when the [NavigationDrawerItem] is enabled and
278      *   selected
279      * @param disabledBorder the [Border] used when the [NavigationDrawerItem] is not enabled
280      * @param focusedSelectedBorder the [Border] used when the [NavigationDrawerItem] is enabled,
281      *   focused and selected
282      * @param focusedDisabledBorder the [Border] used when the [NavigationDrawerItem] is not enabled
283      *   and focused
284      * @param pressedSelectedBorder the [Border] used when the [NavigationDrawerItem] is enabled,
285      *   pressed and selected
286      */
287     @ReadOnlyComposable
288     @Composable
289     fun border(
290         border: Border = Border.None,
291         focusedBorder: Border = border,
292         pressedBorder: Border = focusedBorder,
293         selectedBorder: Border = border,
294         disabledBorder: Border = border,
295         focusedSelectedBorder: Border = focusedBorder,
296         focusedDisabledBorder: Border = DefaultBorder,
297         pressedSelectedBorder: Border = border
298     ) =
299         NavigationDrawerItemBorder(
300             border = border,
301             focusedBorder = focusedBorder,
302             pressedBorder = pressedBorder,
303             selectedBorder = selectedBorder,
304             disabledBorder = disabledBorder,
305             focusedSelectedBorder = focusedSelectedBorder,
306             focusedDisabledBorder = focusedDisabledBorder,
307             pressedSelectedBorder = pressedSelectedBorder
308         )
309 
310     /**
311      * Creates a [NavigationDrawerItemGlow] that represents the default [Glow]s used in a selectable
312      * [NavigationDrawerItem]
313      *
314      * @param glow the [Glow] used when the [NavigationDrawerItem] is enabled, and has no other
315      *   [Interaction]s
316      * @param focusedGlow the [Glow] used when the [NavigationDrawerItem] is enabled and focused
317      * @param pressedGlow the [Glow] used when the [NavigationDrawerItem] is enabled and pressed
318      * @param selectedGlow the [Glow] used when the [NavigationDrawerItem] is enabled and selected
319      * @param focusedSelectedGlow the [Glow] used when the [NavigationDrawerItem] is enabled,
320      *   focused and selected
321      * @param pressedSelectedGlow the [Glow] used when the [NavigationDrawerItem] is enabled,
322      *   pressed and selected
323      */
324     fun glow(
325         glow: Glow = Glow.None,
326         focusedGlow: Glow = glow,
327         pressedGlow: Glow = glow,
328         selectedGlow: Glow = glow,
329         focusedSelectedGlow: Glow = focusedGlow,
330         pressedSelectedGlow: Glow = glow
331     ) =
332         NavigationDrawerItemGlow(
333             glow = glow,
334             focusedGlow = focusedGlow,
335             pressedGlow = pressedGlow,
336             selectedGlow = selectedGlow,
337             focusedSelectedGlow = focusedSelectedGlow,
338             pressedSelectedGlow = pressedSelectedGlow
339         )
340 }
341