From 5ace169440daf61320a14e7eb3ae7ffa92c34e38 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 28 Jul 2023 10:29:13 +0200 Subject: [PATCH] Update the API and add UI screenshots demoing it. --- .../impl/components/RoomListTopBar.kt | 6 +- .../libraries/designsystem/text/DpScale.kt | 119 ++++++++++++++++++ .../libraries/designsystem/text/FontSize.kt | 37 ------ .../libraries/textcomposer/TextComposer.kt | 28 ++--- 4 files changed, 136 insertions(+), 54 deletions(-) create mode 100644 libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/text/DpScale.kt delete mode 100644 libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/text/FontSize.kt diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/RoomListTopBar.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/RoomListTopBar.kt index 0c8522e7be..c144ef8671 100644 --- a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/RoomListTopBar.kt +++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/RoomListTopBar.kt @@ -43,7 +43,7 @@ import io.element.android.libraries.designsystem.components.avatar.Avatar import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.designsystem.preview.ElementPreviewDark import io.element.android.libraries.designsystem.preview.ElementPreviewLight -import io.element.android.libraries.designsystem.text.scaleMax +import io.element.android.libraries.designsystem.text.applyScaleDown import io.element.android.libraries.designsystem.text.toSp import io.element.android.libraries.designsystem.theme.aliasScreenTitle import io.element.android.libraries.designsystem.theme.components.DropdownMenu @@ -118,8 +118,8 @@ private fun DefaultRoomListTopBar( else ElementTheme.typography.fontHeadingLgBold.copy( // Due to a limitation of MediumTopAppBar, and to avoid the text to be truncated, - // limit the size to 28.dp instead of 28.sp - fontSize = 28.dp.scaleMax().toSp() + // ensure that the font size will never be bigger than 28.dp. + fontSize = 28.dp.applyScaleDown().toSp() ) Text( style = fontStyle, diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/text/DpScale.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/text/DpScale.kt new file mode 100644 index 0000000000..c4c524e804 --- /dev/null +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/text/DpScale.kt @@ -0,0 +1,119 @@ +/* + * 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.text + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.padding +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalDensity +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.ElementPreviewLight +import io.element.android.libraries.designsystem.theme.components.Text +import io.element.android.libraries.theme.ElementTheme + +/** + * Return the maximum value between the receiver value and the value with fonScale applied. + * So if fontScale is >= 1f, the same value is returned, and if fontScale is < 1f, so returned value + * will be smaller. + */ +@Composable +fun Dp.applyScaleDown(): Dp = with(LocalDensity.current) { + return this@applyScaleDown * fontScale.coerceAtMost(1f) +} + +/** + * Return the minimum value between the receiver value and the value with fonScale applied. + * So if fontScale is <= 1f, the same value is returned, and if fontScale is > 1f, so returned value + * will be bigger. + */ +@Composable +fun Dp.applyScaleUp(): Dp = with(LocalDensity.current) { + return this@applyScaleUp * fontScale.coerceAtLeast(1f) +} + +@Preview(fontScale = 0.75f) +@Composable +fun DpScalePreview_0_75f() = ElementPreviewLight { + val fontSizeInDp = 16.dp + Column( + modifier = Modifier.padding(4.dp), + verticalArrangement = Arrangement.spacedBy(6.dp) + ) { + Text( + text = "A text should have a size of 16.sp", + style = ElementTheme.typography.fontBodyLgRegular.copy(fontSize = fontSizeInDp.toSp()) + ) + Text( + text = "A text should have the same size (applyScaleUp)", + style = ElementTheme.typography.fontBodyLgRegular.copy(fontSize = fontSizeInDp.applyScaleUp().toSp()) + ) + Text( + text = "A text should be smaller (applyScaleDown)", + style = ElementTheme.typography.fontBodyLgRegular.copy(fontSize = fontSizeInDp.applyScaleDown().toSp()) + ) + } +} + +@Preview(fontScale = 1.0f) +@Composable +fun DpScalePreview_1_0f() = ElementPreviewLight { + val fontSizeInDp = 16.dp + Column( + modifier = Modifier.padding(4.dp), + verticalArrangement = Arrangement.spacedBy(6.dp) + ) { + Text( + text = "A text with a size of 16.sp", + style = ElementTheme.typography.fontBodyLgRegular.copy(fontSize = fontSizeInDp.toSp()) + ) + Text( + text = "A text with the same size (applyScaleUp)", + style = ElementTheme.typography.fontBodyLgRegular.copy(fontSize = fontSizeInDp.applyScaleUp().toSp()) + ) + Text( + text = "A text with the same size (applyScaleDown)", + style = ElementTheme.typography.fontBodyLgRegular.copy(fontSize = fontSizeInDp.applyScaleDown().toSp()) + ) + } +} + +@Preview(fontScale = 1.5f) +@Composable +fun DpScalePreview_1_5f() = ElementPreviewLight { + val fontSizeInDp = 16.dp + Column( + modifier = Modifier.padding(4.dp), + verticalArrangement = Arrangement.spacedBy(6.dp) + ) { + Text( + text = "A text with a size of 16.sp", + style = ElementTheme.typography.fontBodyLgRegular.copy(fontSize = fontSizeInDp.toSp()) + ) + Text( + text = "A text with a bigger size (applyScaleUp)", + style = ElementTheme.typography.fontBodyLgRegular.copy(fontSize = fontSizeInDp.applyScaleUp().toSp()) + ) + Text( + text = "A text with the same size (applyScaleDown)", + style = ElementTheme.typography.fontBodyLgRegular.copy(fontSize = fontSizeInDp.applyScaleDown().toSp()) + ) + } +} diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/text/FontSize.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/text/FontSize.kt deleted file mode 100644 index 4dcc05ee29..0000000000 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/text/FontSize.kt +++ /dev/null @@ -1,37 +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.text - -import androidx.compose.runtime.Composable -import androidx.compose.ui.platform.LocalDensity -import androidx.compose.ui.unit.Dp - -/** - * Return the maximum value between the receiver value and the value with fonScale applied. - */ -@Composable -fun Dp.scaleMax(): Dp = with(LocalDensity.current) { - return this@scaleMax * fontScale.coerceAtMost(1f) -} - -/** - * Return the minimum value between the receiver value and the value with fonScale applied. - */ -@Composable -fun Dp.scaleMin(): Dp = with(LocalDensity.current) { - return this@scaleMin * fontScale.coerceAtLeast(1f) -} diff --git a/libraries/textcomposer/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt b/libraries/textcomposer/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt index ecf721ac1d..a802298624 100644 --- a/libraries/textcomposer/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt +++ b/libraries/textcomposer/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt @@ -73,7 +73,7 @@ import io.element.android.libraries.designsystem.VectorIcons import io.element.android.libraries.designsystem.modifiers.applyIf import io.element.android.libraries.designsystem.preview.DayNightPreviews import io.element.android.libraries.designsystem.preview.ElementPreview -import io.element.android.libraries.designsystem.text.scaleMin +import io.element.android.libraries.designsystem.text.applyScaleUp 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 @@ -110,8 +110,8 @@ fun TextComposer( ) { AttachmentButton(onClick = onAddAttachment, modifier = Modifier.padding(vertical = 6.dp)) Spacer(modifier = Modifier.width(12.dp)) - val roundCornerSmall = 20.dp.scaleMin() - val roundCornerLarge = 28.dp.scaleMin() + val roundCornerSmall = 20.dp.applyScaleUp() + val roundCornerLarge = 28.dp.applyScaleUp() var lineCount by remember { mutableStateOf(0) } val roundedCornerSize = remember(lineCount, composerMode) { @@ -128,7 +128,7 @@ fun TextComposer( ) ) val roundedCorners = RoundedCornerShape(roundedCornerSizeState.value) - val minHeight = 42.dp.scaleMin() + val minHeight = 42.dp.applyScaleUp() val bgColor = ElementTheme.colors.bgSubtleSecondary // Change border color depending on focus var hasFocus by remember { mutableStateOf(false) } @@ -169,7 +169,7 @@ fun TextComposer( singleLine = false, visualTransformation = VisualTransformation.None, shape = roundedCorners, - contentPadding = PaddingValues(top = 10.dp.scaleMin(), bottom = 10.dp.scaleMin(), start = 12.dp.scaleMin(), end = 42.dp.scaleMin()), + contentPadding = PaddingValues(top = 10.dp.applyScaleUp(), bottom = 10.dp.applyScaleUp(), start = 12.dp.applyScaleUp(), end = 42.dp.applyScaleUp()), interactionSource = remember { MutableInteractionSource() }, placeholder = { Text(stringResource(CommonStrings.common_message), style = defaultTypography) @@ -197,7 +197,7 @@ fun TextComposer( canSendMessage = composerCanSendMessage, onSendMessage = onSendMessage, composerMode = composerMode, - modifier = Modifier.padding(end = 6.dp.scaleMin(), bottom = 6.dp.scaleMin()) + modifier = Modifier.padding(end = 6.dp.applyScaleUp(), bottom = 6.dp.applyScaleUp()) ) } } @@ -257,7 +257,7 @@ private fun EditingModeView( tint = ElementTheme.materialColors.secondary, modifier = Modifier .padding(vertical = 8.dp) - .size(16.dp.scaleMin()), + .size(16.dp.applyScaleUp()), ) Text( stringResource(CommonStrings.common_editing), @@ -274,7 +274,7 @@ private fun EditingModeView( tint = ElementTheme.materialColors.secondary, modifier = Modifier .padding(top = 8.dp, bottom = 8.dp, start = 16.dp, end = 12.dp) - .size(16.dp.scaleMin()) + .size(16.dp.applyScaleUp()) .clickable( enabled = true, onClick = onResetComposerMode, @@ -337,7 +337,7 @@ private fun ReplyToModeView( tint = MaterialTheme.colorScheme.secondary, modifier = Modifier .padding(end = 4.dp, top = 4.dp, start = 16.dp, bottom = 16.dp) - .size(16.dp.scaleMin()) + .size(16.dp.applyScaleUp()) .clickable( enabled = true, onClick = onResetComposerMode, @@ -355,13 +355,13 @@ private fun AttachmentButton( ) { Surface( modifier - .size(30.dp.scaleMin()) + .size(30.dp.applyScaleUp()) .clickable(onClick = onClick), shape = CircleShape, color = ElementTheme.colors.iconPrimary ) { Image( - modifier = Modifier.size(12.5f.dp.scaleMin()), + modifier = Modifier.size(12.5f.dp.applyScaleUp()), painter = painterResource(R.drawable.ic_add_attachment), contentDescription = stringResource(R.string.rich_text_editor_a11y_add_attachment), contentScale = ContentScale.Inside, @@ -385,10 +385,10 @@ private fun BoxScope.SendButton( modifier = modifier .clip(CircleShape) .background(if (canSendMessage) ElementTheme.colors.iconAccentTertiary else Color.Transparent) - .size(30.dp.scaleMin()) + .size(30.dp.applyScaleUp()) .align(Alignment.BottomEnd) .applyIf(composerMode !is MessageComposerMode.Edit, ifTrue = { - padding(start = 1.dp.scaleMin()) // Center the arrow in the circle + padding(start = 1.dp.applyScaleUp()) // Center the arrow in the circle }) .clickable( enabled = canSendMessage, @@ -408,7 +408,7 @@ private fun BoxScope.SendButton( else -> stringResource(CommonStrings.action_send) } Icon( - modifier = Modifier.size(16.dp.scaleMin()), + modifier = Modifier.size(16.dp.applyScaleUp()), resourceId = iconId, contentDescription = contentDescription, // Exception here, we use Color.White instead of ElementTheme.colors.iconOnSolidPrimary