Benoit Marty
2 years ago
50 changed files with 1082 additions and 377 deletions
@ -1,39 +0,0 @@
@@ -1,39 +0,0 @@
|
||||
/* |
||||
* Copyright (c) 2023 New Vector Ltd |
||||
* |
||||
* 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 io.element.android.libraries.designsystem |
||||
|
||||
import androidx.compose.runtime.Immutable |
||||
import androidx.compose.ui.graphics.Color |
||||
|
||||
@Immutable |
||||
data class ExtendedColors( |
||||
val messageFromMeBackground: Color, |
||||
val messageFromOtherBackground: Color, |
||||
val messageHighlightedBackground: Color, |
||||
) |
||||
|
||||
internal val extendedColorsLight = ExtendedColors( |
||||
messageFromMeBackground = SystemGrey5Light, |
||||
messageFromOtherBackground = SystemGrey6Light, |
||||
messageHighlightedBackground = Azure, |
||||
) |
||||
|
||||
internal val extendedColorsDark = ExtendedColors( |
||||
messageFromMeBackground = SystemGrey5Dark, |
||||
messageFromOtherBackground = SystemGrey6Dark, |
||||
messageHighlightedBackground = Azure, |
||||
) |
@ -1,120 +0,0 @@
@@ -1,120 +0,0 @@
|
||||
/* |
||||
* Copyright (c) 2023 New Vector Ltd |
||||
* |
||||
* 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 io.element.android.libraries.designsystem |
||||
|
||||
import android.os.Build |
||||
import androidx.compose.foundation.isSystemInDarkTheme |
||||
import androidx.compose.material3.MaterialTheme |
||||
import androidx.compose.material3.darkColorScheme |
||||
import androidx.compose.material3.dynamicDarkColorScheme |
||||
import androidx.compose.material3.dynamicLightColorScheme |
||||
import androidx.compose.material3.lightColorScheme |
||||
import androidx.compose.runtime.Composable |
||||
import androidx.compose.runtime.CompositionLocalProvider |
||||
import androidx.compose.runtime.SideEffect |
||||
import androidx.compose.runtime.compositionLocalOf |
||||
import androidx.compose.runtime.staticCompositionLocalOf |
||||
import androidx.compose.ui.graphics.Color |
||||
import androidx.compose.ui.platform.LocalContext |
||||
import com.google.accompanist.systemuicontroller.rememberSystemUiController |
||||
|
||||
private val DarkColorScheme = darkColorScheme( |
||||
primary = Color.White, |
||||
secondary = DarkGrey, |
||||
tertiary = Color.White, |
||||
background = Color.Black, |
||||
onBackground = Color.White, |
||||
surface = Color.Black, |
||||
surfaceVariant = SystemGrey5Dark, |
||||
onSurface = Color.White, |
||||
onSurfaceVariant = Color.White, |
||||
) |
||||
|
||||
private val LightColorScheme = lightColorScheme( |
||||
primary = Color.Black, |
||||
secondary = LightGrey, |
||||
tertiary = Color.Black, |
||||
background = Color.White, |
||||
onBackground = Color.Black, |
||||
surface = Color.White, |
||||
surfaceVariant = SystemGrey5Light, |
||||
onSurface = Color.Black, |
||||
onSurfaceVariant = Color.Black, |
||||
|
||||
/* Other default colors to override |
||||
background = Color(0xFFFFFBFE), |
||||
surface = Color(0xFFFFFBFE), |
||||
onPrimary = Color.White, |
||||
onSecondary = Color.White, |
||||
onTertiary = Color.White, |
||||
onBackground = Color(0xFF1C1B1F), |
||||
onSurface = Color(0xFF1C1B1F), |
||||
*/ |
||||
) |
||||
|
||||
@Suppress("CompositionLocalAllowlist") |
||||
val LocalIsDarkTheme = compositionLocalOf<Boolean> { error("Not defined") } |
||||
|
||||
val LocalExtendedColors = staticCompositionLocalOf { |
||||
ExtendedColors( |
||||
messageFromMeBackground = Color.Unspecified, |
||||
messageFromOtherBackground = Color.Unspecified, |
||||
messageHighlightedBackground = Color.Unspecified, |
||||
) |
||||
} |
||||
|
||||
@Composable |
||||
fun ElementXTheme( |
||||
darkTheme: Boolean = isSystemInDarkTheme(), |
||||
// Dynamic color is available on Android 12+ |
||||
dynamicColor: Boolean = false, |
||||
content: @Composable () -> Unit |
||||
) { |
||||
val colorScheme = when { |
||||
dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> { |
||||
val context = LocalContext.current |
||||
if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context) |
||||
} |
||||
darkTheme -> DarkColorScheme |
||||
else -> LightColorScheme |
||||
} |
||||
val systemUiController = rememberSystemUiController() |
||||
val useDarkIcons = !darkTheme |
||||
|
||||
SideEffect { |
||||
systemUiController.setStatusBarColor( |
||||
color = colorScheme.background |
||||
) |
||||
systemUiController.setSystemBarsColor( |
||||
color = Color.Transparent, |
||||
darkIcons = useDarkIcons |
||||
) |
||||
} |
||||
|
||||
val extendedColors = if (darkTheme) extendedColorsDark else extendedColorsLight |
||||
|
||||
CompositionLocalProvider( |
||||
LocalIsDarkTheme provides darkTheme, |
||||
LocalExtendedColors provides extendedColors, |
||||
) { |
||||
MaterialTheme( |
||||
colorScheme = colorScheme, |
||||
typography = Typography, |
||||
content = content |
||||
) |
||||
} |
||||
} |
@ -0,0 +1,53 @@
@@ -0,0 +1,53 @@
|
||||
/* |
||||
* Copyright (c) 2023 New Vector Ltd |
||||
* |
||||
* 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 io.element.android.libraries.designsystem.theme |
||||
|
||||
import androidx.compose.ui.graphics.Color |
||||
import io.element.android.libraries.designsystem.Azure |
||||
import io.element.android.libraries.designsystem.DarkGrey |
||||
import io.element.android.libraries.designsystem.SystemGrey5Dark |
||||
import io.element.android.libraries.designsystem.SystemGrey6Dark |
||||
|
||||
fun elementColorsDark() = ElementColors( |
||||
primary = Color.White, |
||||
onPrimary = Color.Black, |
||||
secondary = DarkGrey, |
||||
text = Color.White, |
||||
background = Color.Black, |
||||
onBackground = Color.White, |
||||
surfaceVariant = SystemGrey5Dark, |
||||
onSurfaceVariant = Color.White, |
||||
messageFromMeBackground = SystemGrey5Dark, |
||||
messageFromOtherBackground = SystemGrey6Dark, |
||||
messageHighlightedBackground = Azure, |
||||
success = Color.Green, |
||||
error = Color.Red, |
||||
isLight = false, |
||||
) |
||||
|
||||
/* |
||||
private val DarkColorScheme = darkColorScheme( |
||||
primary = Color.White, |
||||
secondary = DarkGrey, |
||||
tertiary = Color.White, |
||||
background = Color.Black, |
||||
onBackground = Color.White, |
||||
surface = Color.Black, |
||||
surfaceVariant = SystemGrey5Dark, |
||||
onSurface = Color.White, |
||||
) |
||||
*/ |
@ -0,0 +1,54 @@
@@ -0,0 +1,54 @@
|
||||
/* |
||||
* Copyright (c) 2023 New Vector Ltd |
||||
* |
||||
* 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 io.element.android.libraries.designsystem.theme |
||||
|
||||
import androidx.compose.ui.graphics.Color |
||||
import io.element.android.libraries.designsystem.Azure |
||||
import io.element.android.libraries.designsystem.LightGrey |
||||
import io.element.android.libraries.designsystem.SystemGrey5Light |
||||
import io.element.android.libraries.designsystem.SystemGrey6Light |
||||
|
||||
fun elementColorsLight() = ElementColors( |
||||
primary = Color.Black, |
||||
onPrimary = Color.White, |
||||
secondary = LightGrey, |
||||
text = Color.Black, |
||||
background = Color.White, |
||||
onBackground = Color.Black, |
||||
surfaceVariant = SystemGrey5Light, |
||||
onSurfaceVariant = Color.Black, |
||||
messageFromMeBackground = SystemGrey5Light, |
||||
messageFromOtherBackground = SystemGrey6Light, |
||||
messageHighlightedBackground = Azure, |
||||
success = Color.Green, |
||||
error = Color.Red, |
||||
isLight = true, |
||||
) |
||||
|
||||
/* |
||||
private val LightColorScheme = lightColorScheme( |
||||
primary = Color.Black, |
||||
secondary = LightGrey, |
||||
tertiary = Color.Black, |
||||
background = Color.White, |
||||
onBackground = Color.Black, |
||||
surface = Color.White, |
||||
surfaceVariant = SystemGrey5Light, |
||||
onSurface = Color.Black, |
||||
onSurfaceVariant = Color.Black, |
||||
|
||||
*/ |
@ -0,0 +1,42 @@
@@ -0,0 +1,42 @@
|
||||
/* |
||||
* Copyright (c) 2023 New Vector Ltd |
||||
* |
||||
* 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 io.element.android.libraries.designsystem.components.color |
||||
|
||||
import androidx.compose.material3.LocalContentColor |
||||
import androidx.compose.runtime.Composable |
||||
import androidx.compose.runtime.ReadOnlyComposable |
||||
import androidx.compose.ui.graphics.Color |
||||
import androidx.compose.ui.graphics.takeOrElse |
||||
import io.element.android.libraries.designsystem.theme.ElementColors |
||||
import io.element.android.libraries.designsystem.theme.ElementTheme |
||||
|
||||
@Composable |
||||
@ReadOnlyComposable |
||||
fun elementContentColorFor(backgroundColor: Color): Color { |
||||
return ElementTheme.colors.elementContentColorFor(backgroundColor).takeOrElse { |
||||
LocalContentColor.current |
||||
} |
||||
} |
||||
|
||||
fun ElementColors.elementContentColorFor(backgroundColor: Color): Color { |
||||
return when (backgroundColor) { |
||||
primary -> onPrimary |
||||
surfaceVariant -> onSurfaceVariant |
||||
background -> onBackground |
||||
else -> Color.Unspecified |
||||
} |
||||
} |
@ -0,0 +1,118 @@
@@ -0,0 +1,118 @@
|
||||
/* |
||||
* Copyright (c) 2023 New Vector Ltd |
||||
* |
||||
* 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 io.element.android.libraries.designsystem.theme |
||||
|
||||
import androidx.compose.runtime.getValue |
||||
import androidx.compose.runtime.mutableStateOf |
||||
import androidx.compose.runtime.setValue |
||||
import androidx.compose.ui.graphics.Color |
||||
|
||||
class ElementColors( |
||||
primary: Color, |
||||
onPrimary: Color, |
||||
secondary: Color, |
||||
text: Color, |
||||
background: Color, |
||||
onBackground: Color, |
||||
surfaceVariant: Color, |
||||
onSurfaceVariant: Color, |
||||
messageFromMeBackground: Color, |
||||
messageFromOtherBackground: Color, |
||||
messageHighlightedBackground: Color, |
||||
success: Color, |
||||
error: Color, |
||||
isLight: Boolean, |
||||
) { |
||||
var primary by mutableStateOf(primary) |
||||
private set |
||||
var onPrimary by mutableStateOf(onPrimary) |
||||
private set |
||||
var secondary by mutableStateOf(secondary) |
||||
private set |
||||
var text by mutableStateOf(text) |
||||
private set |
||||
var success by mutableStateOf(success) |
||||
private set |
||||
var error by mutableStateOf(error) |
||||
private set |
||||
var background by mutableStateOf(background) |
||||
private set |
||||
var onBackground by mutableStateOf(onBackground) |
||||
private set |
||||
var surfaceVariant by mutableStateOf(surfaceVariant) |
||||
private set |
||||
var onSurfaceVariant by mutableStateOf(onSurfaceVariant) |
||||
private set |
||||
var messageFromMeBackground by mutableStateOf(messageFromMeBackground) |
||||
private set |
||||
var messageFromOtherBackground by mutableStateOf(messageFromOtherBackground) |
||||
private set |
||||
var messageHighlightedBackground by mutableStateOf(messageHighlightedBackground) |
||||
private set |
||||
|
||||
var isLight by mutableStateOf(isLight) |
||||
private set |
||||
|
||||
fun copy( |
||||
primary: Color = this.primary, |
||||
onPrimary: Color = this.onPrimary, |
||||
secondary: Color = this.secondary, |
||||
text: Color = this.text, |
||||
background: Color = this.background, |
||||
onBackground: Color = this.onBackground, |
||||
surfaceVariant: Color = this.surfaceVariant, |
||||
onSurfaceVariant: Color = this.onSurfaceVariant, |
||||
messageFromMeBackground: Color = this.messageFromMeBackground, |
||||
messageFromOtherBackground: Color = this.messageFromOtherBackground, |
||||
messageHighlightedBackground: Color = this.messageHighlightedBackground, |
||||
success: Color = this.success, |
||||
error: Color = this.error, |
||||
isLight: Boolean = this.isLight, |
||||
) = ElementColors( |
||||
primary = primary, |
||||
onPrimary = onPrimary, |
||||
secondary = secondary, |
||||
text = text, |
||||
background = background, |
||||
onBackground = onBackground, |
||||
surfaceVariant = surfaceVariant, |
||||
onSurfaceVariant = onSurfaceVariant, |
||||
messageFromMeBackground = messageFromMeBackground, |
||||
messageFromOtherBackground = messageFromOtherBackground, |
||||
messageHighlightedBackground = messageHighlightedBackground, |
||||
success = success, |
||||
error = error, |
||||
isLight = isLight, |
||||
) |
||||
|
||||
fun updateColorsFrom(other: ElementColors) { |
||||
primary = other.primary |
||||
onPrimary = other.onPrimary |
||||
secondary = other.secondary |
||||
text = other.text |
||||
success = other.success |
||||
background = other.background |
||||
onBackground = other.onBackground |
||||
surfaceVariant = other.surfaceVariant |
||||
onSurfaceVariant = other.onSurfaceVariant |
||||
messageFromMeBackground = other.messageFromMeBackground |
||||
messageFromOtherBackground = other.messageFromOtherBackground |
||||
messageHighlightedBackground = other.messageHighlightedBackground |
||||
error = other.error |
||||
isLight = other.isLight |
||||
} |
||||
} |
@ -0,0 +1,84 @@
@@ -0,0 +1,84 @@
|
||||
/* |
||||
* Copyright (c) 2023 New Vector Ltd |
||||
* |
||||
* 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 io.element.android.libraries.designsystem.theme |
||||
|
||||
import androidx.compose.foundation.isSystemInDarkTheme |
||||
import androidx.compose.material.ProvideTextStyle |
||||
import androidx.compose.runtime.Composable |
||||
import androidx.compose.runtime.CompositionLocalProvider |
||||
import androidx.compose.runtime.ReadOnlyComposable |
||||
import androidx.compose.runtime.SideEffect |
||||
import androidx.compose.runtime.remember |
||||
import androidx.compose.runtime.staticCompositionLocalOf |
||||
import androidx.compose.ui.graphics.Color |
||||
import com.google.accompanist.systemuicontroller.rememberSystemUiController |
||||
|
||||
/** |
||||
* Inspired from https://medium.com/@lucasyujideveloper/54cbcbde1ace |
||||
*/ |
||||
object ElementTheme { |
||||
val colors: ElementColors |
||||
@Composable |
||||
@ReadOnlyComposable |
||||
get() = LocalColors.current |
||||
|
||||
val typography: ElementTypography |
||||
@Composable |
||||
@ReadOnlyComposable |
||||
get() = LocalTypography.current |
||||
|
||||
val spaces: ElementSpaces |
||||
@Composable |
||||
@ReadOnlyComposable |
||||
get() = LocalSpaces.current |
||||
} |
||||
|
||||
/* Global variables (application level) */ |
||||
val LocalSpaces = staticCompositionLocalOf { ElementSpaces() } |
||||
val LocalColors = staticCompositionLocalOf { elementColorsLight() } |
||||
val LocalTypography = staticCompositionLocalOf { ElementTypography() } |
||||
|
||||
@Composable |
||||
fun ElementTheme( |
||||
darkTheme: Boolean = isSystemInDarkTheme(), |
||||
lightColors: ElementColors = elementColorsLight(), |
||||
darkColors: ElementColors = elementColorsDark(), |
||||
typography: ElementTypography = ElementTheme.typography, |
||||
spaces: ElementSpaces = ElementTheme.spaces, |
||||
content: @Composable () -> Unit, |
||||
) { |
||||
val systemUiController = rememberSystemUiController() |
||||
val useDarkIcons = !darkTheme |
||||
val currentColor = remember { if (darkTheme) darkColors else lightColors } |
||||
SideEffect { |
||||
systemUiController.setStatusBarColor( |
||||
color = currentColor.background |
||||
) |
||||
systemUiController.setSystemBarsColor( |
||||
color = Color.Transparent, |
||||
darkIcons = useDarkIcons |
||||
) |
||||
} |
||||
val rememberedColors = remember { currentColor.copy() }.apply { updateColorsFrom(currentColor) } |
||||
CompositionLocalProvider( |
||||
LocalColors provides rememberedColors, |
||||
LocalSpaces provides spaces, |
||||
LocalTypography provides typography, |
||||
) { |
||||
ProvideTextStyle(typography.body1, content = content) |
||||
} |
||||
} |
@ -0,0 +1,118 @@
@@ -0,0 +1,118 @@
|
||||
/* |
||||
* Copyright (c) 2023 New Vector Ltd |
||||
* |
||||
* 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 io.element.android.libraries.designsystem.theme |
||||
|
||||
import androidx.compose.ui.text.TextStyle |
||||
import androidx.compose.ui.text.font.FontFamily |
||||
import androidx.compose.ui.text.font.FontWeight |
||||
import androidx.compose.ui.unit.sp |
||||
import com.airbnb.android.showkase.annotation.ShowkaseTypography |
||||
|
||||
@ShowkaseTypography(name = "H1", group = "Element") |
||||
val h1Default: TextStyle = TextStyle( |
||||
fontFamily = FontFamily.SansSerif, |
||||
fontWeight = FontWeight.Bold, |
||||
fontSize = 24.sp |
||||
) |
||||
|
||||
@ShowkaseTypography(name = "Body1", group = "Element") |
||||
val body1Default: TextStyle = TextStyle( |
||||
fontFamily = FontFamily.SansSerif, |
||||
fontWeight = FontWeight.Normal, |
||||
fontSize = 16.sp |
||||
) |
||||
|
||||
@ShowkaseTypography(name = "BodySmall", group = "Element") |
||||
val bodySmallDefault: TextStyle = TextStyle( |
||||
fontFamily = FontFamily.SansSerif, |
||||
fontWeight = FontWeight.Normal, |
||||
fontSize = 14.sp |
||||
) |
||||
|
||||
@ShowkaseTypography(name = "bodyMedium", group = "Element") |
||||
val bodyMediumDefault: TextStyle = TextStyle( |
||||
fontFamily = FontFamily.SansSerif, |
||||
fontWeight = FontWeight.Normal, |
||||
fontSize = 18.sp |
||||
) |
||||
|
||||
@ShowkaseTypography(name = "Body Large", group = "Element") |
||||
val bodyLargeDefault: TextStyle = TextStyle( |
||||
fontFamily = FontFamily.Default, |
||||
fontWeight = FontWeight.Normal, |
||||
fontSize = 16.sp, |
||||
lineHeight = 24.sp, |
||||
letterSpacing = 0.5.sp |
||||
) |
||||
|
||||
@ShowkaseTypography(name = "Headline Small", group = "Element") |
||||
val headlineSmallDefault: TextStyle = TextStyle( |
||||
fontFamily = FontFamily.Default, |
||||
fontWeight = FontWeight.Bold, |
||||
fontSize = 24.sp, |
||||
lineHeight = 30.sp, |
||||
letterSpacing = 1.sp |
||||
) |
||||
|
||||
@ShowkaseTypography(name = "Headline Medium", group = "Element") |
||||
val headlineMediumDefault: TextStyle = TextStyle( |
||||
fontFamily = FontFamily.Default, |
||||
fontWeight = FontWeight.Bold, |
||||
fontSize = 28.sp, |
||||
lineHeight = 34.sp, |
||||
letterSpacing = 1.sp |
||||
) |
||||
|
||||
@ShowkaseTypography(name = "Headline Large", group = "Element") |
||||
val headlineLargeDefault: TextStyle = TextStyle( |
||||
fontFamily = FontFamily.Default, |
||||
fontWeight = FontWeight.Bold, |
||||
fontSize = 32.sp, |
||||
lineHeight = 38.sp, |
||||
letterSpacing = 1.sp |
||||
) |
||||
|
||||
@ShowkaseTypography(name = "titleSmall", group = "Element") |
||||
val titleSmallDefault: TextStyle = TextStyle( |
||||
fontFamily = FontFamily.Default, |
||||
fontWeight = FontWeight.Normal, |
||||
fontSize = 14.sp, |
||||
lineHeight = 20.sp, |
||||
letterSpacing = 0.5.sp |
||||
) |
||||
|
||||
@ShowkaseTypography(name = "titleMedium", group = "Element") |
||||
val titleMediumDefault: TextStyle = TextStyle( |
||||
fontFamily = FontFamily.Default, |
||||
fontWeight = FontWeight.Normal, |
||||
fontSize = 18.sp, |
||||
lineHeight = 24.sp, |
||||
letterSpacing = 0.5.sp |
||||
) |
||||
|
||||
data class ElementTypography( |
||||
val h1: TextStyle = h1Default, |
||||
val body1: TextStyle = body1Default, |
||||
val bodySmall: TextStyle = bodySmallDefault, |
||||
val bodyMedium: TextStyle = bodyMediumDefault, |
||||
val bodyLarge: TextStyle = bodyLargeDefault, |
||||
val headlineSmall: TextStyle = headlineSmallDefault, |
||||
val headlineMedium: TextStyle = headlineMediumDefault, |
||||
val headlineLarge: TextStyle = headlineLargeDefault, |
||||
val titleSmall: TextStyle = titleSmallDefault, |
||||
val titleMedium: TextStyle = titleMediumDefault, |
||||
) |
@ -0,0 +1,66 @@
@@ -0,0 +1,66 @@
|
||||
/* |
||||
* Copyright (c) 2023 New Vector Ltd |
||||
* |
||||
* 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 io.element.android.libraries.designsystem.theme.components |
||||
|
||||
import androidx.compose.foundation.layout.RowScope |
||||
import androidx.compose.material.ContentAlpha |
||||
import androidx.compose.material.ProvideTextStyle |
||||
import androidx.compose.material3.Button |
||||
import androidx.compose.material3.ButtonDefaults |
||||
import androidx.compose.runtime.Composable |
||||
import androidx.compose.ui.Modifier |
||||
import androidx.compose.ui.graphics.Color |
||||
import androidx.compose.ui.graphics.compositeOver |
||||
import io.element.android.libraries.designsystem.components.color.elementContentColorFor |
||||
import io.element.android.libraries.designsystem.theme.ElementTheme |
||||
|
||||
@Composable |
||||
fun ElementButton( |
||||
onClick: () -> Unit, |
||||
modifier: Modifier = Modifier, |
||||
enabled: Boolean = true, |
||||
containerColor: Color = ElementTheme.colors.primary, |
||||
content: @Composable RowScope.() -> Unit |
||||
) { |
||||
Button( |
||||
colors = ButtonDefaults.buttonColors( |
||||
containerColor = containerColor, |
||||
contentColor = elementContentColorFor(backgroundColor = containerColor), |
||||
disabledContainerColor = containerColor |
||||
.copy(alpha = 0.12f) |
||||
.compositeOver(containerColor), |
||||
disabledContentColor = elementContentColorFor(backgroundColor = containerColor) |
||||
.copy(alpha = ContentAlpha.disabled) |
||||
), |
||||
// TODO shape = ButtonShape, |
||||
// TODO elevation = ButtonDefaults.elevation( |
||||
// defaultElevation = ElementTheme.elevation.default, |
||||
// pressedElevation = ElementTheme.elevation.pressed |
||||
// /* disabledElevation = 0.dp */ |
||||
// ), |
||||
onClick = onClick, |
||||
modifier = modifier, |
||||
enabled = enabled, |
||||
content = { |
||||
ProvideTextStyle( |
||||
value = ElementTheme.typography.body1 |
||||
) { |
||||
content() |
||||
} |
||||
} |
||||
) |
||||
} |
@ -0,0 +1,55 @@
@@ -0,0 +1,55 @@
|
||||
/* |
||||
* Copyright (c) 2023 New Vector Ltd |
||||
* |
||||
* 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 io.element.android.libraries.designsystem.theme.components |
||||
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource |
||||
import androidx.compose.material3.Checkbox |
||||
import androidx.compose.material3.CheckboxColors |
||||
import androidx.compose.material3.CheckboxDefaults |
||||
import androidx.compose.runtime.Composable |
||||
import androidx.compose.runtime.remember |
||||
import androidx.compose.ui.Modifier |
||||
import androidx.compose.ui.graphics.Color |
||||
import io.element.android.libraries.designsystem.theme.ElementTheme |
||||
|
||||
@Composable |
||||
fun ElementCheckbox( |
||||
checked: Boolean, |
||||
onCheckedChange: ((Boolean) -> Unit)?, |
||||
modifier: Modifier = Modifier, |
||||
enabled: Boolean = true, |
||||
colors: CheckboxColors = CheckboxDefaults.colors( |
||||
checkedColor = ElementTheme.colors.primary, |
||||
uncheckedColor = Color.Gray, // TODO ElementTheme.colors. |
||||
checkmarkColor = Color.Gray, // TODO ElementTheme.colors. |
||||
disabledCheckedColor = Color.Gray // TODO ElementTheme.colors. |
||||
.copy(alpha = 0.2F), |
||||
disabledUncheckedColor = Color.Gray // TODO ElementTheme.colors. |
||||
.copy(alpha = 0.2F), |
||||
disabledIndeterminateColor = Color.Gray // TODO ElementTheme.colors. |
||||
), |
||||
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() } |
||||
) { |
||||
Checkbox( |
||||
checked = checked, |
||||
onCheckedChange = onCheckedChange, |
||||
modifier = modifier, |
||||
enabled = enabled, |
||||
colors = colors, |
||||
interactionSource = interactionSource, |
||||
) |
||||
} |
@ -0,0 +1,56 @@
@@ -0,0 +1,56 @@
|
||||
/* |
||||
* Copyright (c) 2023 New Vector Ltd |
||||
* |
||||
* 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 io.element.android.libraries.designsystem.theme.components |
||||
|
||||
import androidx.compose.foundation.layout.RowScope |
||||
import androidx.compose.foundation.layout.WindowInsets |
||||
import androidx.compose.material3.ExperimentalMaterial3Api |
||||
import androidx.compose.material3.MediumTopAppBar |
||||
import androidx.compose.material3.TopAppBarColors |
||||
import androidx.compose.material3.TopAppBarDefaults |
||||
import androidx.compose.material3.TopAppBarScrollBehavior |
||||
import androidx.compose.runtime.Composable |
||||
import androidx.compose.ui.Modifier |
||||
import io.element.android.libraries.designsystem.theme.ElementTheme |
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class) |
||||
@Composable |
||||
fun ElementMediumAppBar( |
||||
title: @Composable () -> Unit, |
||||
modifier: Modifier = Modifier, |
||||
navigationIcon: @Composable () -> Unit = {}, |
||||
actions: @Composable RowScope.() -> Unit = {}, |
||||
windowInsets: WindowInsets = TopAppBarDefaults.windowInsets, |
||||
colors: TopAppBarColors = TopAppBarDefaults.mediumTopAppBarColors( |
||||
containerColor = ElementTheme.colors.background, |
||||
scrolledContainerColor = ElementTheme.colors.background, |
||||
navigationIconContentColor = ElementTheme.colors.onBackground, |
||||
titleContentColor = ElementTheme.colors.onBackground, |
||||
actionIconContentColor = ElementTheme.colors.onBackground, |
||||
), |
||||
scrollBehavior: TopAppBarScrollBehavior? = null |
||||
) { |
||||
MediumTopAppBar( |
||||
title = title, |
||||
modifier = modifier, |
||||
navigationIcon = navigationIcon, |
||||
actions = actions, |
||||
windowInsets = windowInsets, |
||||
colors = colors, |
||||
scrollBehavior = scrollBehavior, |
||||
) |
||||
} |
@ -0,0 +1,57 @@
@@ -0,0 +1,57 @@
|
||||
/* |
||||
* Copyright (c) 2023 New Vector Ltd |
||||
* |
||||
* 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 io.element.android.libraries.designsystem.theme.components |
||||
|
||||
import androidx.compose.foundation.layout.PaddingValues |
||||
import androidx.compose.foundation.layout.WindowInsets |
||||
import androidx.compose.material3.ExperimentalMaterial3Api |
||||
import androidx.compose.material3.FabPosition |
||||
import androidx.compose.material3.Scaffold |
||||
import androidx.compose.material3.ScaffoldDefaults |
||||
import androidx.compose.runtime.Composable |
||||
import androidx.compose.ui.Modifier |
||||
import androidx.compose.ui.graphics.Color |
||||
import io.element.android.libraries.designsystem.components.color.elementContentColorFor |
||||
import io.element.android.libraries.designsystem.theme.ElementTheme |
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class) |
||||
@Composable |
||||
fun ElementScaffold( |
||||
modifier: Modifier = Modifier, |
||||
topBar: @Composable () -> Unit = {}, |
||||
bottomBar: @Composable () -> Unit = {}, |
||||
snackbarHost: @Composable () -> Unit = {}, |
||||
floatingActionButton: @Composable () -> Unit = {}, |
||||
floatingActionButtonPosition: FabPosition = FabPosition.End, |
||||
containerColor: Color = ElementTheme.colors.background, |
||||
contentColor: Color = elementContentColorFor(containerColor), |
||||
contentWindowInsets: WindowInsets = ScaffoldDefaults.contentWindowInsets, |
||||
content: @Composable (PaddingValues) -> Unit |
||||
) { |
||||
Scaffold( |
||||
modifier = modifier, |
||||
topBar = topBar, |
||||
bottomBar = bottomBar, |
||||
snackbarHost = snackbarHost, |
||||
floatingActionButton = floatingActionButton, |
||||
floatingActionButtonPosition = floatingActionButtonPosition, |
||||
containerColor = containerColor, |
||||
contentColor = contentColor, |
||||
contentWindowInsets = contentWindowInsets, |
||||
content = content, |
||||
) |
||||
} |
@ -0,0 +1,63 @@
@@ -0,0 +1,63 @@
|
||||
/* |
||||
* Copyright (c) 2023 New Vector Ltd |
||||
* |
||||
* 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 io.element.android.libraries.designsystem.theme.components |
||||
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource |
||||
import androidx.compose.material3.Slider |
||||
import androidx.compose.material3.SliderColors |
||||
import androidx.compose.material3.SliderDefaults |
||||
import androidx.compose.runtime.Composable |
||||
import androidx.compose.runtime.remember |
||||
import androidx.compose.ui.Modifier |
||||
import io.element.android.libraries.designsystem.theme.ElementTheme |
||||
|
||||
@Composable |
||||
fun ElementSlider( |
||||
value: Float, |
||||
onValueChange: (Float) -> Unit, |
||||
modifier: Modifier = Modifier, |
||||
enabled: Boolean = true, |
||||
valueRange: ClosedFloatingPointRange<Float> = 0f..1f, |
||||
/*@IntRange(from = 0)*/ |
||||
steps: Int = 0, |
||||
onValueChangeFinished: (() -> Unit)? = null, |
||||
colors: SliderColors = SliderDefaults.colors( |
||||
thumbColor = ElementTheme.colors.primary, |
||||
activeTrackColor = ElementTheme.colors.primary, |
||||
activeTickColor = ElementTheme.colors.primary, |
||||
inactiveTrackColor = ElementTheme.colors.primary, |
||||
inactiveTickColor = ElementTheme.colors.primary, |
||||
disabledThumbColor = ElementTheme.colors.primary, |
||||
disabledActiveTrackColor = ElementTheme.colors.primary, |
||||
disabledActiveTickColor = ElementTheme.colors.primary, |
||||
disabledInactiveTrackColor = ElementTheme.colors.primary, |
||||
disabledInactiveTickColor = ElementTheme.colors.primary, |
||||
), |
||||
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() } |
||||
) { |
||||
Slider( |
||||
value = value, |
||||
onValueChange = onValueChange, |
||||
modifier = modifier, |
||||
enabled = enabled, |
||||
valueRange = valueRange, |
||||
steps = steps, |
||||
onValueChangeFinished = onValueChangeFinished, |
||||
colors = colors, |
||||
interactionSource = interactionSource, |
||||
) |
||||
} |
@ -0,0 +1,52 @@
@@ -0,0 +1,52 @@
|
||||
/* |
||||
* Copyright (c) 2023 New Vector Ltd |
||||
* |
||||
* 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 io.element.android.libraries.designsystem.theme.components |
||||
|
||||
import androidx.compose.foundation.BorderStroke |
||||
import androidx.compose.material3.Surface |
||||
import androidx.compose.runtime.Composable |
||||
import androidx.compose.ui.Modifier |
||||
import androidx.compose.ui.graphics.Color |
||||
import androidx.compose.ui.graphics.RectangleShape |
||||
import androidx.compose.ui.graphics.Shape |
||||
import androidx.compose.ui.unit.Dp |
||||
import androidx.compose.ui.unit.dp |
||||
import io.element.android.libraries.designsystem.components.color.elementContentColorFor |
||||
import io.element.android.libraries.designsystem.theme.ElementTheme |
||||
|
||||
@Composable |
||||
fun ElementSurface( |
||||
modifier: Modifier = Modifier, |
||||
shape: Shape = RectangleShape, |
||||
color: Color = ElementTheme.colors.surfaceVariant, |
||||
contentColor: Color = elementContentColorFor(color), |
||||
tonalElevation: Dp = 0.dp, |
||||
shadowElevation: Dp = 0.dp, |
||||
border: BorderStroke? = null, |
||||
content: @Composable () -> Unit |
||||
) { |
||||
Surface( |
||||
modifier = modifier, |
||||
shape = shape, |
||||
color = color, |
||||
contentColor = contentColor, |
||||
tonalElevation = tonalElevation, |
||||
shadowElevation = shadowElevation, |
||||
border = border, |
||||
content = content, |
||||
) |
||||
} |
@ -0,0 +1,56 @@
@@ -0,0 +1,56 @@
|
||||
/* |
||||
* Copyright (c) 2023 New Vector Ltd |
||||
* |
||||
* 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 io.element.android.libraries.designsystem.theme.components |
||||
|
||||
import androidx.compose.foundation.layout.RowScope |
||||
import androidx.compose.foundation.layout.WindowInsets |
||||
import androidx.compose.material3.ExperimentalMaterial3Api |
||||
import androidx.compose.material3.TopAppBar |
||||
import androidx.compose.material3.TopAppBarColors |
||||
import androidx.compose.material3.TopAppBarDefaults |
||||
import androidx.compose.material3.TopAppBarScrollBehavior |
||||
import androidx.compose.runtime.Composable |
||||
import androidx.compose.ui.Modifier |
||||
import io.element.android.libraries.designsystem.theme.ElementTheme |
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class) |
||||
@Composable |
||||
fun ElementTopAppBar( |
||||
title: @Composable () -> Unit, |
||||
modifier: Modifier = Modifier, |
||||
navigationIcon: @Composable () -> Unit = {}, |
||||
actions: @Composable RowScope.() -> Unit = {}, |
||||
windowInsets: WindowInsets = TopAppBarDefaults.windowInsets, |
||||
colors: TopAppBarColors = TopAppBarDefaults.smallTopAppBarColors( |
||||
containerColor = ElementTheme.colors.background, |
||||
scrolledContainerColor = ElementTheme.colors.background, |
||||
navigationIconContentColor = ElementTheme.colors.onBackground, |
||||
titleContentColor = ElementTheme.colors.onBackground, |
||||
actionIconContentColor = ElementTheme.colors.onBackground, |
||||
), |
||||
scrollBehavior: TopAppBarScrollBehavior? = null |
||||
) { |
||||
TopAppBar( |
||||
title = title, |
||||
modifier = modifier, |
||||
navigationIcon = navigationIcon, |
||||
actions = actions, |
||||
windowInsets = windowInsets, |
||||
colors = colors, |
||||
scrollBehavior = scrollBehavior, |
||||
) |
||||
} |
Loading…
Reference in new issue