Link Compound's TypographyTokens to ElementTheme. (#700)

* Link Compound's `TypographyTokens` to `ElementTheme`.

Also add some docs about when we should use each set of tokens.

* Renamed `LocalColors` to `LocalLegacyColors`.

Made both `LocalLegacyColors` and `LocalCompoundColors` internal. This means it will need to always be used through `ElementTheme.`

Also, removed any usages of `LocalColors.current` accross the project, they're now used through `ElementTheme.legacyColors`.
This commit is contained in:
Jorge Martin Espinosa 2023-06-28 10:53:20 +02:00 committed by GitHub
parent d3d8ba0cd2
commit c5a5810c05
21 changed files with 78 additions and 53 deletions

View file

@ -55,12 +55,12 @@ import io.element.android.libraries.designsystem.atomic.pages.HeaderFooterPage
import io.element.android.libraries.designsystem.preview.ElementPreviewDark import io.element.android.libraries.designsystem.preview.ElementPreviewDark
import io.element.android.libraries.designsystem.preview.ElementPreviewLight import io.element.android.libraries.designsystem.preview.ElementPreviewLight
import io.element.android.libraries.designsystem.text.buildAnnotatedStringWithStyledPart import io.element.android.libraries.designsystem.text.buildAnnotatedStringWithStyledPart
import io.element.android.libraries.theme.LocalColors
import io.element.android.libraries.designsystem.theme.components.Button import io.element.android.libraries.designsystem.theme.components.Button
import io.element.android.libraries.designsystem.theme.components.Icon import io.element.android.libraries.designsystem.theme.components.Icon
import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.theme.components.TextButton import io.element.android.libraries.designsystem.theme.components.TextButton
import io.element.android.libraries.designsystem.utils.LogCompositions import io.element.android.libraries.designsystem.utils.LogCompositions
import io.element.android.libraries.theme.ElementTheme
import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.libraries.ui.strings.CommonStrings
@Composable @Composable
@ -162,7 +162,7 @@ private fun AnalyticsOptInContentRow(
modifier = modifier modifier = modifier
.fillMaxWidth() .fillMaxWidth()
.background( .background(
color = LocalColors.current.quinary, color = ElementTheme.legacyColors.quinary,
shape = bgShape, shape = bgShape,
) )
.padding(vertical = 12.dp, horizontal = 20.dp), .padding(vertical = 12.dp, horizontal = 20.dp),
@ -174,8 +174,7 @@ private fun AnalyticsOptInContentRow(
.padding(2.dp), .padding(2.dp),
imageVector = Icons.Rounded.Check, imageVector = Icons.Rounded.Check,
contentDescription = null, contentDescription = null,
// TODO Compound, this color is not yet in the theme tint = ElementTheme.colors.iconSuccessPrimary,
tint = Color(0xFF007A61)
) )
Text( Text(
modifier = Modifier.padding(start = 16.dp), modifier = Modifier.padding(start = 16.dp),

View file

@ -67,7 +67,7 @@ import kotlin.coroutines.suspendCoroutine
fun MapView( fun MapView(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
mapState: MapState = rememberMapState(), mapState: MapState = rememberMapState(),
darkMode: Boolean = !ElementTheme.colors.isLight, darkMode: Boolean = !ElementTheme.isLightTheme,
onLocationClick: () -> Unit, onLocationClick: () -> Unit,
) { ) {
// When in preview, early return a Box with the received modifier preserving layout // When in preview, early return a Box with the received modifier preserving layout

View file

@ -34,11 +34,11 @@ import androidx.compose.ui.unit.dp
import coil.compose.AsyncImagePainter import coil.compose.AsyncImagePainter
import coil.compose.rememberAsyncImagePainter import coil.compose.rememberAsyncImagePainter
import coil.request.ImageRequest import coil.request.ImageRequest
import io.element.android.features.location.api.internal.StaticMapPlaceholder
import io.element.android.features.location.api.internal.buildStaticMapsApiUrl
import io.element.android.libraries.designsystem.preview.ElementPreviewDark import io.element.android.libraries.designsystem.preview.ElementPreviewDark
import io.element.android.libraries.designsystem.preview.ElementPreviewLight import io.element.android.libraries.designsystem.preview.ElementPreviewLight
import io.element.android.libraries.designsystem.theme.components.Icon import io.element.android.libraries.designsystem.theme.components.Icon
import io.element.android.features.location.api.internal.StaticMapPlaceholder
import io.element.android.features.location.api.internal.buildStaticMapsApiUrl
import io.element.android.libraries.theme.ElementTheme import io.element.android.libraries.theme.ElementTheme
import timber.log.Timber import timber.log.Timber
@ -52,7 +52,7 @@ fun StaticMapView(
zoom: Double, zoom: Double,
contentDescription: String?, contentDescription: String?,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
darkMode: Boolean = !ElementTheme.colors.isLight, darkMode: Boolean = !ElementTheme.isLightTheme,
) { ) {
// Using BoxWithConstraints to: // Using BoxWithConstraints to:
// 1) Size the inner Image to the same Dp size of the outer BoxWithConstraints. // 1) Size the inner Image to the same Dp size of the outer BoxWithConstraints.

View file

@ -33,12 +33,12 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.tooling.preview.PreviewParameterProvider import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import io.element.android.features.location.api.R
import io.element.android.libraries.designsystem.preview.ElementPreviewDark import io.element.android.libraries.designsystem.preview.ElementPreviewDark
import io.element.android.libraries.designsystem.preview.ElementPreviewLight import io.element.android.libraries.designsystem.preview.ElementPreviewLight
import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator
import io.element.android.libraries.designsystem.theme.components.Icon import io.element.android.libraries.designsystem.theme.components.Icon
import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.features.location.api.R
import io.element.android.libraries.theme.ElementTheme import io.element.android.libraries.theme.ElementTheme
import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.libraries.ui.strings.CommonStrings
@ -47,7 +47,7 @@ internal fun StaticMapPlaceholder(
showProgress: Boolean, showProgress: Boolean,
contentDescription: String?, contentDescription: String?,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
darkMode: Boolean = !ElementTheme.colors.isLight, darkMode: Boolean = !ElementTheme.isLightTheme,
onLoadMapClick: () -> Unit, onLoadMapClick: () -> Unit,
) { ) {
Box( Box(

View file

@ -18,6 +18,7 @@ package io.element.android.features.login.impl
import android.app.Activity import android.app.Activity
import android.os.Parcelable import android.os.Parcelable
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.DisposableEffect
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
@ -45,9 +46,9 @@ import io.element.android.libraries.architecture.NodeInputs
import io.element.android.libraries.architecture.animation.rememberDefaultTransitionHandler import io.element.android.libraries.architecture.animation.rememberDefaultTransitionHandler
import io.element.android.libraries.architecture.createNode import io.element.android.libraries.architecture.createNode
import io.element.android.libraries.architecture.inputs import io.element.android.libraries.architecture.inputs
import io.element.android.libraries.theme.ElementTheme
import io.element.android.libraries.di.AppScope import io.element.android.libraries.di.AppScope
import io.element.android.libraries.matrix.api.auth.OidcDetails import io.element.android.libraries.matrix.api.auth.OidcDetails
import io.element.android.libraries.theme.ElementTheme
import kotlinx.parcelize.Parcelize import kotlinx.parcelize.Parcelize
@ContributesNode(AppScope::class) @ContributesNode(AppScope::class)
@ -155,7 +156,7 @@ class LoginFlowNode @AssistedInject constructor(
@Composable @Composable
override fun View(modifier: Modifier) { override fun View(modifier: Modifier) {
activity = LocalContext.current as? Activity activity = LocalContext.current as? Activity
darkTheme = !ElementTheme.colors.isLight darkTheme = !ElementTheme.isLightTheme
DisposableEffect(Unit) { DisposableEffect(Unit) {
onDispose { onDispose {
activity = null activity = null

View file

@ -98,12 +98,12 @@ fun MessageEventBubble(
} }
val backgroundBubbleColor = if (state.isHighlighted) { val backgroundBubbleColor = if (state.isHighlighted) {
ElementTheme.colors.messageHighlightedBackground ElementTheme.legacyColors.messageHighlightedBackground
} else { } else {
if (state.isMine) { if (state.isMine) {
ElementTheme.colors.messageFromMeBackground ElementTheme.legacyColors.messageFromMeBackground
} else { } else {
ElementTheme.colors.messageFromOtherBackground ElementTheme.legacyColors.messageFromOtherBackground
} }
} }
val bubbleShape = bubbleShape() val bubbleShape = bubbleShape()

View file

@ -49,7 +49,7 @@ fun MessageStateEventContainer(
content: @Composable () -> Unit = {}, content: @Composable () -> Unit = {},
) { ) {
val backgroundColor = if (isHighlighted) { val backgroundColor = if (isHighlighted) {
ElementTheme.colors.messageHighlightedBackground ElementTheme.legacyColors.messageHighlightedBackground
} else { } else {
Color.Companion.Transparent Color.Companion.Transparent
} }

View file

@ -48,7 +48,7 @@ fun MessagesReactionButton(reaction: AggregatedReaction, modifier: Modifier = Mo
Surface( Surface(
modifier = modifier, modifier = modifier,
// TODO Should use compound.bgSubtlePrimary // TODO Should use compound.bgSubtlePrimary
color = ElementTheme.colors.gray300, color = ElementTheme.legacyColors.gray300,
border = BorderStroke(2.dp, MaterialTheme.colorScheme.background), border = BorderStroke(2.dp, MaterialTheme.colorScheme.background),
shape = RoundedCornerShape(corner = CornerSize(14.dp)), shape = RoundedCornerShape(corner = CornerSize(14.dp)),
) { ) {

View file

@ -63,7 +63,6 @@ import io.element.android.libraries.designsystem.ElementTextStyles
import io.element.android.libraries.designsystem.components.EqualWidthColumn import io.element.android.libraries.designsystem.components.EqualWidthColumn
import io.element.android.libraries.designsystem.components.avatar.Avatar import io.element.android.libraries.designsystem.components.avatar.Avatar
import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarData
import io.element.android.libraries.theme.LocalColors
import io.element.android.libraries.designsystem.preview.ElementPreviewDark import io.element.android.libraries.designsystem.preview.ElementPreviewDark
import io.element.android.libraries.designsystem.preview.ElementPreviewLight import io.element.android.libraries.designsystem.preview.ElementPreviewLight
import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.Text
@ -76,6 +75,7 @@ import io.element.android.libraries.matrix.api.timeline.item.event.VideoMessageT
import io.element.android.libraries.matrix.ui.components.AttachmentThumbnail import io.element.android.libraries.matrix.ui.components.AttachmentThumbnail
import io.element.android.libraries.matrix.ui.components.AttachmentThumbnailInfo import io.element.android.libraries.matrix.ui.components.AttachmentThumbnailInfo
import io.element.android.libraries.matrix.ui.components.AttachmentThumbnailType import io.element.android.libraries.matrix.ui.components.AttachmentThumbnailType
import io.element.android.libraries.theme.ElementTheme
import org.jsoup.Jsoup import org.jsoup.Jsoup
@Composable @Composable
@ -251,7 +251,7 @@ private fun MessageEventBubbleContent(
onClick = onTimestampClicked, onClick = onTimestampClicked,
modifier = timestampModifier modifier = timestampModifier
.padding(horizontal = 4.dp, vertical = 4.dp) // Outer padding .padding(horizontal = 4.dp, vertical = 4.dp) // Outer padding
.background(LocalColors.current.gray300, RoundedCornerShape(10.0.dp)) .background(ElementTheme.legacyColors.gray300, RoundedCornerShape(10.0.dp))
.align(Alignment.BottomEnd) .align(Alignment.BottomEnd)
.padding(horizontal = 4.dp, vertical = 2.dp) // Inner padding .padding(horizontal = 4.dp, vertical = 2.dp) // Inner padding
) )
@ -364,7 +364,7 @@ private fun ReplyToContent(
text = text.orEmpty(), text = text.orEmpty(),
style = ElementTextStyles.Regular.caption1, style = ElementTextStyles.Regular.caption1,
textAlign = TextAlign.Start, textAlign = TextAlign.Start,
color = LocalColors.current.placeholder, color = ElementTheme.legacyColors.placeholder,
maxLines = 1, maxLines = 1,
overflow = TextOverflow.Ellipsis, overflow = TextOverflow.Ellipsis,
) )

View file

@ -54,7 +54,7 @@ fun GroupHeaderView(
modifier: Modifier = Modifier modifier: Modifier = Modifier
) { ) {
val backgroundColor = if (isHighlighted) { val backgroundColor = if (isHighlighted) {
ElementTheme.colors.messageHighlightedBackground ElementTheme.legacyColors.messageHighlightedBackground
} else { } else {
Color.Companion.Transparent Color.Companion.Transparent
} }

View file

@ -55,7 +55,7 @@ internal fun RoomSummaryPlaceholderRow(
modifier = Modifier modifier = Modifier
.size(AvatarSize.RoomListItem.dp) .size(AvatarSize.RoomListItem.dp)
.align(Alignment.CenterVertically) .align(Alignment.CenterVertically)
.background(color = ElementTheme.compoundColors.textPlaceholder, shape = CircleShape) .background(color = ElementTheme.colors.textPlaceholder, shape = CircleShape)
) )
Column( Column(
modifier = Modifier modifier = Modifier

View file

@ -36,7 +36,7 @@ fun PlaceholderAtom(
width: Dp, width: Dp,
height: Dp, height: Dp,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
color: Color = ElementTheme.compoundColors.textPlaceholder, color: Color = ElementTheme.colors.textPlaceholder,
) { ) {
Box( Box(
modifier = modifier modifier = modifier

View file

@ -35,8 +35,8 @@ import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import io.element.android.libraries.designsystem.preview.ElementPreviewDark import io.element.android.libraries.designsystem.preview.ElementPreviewDark
import io.element.android.libraries.designsystem.preview.ElementPreviewLight import io.element.android.libraries.designsystem.preview.ElementPreviewLight
import io.element.android.libraries.theme.LocalColors
import io.element.android.libraries.designsystem.theme.components.Icon import io.element.android.libraries.designsystem.theme.components.Icon
import io.element.android.libraries.theme.ElementTheme
/** /**
* RoundedIconAtom is an atom which displays an icon inside a rounded container. * RoundedIconAtom is an atom which displays an icon inside a rounded container.
@ -59,7 +59,7 @@ fun RoundedIconAtom(
modifier = modifier modifier = modifier
.size(size.toContainerSize()) .size(size.toContainerSize())
.background( .background(
color = LocalColors.current.quinary, color = ElementTheme.legacyColors.quinary,
shape = RoundedCornerShape(size.toCornerSize()) shape = RoundedCornerShape(size.toCornerSize())
) )
) { ) {

View file

@ -51,7 +51,7 @@ fun ModalBottomSheet(
shape: Shape = BottomSheetDefaults.ExpandedShape, shape: Shape = BottomSheetDefaults.ExpandedShape,
containerColor: Color = BottomSheetDefaults.ContainerColor, containerColor: Color = BottomSheetDefaults.ContainerColor,
contentColor: Color = contentColorFor(containerColor), contentColor: Color = contentColorFor(containerColor),
tonalElevation: Dp = if (ElementTheme.colors.isLight) 0.dp else BottomSheetDefaults.Elevation, tonalElevation: Dp = if (ElementTheme.isLightTheme) 0.dp else BottomSheetDefaults.Elevation,
scrimColor: Color = BottomSheetDefaults.ScrimColor, scrimColor: Color = BottomSheetDefaults.ScrimColor,
dragHandle: @Composable (() -> Unit)? = { BottomSheetDefaults.DragHandle() }, dragHandle: @Composable (() -> Unit)? = { BottomSheetDefaults.DragHandle() },
windowInsets: WindowInsets = BottomSheetDefaults.windowInsets, windowInsets: WindowInsets = BottomSheetDefaults.windowInsets,

View file

@ -46,7 +46,7 @@ import androidx.compose.ui.unit.dp
import io.element.android.libraries.designsystem.components.button.BackButton import io.element.android.libraries.designsystem.components.button.BackButton
import io.element.android.libraries.designsystem.preview.ElementThemedPreview import io.element.android.libraries.designsystem.preview.ElementThemedPreview
import io.element.android.libraries.designsystem.preview.PreviewGroup import io.element.android.libraries.designsystem.preview.PreviewGroup
import io.element.android.libraries.theme.LocalColors import io.element.android.libraries.theme.ElementTheme
import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.libraries.ui.strings.CommonStrings
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@ -156,10 +156,10 @@ object ElementSearchBarDefaults {
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
fun inactiveColors() = SearchBarDefaults.colors( fun inactiveColors() = SearchBarDefaults.colors(
containerColor = LocalColors.current.gray300, containerColor = ElementTheme.legacyColors.gray300,
inputFieldColors = TextFieldDefaults.colors( inputFieldColors = TextFieldDefaults.colors(
unfocusedPlaceholderColor = LocalColors.current.placeholder, unfocusedPlaceholderColor = ElementTheme.legacyColors.placeholder,
focusedPlaceholderColor = LocalColors.current.placeholder, focusedPlaceholderColor = ElementTheme.legacyColors.placeholder,
unfocusedLeadingIconColor = MaterialTheme.colorScheme.primary, unfocusedLeadingIconColor = MaterialTheme.colorScheme.primary,
focusedLeadingIconColor = MaterialTheme.colorScheme.primary, focusedLeadingIconColor = MaterialTheme.colorScheme.primary,
unfocusedTrailingIconColor = MaterialTheme.colorScheme.primary, unfocusedTrailingIconColor = MaterialTheme.colorScheme.primary,
@ -172,8 +172,8 @@ object ElementSearchBarDefaults {
fun activeColors() = SearchBarDefaults.colors( fun activeColors() = SearchBarDefaults.colors(
containerColor = Color.Transparent, containerColor = Color.Transparent,
inputFieldColors = TextFieldDefaults.colors( inputFieldColors = TextFieldDefaults.colors(
unfocusedPlaceholderColor = LocalColors.current.placeholder, unfocusedPlaceholderColor = ElementTheme.legacyColors.placeholder,
focusedPlaceholderColor = LocalColors.current.placeholder, focusedPlaceholderColor = ElementTheme.legacyColors.placeholder,
unfocusedLeadingIconColor = MaterialTheme.colorScheme.primary, unfocusedLeadingIconColor = MaterialTheme.colorScheme.primary,
focusedLeadingIconColor = MaterialTheme.colorScheme.primary, focusedLeadingIconColor = MaterialTheme.colorScheme.primary,
unfocusedTrailingIconColor = MaterialTheme.colorScheme.primary, unfocusedTrailingIconColor = MaterialTheme.colorScheme.primary,

View file

@ -39,8 +39,8 @@ import coil.request.ImageRequest
import io.element.android.libraries.designsystem.preview.ElementPreviewDark import io.element.android.libraries.designsystem.preview.ElementPreviewDark
import io.element.android.libraries.designsystem.preview.ElementPreviewLight import io.element.android.libraries.designsystem.preview.ElementPreviewLight
import io.element.android.libraries.designsystem.preview.debugPlaceholderBackground import io.element.android.libraries.designsystem.preview.debugPlaceholderBackground
import io.element.android.libraries.theme.LocalColors
import io.element.android.libraries.designsystem.theme.components.Icon import io.element.android.libraries.designsystem.theme.components.Icon
import io.element.android.libraries.theme.ElementTheme
/** /**
* An avatar that the user has selected, but which has not yet been uploaded to Matrix. * An avatar that the user has selected, but which has not yet been uploaded to Matrix.
@ -69,7 +69,7 @@ fun UnsavedAvatar(
contentDescription = null, contentDescription = null,
) )
} else { } else {
Box(modifier = commonModifier.background(LocalColors.current.quinary)) { Box(modifier = commonModifier.background(ElementTheme.legacyColors.quinary)) {
Icon( Icon(
imageVector = Icons.Outlined.AddAPhoto, imageVector = Icons.Outlined.AddAPhoto,
contentDescription = "", contentDescription = "",

View file

@ -78,7 +78,7 @@ import io.element.android.libraries.matrix.api.media.MediaSource
import io.element.android.libraries.matrix.ui.components.AttachmentThumbnail import io.element.android.libraries.matrix.ui.components.AttachmentThumbnail
import io.element.android.libraries.matrix.ui.components.AttachmentThumbnailInfo import io.element.android.libraries.matrix.ui.components.AttachmentThumbnailInfo
import io.element.android.libraries.matrix.ui.components.AttachmentThumbnailType import io.element.android.libraries.matrix.ui.components.AttachmentThumbnailType
import io.element.android.libraries.theme.LocalColors import io.element.android.libraries.theme.ElementTheme
import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.libraries.ui.strings.CommonStrings
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@ -136,7 +136,7 @@ fun TextComposer(
lineCount = it.lineCount lineCount = it.lineCount
}, },
textStyle = defaultTypography.copy(color = MaterialTheme.colorScheme.primary), textStyle = defaultTypography.copy(color = MaterialTheme.colorScheme.primary),
cursorBrush = SolidColor(LocalColors.current.accentColor), cursorBrush = SolidColor(ElementTheme.legacyColors.accentColor),
decorationBox = { innerTextField -> decorationBox = { innerTextField ->
TextFieldDefaults.DecorationBox( TextFieldDefaults.DecorationBox(
value = text, value = text,
@ -346,7 +346,7 @@ private fun BoxScope.SendButton(
Box( Box(
modifier = modifier modifier = modifier
.clip(CircleShape) .clip(CircleShape)
.background(if (canSendMessage) LocalColors.current.accentColor else Color.Transparent) .background(if (canSendMessage) ElementTheme.legacyColors.accentColor else Color.Transparent)
.size(30.dp) .size(30.dp)
.align(Alignment.BottomEnd) .align(Alignment.BottomEnd)
.applyIf(composerMode !is MessageComposerMode.Edit, ifTrue = { .applyIf(composerMode !is MessageComposerMode.Edit, ifTrue = {
@ -373,7 +373,7 @@ private fun BoxScope.SendButton(
modifier = Modifier.size(16.dp), modifier = Modifier.size(16.dp),
resourceId = iconId, resourceId = iconId,
contentDescription = contentDescription, contentDescription = contentDescription,
tint = if (canSendMessage) Color.White else LocalColors.current.quaternary tint = if (canSendMessage) Color.White else ElementTheme.legacyColors.quaternary
) )
} }
} }

View file

@ -6,6 +6,14 @@ This module contains the theme tokens for the application, including those auto-
The module contains public tokens and color schemes that are later used in `MaterialTheme` and added to `ElementTheme` for use in the application. The module contains public tokens and color schemes that are later used in `MaterialTheme` and added to `ElementTheme` for use in the application.
All tokens can be accessed through the `ElementTheme` object, which contains the following properties:
* `ElementTheme.legacyColors`: contains legacy colors and custom colors not present in either Material or Compound. Usage of these colors should be avoided, and they're usually prefixed in Figma with the `Zzz/` prefix or have no name at all.
* `ElementTheme.materialColors`: contains all Material color tokens. In Figma, they're prefixed with `M3/`. It's an alias to `MaterialTheme.colorScheme`.
* `ElementTheme.colors`: contains all Compound semantic color tokens. In Figma, they're prefixed with either `Light/` or `Dark/`.
* `ElementTheme.materialTypography`: contains the Material `Typography` values. In Figma, they're prefixed with `M3/`. It's an alias to `MaterialTheme.typography`.
* `ElementTheme.typography`: contains the Compound `TypographyTokens` values. In Figma, they're prefixed with `Android/font/`.
## Adding new tokens ## Adding new tokens
All new tokens **should** come from Compound and added to the `compound.generated` package. To map the literal tokens to the semantic ones, you'll have to update both `compoundColorsLight` and `compoundColorsDark` in `CompoundColors.kt`. All new tokens **should** come from Compound and added to the `compound.generated` package. To map the literal tokens to the semantic ones, you'll have to update both `compoundColorsLight` and `compoundColorsDark` in `CompoundColors.kt`.

View file

@ -26,7 +26,7 @@ import io.element.android.libraries.theme.compound.generated.internal.LightDesig
import io.element.android.libraries.theme.compound.generated.SemanticColors import io.element.android.libraries.theme.compound.generated.SemanticColors
/** /**
* Element color palette. * Element Android legacy color palette.
* *
* ## IMPORTANT! * ## IMPORTANT!
* **We should not add any new colors here, all new colors should come from [SemanticColors] instead.** * **We should not add any new colors here, all new colors should come from [SemanticColors] instead.**

View file

@ -38,6 +38,7 @@ import io.element.android.libraries.theme.compound.compoundColorsDark
import io.element.android.libraries.theme.compound.compoundColorsLight import io.element.android.libraries.theme.compound.compoundColorsLight
import io.element.android.libraries.theme.compound.compoundTypography import io.element.android.libraries.theme.compound.compoundTypography
import io.element.android.libraries.theme.compound.generated.SemanticColors import io.element.android.libraries.theme.compound.generated.SemanticColors
import io.element.android.libraries.theme.compound.generated.TypographyTokens
/** /**
* Inspired from https://medium.com/@lucasyujideveloper/54cbcbde1ace * Inspired from https://medium.com/@lucasyujideveloper/54cbcbde1ace
@ -45,23 +46,26 @@ import io.element.android.libraries.theme.compound.generated.SemanticColors
object ElementTheme { object ElementTheme {
/** /**
* The current [ElementColors] provided by [ElementTheme]. Usage of these colors is discouraged. * The current [ElementColors] provided by [ElementTheme]. Usage of these colors is discouraged.
* In Figma, they usually have the `Zzz` prefix or have no name at all.
*/ */
val colors: ElementColors val legacyColors: ElementColors
@Composable @Composable
@ReadOnlyComposable @ReadOnlyComposable
get() = LocalColors.current get() = LocalLegacyColors.current
/** /**
* The current [SemanticColors] provided by [ElementTheme]. * The current [SemanticColors] provided by [ElementTheme].
* These come from Compound and are the recommended colors to use for custom components. * These come from Compound and are the recommended colors to use for custom components.
* In Figma, these colors usually have the `Light/` or `Dark/` prefix.
*/ */
val compoundColors: SemanticColors val colors: SemanticColors
@Composable @Composable
@ReadOnlyComposable @ReadOnlyComposable
get() = LocalCompoundColors.current get() = LocalCompoundColors.current
/** /**
* The current Material 3 [ColorScheme] provided by [ElementTheme], coming from [MaterialTheme]. * The current Material 3 [ColorScheme] provided by [ElementTheme], coming from [MaterialTheme].
* In Figma, these colors usually have the `M3/` prefix.
*/ */
val materialColors: ColorScheme val materialColors: ColorScheme
@Composable @Composable
@ -69,23 +73,36 @@ object ElementTheme {
get() = MaterialTheme.colorScheme get() = MaterialTheme.colorScheme
/** /**
* Material 3 [Typography] tokens. * Material 3 [Typography] tokens. In Figma, these have the `M3/` prefix.
*/ */
val typography: Typography val materialTypography: Typography
@Composable @Composable
@ReadOnlyComposable @ReadOnlyComposable
get() = MaterialTheme.typography get() = MaterialTheme.typography
/**
* Compound [Typography] tokens. In Figma, these have the `Android/font/` prefix.
*/
val typography: TypographyTokens = TypographyTokens
/**
* Returns whether the theme version used is the light or the dark one.
*/
val isLightTheme: Boolean
@Composable
@ReadOnlyComposable
get() = LocalCompoundColors.current.isLight
} }
/* Global variables (application level) */ /* Global variables (application level) */
val LocalColors = staticCompositionLocalOf { elementColorsLight() } internal val LocalLegacyColors = staticCompositionLocalOf { elementColorsLight() }
val LocalCompoundColors = staticCompositionLocalOf { compoundColorsLight } internal val LocalCompoundColors = staticCompositionLocalOf { compoundColorsLight }
@Composable @Composable
fun ElementTheme( fun ElementTheme(
darkTheme: Boolean = isSystemInDarkTheme(), darkTheme: Boolean = isSystemInDarkTheme(),
dynamicColor: Boolean = false, /* true to enable MaterialYou */ dynamicColor: Boolean = false, /* true to enable MaterialYou */
colors: ElementColors = if (darkTheme) elementColorsDark() else elementColorsLight(), legacyColors: ElementColors = if (darkTheme) elementColorsDark() else elementColorsLight(),
compoundColors: SemanticColors = if (darkTheme) compoundColorsDark else compoundColorsLight, compoundColors: SemanticColors = if (darkTheme) compoundColorsDark else compoundColorsLight,
materialLightColors: ColorScheme = materialColorSchemeLight, materialLightColors: ColorScheme = materialColorSchemeLight,
materialDarkColors: ColorScheme = materialColorSchemeDark, materialDarkColors: ColorScheme = materialColorSchemeDark,
@ -93,9 +110,9 @@ fun ElementTheme(
content: @Composable () -> Unit, content: @Composable () -> Unit,
) { ) {
val systemUiController = rememberSystemUiController() val systemUiController = rememberSystemUiController()
val currentColor = remember(darkTheme) { val currentLegacyColor = remember(darkTheme) {
colors.copy() legacyColors.copy()
}.apply { updateColorsFrom(colors) } }.apply { updateColorsFrom(legacyColors) }
val currentCompoundColor = remember(darkTheme) { val currentCompoundColor = remember(darkTheme) {
compoundColors.copy() compoundColors.copy()
}.apply { updateColorsFrom(compoundColors) } }.apply { updateColorsFrom(compoundColors) }
@ -111,7 +128,7 @@ fun ElementTheme(
systemUiController.applyTheme(colorScheme = colorScheme, darkTheme = darkTheme) systemUiController.applyTheme(colorScheme = colorScheme, darkTheme = darkTheme)
} }
CompositionLocalProvider( CompositionLocalProvider(
LocalColors provides currentColor, LocalLegacyColors provides currentLegacyColor,
LocalCompoundColors provides currentCompoundColor, LocalCompoundColors provides currentCompoundColor,
) { ) {
MaterialTheme( MaterialTheme(
@ -132,7 +149,7 @@ fun ForcedDarkElementTheme(
) { ) {
val systemUiController = rememberSystemUiController() val systemUiController = rememberSystemUiController()
val colorScheme = MaterialTheme.colorScheme val colorScheme = MaterialTheme.colorScheme
val wasDarkTheme = !ElementTheme.colors.isLight val wasDarkTheme = !ElementTheme.legacyColors.isLight
DisposableEffect(Unit) { DisposableEffect(Unit) {
onDispose { onDispose {
systemUiController.applyTheme(colorScheme, wasDarkTheme) systemUiController.applyTheme(colorScheme, wasDarkTheme)

View file

@ -114,7 +114,7 @@ Compose:
active: true active: true
# You can optionally define a list of CompositionLocals that are allowed here # You can optionally define a list of CompositionLocals that are allowed here
allowedCompositionLocals: LocalColors, LocalCompoundColors, LocalSnackbarDispatcher allowedCompositionLocals: LocalLegacyColors, LocalCompoundColors, LocalSnackbarDispatcher
CompositionLocalNaming: CompositionLocalNaming:
active: true active: true
ContentEmitterReturningValues: ContentEmitterReturningValues: