Merge pull request #1651 from vector-im/feature/bma/uiUpdate

Preparatory work for SecureBackup: UI update
This commit is contained in:
Benoit Marty
2023-10-27 11:03:29 +02:00
committed by GitHub
22 changed files with 375 additions and 180 deletions

View File

@@ -16,41 +16,27 @@
package io.element.android.features.preferences.impl.notifications
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.dp
import androidx.lifecycle.Lifecycle
import io.element.android.libraries.androidutils.system.startNotificationSettingsIntent
import io.element.android.libraries.architecture.Async
import io.element.android.libraries.designsystem.atomic.molecules.DialogLikeBannerMolecule
import io.element.android.libraries.designsystem.components.ProgressDialog
import io.element.android.libraries.designsystem.components.dialogs.ErrorDialog
import io.element.android.libraries.designsystem.components.preferences.PreferenceCategory
import io.element.android.libraries.designsystem.components.preferences.PreferencePage
import io.element.android.libraries.designsystem.components.preferences.PreferenceSwitch
import io.element.android.libraries.designsystem.components.preferences.PreferenceText
import io.element.android.libraries.designsystem.components.preferences.PreferencePage
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.theme.components.Button
import io.element.android.libraries.designsystem.theme.components.ButtonSize
import io.element.android.libraries.designsystem.theme.components.Surface
import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.utils.CommonDrawables
import io.element.android.libraries.designsystem.utils.OnLifecycleEvent
import io.element.android.libraries.matrix.api.room.RoomNotificationMode
import io.element.android.libraries.theme.ElementTheme
import io.element.android.libraries.ui.strings.CommonStrings
/**
@@ -197,41 +183,14 @@ private fun InvalidNotificationSettingsView(
onDismissError: () -> Unit,
modifier: Modifier = Modifier
) {
Box(modifier = modifier.padding(horizontal = 16.dp, vertical = 8.dp)) {
Surface(
Modifier.fillMaxWidth(),
shape = MaterialTheme.shapes.small,
color = MaterialTheme.colorScheme.surfaceVariant
) {
Column(
Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 12.dp)
) {
Row {
Text(
stringResource(CommonStrings.screen_notification_settings_configuration_mismatch),
modifier = Modifier.weight(1f),
style = ElementTheme.typography.fontBodyLgMedium,
color = MaterialTheme.colorScheme.primary,
textAlign = TextAlign.Start,
)
}
Spacer(modifier = Modifier.height(4.dp))
Text(
stringResource(CommonStrings.screen_notification_settings_configuration_mismatch_description),
style = ElementTheme.typography.fontBodyMdRegular,
)
Spacer(modifier = Modifier.height(12.dp))
Button(
text = stringResource(CommonStrings.action_continue),
size = ButtonSize.Medium,
modifier = Modifier.fillMaxWidth(),
onClick = onContinueClicked,
)
}
}
}
DialogLikeBannerMolecule(
modifier = modifier,
title = stringResource(CommonStrings.screen_notification_settings_configuration_mismatch),
content = stringResource(CommonStrings.screen_notification_settings_configuration_mismatch_description),
onSubmitClicked = onContinueClicked,
onDismissClicked = null,
)
if (showError) {
ErrorDialog(
title = stringResource(id = CommonStrings.dialog_title_error),

View File

@@ -16,31 +16,13 @@
package io.element.android.features.roomlist.impl.components
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import io.element.android.features.roomlist.impl.R
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.atomic.molecules.DialogLikeBannerMolecule
import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.theme.components.Button
import io.element.android.libraries.designsystem.theme.components.ButtonSize
import io.element.android.libraries.designsystem.theme.components.Icon
import io.element.android.libraries.designsystem.theme.components.Surface
import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.utils.CommonDrawables
import io.element.android.libraries.theme.ElementTheme
import io.element.android.libraries.ui.strings.CommonStrings
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
@Composable
internal fun RequestVerificationHeader(
@@ -48,50 +30,20 @@ internal fun RequestVerificationHeader(
onDismissClicked: () -> Unit,
modifier: Modifier = Modifier,
) {
Box(modifier = modifier.padding(horizontal = 16.dp, vertical = 8.dp)) {
Surface(
Modifier.fillMaxWidth(),
shape = MaterialTheme.shapes.small,
color = MaterialTheme.colorScheme.surfaceVariant
) {
Column(
Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 12.dp)
) {
Row {
Text(
stringResource(R.string.session_verification_banner_title),
modifier = Modifier.weight(1f),
style = ElementTheme.typography.fontBodyLgMedium,
color = MaterialTheme.colorScheme.primary,
textAlign = TextAlign.Start,
)
Icon(
modifier = Modifier.clickable(onClick = onDismissClicked),
resourceId = CommonDrawables.ic_compound_close,
contentDescription = stringResource(CommonStrings.action_close)
)
}
Spacer(modifier = Modifier.height(4.dp))
Text(
stringResource(R.string.session_verification_banner_message),
style = ElementTheme.typography.fontBodyMdRegular,
)
Spacer(modifier = Modifier.height(12.dp))
Button(
text = stringResource(CommonStrings.action_continue),
size = ButtonSize.Medium,
modifier = Modifier.fillMaxWidth(),
onClick = onVerifyClicked,
)
}
}
}
DialogLikeBannerMolecule(
modifier = modifier,
title = stringResource(R.string.session_verification_banner_title),
content = stringResource(R.string.session_verification_banner_message),
onSubmitClicked = onVerifyClicked,
onDismissClicked = onDismissClicked,
)
}
@PreviewsDayNight
@Composable
internal fun RequestVerificationHeaderPreview() = ElementPreview {
RequestVerificationHeader(onVerifyClicked = {}, onDismissClicked = {})
RequestVerificationHeader(
onVerifyClicked = {},
onDismissClicked = {},
)
}

View File

@@ -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.atomic.atoms
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.theme.ElementTheme
@Composable
fun RedIndicatorAtom(
modifier: Modifier = Modifier,
size: Dp = 10.dp,
borderSize: Dp = 1.dp,
color: Color = ElementTheme.colors.bgCriticalPrimary,
) {
Box(
modifier = modifier
.size(size)
.border(borderSize, ElementTheme.materialColors.background, CircleShape)
.padding(borderSize / 2)
.clip(CircleShape)
.background(color)
)
}
@PreviewsDayNight
@Composable
internal fun RedIndicatorAtomPreview() = ElementPreview {
RedIndicatorAtom()
}

View File

@@ -0,0 +1,105 @@
/*
* 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.atomic.molecules
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.theme.components.Button
import io.element.android.libraries.designsystem.theme.components.ButtonSize
import io.element.android.libraries.designsystem.theme.components.Icon
import io.element.android.libraries.designsystem.theme.components.Surface
import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.utils.CommonDrawables
import io.element.android.libraries.theme.ElementTheme
import io.element.android.libraries.ui.strings.CommonStrings
@Composable
fun DialogLikeBannerMolecule(
title: String,
content: String,
onSubmitClicked: () -> Unit,
onDismissClicked: (() -> Unit)?,
modifier: Modifier = Modifier,
) {
Box(modifier = modifier.padding(horizontal = 16.dp, vertical = 8.dp)) {
Surface(
Modifier.fillMaxWidth(),
shape = MaterialTheme.shapes.small,
color = MaterialTheme.colorScheme.surfaceVariant
) {
Column(
Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 12.dp)
) {
Row {
Text(
text = title,
modifier = Modifier.weight(1f),
style = ElementTheme.typography.fontBodyLgMedium,
color = MaterialTheme.colorScheme.primary,
textAlign = TextAlign.Start,
)
if (onDismissClicked != null) {
Icon(
modifier = Modifier.clickable(onClick = onDismissClicked),
resourceId = CommonDrawables.ic_compound_close,
contentDescription = stringResource(CommonStrings.action_close)
)
}
}
Spacer(modifier = Modifier.height(4.dp))
Text(
text = content,
style = ElementTheme.typography.fontBodyMdRegular,
)
Spacer(modifier = Modifier.height(12.dp))
Button(
text = stringResource(CommonStrings.action_continue),
size = ButtonSize.Medium,
modifier = Modifier.fillMaxWidth(),
onClick = onSubmitClicked,
)
}
}
}
}
@PreviewsDayNight
@Composable
internal fun DialogLikeBannerMoleculePreview() = ElementPreview {
DialogLikeBannerMolecule(
title = "Title",
content = "Content",
onSubmitClicked = {},
onDismissClicked = {}
)
}

View File

@@ -38,6 +38,7 @@ fun ConfirmationDialog(
title: String? = null,
submitText: String = stringResource(id = CommonStrings.action_ok),
cancelText: String = stringResource(id = CommonStrings.action_cancel),
destructiveSubmit: Boolean = false,
thirdButtonText: String? = null,
onCancelClicked: () -> Unit = onDismiss,
onThirdButtonClicked: () -> Unit = {},
@@ -49,6 +50,7 @@ fun ConfirmationDialog(
submitText = submitText,
cancelText = cancelText,
thirdButtonText = thirdButtonText,
destructiveSubmit = destructiveSubmit,
onSubmitClicked = onSubmitClicked,
onCancelClicked = onCancelClicked,
onThirdButtonClicked = onThirdButtonClicked,
@@ -67,6 +69,7 @@ private fun ConfirmationDialogContent(
title: String? = null,
thirdButtonText: String? = null,
onThirdButtonClicked: () -> Unit = {},
destructiveSubmit: Boolean = false,
icon: @Composable (() -> Unit)? = null,
) {
SimpleAlertDialogContent(
@@ -79,6 +82,7 @@ private fun ConfirmationDialogContent(
onCancelClicked = onCancelClicked,
thirdButtonText = thirdButtonText,
onThirdButtonClicked = onThirdButtonClicked,
destructiveSubmit = destructiveSubmit,
icon = icon,
)
}

View File

@@ -57,6 +57,7 @@ fun PreferenceText(
icon: ImageVector? = null,
@DrawableRes iconResourceId: Int? = null,
showIconAreaIfNoIcon: Boolean = false,
showIconBadge: Boolean = false,
tintColor: Color? = null,
onClick: () -> Unit = {},
) {
@@ -73,6 +74,7 @@ fun PreferenceText(
PreferenceIcon(
icon = icon,
iconResourceId = iconResourceId,
showIconBadge = showIconBadge,
enabled = enabled,
isVisible = showIconAreaIfNoIcon,
tintColor = tintColor ?: enabled.toSecondaryEnabledColor(),

View File

@@ -17,17 +17,20 @@
package io.element.android.libraries.designsystem.components.preferences.components
import androidx.annotation.DrawableRes
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.dp
import io.element.android.libraries.designsystem.atomic.atoms.RedIndicatorAtom
import io.element.android.libraries.designsystem.preview.ElementThemedPreview
import io.element.android.libraries.designsystem.preview.PreviewGroup
import io.element.android.libraries.designsystem.theme.components.Icon
@@ -38,20 +41,30 @@ fun PreferenceIcon(
modifier: Modifier = Modifier,
icon: ImageVector? = null,
@DrawableRes iconResourceId: Int? = null,
showIconBadge: Boolean = false,
tintColor: Color? = null,
enabled: Boolean = true,
isVisible: Boolean = true,
) {
if (icon != null || iconResourceId != null) {
Icon(
imageVector = icon,
resourceId = iconResourceId,
contentDescription = "",
tint = tintColor ?: enabled.toSecondaryEnabledColor(),
modifier = modifier
.padding(end = 16.dp)
.size(24.dp),
)
Box(modifier = modifier) {
Icon(
imageVector = icon,
resourceId = iconResourceId,
contentDescription = "",
tint = tintColor ?: enabled.toSecondaryEnabledColor(),
modifier = Modifier
.padding(end = 16.dp)
.size(24.dp),
)
if (showIconBadge) {
RedIndicatorAtom(
modifier = Modifier
.align(Alignment.TopEnd)
.padding(end = 16.dp)
)
}
}
} else if (isVisible) {
Spacer(modifier = modifier.width(40.dp))
}
@@ -60,9 +73,19 @@ fun PreferenceIcon(
@Preview(group = PreviewGroup.Preferences)
@Composable
internal fun PreferenceIconPreview(@PreviewParameter(ImageVectorProvider::class) content: ImageVector?) =
ElementThemedPreview { ContentToPreview(content) }
ElementThemedPreview {
PreferenceIcon(
icon = content,
showIconBadge = false,
)
}
@Preview(group = PreviewGroup.Preferences)
@Composable
private fun ContentToPreview(content: ImageVector?) {
PreferenceIcon(icon = content)
}
internal fun PreferenceIconWithBadgePreview(@PreviewParameter(ImageVectorProvider::class) content: ImageVector?) =
ElementThemedPreview {
PreferenceIcon(
icon = content,
showIconBadge = true,
)
}

View File

@@ -57,6 +57,7 @@ internal fun SimpleAlertDialogContent(
title: String? = null,
subtitle: @Composable (() -> Unit)? = null,
submitText: String? = null,
destructiveSubmit: Boolean = false,
onSubmitClicked: () -> Unit = {},
thirdButtonText: String? = null,
onThirdButtonClicked: () -> Unit = {},
@@ -76,6 +77,7 @@ internal fun SimpleAlertDialogContent(
title = title,
subtitle = subtitle,
submitText = submitText,
destructiveSubmit = destructiveSubmit,
onSubmitClicked = onSubmitClicked,
thirdButtonText = thirdButtonText,
onThirdButtonClicked = onThirdButtonClicked,
@@ -92,6 +94,7 @@ internal fun SimpleAlertDialogContent(
title: String? = null,
subtitle: @Composable (() -> Unit)? = null,
submitText: String? = null,
destructiveSubmit: Boolean = false,
onSubmitClicked: () -> Unit = {},
thirdButtonText: String? = null,
onThirdButtonClicked: () -> Unit = {},
@@ -126,6 +129,7 @@ internal fun SimpleAlertDialogContent(
enabled = enabled,
size = ButtonSize.Medium,
onClick = onSubmitClicked,
destructive = destructiveSubmit,
)
}
}
@@ -345,8 +349,10 @@ private fun AlertDialogFlowRow(
val arrangement = Arrangement.End
val mainAxisPositions = IntArray(childrenMainAxisSizes.size) { 0 }
with(arrangement) {
arrange(mainAxisLayoutSize, childrenMainAxisSizes,
layoutDirection, mainAxisPositions)
arrange(
mainAxisLayoutSize, childrenMainAxisSizes,
layoutDirection, mainAxisPositions
)
}
placeables.forEachIndexed { j, placeable ->
placeable.place(
@@ -385,22 +391,22 @@ internal object DialogContentDefaults {
val containerColor: Color
@Composable
@ReadOnlyComposable
get()= ElementTheme.colors.bgCanvasDefault
get() = ElementTheme.colors.bgCanvasDefault
val textContentColor: Color
@Composable
@ReadOnlyComposable
get()= ElementTheme.materialColors.onSurfaceVariant
get() = ElementTheme.materialColors.onSurfaceVariant
val titleContentColor: Color
@Composable
@ReadOnlyComposable
get()= ElementTheme.materialColors.onSurface
get() = ElementTheme.materialColors.onSurface
val iconContentColor: Color
@Composable
@ReadOnlyComposable
get()= ElementTheme.materialColors.primary
get() = ElementTheme.materialColors.primary
}
// Paddings for each of the dialog's parts. Taken from M3 source code.
@@ -462,3 +468,21 @@ internal fun DialogWithOnlyMessageAndOkButtonPreview() {
}
}
}
@Preview(group = PreviewGroup.Dialogs, name = "Dialog with destructive button")
@Composable
@Suppress("MaxLineLength")
internal fun DialogWithDestructiveButtonPreview() {
ElementThemedPreview(showBackground = false) {
DialogPreview {
SimpleAlertDialogContent(
title = "Dialog Title",
content = "A dialog with a destructive action",
cancelText = "Cancel",
submitText = "Delete",
destructiveSubmit = true,
onCancelClicked = {},
)
}
}
}

View File

@@ -20,6 +20,7 @@ import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.foundation.layout.IntrinsicSize
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
@@ -64,6 +65,7 @@ fun Button(
enabled: Boolean = true,
size: ButtonSize = ButtonSize.Large,
showProgress: Boolean = false,
destructive: Boolean = false,
leadingIcon: IconSource? = null,
) = ButtonInternal(
text = text,
@@ -73,6 +75,7 @@ fun Button(
enabled = enabled,
size = size,
showProgress = showProgress,
destructive = destructive,
leadingIcon = leadingIcon
)
@@ -84,6 +87,7 @@ fun OutlinedButton(
enabled: Boolean = true,
size: ButtonSize = ButtonSize.Large,
showProgress: Boolean = false,
destructive: Boolean = false,
leadingIcon: IconSource? = null,
) = ButtonInternal(
text = text,
@@ -93,6 +97,7 @@ fun OutlinedButton(
enabled = enabled,
size = size,
showProgress = showProgress,
destructive = destructive,
leadingIcon = leadingIcon
)
@@ -104,6 +109,7 @@ fun TextButton(
enabled: Boolean = true,
size: ButtonSize = ButtonSize.Large,
showProgress: Boolean = false,
destructive: Boolean = false,
leadingIcon: IconSource? = null,
) = ButtonInternal(
text = text,
@@ -113,6 +119,7 @@ fun TextButton(
enabled = enabled,
size = size,
showProgress = showProgress,
destructive = destructive,
leadingIcon = leadingIcon
)
@@ -122,7 +129,8 @@ private fun ButtonInternal(
onClick: () -> Unit,
style: ButtonStyle,
modifier: Modifier = Modifier,
colors: ButtonColors = style.getColors(),
destructive: Boolean = false,
colors: ButtonColors = style.getColors(destructive),
enabled: Boolean = true,
size: ButtonSize = ButtonSize.Large,
showProgress: Boolean = false,
@@ -170,7 +178,12 @@ private fun ButtonInternal(
ButtonStyle.Filled -> null
ButtonStyle.Outlined -> BorderStroke(
width = 1.dp,
color = ElementTheme.colors.borderInteractiveSecondary
color = if (destructive)
ElementTheme.colors.borderCriticalPrimary.copy(
alpha = if (enabled) 1f else 0.5f
)
else
ElementTheme.colors.borderInteractiveSecondary
)
ButtonStyle.Text -> null
}
@@ -246,26 +259,52 @@ internal enum class ButtonStyle {
Filled, Outlined, Text;
@Composable
fun getColors(): ButtonColors = when (this) {
fun getColors(destructive: Boolean): ButtonColors = when (this) {
Filled -> ButtonDefaults.buttonColors(
containerColor = ElementTheme.materialColors.primary,
containerColor = getPrimaryColor(destructive),
contentColor = ElementTheme.materialColors.onPrimary,
disabledContainerColor = ElementTheme.colors.bgActionPrimaryDisabled,
disabledContainerColor = if (destructive) {
ElementTheme.colors.bgCriticalPrimary.copy(alpha = 0.5f)
} else {
ElementTheme.colors.bgActionPrimaryDisabled
},
disabledContentColor = ElementTheme.colors.textOnSolidPrimary
)
Outlined -> ButtonDefaults.buttonColors(
containerColor = Color.Transparent,
contentColor = ElementTheme.materialColors.primary,
contentColor = getPrimaryColor(destructive),
disabledContainerColor = Color.Transparent,
disabledContentColor = ElementTheme.colors.textDisabled,
disabledContentColor = getDisabledContentColor(destructive),
)
Text -> ButtonDefaults.buttonColors(
containerColor = Color.Transparent,
contentColor = if (LocalContentColor.current.isSpecified) LocalContentColor.current else ElementTheme.materialColors.primary,
contentColor = if (destructive) {
ElementTheme.colors.textCriticalPrimary
} else {
if (LocalContentColor.current.isSpecified) LocalContentColor.current else ElementTheme.materialColors.primary
},
disabledContainerColor = Color.Transparent,
disabledContentColor = ElementTheme.colors.textDisabled,
disabledContentColor = getDisabledContentColor(destructive),
)
}
@Composable
private fun getPrimaryColor(destructive: Boolean): Color {
return if (destructive) {
ElementTheme.colors.bgCriticalPrimary
} else {
ElementTheme.materialColors.primary
}
}
@Composable
private fun getDisabledContentColor(destructive: Boolean): Color {
return if (destructive) {
ElementTheme.colors.textCriticalPrimary.copy(alpha = 0.5f)
} else {
ElementTheme.colors.textDisabled
}
}
}
@Preview(group = PreviewGroup.Buttons)
@@ -326,7 +365,6 @@ internal fun TextButtonLargePreview() {
private fun ButtonCombinationPreview(
style: ButtonStyle,
size: ButtonSize,
modifier: Modifier = Modifier,
) {
ElementThemedPreview {
Column(
@@ -335,59 +373,70 @@ private fun ButtonCombinationPreview(
.padding(16.dp)
.width(IntrinsicSize.Max),
) {
// Normal
ButtonRowPreview(
modifier = Modifier.then(modifier),
style = style,
size = size,
)
// With icon
ButtonRowPreview(
modifier = Modifier.then(modifier),
leadingIcon = IconSource.Resource(CommonDrawables.ic_compound_share_android),
style = style,
size = size,
)
// With progress
ButtonRowPreview(
modifier = Modifier.then(modifier),
showProgress = true,
style = style,
size = size,
)
ButtonMatrixPreview(style = style, size = size, destructive = false)
ButtonMatrixPreview(style = style, size = size, destructive = true)
}
}
}
@Composable
private fun ColumnScope.ButtonMatrixPreview(
style: ButtonStyle,
size: ButtonSize,
destructive: Boolean,
) {
// Normal
ButtonRowPreview(
style = style,
size = size,
destructive = destructive,
)
// With icon
ButtonRowPreview(
leadingIcon = IconSource.Resource(CommonDrawables.ic_compound_share_android),
style = style,
size = size,
destructive = destructive,
)
// With progress
ButtonRowPreview(
showProgress = true,
style = style,
size = size,
destructive = destructive,
)
}
@Composable
private fun ButtonRowPreview(
style: ButtonStyle,
size: ButtonSize,
modifier: Modifier = Modifier,
leadingIcon: IconSource? = null,
showProgress: Boolean = false,
destructive: Boolean = false,
) {
Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(8.dp, Alignment.CenterHorizontally)) {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.spacedBy(8.dp, Alignment.CenterHorizontally),
) {
ButtonInternal(
text = "A button",
showProgress = showProgress,
destructive = destructive,
onClick = {},
style = style,
size = size,
leadingIcon = leadingIcon,
modifier = Modifier.then(modifier),
)
ButtonInternal(
text = "A button",
showProgress = showProgress,
destructive = destructive,
enabled = false,
onClick = {},
style = style,
size = size,
leadingIcon = leadingIcon,
modifier = Modifier.then(modifier),
)
}
}