From 421b29ef5a1352f786c840ed5d01015c2148d3c4 Mon Sep 17 00:00:00 2001 From: Bruno Deanoz Date: Tue, 23 Jun 2026 01:35:45 +0200 Subject: [PATCH] feat: redesign ReasoningBlock + SourceCards to match design system MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ReasoningBlock: accent-tinted background + gradient border (matches pill language), KaizenShapes.md (16dp radius), larger padding, better line height (20sp), softer icon tint. Replaces flat gray box with solid border. SourceCards: gradient border instead of solid, KaizenShapes.md, shows domain instead of full URL in the link line, slightly larger padding. Both blocks now use the same visual language as the rest of the app — gradient borders, accent tinting, squircle shapes. --- .../java/dev/kaizen/app/chat/StreamBlocks.kt | 59 ++++++++++++------- 1 file changed, 37 insertions(+), 22 deletions(-) diff --git a/app/src/main/java/dev/kaizen/app/chat/StreamBlocks.kt b/app/src/main/java/dev/kaizen/app/chat/StreamBlocks.kt index d186d59..9789dfd 100644 --- a/app/src/main/java/dev/kaizen/app/chat/StreamBlocks.kt +++ b/app/src/main/java/dev/kaizen/app/chat/StreamBlocks.kt @@ -28,6 +28,7 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextOverflow @@ -49,44 +50,51 @@ fun ReasoningBlock(reasoning: String, streaming: Boolean = false) { val accent = LocalKaizenAccent.current var expanded by remember { mutableStateOf(streaming) } - val bg = if (isDark) Color.White.copy(alpha = 0.05f) else Color.Black.copy(alpha = 0.03f) - val borderColor = if (isDark) Color.White.copy(alpha = 0.08f) else Color.Black.copy(alpha = 0.06f) + val bg = accent.primary.copy(alpha = if (isDark) 0.06f else 0.04f) + val borderBrush = remember(isDark, accent) { + Brush.verticalGradient( + listOf( + accent.primary.copy(alpha = if (isDark) 0.20f else 0.15f), + accent.primary.copy(alpha = if (isDark) 0.05f else 0.03f), + ) + ) + } Column( Modifier .fillMaxWidth() - .clip(KaizenShapes.sm) + .clip(KaizenShapes.md) .background(bg) - .border(1.dp, borderColor, KaizenShapes.sm) + .border(0.8.dp, borderBrush, KaizenShapes.md) ) { Row( Modifier .fillMaxWidth() .clickable { expanded = !expanded } - .padding(horizontal = 12.dp, vertical = 8.dp), + .padding(horizontal = 14.dp, vertical = 10.dp), verticalAlignment = Alignment.CenterVertically, ) { - Icon(KaizenIcons.Brain, null, tint = accent.primary, modifier = Modifier.size(16.dp)) - Spacer(Modifier.width(8.dp)) + Icon(KaizenIcons.Brain, null, tint = accent.primary.copy(alpha = 0.75f), modifier = Modifier.size(17.dp)) + Spacer(Modifier.width(9.dp)) Text( stringResource(R.string.stream_reasoning), - color = cs.onSurfaceVariant, + color = cs.onSurfaceVariant.copy(alpha = 0.75f), fontSize = 13.sp, fontWeight = FontWeight.Medium, modifier = Modifier.weight(1f), ) Icon( if (expanded) KaizenIcons.ChevronUp else KaizenIcons.ChevronDown, - null, tint = cs.onSurfaceVariant, modifier = Modifier.size(16.dp), + null, tint = cs.onSurfaceVariant.copy(alpha = 0.40f), modifier = Modifier.size(15.dp), ) } AnimatedVisibility(expanded, enter = expandVertically(), exit = shrinkVertically()) { Text( reasoning, - color = cs.onSurfaceVariant.copy(alpha = 0.8f), + color = cs.onSurfaceVariant.copy(alpha = 0.70f), fontSize = 13.sp, - lineHeight = 18.sp, - modifier = Modifier.padding(start = 12.dp, end = 12.dp, bottom = 10.dp), + lineHeight = 20.sp, + modifier = Modifier.padding(start = 14.dp, end = 14.dp, bottom = 12.dp), ) } } @@ -175,18 +183,18 @@ fun SourcesBlock(sources: List, query: String = "") { .padding(vertical = 4.dp), verticalAlignment = Alignment.CenterVertically, ) { - Icon(KaizenIcons.Globe, null, tint = cs.onSurfaceVariant.copy(alpha = 0.6f), modifier = Modifier.size(13.dp)) + Icon(KaizenIcons.Globe, null, tint = cs.onSurfaceVariant.copy(alpha = 0.55f), modifier = Modifier.size(14.dp)) Spacer(Modifier.width(6.dp)) Text( stringResource(R.string.stream_sources) + " (${sources.size})", - color = cs.onSurfaceVariant.copy(alpha = 0.6f), + color = cs.onSurfaceVariant.copy(alpha = 0.55f), fontSize = 12.sp, fontWeight = FontWeight.Medium, ) Spacer(Modifier.width(4.dp)) Icon( if (expanded) KaizenIcons.ChevronUp else KaizenIcons.ChevronDown, - null, tint = cs.onSurfaceVariant.copy(alpha = 0.4f), modifier = Modifier.size(12.dp), + null, tint = cs.onSurfaceVariant.copy(alpha = 0.35f), modifier = Modifier.size(13.dp), ) } AnimatedVisibility(expanded, enter = expandVertically(), exit = shrinkVertically()) { @@ -208,7 +216,14 @@ fun SourcesBlock(sources: List, query: String = "") { private fun SourceCard(source: SearchSource, isDark: Boolean, accent: dev.kaizen.app.ui.theme.themes.KaizenAccentScheme, onClick: () -> Unit) { val cs = MaterialTheme.colorScheme val bg = if (isDark) Color.White.copy(alpha = 0.05f) else Color.Black.copy(alpha = 0.03f) - val borderColor = if (isDark) Color.White.copy(alpha = 0.06f) else Color.Black.copy(alpha = 0.05f) + val borderBrush = remember(isDark) { + Brush.verticalGradient( + listOf( + if (isDark) Color.White.copy(alpha = 0.10f) else Color.Black.copy(alpha = 0.06f), + if (isDark) Color.White.copy(alpha = 0.03f) else Color.Black.copy(alpha = 0.02f), + ) + ) + } val domain = remember(source.url) { try { @@ -219,11 +234,11 @@ private fun SourceCard(source: SearchSource, isDark: Boolean, accent: dev.kaizen Column( Modifier .fillMaxWidth() - .clip(KaizenShapes.sm) + .clip(KaizenShapes.md) .background(bg) - .border(1.dp, borderColor, KaizenShapes.sm) + .border(0.8.dp, borderBrush, KaizenShapes.md) .clickable(onClick = onClick) - .padding(horizontal = 12.dp, vertical = 10.dp), + .padding(horizontal = 14.dp, vertical = 10.dp), ) { Text( source.title.ifEmpty { domain }, @@ -235,8 +250,8 @@ private fun SourceCard(source: SearchSource, isDark: Boolean, accent: dev.kaizen ) Spacer(Modifier.height(2.dp)) Text( - source.url, - color = accent.primary.copy(alpha = 0.7f), + domain, + color = accent.primary.copy(alpha = 0.65f), fontSize = 11.sp, maxLines = 1, overflow = TextOverflow.Ellipsis, @@ -245,7 +260,7 @@ private fun SourceCard(source: SearchSource, isDark: Boolean, accent: dev.kaizen Spacer(Modifier.height(3.dp)) Text( source.snippet, - color = cs.onSurfaceVariant.copy(alpha = 0.5f), + color = cs.onSurfaceVariant.copy(alpha = 0.50f), fontSize = 11.sp, maxLines = 2, overflow = TextOverflow.Ellipsis,