[Rich text editor] Update design (#1332)

* Fix composer height and padding

* Update plus and cancel icons with design system icons

* Update border so that it is always visible

* Update placeholder color

* Update send and tick icons

* Update design of formatting buttons

* Update RTE icons

* Reduce bottom padding

---------

Co-authored-by: ElementBot <benoitm+elementbot@element.io>
This commit is contained in:
jonnyandrew 2023-09-15 11:16:30 +01:00 committed by GitHub
parent 2d98b397c6
commit 6563dca4f2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
47 changed files with 282 additions and 165 deletions

View file

@ -114,7 +114,7 @@ fun TextComposer(
start = 3.dp,
end = 6.dp,
top = 8.dp,
bottom = 5.dp,
bottom = 4.dp,
)
.fillMaxWidth(),
) {
@ -137,7 +137,7 @@ fun TextComposer(
) {
Icon(
modifier = Modifier.size(30.dp.applyScaleUp()),
resourceId = R.drawable.ic_plus, // TODO Replace with design system icon when available
resourceId = VectorIcons.Plus,
contentDescription = stringResource(R.string.rich_text_editor_a11y_add_attachment),
tint = ElementTheme.colors.iconPrimary,
)
@ -146,7 +146,7 @@ fun TextComposer(
val roundCornerLarge = 28.dp.applyScaleUp()
val roundedCornerSize = remember(state.lineCount, composerMode) {
if (state.lineCount > 1 || composerMode is MessageComposerMode.Special) {
if (composerMode is MessageComposerMode.Special) {
roundCornerSmall
} else {
roundCornerLarge
@ -156,17 +156,13 @@ fun TextComposer(
targetValue = roundedCornerSize,
animationSpec = tween(
durationMillis = 100,
)
),
label = "roundedCornerSizeAnimation"
)
val roundedCorners = RoundedCornerShape(roundedCornerSizeState.value)
val colors = ElementTheme.colors
val bgColor = colors.bgSubtleSecondary
val borderColor by remember(state.hasFocus, colors) {
derivedStateOf {
if (state.hasFocus) colors.borderDisabled else bgColor
}
}
val borderColor = colors.borderDisabled
Column(
modifier = Modifier
@ -180,7 +176,7 @@ fun TextComposer(
.fillMaxWidth()
.clip(roundedCorners)
.background(color = bgColor)
.border(1.dp, borderColor, roundedCorners)
.border(0.5.dp, borderColor, roundedCorners)
) {
if (composerMode is MessageComposerMode.Special) {
ComposerModeView(composerMode = composerMode, onResetComposerMode = onResetComposerMode)
@ -272,7 +268,7 @@ private fun TextInput(
Text(
placeholder,
style = defaultTypography.copy(
color = ElementTheme.colors.textDisabled,
color = ElementTheme.colors.textSecondary,
),
)
}
@ -280,6 +276,7 @@ private fun TextInput(
RichTextEditor(
state = state,
modifier = Modifier
.padding(top = 6.dp, bottom = 6.dp)
.fillMaxWidth(),
style = RichTextEditorDefaults.style(
text = RichTextEditorDefaults.textStyle(
@ -323,7 +320,7 @@ private fun TextFormatting(
) {
Icon(
modifier = Modifier.size(30.dp.applyScaleUp()),
resourceId = R.drawable.ic_cancel, // TODO Replace with design system icon when available
resourceId = VectorIcons.Cancel,
contentDescription = stringResource(CommonStrings.action_close),
tint = ElementTheme.colors.iconPrimary,
)
@ -335,8 +332,8 @@ private fun TextFormatting(
.constrainAs(formatting) {
top.linkTo(parent.top)
bottom.linkTo(parent.bottom)
start.linkTo(close.end, margin = 3.dp)
end.linkTo(send.start, margin = 20.dp)
start.linkTo(close.end, margin = 1.dp)
end.linkTo(send.start, margin = 14.dp)
width = fillToConstraints
}
.horizontalScroll(scrollState),
@ -589,7 +586,7 @@ private fun SendButton(
) {
Icon(
modifier = Modifier
.height(18.dp.applyScaleUp())
.height(24.dp.applyScaleUp())
.align(Alignment.Center),
resourceId = iconId,
contentDescription = contentDescription,

View file

@ -18,17 +18,26 @@ package io.element.android.libraries.textcomposer.components
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.ripple.rememberRipple
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
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.res.vectorResource
import androidx.compose.ui.unit.dp
import io.element.android.libraries.designsystem.VectorIcons
import io.element.android.libraries.designsystem.preview.DayNightPreviews
import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.text.applyScaleUp
import io.element.android.libraries.designsystem.theme.components.Icon
import io.element.android.libraries.designsystem.theme.iconSuccessPrimaryBackground
import io.element.android.libraries.theme.ElementTheme
import io.element.android.libraries.theme.compound.generated.SemanticColors
@ -42,27 +51,65 @@ internal fun FormattingOption(
colors: SemanticColors = ElementTheme.colors,
) {
val backgroundColor = when (state) {
FormattingOptionState.Selected -> colors.bgActionPrimaryRest
FormattingOptionState.Selected -> colors.iconSuccessPrimaryBackground
FormattingOptionState.Default,
FormattingOptionState.Disabled -> Color.Transparent
}
val foregroundColor = when (state) {
FormattingOptionState.Selected -> colors.iconOnSolidPrimary
FormattingOptionState.Default -> colors.iconPrimary
FormattingOptionState.Selected -> colors.iconSuccessPrimary
FormattingOptionState.Default -> colors.iconSecondary
FormattingOptionState.Disabled -> colors.iconDisabled
}
Box(
modifier = modifier
.clickable { onClick() }
.size(44.dp.applyScaleUp())
.background(backgroundColor, shape = RoundedCornerShape(4.dp.applyScaleUp()))
.clickable(
onClick = onClick,
interactionSource = remember { MutableInteractionSource() },
indication = rememberRipple(
bounded = false,
radius = 20.dp,
),
)
.size(48.dp.applyScaleUp())
) {
Icon(
modifier = Modifier.align(Alignment.Center),
imageVector = imageVector,
contentDescription = contentDescription,
tint = foregroundColor,
Box(
modifier = Modifier
.size(36.dp.applyScaleUp())
.align(Alignment.Center)
.background(backgroundColor, shape = RoundedCornerShape(8.dp.applyScaleUp()))
) {
Icon(
modifier = Modifier.align(Alignment.Center),
imageVector = imageVector,
contentDescription = contentDescription,
tint = foregroundColor,
)
}
}
}
@DayNightPreviews
@Composable
internal fun FormattingButtonPreview() = ElementPreview {
Row {
FormattingOption(
state = FormattingOptionState.Default,
onClick = { },
imageVector = ImageVector.vectorResource(VectorIcons.Bold),
contentDescription = "",
)
FormattingOption(
state = FormattingOptionState.Selected,
onClick = { },
imageVector = ImageVector.vectorResource(VectorIcons.Italic),
contentDescription = "",
)
FormattingOption(
state = FormattingOptionState.Disabled,
onClick = { },
imageVector = ImageVector.vectorResource(VectorIcons.Underline),
contentDescription = "",
)
}
}

View file

@ -1,9 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="32dp"
android:height="32dp"
android:viewportWidth="32"
android:viewportHeight="32">
<path
android:pathData="M16,18.121L19.182,21.303C19.483,21.604 19.836,21.754 20.243,21.754C20.649,21.754 21.003,21.604 21.303,21.303C21.604,21.003 21.754,20.649 21.754,20.243C21.754,19.836 21.604,19.483 21.303,19.182L18.121,16L21.303,12.818C21.604,12.517 21.754,12.164 21.754,11.757C21.754,11.351 21.604,10.997 21.303,10.697C21.003,10.396 20.649,10.246 20.243,10.246C19.836,10.246 19.483,10.396 19.182,10.697L16,13.879L12.818,10.697C12.517,10.396 12.164,10.246 11.757,10.246C11.351,10.246 10.997,10.396 10.697,10.697C10.396,10.997 10.246,11.351 10.246,11.757C10.246,12.164 10.396,12.517 10.697,12.818L13.879,16L10.697,19.182C10.396,19.483 10.246,19.836 10.246,20.243C10.246,20.649 10.396,21.003 10.697,21.303C10.997,21.604 11.351,21.754 11.757,21.754C12.164,21.754 12.517,21.604 12.818,21.303L16,18.121ZM26.607,26.607C25.139,28.074 23.482,29.174 21.635,29.908C19.787,30.642 17.909,31.008 16,31.008C14.091,31.008 12.213,30.642 10.365,29.908C8.518,29.174 6.861,28.074 5.393,26.607C3.926,25.139 2.826,23.482 2.092,21.635C1.358,19.787 0.992,17.909 0.992,16C0.992,14.091 1.358,12.213 2.092,10.365C2.826,8.518 3.926,6.861 5.393,5.393C6.861,3.926 8.518,2.826 10.365,2.092C12.213,1.358 14.091,0.992 16,0.992C17.909,0.992 19.787,1.358 21.635,2.092C23.482,2.826 25.139,3.926 26.607,5.393C28.074,6.861 29.174,8.518 29.908,10.365C30.642,12.213 31.008,14.091 31.008,16C31.008,17.909 30.642,19.787 29.908,21.635C29.174,23.482 28.074,25.139 26.607,26.607Z"
android:fillColor="#1B1D22"/>
</vector>

View file

@ -1,9 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="30dp"
android:height="30dp"
android:viewportWidth="30"
android:viewportHeight="30">
<path
android:pathData="M13.5,16.5V21C13.5,21.425 13.644,21.781 13.931,22.069C14.219,22.356 14.575,22.5 15,22.5C15.425,22.5 15.781,22.356 16.069,22.069C16.356,21.781 16.5,21.425 16.5,21V16.5H21C21.425,16.5 21.781,16.356 22.069,16.069C22.356,15.781 22.5,15.425 22.5,15C22.5,14.575 22.356,14.219 22.069,13.931C21.781,13.644 21.425,13.5 21,13.5H16.5V9C16.5,8.575 16.356,8.219 16.069,7.931C15.781,7.644 15.425,7.5 15,7.5C14.575,7.5 14.219,7.644 13.931,7.931C13.644,8.219 13.5,8.575 13.5,9V13.5H9C8.575,13.5 8.219,13.644 7.931,13.931C7.644,14.219 7.5,14.575 7.5,15C7.5,15.425 7.644,15.781 7.931,16.069C8.219,16.356 8.575,16.5 9,16.5H13.5ZM15,30C12.925,30 10.975,29.606 9.15,28.819C7.325,28.031 5.738,26.962 4.387,25.612C3.037,24.263 1.969,22.675 1.181,20.85C0.394,19.025 0,17.075 0,15C0,12.925 0.394,10.975 1.181,9.15C1.969,7.325 3.037,5.738 4.387,4.387C5.738,3.037 7.325,1.969 9.15,1.181C10.975,0.394 12.925,0 15,0C17.075,0 19.025,0.394 20.85,1.181C22.675,1.969 24.263,3.037 25.612,4.387C26.962,5.738 28.031,7.325 28.819,9.15C29.606,10.975 30,12.925 30,15C30,17.075 29.606,19.025 28.819,20.85C28.031,22.675 26.962,24.263 25.612,25.612C24.263,26.962 22.675,28.031 20.85,28.819C19.025,29.606 17.075,30 15,30Z"
android:fillColor="#1B1D22"/>
</vector>

View file

@ -1,9 +1,25 @@
<!--
~ 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.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="21dp"
android:height="18dp"
android:viewportWidth="21"
android:viewportHeight="18">
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M20.252,10.085 L4.681,17.867c-1.049,0.525 -2.141,-0.601 -1.628,-1.627 0,0 1.93,-3.897 2.461,-4.918 0.531,-1.021 1.138,-1.197 6.781,-1.927 0.209,-0.027 0.38,-0.185 0.38,-0.395 0,-0.21 -0.171,-0.368 -0.38,-0.395C6.652,7.876 6.045,7.699 5.514,6.678 4.983,5.658 3.053,1.76 3.053,1.76 2.54,0.734 3.632,-0.391 4.681,0.133L20.252,7.915c0.894,0.446 0.894,1.723 0,2.17z"
android:fillColor="@android:color/white"/>
android:pathData="M21.829,13.085 L6.259,20.867c-1.049,0.525 -2.141,-0.601 -1.628,-1.627 0,0 1.93,-3.897 2.461,-4.918 0.531,-1.021 1.138,-1.197 6.781,-1.927 0.209,-0.027 0.38,-0.185 0.38,-0.395 0,-0.21 -0.171,-0.368 -0.38,-0.395C8.23,10.876 7.622,10.699 7.091,9.678c-0.531,-1.02 -2.461,-4.918 -2.461,-4.918 -0.513,-1.026 0.579,-2.152 1.628,-1.627L21.829,10.915c0.894,0.446 0.894,1.723 0,2.17z"
android:fillColor="#ffffff"/>
</vector>

View file

@ -1,9 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="16dp"
android:height="15dp"
android:viewportWidth="16"
android:viewportHeight="15">
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M6.518,14.779C6.953,14.779 7.297,14.597 7.535,14.233L15.403,1.968C15.579,1.692 15.65,1.461 15.65,1.234C15.65,0.657 15.245,0.26 14.662,0.26C14.249,0.26 14.009,0.399 13.759,0.792L6.484,12.348L2.736,7.529C2.492,7.205 2.236,7.07 1.874,7.07C1.277,7.07 0.857,7.489 0.857,8.066C0.857,8.315 0.95,8.565 1.158,8.819L5.495,14.245C5.784,14.606 6.096,14.779 6.518,14.779Z"
android:pathData="M9.55,17.575C9.417,17.575 9.292,17.555 9.175,17.513C9.058,17.471 8.95,17.4 8.85,17.3L4.55,13C4.367,12.817 4.279,12.58 4.288,12.288C4.296,11.996 4.392,11.759 4.575,11.575C4.758,11.392 4.992,11.3 5.275,11.3C5.558,11.3 5.792,11.392 5.975,11.575L9.55,15.15L18.025,6.675C18.208,6.492 18.446,6.4 18.737,6.4C19.029,6.4 19.267,6.492 19.45,6.675C19.633,6.859 19.725,7.096 19.725,7.388C19.725,7.68 19.633,7.917 19.45,8.1L10.25,17.3C10.15,17.4 10.042,17.471 9.925,17.513C9.808,17.555 9.683,17.575 9.55,17.575Z"
android:fillColor="#ffffff"/>
</vector>