From 6600d2b0842c4b2c93f8771920f028381204c16f Mon Sep 17 00:00:00 2001 From: Brandon McAnsh Date: Thu, 18 Jun 2026 10:21:55 -0400 Subject: [PATCH] fix(ui/chat): improve ChatInput resizability; improve send button animation Signed-off-by: Brandon McAnsh --- .../getcode/ui/components/chat/ChatInput.kt | 78 +++++++++---------- 1 file changed, 36 insertions(+), 42 deletions(-) diff --git a/ui/components/src/main/kotlin/com/getcode/ui/components/chat/ChatInput.kt b/ui/components/src/main/kotlin/com/getcode/ui/components/chat/ChatInput.kt index ff690ea6e..d985f420c 100644 --- a/ui/components/src/main/kotlin/com/getcode/ui/components/chat/ChatInput.kt +++ b/ui/components/src/main/kotlin/com/getcode/ui/components/chat/ChatInput.kt @@ -1,32 +1,23 @@ package com.getcode.ui.components.chat -import androidx.compose.animation.AnimatedContent +import androidx.compose.animation.animateContentSize +import androidx.compose.animation.core.animateFloatAsState import androidx.compose.animation.core.spring -import androidx.compose.animation.fadeIn -import androidx.compose.animation.fadeOut -import androidx.compose.animation.scaleIn -import androidx.compose.animation.scaleOut -import androidx.compose.animation.togetherWith import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.IntrinsicSize import androidx.compose.foundation.layout.PaddingValues 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.foundation.layout.requiredSize import androidx.compose.foundation.layout.size import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.foundation.text.input.TextFieldState import androidx.compose.foundation.text.input.rememberTextFieldState import androidx.compose.material3.Icon -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.rounded.ArrowUpward import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -57,13 +48,25 @@ fun ChatInput( onSendMessage: () -> Unit, ) { val shape = CodeTheme.shapes.medium + val sendVisible = state.text.isNotEmpty() + val sendSpec = spring(dampingRatio = 0.66f, stiffness = 4000f) + val sendAlpha by animateFloatAsState( + targetValue = if (sendVisible) 1f else 0f, + animationSpec = sendSpec, + label = "send button alpha", + ) + val sendScale by animateFloatAsState( + targetValue = if (sendVisible) 1f else 0.6f, + animationSpec = sendSpec, + label = "send button scale", + ) Row( modifier = Modifier .graphicsLayer { compositingStrategy = CompositingStrategy.Offscreen } .clip(shape) .then(modifier) .fillMaxWidth() - .height(IntrinsicSize.Min), + .animateContentSize(), horizontalArrangement = Arrangement.spacedBy(CodeTheme.dimens.grid.x2), verticalAlignment = Alignment.Bottom ) { @@ -93,36 +96,27 @@ fun ChatInput( unfocusedBorderColor = Color.Transparent, ), trailingIcon = { - AnimatedContent( - targetState = state.text.isNotEmpty(), - label = "show/hide send button", - transitionSpec = { - val spec = spring(dampingRatio = 0.66f, stiffness = 4000f) - (fadeIn(spec) + scaleIn(spec, initialScale = 0.6f)) togetherWith - (fadeOut(spec) + scaleOut(spec, targetScale = 0.6f)) - } - ) { show -> - if (show) { - Icon( - modifier = Modifier - .padding(vertical = CodeTheme.dimens.grid.x1) - .padding(end = CodeTheme.dimens.staticGrid.x1) - .background( - Color.White, - shape = CodeTheme.shapes.extraSmall - ) - .clip(CodeTheme.shapes.extraSmall) - .clickable { onSendMessage() } - .padding(CodeTheme.dimens.staticGrid.x1) - .size(CodeTheme.dimens.staticGrid.x5), - painter = painterResource(R.drawable.ic_arrow_up), - tint = Color.Black, - contentDescription = "Send message" + Icon( + modifier = Modifier + .graphicsLayer { + alpha = sendAlpha + scaleX = sendScale + scaleY = sendScale + } + .padding(vertical = CodeTheme.dimens.grid.x1) + .padding(end = CodeTheme.dimens.staticGrid.x1) + .background( + Color.White, + shape = CodeTheme.shapes.extraSmall ) - } else { - Spacer(Modifier.requiredSize(CodeTheme.dimens.staticGrid.x9)) - } - } + .clip(CodeTheme.shapes.extraSmall) + .clickable(enabled = sendVisible) { onSendMessage() } + .padding(CodeTheme.dimens.staticGrid.x1) + .size(CodeTheme.dimens.staticGrid.x5), + painter = painterResource(R.drawable.ic_arrow_up), + tint = Color.Black, + contentDescription = "Send message" + ) } ) }