From 34a527cdb646c08cd8f3365799584b5379facac8 Mon Sep 17 00:00:00 2001 From: Bruno Deanoz Date: Mon, 22 Jun 2026 18:54:32 +0200 Subject: [PATCH] =?UTF-8?q?redesign=20ChatInput=20=E2=80=94=20two-row=20la?= =?UTF-8?q?yout,=20rounder,=20elevated?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Text field on top with full width, action icons below. More padding (16dp margins, 14dp inner), pill shape with 32dp corners, level3 shadow for float effect. Plus and Mic buttons get subtle circular backgrounds. --- .../dev/kaizen/app/chat/ChatComponents.kt | 62 ++++++++++++------- 1 file changed, 40 insertions(+), 22 deletions(-) diff --git a/app/src/main/java/dev/kaizen/app/chat/ChatComponents.kt b/app/src/main/java/dev/kaizen/app/chat/ChatComponents.kt index c8a1483..7558350 100644 --- a/app/src/main/java/dev/kaizen/app/chat/ChatComponents.kt +++ b/app/src/main/java/dev/kaizen/app/chat/ChatComponents.kt @@ -532,48 +532,66 @@ fun ChatInput( ) { val cs = MaterialTheme.colorScheme val isDark = isSystemInDarkTheme() + val accent = LocalKaizenAccent.current val hasContent = value.isNotBlank() || pendingFiles.any { it.uploaded != null } val canSend = enabled && hasContent && pendingFiles.none { it.uploading } + val iconBg = if (isDark) Color.White.copy(alpha = 0.07f) else Color.Black.copy(alpha = 0.05f) + GlassSurface( modifier = modifier .fillMaxWidth() - .padding(horizontal = 8.dp), + .padding(horizontal = 16.dp), shape = KaizenShapes.pill, - tintAlpha = if (isDark) 0.85f else 0.90f, - shadowStack = KaizenShadows.level2, - cornerRadius = 28.dp, + tintAlpha = if (isDark) 0.82f else 0.88f, + shadowStack = KaizenShadows.level3, + cornerRadius = 32.dp, ) { - Column { + Column(Modifier.padding(horizontal = 14.dp, vertical = 14.dp)) { if (pendingFiles.isNotEmpty()) { Row( - Modifier.fillMaxWidth().horizontalScroll(rememberScrollState()).padding(start = 14.dp, end = 14.dp, top = 10.dp), + Modifier.fillMaxWidth().horizontalScroll(rememberScrollState()).padding(bottom = 10.dp), horizontalArrangement = Arrangement.spacedBy(6.dp), ) { pendingFiles.forEach { pf -> PendingFileChip(pf, onRemove = { onRemoveFile(pf.id) }) } } } - Row(Modifier.padding(start = 6.dp, end = 8.dp, top = 10.dp, bottom = 10.dp), verticalAlignment = Alignment.Bottom) { - Box(Modifier.size(42.dp).clip(KaizenShapes.circle).clickable(onClick = onAddClick), contentAlignment = Alignment.Center) { - Icon(KaizenIcons.Plus, stringResource(R.string.chat_attachment), tint = cs.onSurfaceVariant, modifier = Modifier.size(22.dp)) + + Box(Modifier.fillMaxWidth().heightIn(min = 48.dp), contentAlignment = Alignment.CenterStart) { + if (value.isEmpty()) Text( + stringResource(R.string.chat_input_placeholder), + color = cs.onSurfaceVariant.copy(alpha = 0.5f), + fontSize = 16.sp, + ) + BasicTextField( + value = value, onValueChange = onValueChange, + textStyle = TextStyle(color = cs.onBackground, fontSize = 16.sp, lineHeight = 24.sp), + cursorBrush = SolidColor(accent.primary), maxLines = 6, modifier = Modifier.fillMaxWidth(), + ) + } + + Spacer(Modifier.height(10.dp)) + + Row(verticalAlignment = Alignment.CenterVertically) { + Box( + Modifier.size(40.dp).clip(KaizenShapes.circle).background(iconBg).clickable(onClick = onAddClick), + contentAlignment = Alignment.Center, + ) { + Icon(KaizenIcons.Plus, stringResource(R.string.chat_attachment), tint = cs.onSurfaceVariant, modifier = Modifier.size(20.dp)) } - Box(Modifier.weight(1f).heightIn(min = 42.dp).padding(horizontal = 6.dp), contentAlignment = Alignment.CenterStart) { - if (value.isEmpty()) Text(stringResource(R.string.chat_input_placeholder), color = cs.onSurfaceVariant.copy(alpha = 0.6f), fontSize = 15.sp) - val accent = LocalKaizenAccent.current - BasicTextField( - value = value, onValueChange = onValueChange, - textStyle = TextStyle(color = cs.onBackground, fontSize = 16.sp, lineHeight = 24.sp), - cursorBrush = SolidColor(accent.primary), maxLines = 6, modifier = Modifier.fillMaxWidth(), - ) + Spacer(Modifier.width(8.dp)) + Box( + Modifier.size(40.dp).clip(KaizenShapes.circle).background(iconBg), + contentAlignment = Alignment.Center, + ) { + Icon(KaizenIcons.Mic, stringResource(R.string.chat_call), tint = cs.onSurfaceVariant, modifier = Modifier.size(20.dp)) } - Spacer(Modifier.width(4.dp)) + + Spacer(Modifier.weight(1f)) + if (hasContent) { SendButton(enabled = canSend, onClick = onSend) - } else { - Box(Modifier.size(44.dp).clip(KaizenShapes.circle), contentAlignment = Alignment.Center) { - Icon(KaizenIcons.Mic, stringResource(R.string.chat_call), tint = cs.onSurfaceVariant, modifier = Modifier.size(22.dp)) - } } } }