Refine sign in flow to match designs and iOS flow (#100)
* Fix dark theme * First attempt at replicating iOS' UI & flows. * Try to fix Maestro tests * Add error dialogs and tests * Remove unused modifiers * Try to fix detekt issues * Tidy up maestro login flow a bit * Add `CompoundColorPalette` with some needed colors * Fixes to designs * Fix detekt issues * More design fixes * Some other minor design fixes * Add changelog * Minor tweaks. * Remove legacy dark material theme as it's no longer needed. * Move sliding sync 'learn more' url to constants object * Remove unused focusManager * Change how the displayed homeserver works * Keep user input as homeserver if it's valid * Remove `CompoundColorPalette`, try to fix issue when toggling dark mode. * Add `@Stable` to the theme, adjust how it toggles in dark mode * Remove unused strings * Update screenshots * Re-organize components in LoginRootScreen * Bump min coverage to 55, max to 60 * Always replace the snapshots contents when running `recordPaparazzi` * Fix dark theme preview of components using content colors * Add `BackButton` component * Handle errors with dialogs in a generic way * Align our Dialog components with the designs, use them were needed * Use a `MatrixHomeserverDetails` data class instead of just an URL. * `AuthenticationService.getHomeserverDetails()` now returns a `StateFlow`. Also, try to fix coverage issues in tests.
This commit is contained in:
parent
7997a65182
commit
c87c0ea28c
271 changed files with 1431 additions and 871 deletions
|
|
@ -41,6 +41,22 @@ val SystemGrey5Dark = Color(0xFF2C2C2E)
|
|||
val SystemGrey6Light = Color(0xFFF2F2F7)
|
||||
val SystemGrey6Dark = Color(0xFF1C1C1E)
|
||||
|
||||
// For light themes
|
||||
val Gray_25 = Color(0xFFF4F6FA)
|
||||
val Gray_50 = Color(0xFFE3E8F0)
|
||||
val Gray_100 = Color(0xFFC1C6CD)
|
||||
val Gray_150 = Color(0xFF8D97A5)
|
||||
val Gray_200 = Color(0xFF737D8C)
|
||||
val Black_900 = Color(0xFF17191C)
|
||||
|
||||
// For dark themes
|
||||
val Gray_250 = Color(0xFFA9B2BC)
|
||||
val Gray_300 = Color(0xFF8E99A4)
|
||||
val Gray_400 = Color(0xFF6F7882)
|
||||
val Gray_450 = Color(0xFF394049)
|
||||
val Black_800 = Color(0xFF15191E)
|
||||
val Black_950 = Color(0xFF21262C)
|
||||
|
||||
val Azure = Color(0xFF368BD6)
|
||||
val Kiwi = Color(0xFF74D12C)
|
||||
val Grape = Color(0xFFAC3BA8)
|
||||
|
|
|
|||
|
|
@ -25,6 +25,14 @@ import androidx.compose.ui.unit.sp
|
|||
// TODO Remove
|
||||
object ElementTextStyles {
|
||||
|
||||
val Button = TextStyle(
|
||||
fontSize = 17.sp,
|
||||
fontWeight = FontWeight.Bold,
|
||||
lineHeight = 22.sp,
|
||||
fontStyle = FontStyle.Normal,
|
||||
textAlign = TextAlign.Center,
|
||||
)
|
||||
|
||||
object Bold {
|
||||
val largeTitle = TextStyle(
|
||||
fontSize = 34.sp,
|
||||
|
|
@ -180,6 +188,14 @@ object ElementTextStyles {
|
|||
textAlign = TextAlign.Center
|
||||
)
|
||||
|
||||
val formHeader = TextStyle(
|
||||
fontSize = 14.sp,
|
||||
fontWeight = FontWeight.Normal,
|
||||
fontStyle = FontStyle.Normal,
|
||||
lineHeight = 20.sp,
|
||||
textAlign = TextAlign.Start
|
||||
)
|
||||
|
||||
val footnote = TextStyle(
|
||||
fontSize = 13.sp,
|
||||
fontWeight = FontWeight.Normal,
|
||||
|
|
|
|||
|
|
@ -17,13 +17,12 @@
|
|||
package io.element.android.libraries.designsystem.components.dialogs
|
||||
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.AlertDialog
|
||||
import androidx.compose.material3.AlertDialogDefaults
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
|
@ -31,10 +30,8 @@ import androidx.compose.ui.graphics.Shape
|
|||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
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.ElementPreviewLight
|
||||
import io.element.android.libraries.designsystem.theme.components.Button
|
||||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
import io.element.android.libraries.ui.strings.R as StringR
|
||||
|
||||
|
|
@ -67,43 +64,24 @@ fun ConfirmationDialog(
|
|||
Text(content)
|
||||
},
|
||||
dismissButton = {
|
||||
Row(
|
||||
modifier = Modifier.padding(all = 8.dp),
|
||||
horizontalArrangement = Arrangement.Center
|
||||
) {
|
||||
Column {
|
||||
Button(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
onClick = {
|
||||
onCancelClicked()
|
||||
}) {
|
||||
Text(cancelText)
|
||||
}
|
||||
if (thirdButtonText != null) {
|
||||
Button(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
onClick = {
|
||||
onThirdButtonClicked()
|
||||
}) {
|
||||
Text(thirdButtonText)
|
||||
}
|
||||
if (thirdButtonText != null) {
|
||||
// If there is a 3rd item it should be at the end of the dialog
|
||||
// Having this 3rd action is discouraged, see https://m3.material.io/components/dialogs/guidelines#e13b68f5-e367-4275-ad6f-c552ee8e358f
|
||||
TextButton(onClick = onThirdButtonClicked) {
|
||||
Text(thirdButtonText)
|
||||
}
|
||||
}
|
||||
TextButton(onClick = onCancelClicked) {
|
||||
Text(cancelText)
|
||||
}
|
||||
},
|
||||
confirmButton = {
|
||||
Row(
|
||||
modifier = Modifier.padding(all = 8.dp),
|
||||
horizontalArrangement = Arrangement.Center
|
||||
) {
|
||||
Button(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
onClick = {
|
||||
onSubmitClicked()
|
||||
}
|
||||
) {
|
||||
Text(submitText)
|
||||
TextButton(
|
||||
onClick = {
|
||||
onSubmitClicked()
|
||||
}
|
||||
) {
|
||||
Text(submitText)
|
||||
}
|
||||
},
|
||||
shape = shape,
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import androidx.compose.foundation.layout.padding
|
|||
import androidx.compose.material3.AlertDialog
|
||||
import androidx.compose.material3.AlertDialogDefaults
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
|
@ -55,24 +56,14 @@ fun ErrorDialog(
|
|||
modifier = modifier,
|
||||
onDismissRequest = onDismiss,
|
||||
title = {
|
||||
Text(text = title)
|
||||
Text(title)
|
||||
},
|
||||
text = {
|
||||
Text(content)
|
||||
},
|
||||
confirmButton = {
|
||||
Row(
|
||||
modifier = Modifier.padding(all = 8.dp),
|
||||
horizontalArrangement = Arrangement.Center
|
||||
) {
|
||||
Button(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
onClick = {
|
||||
onDismiss()
|
||||
}
|
||||
) {
|
||||
Text(submitText)
|
||||
}
|
||||
TextButton(onClick = onDismiss) {
|
||||
Text(submitText)
|
||||
}
|
||||
},
|
||||
shape = shape,
|
||||
|
|
|
|||
|
|
@ -16,12 +16,9 @@
|
|||
|
||||
package io.element.android.libraries.designsystem.preview
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import io.element.android.libraries.designsystem.theme.ElementTheme
|
||||
import io.element.android.libraries.designsystem.theme.components.Surface
|
||||
|
||||
@Composable
|
||||
fun ElementPreviewLight(
|
||||
|
|
@ -55,9 +52,8 @@ private fun ElementPreview(
|
|||
) {
|
||||
ElementTheme(darkTheme = darkTheme) {
|
||||
if (showBackground) {
|
||||
Box(modifier = Modifier.background(MaterialTheme.colorScheme.background)) {
|
||||
content()
|
||||
}
|
||||
// If we have a proper contentColor applied we need a Surface instead of a Box
|
||||
Surface { content() }
|
||||
} else {
|
||||
content()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,11 @@ import androidx.compose.runtime.Composable
|
|||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import io.element.android.libraries.designsystem.Azure
|
||||
import io.element.android.libraries.designsystem.Black_800
|
||||
import io.element.android.libraries.designsystem.Black_950
|
||||
import io.element.android.libraries.designsystem.DarkGrey
|
||||
import io.element.android.libraries.designsystem.Gray_400
|
||||
import io.element.android.libraries.designsystem.Gray_450
|
||||
import io.element.android.libraries.designsystem.SystemGrey5Dark
|
||||
import io.element.android.libraries.designsystem.SystemGrey6Dark
|
||||
import io.element.android.libraries.designsystem.theme.previews.ColorsSchemePreview
|
||||
|
|
@ -30,6 +34,8 @@ fun elementColorsDark() = ElementColors(
|
|||
messageFromMeBackground = SystemGrey5Dark,
|
||||
messageFromOtherBackground = SystemGrey6Dark,
|
||||
messageHighlightedBackground = Azure,
|
||||
quaternary = Gray_400,
|
||||
quinary = Gray_450,
|
||||
isLight = false,
|
||||
)
|
||||
|
||||
|
|
@ -48,12 +54,12 @@ val materialColorSchemeDark = darkColorScheme(
|
|||
// TODO onTertiary = ColorDarkTokens.OnTertiary,
|
||||
// TODO tertiaryContainer = ColorDarkTokens.TertiaryContainer,
|
||||
// TODO onTertiaryContainer = ColorDarkTokens.OnTertiaryContainer,
|
||||
background = Color.Black,
|
||||
background = Black_800,
|
||||
onBackground = Color.White,
|
||||
surface = Color.Black,
|
||||
surface = Black_800,
|
||||
onSurface = Color.White,
|
||||
surfaceVariant = SystemGrey5Dark,
|
||||
// TODO onSurfaceVariant = ColorDarkTokens.OnSurfaceVariant,
|
||||
surfaceVariant = Black_950,
|
||||
onSurfaceVariant = Color.White,
|
||||
// TODO surfaceTint = primary,
|
||||
// TODO inverseSurface = ColorDarkTokens.InverseSurface,
|
||||
// TODO inverseOnSurface = ColorDarkTokens.InverseOnSurface,
|
||||
|
|
|
|||
|
|
@ -21,7 +21,12 @@ import androidx.compose.runtime.Composable
|
|||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import io.element.android.libraries.designsystem.Azure
|
||||
import io.element.android.libraries.designsystem.LightGrey
|
||||
import io.element.android.libraries.designsystem.Black_900
|
||||
import io.element.android.libraries.designsystem.Gray_100
|
||||
import io.element.android.libraries.designsystem.Gray_150
|
||||
import io.element.android.libraries.designsystem.Gray_200
|
||||
import io.element.android.libraries.designsystem.Gray_25
|
||||
import io.element.android.libraries.designsystem.Gray_50
|
||||
import io.element.android.libraries.designsystem.SystemGrey5Light
|
||||
import io.element.android.libraries.designsystem.SystemGrey6Light
|
||||
import io.element.android.libraries.designsystem.theme.previews.ColorsSchemePreview
|
||||
|
|
@ -30,21 +35,23 @@ fun elementColorsLight() = ElementColors(
|
|||
messageFromMeBackground = SystemGrey5Light,
|
||||
messageFromOtherBackground = SystemGrey6Light,
|
||||
messageHighlightedBackground = Azure,
|
||||
quaternary = Gray_100,
|
||||
quinary = Gray_50,
|
||||
isLight = true,
|
||||
)
|
||||
|
||||
// TODO Lots of colors are missing
|
||||
val materialColorSchemeLight = lightColorScheme(
|
||||
primary = Color.Black,
|
||||
primary = Black_900,
|
||||
onPrimary = Color.White,
|
||||
// TODO primaryContainer = ColorLightTokens.PrimaryContainer,
|
||||
// TODO onPrimaryContainer = ColorLightTokens.OnPrimaryContainer,
|
||||
// TODO inversePrimary = ColorLightTokens.InversePrimary,
|
||||
secondary = LightGrey,
|
||||
secondary = Gray_200,
|
||||
// TODO onSecondary = ColorLightTokens.OnSecondary,
|
||||
// TODO secondaryContainer = ColorLightTokens.SecondaryContainer,
|
||||
// TODO onSecondaryContainer = ColorLightTokens.OnSecondaryContainer,
|
||||
tertiary = Color.Black,
|
||||
tertiary = Gray_150,
|
||||
// TODO onTertiary = ColorLightTokens.OnTertiary,
|
||||
// TODO tertiaryContainer = ColorLightTokens.TertiaryContainer,
|
||||
// TODO onTertiaryContainer = ColorLightTokens.OnTertiaryContainer,
|
||||
|
|
@ -52,8 +59,8 @@ val materialColorSchemeLight = lightColorScheme(
|
|||
onBackground = Color.Black,
|
||||
surface = Color.White,
|
||||
onSurface = Color.Black,
|
||||
surfaceVariant = SystemGrey5Light,
|
||||
onSurfaceVariant = Color.Black,
|
||||
surfaceVariant = Gray_25,
|
||||
onSurfaceVariant = Gray_150,
|
||||
// TODO surfaceTint = primary,
|
||||
// TODO inverseSurface = ColorLightTokens.InverseSurface,
|
||||
// TODO inverseOnSurface = ColorLightTokens.InverseOnSurface,
|
||||
|
|
|
|||
|
|
@ -16,15 +16,19 @@
|
|||
|
||||
package io.element.android.libraries.designsystem.theme
|
||||
|
||||
import androidx.compose.runtime.Stable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
||||
@Stable
|
||||
class ElementColors(
|
||||
messageFromMeBackground: Color,
|
||||
messageFromOtherBackground: Color,
|
||||
messageHighlightedBackground: Color,
|
||||
quaternary: Color,
|
||||
quinary: Color,
|
||||
isLight: Boolean,
|
||||
) {
|
||||
var messageFromMeBackground by mutableStateOf(messageFromMeBackground)
|
||||
|
|
@ -34,6 +38,12 @@ class ElementColors(
|
|||
var messageHighlightedBackground by mutableStateOf(messageHighlightedBackground)
|
||||
private set
|
||||
|
||||
var quaternary by mutableStateOf(quaternary)
|
||||
private set
|
||||
|
||||
var quinary by mutableStateOf(quinary)
|
||||
private set
|
||||
|
||||
var isLight by mutableStateOf(isLight)
|
||||
private set
|
||||
|
||||
|
|
@ -41,11 +51,15 @@ class ElementColors(
|
|||
messageFromMeBackground: Color = this.messageFromMeBackground,
|
||||
messageFromOtherBackground: Color = this.messageFromOtherBackground,
|
||||
messageHighlightedBackground: Color = this.messageHighlightedBackground,
|
||||
quaternary: Color = this.quaternary,
|
||||
quinary: Color = this.quinary,
|
||||
isLight: Boolean = this.isLight,
|
||||
) = ElementColors(
|
||||
messageFromMeBackground = messageFromMeBackground,
|
||||
messageFromOtherBackground = messageFromOtherBackground,
|
||||
messageHighlightedBackground = messageHighlightedBackground,
|
||||
quaternary = quaternary,
|
||||
quinary = quinary,
|
||||
isLight = isLight,
|
||||
)
|
||||
|
||||
|
|
@ -53,6 +67,8 @@ class ElementColors(
|
|||
messageFromMeBackground = other.messageFromMeBackground
|
||||
messageFromOtherBackground = other.messageFromOtherBackground
|
||||
messageHighlightedBackground = other.messageHighlightedBackground
|
||||
quaternary = other.quaternary
|
||||
quinary = other.quinary
|
||||
isLight = other.isLight
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,15 +49,16 @@ val LocalColors = staticCompositionLocalOf { elementColorsLight() }
|
|||
fun ElementTheme(
|
||||
darkTheme: Boolean = isSystemInDarkTheme(),
|
||||
dynamicColor: Boolean = false, /* true to enable MaterialYou */
|
||||
lightColors: ElementColors = elementColorsLight(),
|
||||
darkColors: ElementColors = elementColorsDark(),
|
||||
colors: ElementColors = if (darkTheme) elementColorsDark() else elementColorsLight(),
|
||||
materialLightColors: ColorScheme = materialColorSchemeLight,
|
||||
materialDarkColors: ColorScheme = materialColorSchemeDark,
|
||||
content: @Composable () -> Unit,
|
||||
) {
|
||||
val systemUiController = rememberSystemUiController()
|
||||
val useDarkIcons = !darkTheme
|
||||
val currentColor = remember { if (darkTheme) darkColors else lightColors }
|
||||
val currentColor = remember(darkTheme) {
|
||||
colors.copy()
|
||||
}.apply { updateColorsFrom(colors) }
|
||||
val colorScheme = when {
|
||||
dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
|
||||
val context = LocalContext.current
|
||||
|
|
@ -75,9 +76,8 @@ fun ElementTheme(
|
|||
darkIcons = useDarkIcons
|
||||
)
|
||||
}
|
||||
val rememberedColors = remember { currentColor.copy() }.apply { updateColorsFrom(currentColor) }
|
||||
CompositionLocalProvider(
|
||||
LocalColors provides rememberedColors,
|
||||
LocalColors provides currentColor,
|
||||
) {
|
||||
MaterialTheme(
|
||||
colorScheme = colorScheme,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* 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.Column
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.ArrowBack
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
|
||||
import io.element.android.libraries.ui.strings.R.string as StringR
|
||||
|
||||
@Composable
|
||||
fun BackButton(
|
||||
action: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
icon: ImageVector = Icons.Default.ArrowBack,
|
||||
contentDescription: String = stringResource(StringR.action_back),
|
||||
enabled: Boolean = true
|
||||
) {
|
||||
IconButton(
|
||||
modifier = modifier,
|
||||
onClick = action,
|
||||
enabled = enabled,
|
||||
) {
|
||||
Icon(imageVector = icon, contentDescription = contentDescription)
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
internal fun BackButtonPreviewLight() = ElementPreviewLight { ContentToPreview() }
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
internal fun BackButtonPreviewDark() = ElementPreviewDark { ContentToPreview() }
|
||||
|
||||
@Composable
|
||||
private fun ContentToPreview() {
|
||||
Column {
|
||||
BackButton(action = { }, enabled = true, contentDescription = "Back")
|
||||
BackButton(action = { }, enabled = false, contentDescription = "Back")
|
||||
}
|
||||
}
|
||||
|
|
@ -29,6 +29,7 @@ import androidx.compose.runtime.remember
|
|||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Shape
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
|
||||
|
||||
|
|
@ -37,11 +38,11 @@ fun Button(
|
|||
onClick: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
enabled: Boolean = true,
|
||||
shape: Shape = ButtonDefaults.shape,
|
||||
colors: ButtonColors = ButtonDefaults.buttonColors(),
|
||||
elevation: ButtonElevation? = ButtonDefaults.buttonElevation(),
|
||||
shape: Shape = ElementButtonDefaults.shape,
|
||||
colors: ButtonColors = ElementButtonDefaults.buttonColors(),
|
||||
elevation: ButtonElevation? = ElementButtonDefaults.buttonElevation(),
|
||||
border: BorderStroke? = null,
|
||||
contentPadding: PaddingValues = ButtonDefaults.ContentPadding,
|
||||
contentPadding: PaddingValues = ElementButtonDefaults.ContentPadding,
|
||||
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
|
||||
content: @Composable RowScope.() -> Unit
|
||||
) {
|
||||
|
|
@ -59,6 +60,17 @@ fun Button(
|
|||
)
|
||||
}
|
||||
|
||||
object ElementButtonDefaults {
|
||||
val ContentPadding = PaddingValues(horizontal = 24.dp, vertical = 14.dp)
|
||||
val shape: Shape @Composable get() = ButtonDefaults.shape
|
||||
@Composable
|
||||
fun buttonElevation(): ButtonElevation = ButtonDefaults.buttonElevation()
|
||||
|
||||
@Composable
|
||||
fun buttonColors(): ButtonColors = ButtonDefaults.buttonColors()
|
||||
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
internal fun ButtonsLightPreview() = ElementPreviewLight { ContentToPreview() }
|
||||
|
|
|
|||
|
|
@ -29,8 +29,17 @@ import androidx.compose.material3.TextFieldColors
|
|||
import androidx.compose.material3.TextFieldDefaults
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.ExperimentalComposeUiApi
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.focus.FocusDirection
|
||||
import androidx.compose.ui.focus.FocusManager
|
||||
import androidx.compose.ui.graphics.Shape
|
||||
import androidx.compose.ui.input.key.Key
|
||||
import androidx.compose.ui.input.key.KeyEventType
|
||||
import androidx.compose.ui.input.key.key
|
||||
import androidx.compose.ui.input.key.onPreviewKeyEvent
|
||||
import androidx.compose.ui.input.key.type
|
||||
import androidx.compose.ui.platform.LocalFocusManager
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.input.VisualTransformation
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
|
|
@ -40,7 +49,7 @@ import io.element.android.libraries.designsystem.preview.ElementPreviewLight
|
|||
import io.element.android.libraries.designsystem.utils.allBooleans
|
||||
import io.element.android.libraries.designsystem.utils.asInt
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@OptIn(ExperimentalMaterial3Api::class, ExperimentalComposeUiApi::class)
|
||||
@Composable
|
||||
fun OutlinedTextField(
|
||||
value: String,
|
||||
|
|
@ -88,6 +97,16 @@ fun OutlinedTextField(
|
|||
)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalComposeUiApi::class)
|
||||
fun Modifier.onTabOrEnterKeyFocusNext(focusManager: FocusManager): Modifier = onPreviewKeyEvent { event ->
|
||||
if (event.type == KeyEventType.KeyUp && (event.key == Key.Tab || event.key == Key.Enter)) {
|
||||
focusManager.moveFocus(FocusDirection.Down)
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
internal fun OutlinedTextFieldsLightPreview() = ElementPreviewLight { ContentToPreview() }
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue