redesign ChatInput — two-row layout, rounder, elevated

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.
This commit is contained in:
Bruno Deanoz 2026-06-22 18:54:32 +02:00
parent 4351428c66
commit 34a527cdb6

View file

@ -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.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
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.width(4.dp))
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))
}
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.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))
}
}
}
}