diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/Config.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/Config.kt index 3b3bc8460e..be8c86448e 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/Config.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/Config.kt @@ -18,7 +18,6 @@ package io.element.android.libraries.designsystem.components.preferences import androidx.compose.ui.unit.dp -internal val preferenceMinHeightOnlyTitle = 48.dp -internal val preferenceMinHeight = 64.dp +internal val preferenceMinHeightOnlyTitle = 56.dp +internal val preferenceMinHeight = 56.dp internal val preferencePaddingHorizontal = 16.dp -internal val preferencePaddingVertical = 16.dp diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceCategory.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceCategory.kt index 0569900b8b..1bfd209a71 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceCategory.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceCategory.kt @@ -23,7 +23,6 @@ import androidx.compose.foundation.layout.padding import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Announcement import androidx.compose.material.icons.filled.BugReport -import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.tooling.preview.Preview @@ -32,6 +31,7 @@ import io.element.android.libraries.designsystem.preview.ElementThemedPreview import io.element.android.libraries.designsystem.preview.PreviewGroup import io.element.android.libraries.designsystem.theme.components.Divider import io.element.android.libraries.designsystem.theme.components.Text +import io.element.android.libraries.theme.ElementTheme @Composable fun PreferenceCategory( @@ -57,9 +57,14 @@ fun PreferenceCategory( @Composable fun PreferenceCategoryTitle(title: String, modifier: Modifier = Modifier) { Text( - modifier = modifier.padding(top = 12.dp, start = 16.dp, end = 16.dp), - style = MaterialTheme.typography.titleMedium, - color = MaterialTheme.colorScheme.primary, + modifier = modifier.padding( + top = 12.dp, + bottom = 8.dp, + start = preferencePaddingHorizontal, + end = preferencePaddingHorizontal, + ), + style = ElementTheme.typography.fontBodyLgMedium, + color = ElementTheme.materialColors.primary, text = title, ) } @@ -85,7 +90,8 @@ private fun ContentToPreview() { PreferenceSlide( title = "Slide", summary = "Summary", - value = 0.75F + value = 0.75F, + showIconAreaIfNoIcon = true, ) } } diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceCheckbox.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceCheckbox.kt new file mode 100644 index 0000000000..276dbf5323 --- /dev/null +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceCheckbox.kt @@ -0,0 +1,92 @@ +/* + * 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.preferences + +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.defaultMinSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Announcement +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import io.element.android.libraries.designsystem.components.preferences.components.PreferenceIcon +import io.element.android.libraries.designsystem.preview.ElementThemedPreview +import io.element.android.libraries.designsystem.preview.PreviewGroup +import io.element.android.libraries.designsystem.theme.components.Checkbox +import io.element.android.libraries.designsystem.theme.components.Text +import io.element.android.libraries.designsystem.toEnabledColor +import io.element.android.libraries.theme.ElementTheme + +@Composable +fun PreferenceCheckbox( + title: String, + isChecked: Boolean, + modifier: Modifier = Modifier, + enabled: Boolean = true, + icon: ImageVector? = null, + showIconAreaIfNoIcon: Boolean = false, + onCheckedChange: (Boolean) -> Unit = {}, +) { + Row( + modifier = modifier + .fillMaxWidth() + .defaultMinSize(minHeight = preferenceMinHeight) + .padding(vertical = 4.dp, horizontal = preferencePaddingHorizontal) + .clickable { onCheckedChange(!isChecked) }, + verticalAlignment = Alignment.CenterVertically + ) { + PreferenceIcon( + icon = icon, + enabled = enabled, + isVisible = showIconAreaIfNoIcon + ) + Text( + modifier = Modifier + .weight(1f), + style = ElementTheme.typography.fontBodyLgRegular, + text = title, + color = enabled.toEnabledColor(), + ) + Checkbox( + modifier = Modifier + .align(Alignment.CenterVertically), + checked = isChecked, + enabled = enabled, + onCheckedChange = onCheckedChange + ) + } +} + +@Preview(group = PreviewGroup.Preferences) +@Composable +internal fun PreferenceCheckboxPreview() = ElementThemedPreview { ContentToPreview() } + +@Composable +private fun ContentToPreview() { + PreferenceCheckbox( + title = "Checkbox", + icon = Icons.Default.Announcement, + enabled = true, + isChecked = true + ) +} diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceScreen.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceScreen.kt index 3826e6ebde..84c6ff7655 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceScreen.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceScreen.kt @@ -136,10 +136,17 @@ private fun ContentToPreview() { isChecked = true, ) Divider() + PreferenceCheckbox( + title = "Checkbox", + icon = Icons.Default.Announcement, + isChecked = true, + ) + Divider() PreferenceSlide( title = "Slide", summary = "Summary", - value = 0.75F + value = 0.75F, + showIconAreaIfNoIcon = true, ) } } diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceSlide.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceSlide.kt index 024f026c4c..91a9852ed4 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceSlide.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceSlide.kt @@ -17,7 +17,6 @@ package io.element.android.libraries.designsystem.components.preferences import androidx.annotation.FloatRange -import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.defaultMinSize @@ -25,17 +24,18 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Person -import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp import io.element.android.libraries.designsystem.components.preferences.components.PreferenceIcon import io.element.android.libraries.designsystem.preview.ElementThemedPreview import io.element.android.libraries.designsystem.preview.PreviewGroup import io.element.android.libraries.designsystem.theme.components.Slider import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.toEnabledColor +import io.element.android.libraries.theme.ElementTheme @Composable fun PreferenceSlide( @@ -44,45 +44,41 @@ fun PreferenceSlide( value: Float, modifier: Modifier = Modifier, icon: ImageVector? = null, + showIconAreaIfNoIcon: Boolean = false, enabled: Boolean = true, summary: String? = null, steps: Int = 0, onValueChange: (Float) -> Unit = {}, ) { - Box( + Row( modifier = modifier .fillMaxWidth() .defaultMinSize(minHeight = preferenceMinHeight) - .padding(top = preferencePaddingVertical), + .padding(vertical = 4.dp, horizontal = preferencePaddingHorizontal), ) { - Row(modifier = Modifier.fillMaxWidth()) { - PreferenceIcon(icon = icon) - Column( - modifier = Modifier - .weight(1f) - .padding(end = preferencePaddingHorizontal), - ) { + PreferenceIcon(icon = icon, isVisible = showIconAreaIfNoIcon) + Column( + modifier = Modifier + .weight(1f), + ) { + Text( + style = ElementTheme.typography.fontBodyLgRegular, + text = title, + color = enabled.toEnabledColor(), + ) + summary?.let { Text( - modifier = Modifier.fillMaxWidth(), - style = MaterialTheme.typography.bodyLarge, + style = ElementTheme.typography.fontBodyMdRegular, + text = summary, color = enabled.toEnabledColor(), - text = title - ) - summary?.let { - Text( - modifier = Modifier.fillMaxWidth(), - style = MaterialTheme.typography.bodyMedium, - color = enabled.toEnabledColor(), - text = summary - ) - } - Slider( - value = value, - steps = steps, - onValueChange = onValueChange, - enabled = enabled, ) } + Slider( + value = value, + steps = steps, + onValueChange = onValueChange, + enabled = enabled, + ) } } } diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceSwitch.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceSwitch.kt index 96427c1dee..41661c2b90 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceSwitch.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceSwitch.kt @@ -17,25 +17,25 @@ package io.element.android.libraries.designsystem.components.preferences import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.defaultMinSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Announcement -import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Switch import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp import io.element.android.libraries.designsystem.components.preferences.components.PreferenceIcon import io.element.android.libraries.designsystem.preview.ElementThemedPreview import io.element.android.libraries.designsystem.preview.PreviewGroup -import io.element.android.libraries.designsystem.theme.components.Checkbox import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.toEnabledColor +import io.element.android.libraries.theme.ElementTheme @Composable fun PreferenceSwitch( @@ -44,38 +44,37 @@ fun PreferenceSwitch( modifier: Modifier = Modifier, enabled: Boolean = true, icon: ImageVector? = null, + showIconAreaIfNoIcon: Boolean = false, onCheckedChange: (Boolean) -> Unit = {}, ) { - Box( + Row( modifier = modifier .fillMaxWidth() .defaultMinSize(minHeight = preferenceMinHeight) + .padding(vertical = 4.dp, horizontal = preferencePaddingHorizontal) .clickable { onCheckedChange(!isChecked) }, - contentAlignment = Alignment.CenterStart + verticalAlignment = Alignment.CenterVertically ) { - Row(modifier = Modifier.fillMaxWidth()) { - PreferenceIcon( - modifier = Modifier.padding(vertical = preferencePaddingVertical), - icon = icon, - enabled = enabled - ) - Text( - modifier = Modifier - .weight(1f) - .padding(vertical = preferencePaddingVertical), - style = MaterialTheme.typography.bodyLarge, - color = enabled.toEnabledColor(), - text = title - ) - Checkbox( - modifier = Modifier - .padding(end = preferencePaddingHorizontal) - .align(Alignment.CenterVertically), - checked = isChecked, - enabled = enabled, - onCheckedChange = onCheckedChange - ) - } + PreferenceIcon( + icon = icon, + enabled = enabled, + isVisible = showIconAreaIfNoIcon + ) + Text( + modifier = Modifier + .weight(1f), + style = ElementTheme.typography.fontBodyLgRegular, + text = title, + color = enabled.toEnabledColor(), + ) + // TODO Create a wrapper for Switch + Switch( + modifier = Modifier + .align(Alignment.CenterVertically), + checked = isChecked, + enabled = enabled, + onCheckedChange = onCheckedChange + ) } } diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceText.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceText.kt index 2195be296f..fd0d4c0b4f 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceText.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceText.kt @@ -18,19 +18,15 @@ package io.element.android.libraries.designsystem.components.preferences import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement -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.defaultMinSize import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.progressSemantics import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.BugReport -import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -43,75 +39,75 @@ import io.element.android.libraries.designsystem.preview.ElementThemedPreview import io.element.android.libraries.designsystem.preview.PreviewGroup import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator import io.element.android.libraries.designsystem.theme.components.Text +import io.element.android.libraries.theme.ElementTheme +/** + * Tried to use ListItem, but it cannot really match the design. Keep custom Layout for now. + */ @Composable fun PreferenceText( - title: String?, + title: String, modifier: Modifier = Modifier, subtitle: String? = null, currentValue: String? = null, loadingCurrentValue: Boolean = false, icon: ImageVector? = null, + showIconAreaIfNoIcon: Boolean = false, tintColor: Color? = null, onClick: () -> Unit = {}, ) { val minHeight = if (subtitle == null) preferenceMinHeightOnlyTitle else preferenceMinHeight - Box( + + Row( modifier = modifier .fillMaxWidth() .defaultMinSize(minHeight = minHeight) .clickable { onClick() } - .padding(end = preferencePaddingHorizontal), + .padding(horizontal = preferencePaddingHorizontal, vertical = 4.dp), + verticalAlignment = Alignment.CenterVertically ) { - Row( + PreferenceIcon( + icon = icon, + isVisible = showIconAreaIfNoIcon, + tintColor = tintColor ?: ElementTheme.materialColors.secondary + ) + Column( modifier = Modifier - .fillMaxWidth() - .padding(vertical = preferencePaddingVertical) + .weight(1f) + .align(Alignment.CenterVertically) ) { - PreferenceIcon(icon = icon, tintColor = tintColor) - Column( - modifier = Modifier - .weight(1f) - .align(Alignment.CenterVertically) - ) { - if (title != null) { - Text( - style = MaterialTheme.typography.bodyLarge, - text = title, - color = tintColor ?: MaterialTheme.colorScheme.primary, - ) - } - if (title != null && subtitle != null) { - Spacer(modifier = Modifier.height(8.dp)) - } - if (subtitle != null) { - Text( - style = MaterialTheme.typography.bodyMedium, - text = subtitle, - color = tintColor ?: MaterialTheme.colorScheme.tertiary, - ) - } - } - if (currentValue != null) { + Text( + style = ElementTheme.typography.fontBodyLgRegular, + text = title, + color = tintColor ?: ElementTheme.materialColors.primary, + ) + if (subtitle != null) { Text( - modifier = Modifier - .align(Alignment.CenterVertically) - .padding(horizontal = 16.dp), - text = currentValue, - style = MaterialTheme.typography.bodyMedium, - color = MaterialTheme.colorScheme.secondary, - ) - } else if (loadingCurrentValue) { - CircularProgressIndicator( - modifier = Modifier - .progressSemantics() - .padding(horizontal = 16.dp) - .size(20.dp) - .align(Alignment.CenterVertically), - strokeWidth = 2.dp + style = ElementTheme.typography.fontBodyMdRegular, + text = subtitle, + color = tintColor ?: ElementTheme.materialColors.secondary, ) } } + if (currentValue != null) { + Text( + modifier = Modifier + .align(Alignment.CenterVertically) + .padding(horizontal = 16.dp), + text = currentValue, + style = ElementTheme.typography.fontBodyXsMedium, + color = ElementTheme.materialColors.secondary, + ) + } else if (loadingCurrentValue) { + CircularProgressIndicator( + modifier = Modifier + .progressSemantics() + .padding(horizontal = 16.dp) + .size(20.dp) + .align(Alignment.CenterVertically), + strokeWidth = 2.dp + ) + } } } @@ -155,5 +151,14 @@ private fun ContentToPreview() { icon = Icons.Default.BugReport, loadingCurrentValue = true, ) + PreferenceText( + title = "Title no icon with icon area", + showIconAreaIfNoIcon = true, + loadingCurrentValue = true, + ) + PreferenceText( + title = "Title no icon", + loadingCurrentValue = true, + ) } } diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/components/PreferenceIcon.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/components/PreferenceIcon.kt index 1f6e07b44c..ec44a7846a 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/components/PreferenceIcon.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/components/PreferenceIcon.kt @@ -17,8 +17,8 @@ package io.element.android.libraries.designsystem.components.preferences.components import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.heightIn 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.Modifier @@ -46,14 +46,11 @@ fun PreferenceIcon( contentDescription = "", tint = tintColor ?: enabled.toSecondaryEnabledColor(), modifier = modifier - .padding(start = 8.dp) - .width(48.dp) - .heightIn(max = 48.dp), + .padding(end = 16.dp) + .size(24.dp), ) } else if (isVisible) { - Spacer(modifier = modifier.width(56.dp)) - } else { - Spacer(modifier = modifier.width(16.dp)) + Spacer(modifier = modifier.width(40.dp)) } }