You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
278 lines
11 KiB
Kotlin
278 lines
11 KiB
Kotlin
// Copyright (c) Tailscale Inc & AUTHORS
|
|
// SPDX-License-Identifier: BSD-3-Clause
|
|
|
|
package com.tailscale.ipn.ui.theme
|
|
|
|
import androidx.compose.foundation.isSystemInDarkTheme
|
|
import androidx.compose.material3.ButtonColors
|
|
import androidx.compose.material3.ButtonDefaults
|
|
import androidx.compose.material3.ColorScheme
|
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
|
import androidx.compose.material3.ListItemColors
|
|
import androidx.compose.material3.ListItemDefaults
|
|
import androidx.compose.material3.MaterialTheme
|
|
import androidx.compose.material3.OutlinedTextFieldDefaults
|
|
import androidx.compose.material3.TextFieldColors
|
|
import androidx.compose.material3.TopAppBarColors
|
|
import androidx.compose.material3.TopAppBarDefaults
|
|
import androidx.compose.material3.Typography
|
|
import androidx.compose.material3.lightColorScheme
|
|
import androidx.compose.runtime.Composable
|
|
import androidx.compose.runtime.DisposableEffect
|
|
import androidx.compose.ui.graphics.Color
|
|
import androidx.compose.ui.text.TextStyle
|
|
import androidx.compose.ui.unit.TextUnit
|
|
import androidx.compose.ui.unit.sp
|
|
import com.google.accompanist.systemuicontroller.rememberSystemUiController
|
|
|
|
@Composable
|
|
fun AppTheme(useDarkTheme: Boolean = isSystemInDarkTheme(), content: @Composable() () -> Unit) {
|
|
val colors = LightColors
|
|
|
|
val typography =
|
|
Typography(
|
|
// titleMedium is styled to be slightly larger than bodyMedium for emphasis
|
|
titleMedium =
|
|
MaterialTheme.typography.titleMedium.copy(fontSize = 18.sp, lineHeight = 26.sp),
|
|
// bodyMedium is styled to use same line height as titleMedium to ensure even vertical
|
|
// margins in list items.
|
|
bodyMedium = MaterialTheme.typography.bodyMedium.copy(fontSize = 16.sp))
|
|
|
|
val systemUiController = rememberSystemUiController()
|
|
|
|
DisposableEffect(systemUiController, useDarkTheme) {
|
|
systemUiController.setStatusBarColor(color = colors.surfaceContainer)
|
|
systemUiController.setNavigationBarColor(color = Color.Black)
|
|
onDispose {}
|
|
}
|
|
|
|
MaterialTheme(colorScheme = colors, typography = typography, content = content)
|
|
}
|
|
|
|
private val LightColors =
|
|
lightColorScheme(
|
|
primary = Color(0xFF4B70CC), // blue-500
|
|
onPrimary = Color(0xFFFFFFFF), // white
|
|
primaryContainer = Color(0xFFF0F5FF), // blue-0
|
|
onPrimaryContainer = Color(0xFF3E5DB3), // blue-600
|
|
error = Color(0xFFB22C30), // red-500
|
|
onError = Color(0xFFFFFFFF), // white
|
|
errorContainer = Color(0xFFFEF6F3), // red-0
|
|
onErrorContainer = Color(0xFF930921), // red-600
|
|
surfaceDim = Color(0xFFF7F5F4), // gray-100
|
|
surface = Color(0xFFFFFFFF), // white,
|
|
background = Color(0xFFF7F5F4), // gray-100
|
|
surfaceBright = Color(0xFFFFFFFF), // white
|
|
surfaceContainerLowest = Color(0xFFFFFFFF), // white
|
|
surfaceContainerLow = Color(0xFFF7F5F4), // gray-100
|
|
surfaceContainer = Color(0xFFF7F5F4), // gray-100
|
|
surfaceContainerHigh = Color(0xFFF7F5F4), // gray-100
|
|
surfaceContainerHighest = Color(0xFFF7F5F4), // gray-100
|
|
surfaceVariant = Color(0xFFF7F5F4), // gray-100,
|
|
onSurface = Color(0xFF232222), // gray-800
|
|
onSurfaceVariant = Color(0xFF706E6D), // gray-500
|
|
outline = Color(0xFF706E6D), // gray-500
|
|
outlineVariant = Color(0xFFEDEBEA), // gray-200
|
|
inverseSurface = Color(0xFF232222), // gray-800
|
|
inverseOnSurface = Color(0xFFFFFFFF), // white
|
|
scrim = Color(0xAA000000), // black
|
|
)
|
|
|
|
val ColorScheme.warning: Color
|
|
get() = Color(0xFFD97916) // yellow-300
|
|
|
|
val ColorScheme.onWarning: Color
|
|
get() = Color(0xFFFFFFFF) // white
|
|
|
|
val ColorScheme.warningContainer: Color
|
|
get() = Color(0xFFFFFAEE) // orange-0
|
|
|
|
val ColorScheme.onWarningContainer: Color
|
|
get() = Color(0xFF7E1E22) // orange-600
|
|
|
|
val ColorScheme.success: Color
|
|
get() = Color(0xFF0A825D) // green-400
|
|
|
|
val ColorScheme.onSuccess: Color
|
|
get() = Color(0xFFFFFFFF) // white
|
|
|
|
val ColorScheme.successContainer: Color
|
|
get() = Color(0xFFEFFEEC) // green-0
|
|
|
|
val ColorScheme.onSuccessContainer: Color
|
|
get() = Color(0xFF0E4B3B) // green-600
|
|
|
|
val ColorScheme.on: Color
|
|
get() = Color(0xFF1CA672) // green-300
|
|
|
|
val ColorScheme.off: Color
|
|
get() = Color(0xFFD9D6D5) // gray-300
|
|
|
|
val ColorScheme.link: Color
|
|
get() = onPrimaryContainer
|
|
|
|
/**
|
|
* Main color scheme for list items, uses onPrimaryContainer color for leading and trailing icons.
|
|
*/
|
|
val ColorScheme.listItem: ListItemColors
|
|
@Composable
|
|
get() {
|
|
val default = ListItemDefaults.colors()
|
|
return ListItemColors(
|
|
containerColor = default.containerColor,
|
|
headlineColor = default.headlineColor,
|
|
leadingIconColor = MaterialTheme.colorScheme.onPrimaryContainer,
|
|
overlineColor = default.overlineColor,
|
|
supportingTextColor = default.supportingTextColor,
|
|
trailingIconColor = MaterialTheme.colorScheme.onPrimaryContainer,
|
|
disabledHeadlineColor = default.disabledHeadlineColor,
|
|
disabledLeadingIconColor = default.disabledLeadingIconColor,
|
|
disabledTrailingIconColor = default.disabledTrailingIconColor)
|
|
}
|
|
|
|
/** Like listItem, but with the overline content using the onSurface color. */
|
|
val ColorScheme.titledListItem: ListItemColors
|
|
@Composable
|
|
get() {
|
|
val default = listItem
|
|
return ListItemColors(
|
|
containerColor = default.containerColor,
|
|
headlineColor = default.headlineColor,
|
|
leadingIconColor = default.leadingIconColor,
|
|
overlineColor = MaterialTheme.colorScheme.onSurface,
|
|
supportingTextColor = default.supportingTextColor,
|
|
trailingIconColor = default.trailingIconColor,
|
|
disabledHeadlineColor = default.disabledHeadlineColor,
|
|
disabledLeadingIconColor = default.disabledLeadingIconColor,
|
|
disabledTrailingIconColor = default.disabledTrailingIconColor)
|
|
}
|
|
|
|
/** Color scheme for disabled list items. */
|
|
val ColorScheme.disabledListItem: ListItemColors
|
|
@Composable
|
|
get() {
|
|
val default = ListItemDefaults.colors()
|
|
return ListItemColors(
|
|
containerColor = default.containerColor,
|
|
headlineColor = MaterialTheme.colorScheme.disabled,
|
|
leadingIconColor = default.leadingIconColor,
|
|
overlineColor = default.overlineColor,
|
|
supportingTextColor = MaterialTheme.colorScheme.onSurfaceVariant,
|
|
trailingIconColor = default.trailingIconColor,
|
|
disabledHeadlineColor = default.disabledHeadlineColor,
|
|
disabledLeadingIconColor = default.disabledLeadingIconColor,
|
|
disabledTrailingIconColor = default.disabledTrailingIconColor)
|
|
}
|
|
|
|
/** Color scheme for list items that should be styled as a surface container. */
|
|
val ColorScheme.surfaceContainerListItem: ListItemColors
|
|
@Composable
|
|
get() {
|
|
val default = ListItemDefaults.colors()
|
|
return ListItemColors(
|
|
containerColor = MaterialTheme.colorScheme.surfaceContainer,
|
|
headlineColor = MaterialTheme.colorScheme.onSurface,
|
|
leadingIconColor = MaterialTheme.colorScheme.onSurface,
|
|
overlineColor = MaterialTheme.colorScheme.onSurfaceVariant,
|
|
supportingTextColor = MaterialTheme.colorScheme.onSurfaceVariant,
|
|
trailingIconColor = MaterialTheme.colorScheme.onSurface,
|
|
disabledHeadlineColor = default.disabledHeadlineColor,
|
|
disabledLeadingIconColor = default.disabledLeadingIconColor,
|
|
disabledTrailingIconColor = default.disabledTrailingIconColor)
|
|
}
|
|
|
|
/** Color scheme for list items that should be styled as a primary item. */
|
|
val ColorScheme.primaryListItem: ListItemColors
|
|
@Composable
|
|
get() {
|
|
val default = ListItemDefaults.colors()
|
|
return ListItemColors(
|
|
containerColor = MaterialTheme.colorScheme.primary,
|
|
headlineColor = MaterialTheme.colorScheme.onPrimary,
|
|
leadingIconColor = MaterialTheme.colorScheme.onPrimary,
|
|
overlineColor = MaterialTheme.colorScheme.onPrimary.copy(alpha = 0.7f),
|
|
supportingTextColor = MaterialTheme.colorScheme.onPrimary,
|
|
trailingIconColor = MaterialTheme.colorScheme.onPrimary,
|
|
disabledHeadlineColor = default.disabledHeadlineColor,
|
|
disabledLeadingIconColor = default.disabledLeadingIconColor,
|
|
disabledTrailingIconColor = default.disabledTrailingIconColor)
|
|
}
|
|
|
|
/** Color scheme for list items that should be styled as a warning item. */
|
|
val ColorScheme.warningListItem: ListItemColors
|
|
@Composable
|
|
get() {
|
|
val default = ListItemDefaults.colors()
|
|
return ListItemColors(
|
|
containerColor = MaterialTheme.colorScheme.warning,
|
|
headlineColor = MaterialTheme.colorScheme.onPrimary,
|
|
leadingIconColor = MaterialTheme.colorScheme.onPrimary,
|
|
overlineColor = MaterialTheme.colorScheme.onPrimary.copy(alpha = 0.7f),
|
|
supportingTextColor = MaterialTheme.colorScheme.onPrimary,
|
|
trailingIconColor = MaterialTheme.colorScheme.onPrimary,
|
|
disabledHeadlineColor = default.disabledHeadlineColor,
|
|
disabledLeadingIconColor = default.disabledLeadingIconColor,
|
|
disabledTrailingIconColor = default.disabledTrailingIconColor)
|
|
}
|
|
|
|
/** Main color scheme for top app bar, styles it as a surface container. */
|
|
@OptIn(ExperimentalMaterial3Api::class)
|
|
val ColorScheme.topAppBar: TopAppBarColors
|
|
@Composable
|
|
get() =
|
|
TopAppBarDefaults.topAppBarColors()
|
|
.copy(
|
|
containerColor = MaterialTheme.colorScheme.surfaceContainer,
|
|
navigationIconContentColor = MaterialTheme.colorScheme.onSurface,
|
|
titleContentColor = MaterialTheme.colorScheme.onSurface,
|
|
)
|
|
|
|
val ColorScheme.secondaryButton: ButtonColors
|
|
@Composable
|
|
get() {
|
|
val defaults = ButtonDefaults.buttonColors()
|
|
return ButtonColors(
|
|
containerColor = Color(0xFF6D94EC), // blue-400
|
|
contentColor = Color(0xFFFFFFFF), // white
|
|
disabledContainerColor = defaults.disabledContainerColor,
|
|
disabledContentColor = defaults.disabledContentColor)
|
|
}
|
|
|
|
val ColorScheme.button: ButtonColors
|
|
@Composable
|
|
get() {
|
|
val defaults = ButtonDefaults.buttonColors()
|
|
return ButtonColors(
|
|
containerColor = Color(0xFF4B70CC), // blue-500
|
|
contentColor = Color(0xFFFFFFFF), // white
|
|
disabledContainerColor = defaults.disabledContainerColor,
|
|
disabledContentColor = defaults.disabledContentColor)
|
|
}
|
|
|
|
val ColorScheme.disabled: Color
|
|
get() = Color(0xFFAFACAB) // gray-400
|
|
|
|
@OptIn(ExperimentalMaterial3Api::class)
|
|
val ColorScheme.searchBarColors: TextFieldColors
|
|
@Composable
|
|
get() {
|
|
val defaults = OutlinedTextFieldDefaults.colors()
|
|
return OutlinedTextFieldDefaults.colors(
|
|
focusedLeadingIconColor = MaterialTheme.colorScheme.onSurface,
|
|
unfocusedLeadingIconColor = MaterialTheme.colorScheme.onSurface,
|
|
focusedTextColor = MaterialTheme.colorScheme.onSurface,
|
|
unfocusedTextColor = MaterialTheme.colorScheme.onSurfaceVariant,
|
|
disabledTextColor = MaterialTheme.colorScheme.onSurfaceVariant,
|
|
focusedContainerColor = MaterialTheme.colorScheme.background,
|
|
unfocusedContainerColor = MaterialTheme.colorScheme.background,
|
|
disabledContainerColor = MaterialTheme.colorScheme.background,
|
|
focusedBorderColor = Color.Transparent,
|
|
unfocusedBorderColor = Color.Transparent)
|
|
}
|
|
|
|
val TextStyle.short: TextStyle
|
|
get() = copy(lineHeight = 20.sp)
|
|
|
|
val Typography.minTextSize: TextUnit
|
|
get() = 10.sp
|