/*
* Copyright 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package androidx.tv.material3
import androidx.annotation.FloatRange
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.slideIn
import androidx.compose.animation.slideOut
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.background
import androidx.compose.foundation.interaction.Interaction
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.runtime.Composable
import androidx.compose.runtime.ReadOnlyComposable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.dp
import androidx.tv.material3.tokens.Elevation
/**
* Contains the default values used by selectable [NavigationDrawerItem]
*/
object NavigationDrawerItemDefaults {
/**
* The default Icon size used by [NavigationDrawerItem]
*/
val IconSize = 24.dp
/**
* The size of the [NavigationDrawerItem] when the drawer is collapsed
*/
val CollapsedDrawerItemWidth = 56.dp
/**
* The size of the [NavigationDrawerItem] when the drawer is expanded
*/
val ExpandedDrawerItemWidth = 256.dp
/**
* The default content padding [PaddingValues] used by [NavigationDrawerItem] with 1 line when
* the drawer is expanded
*/
val ContainerHeightOneLine = 56.dp
/**
* The default content padding [PaddingValues] used by [NavigationDrawerItem] with 2 lines when
* the drawer is expanded
*/
val ContainerHeightTwoLine = 64.dp
/**
* The default elevation used by [NavigationDrawerItem]
*/
val NavigationDrawerItemElevation = Elevation.Level0
/**
* Animation enter default for inner content
*/
val ContentAnimationEnter = fadeIn() + slideIn { IntOffset(-it.width, 0) }
/**
* Animation exit default for inner content
*/
val ContentAnimationExit = fadeOut() + slideOut { IntOffset(0, 0) }
/**
* Default border used by [NavigationDrawerItem]
*/
val DefaultBorder
@ReadOnlyComposable
@Composable get() = Border(
border = BorderStroke(
width = 2.dp,
color = MaterialTheme.colorScheme.border
),
)
/**
* The default container color used by [NavigationDrawerItem]'s trailing badge
*/
val TrailingBadgeContainerColor
@ReadOnlyComposable
@Composable get() = MaterialTheme.colorScheme.tertiary
/**
* The default text style used by [NavigationDrawerItem]'s trailing badge
*/
val TrailingBadgeTextStyle
@ReadOnlyComposable
@Composable get() = MaterialTheme.typography.labelSmall
/**
* The default content color used by [NavigationDrawerItem]'s trailing badge
*/
val TrailingBadgeContentColor
@ReadOnlyComposable
@Composable get() = MaterialTheme.colorScheme.onTertiary
/**
* Creates a trailing badge for [NavigationDrawerItem]
*/
@Composable
@OptIn(ExperimentalTvMaterial3Api::class) // TODO: This will be removed once Text API is marked as stable
fun TrailingBadge(
text: String,
containerColor: Color = TrailingBadgeContainerColor,
contentColor: Color = TrailingBadgeContentColor
) {
Box(
modifier = Modifier
.background(containerColor, RoundedCornerShape(50))
.padding(10.dp, 2.dp)
) {
ProvideTextStyle(value = TrailingBadgeTextStyle) {
Text(
text = text,
color = contentColor,
)
}
}
}
/**
* Creates a [NavigationDrawerItemShape] that represents the default container shapes
* used in a selectable [NavigationDrawerItem]
*
* @param shape the default shape used when the [NavigationDrawerItem] is enabled
* @param focusedShape the shape used when the [NavigationDrawerItem] is enabled and focused
* @param pressedShape the shape used when the [NavigationDrawerItem] is enabled and pressed
* @param selectedShape the shape used when the [NavigationDrawerItem] is enabled and selected
* @param disabledShape the shape used when the [NavigationDrawerItem] is not enabled
* @param focusedSelectedShape the shape used when the [NavigationDrawerItem] is enabled,
* focused and selected
* @param focusedDisabledShape the shape used when the [NavigationDrawerItem] is not enabled
* and focused
* @param pressedSelectedShape the shape used when the [NavigationDrawerItem] is enabled,
* pressed and selected
*/
fun shape(
shape: Shape = RoundedCornerShape(50),
focusedShape: Shape = shape,
pressedShape: Shape = shape,
selectedShape: Shape = shape,
disabledShape: Shape = shape,
focusedSelectedShape: Shape = shape,
focusedDisabledShape: Shape = disabledShape,
pressedSelectedShape: Shape = shape
) = NavigationDrawerItemShape(
shape = shape,
focusedShape = focusedShape,
pressedShape = pressedShape,
selectedShape = selectedShape,
disabledShape = disabledShape,
focusedSelectedShape = focusedSelectedShape,
focusedDisabledShape = focusedDisabledShape,
pressedSelectedShape = pressedSelectedShape
)
/**
* Creates a [NavigationDrawerItemColors] that represents the default container &
* content colors used in a selectable [NavigationDrawerItem]
*
* @param containerColor the default container color used when the [NavigationDrawerItem] is
* enabled
* @param contentColor the default content color used when the [NavigationDrawerItem] is enabled
* @param inactiveContentColor the content color used when none of the navigation items have
* focus
* @param focusedContainerColor the container color used when the [NavigationDrawerItem] is
* enabled and focused
* @param focusedContentColor the content color used when the [NavigationDrawerItem] is enabled
* and focused
* @param pressedContainerColor the container color used when the [NavigationDrawerItem] is
* enabled and pressed
* @param pressedContentColor the content color used when the [NavigationDrawerItem] is enabled
* and pressed
* @param selectedContainerColor the container color used when the [NavigationDrawerItem] is
* enabled and selected
* @param selectedContentColor the content color used when the [NavigationDrawerItem] is
* enabled and selected
* @param disabledContainerColor the container color used when the [NavigationDrawerItem] is
* not enabled
* @param disabledContentColor the content color used when the [NavigationDrawerItem] is not
* enabled
* @param disabledInactiveContentColor the content color used when none of the navigation items
* have focus and this item is disabled
* @param focusedSelectedContainerColor the container color used when the
* NavigationDrawerItem is enabled, focused and selected
* @param focusedSelectedContentColor the content color used when the [NavigationDrawerItem]
* is enabled, focused and selected
* @param pressedSelectedContainerColor the container color used when the
* [NavigationDrawerItem] is enabled, pressed and selected
* @param pressedSelectedContentColor the content color used when the [NavigationDrawerItem] is
* enabled, pressed and selected
*/
@ReadOnlyComposable
@Composable
fun colors(
containerColor: Color = Color.Transparent,
contentColor: Color = MaterialTheme.colorScheme.onSurface,
inactiveContentColor: Color = contentColor.copy(alpha = 0.4f),
focusedContainerColor: Color = MaterialTheme.colorScheme.inverseSurface,
focusedContentColor: Color = contentColorFor(focusedContainerColor),
pressedContainerColor: Color = focusedContainerColor,
pressedContentColor: Color = contentColorFor(focusedContainerColor),
selectedContainerColor: Color =
MaterialTheme.colorScheme.secondaryContainer.copy(alpha = 0.4f),
selectedContentColor: Color = MaterialTheme.colorScheme.onSecondaryContainer,
disabledContainerColor: Color = Color.Transparent,
disabledContentColor: Color = MaterialTheme.colorScheme.onSurface,
disabledInactiveContentColor: Color = disabledContentColor.copy(alpha = 0.4f),
focusedSelectedContainerColor: Color = focusedContainerColor,
focusedSelectedContentColor: Color = focusedContentColor,
pressedSelectedContainerColor: Color = pressedContainerColor,
pressedSelectedContentColor: Color = pressedContentColor
) = NavigationDrawerItemColors(
containerColor = containerColor,
contentColor = contentColor,
inactiveContentColor = inactiveContentColor,
focusedContainerColor = focusedContainerColor,
focusedContentColor = focusedContentColor,
pressedContainerColor = pressedContainerColor,
pressedContentColor = pressedContentColor,
selectedContainerColor = selectedContainerColor,
selectedContentColor = selectedContentColor,
disabledContainerColor = disabledContainerColor,
disabledContentColor = disabledContentColor,
disabledInactiveContentColor = disabledInactiveContentColor,
focusedSelectedContainerColor = focusedSelectedContainerColor,
focusedSelectedContentColor = focusedSelectedContentColor,
pressedSelectedContainerColor = pressedSelectedContainerColor,
pressedSelectedContentColor = pressedSelectedContentColor
)
/**
* Creates a [NavigationDrawerItemScale] that represents the default scales used in a
* selectable [NavigationDrawerItem]
*
* scales are used to modify the size of a composable in different [Interaction] states
* e.g. `1f` (original) in default state, `1.2f` (scaled up) in focused state, `0.8f` (scaled
* down) in pressed state, etc.
*
* @param scale the scale used when the [NavigationDrawerItem] is enabled
* @param focusedScale the scale used when the [NavigationDrawerItem] is enabled and focused
* @param pressedScale the scale used when the [NavigationDrawerItem] is enabled and pressed
* @param selectedScale the scale used when the [NavigationDrawerItem] is enabled and selected
* @param disabledScale the scale used when the [NavigationDrawerItem] is not enabled
* @param focusedSelectedScale the scale used when the [NavigationDrawerItem] is enabled,
* focused and selected
* @param focusedDisabledScale the scale used when the [NavigationDrawerItem] is not enabled and
* focused
* @param pressedSelectedScale the scale used when the [NavigationDrawerItem] is enabled,
* pressed and selected
*/
fun scale(
@FloatRange(from = 0.0) scale: Float = 1f,
@FloatRange(from = 0.0) focusedScale: Float = 1.05f,
@FloatRange(from = 0.0) pressedScale: Float = scale,
@FloatRange(from = 0.0) selectedScale: Float = scale,
@FloatRange(from = 0.0) disabledScale: Float = scale,
@FloatRange(from = 0.0) focusedSelectedScale: Float = focusedScale,
@FloatRange(from = 0.0) focusedDisabledScale: Float = disabledScale,
@FloatRange(from = 0.0) pressedSelectedScale: Float = scale
) = NavigationDrawerItemScale(
scale = scale,
focusedScale = focusedScale,
pressedScale = pressedScale,
selectedScale = selectedScale,
disabledScale = disabledScale,
focusedSelectedScale = focusedSelectedScale,
focusedDisabledScale = focusedDisabledScale,
pressedSelectedScale = pressedSelectedScale
)
/**
* Creates a [NavigationDrawerItemBorder] that represents the default [Border]s
* applied on a selectable [NavigationDrawerItem] in different [Interaction] states
*
* @param border the default [Border] used when the [NavigationDrawerItem] is enabled
* @param focusedBorder the [Border] used when the [NavigationDrawerItem] is enabled and focused
* @param pressedBorder the [Border] used when the [NavigationDrawerItem] is enabled and pressed
* @param selectedBorder the [Border] used when the [NavigationDrawerItem] is enabled and
* selected
* @param disabledBorder the [Border] used when the [NavigationDrawerItem] is not enabled
* @param focusedSelectedBorder the [Border] used when the [NavigationDrawerItem] is enabled,
* focused and selected
* @param focusedDisabledBorder the [Border] used when the [NavigationDrawerItem] is not
* enabled and focused
* @param pressedSelectedBorder the [Border] used when the [NavigationDrawerItem] is enabled,
* pressed and selected
*/
@ReadOnlyComposable
@Composable
fun border(
border: Border = Border.None,
focusedBorder: Border = border,
pressedBorder: Border = focusedBorder,
selectedBorder: Border = border,
disabledBorder: Border = border,
focusedSelectedBorder: Border = focusedBorder,
focusedDisabledBorder: Border = DefaultBorder,
pressedSelectedBorder: Border = border
) = NavigationDrawerItemBorder(
border = border,
focusedBorder = focusedBorder,
pressedBorder = pressedBorder,
selectedBorder = selectedBorder,
disabledBorder = disabledBorder,
focusedSelectedBorder = focusedSelectedBorder,
focusedDisabledBorder = focusedDisabledBorder,
pressedSelectedBorder = pressedSelectedBorder
)
/**
* Creates a [NavigationDrawerItemGlow] that represents the default [Glow]s used in a
* selectable [NavigationDrawerItem]
*
* @param glow the [Glow] used when the [NavigationDrawerItem] is enabled, and has no other
* [Interaction]s
* @param focusedGlow the [Glow] used when the [NavigationDrawerItem] is enabled and focused
* @param pressedGlow the [Glow] used when the [NavigationDrawerItem] is enabled and pressed
* @param selectedGlow the [Glow] used when the [NavigationDrawerItem] is enabled and selected
* @param focusedSelectedGlow the [Glow] used when the [NavigationDrawerItem] is enabled,
* focused and selected
* @param pressedSelectedGlow the [Glow] used when the [NavigationDrawerItem] is enabled,
* pressed and selected
*/
fun glow(
glow: Glow = Glow.None,
focusedGlow: Glow = glow,
pressedGlow: Glow = glow,
selectedGlow: Glow = glow,
focusedSelectedGlow: Glow = focusedGlow,
pressedSelectedGlow: Glow = glow
) = NavigationDrawerItemGlow(
glow = glow,
focusedGlow = focusedGlow,
pressedGlow = pressedGlow,
selectedGlow = selectedGlow,
focusedSelectedGlow = focusedSelectedGlow,
pressedSelectedGlow = pressedSelectedGlow
)
}