fix(desktop): Messages list typography hierarchy — name vs. preview

Conversation cards had the name (bodyMedium) and last-message preview
(bodySmall) stacked flush against each other with very similar color
weight, so they blurred into one visual block. Now:

- Name: titleSmall (14sp Medium) — the focal top line.
- Preview: bodySmall at onSurfaceVariant.alpha = 0.7 with a 2dp spacer
  above so it sits as a clearly secondary line.
- Timestamp: labelSmall at alpha 0.6, with an 8dp gutter before it so
  long names don't collide with the time.
- Group badge: onSurfaceVariant.alpha = 0.5 instead of primary-70% so
  it doesn't compete with the name for attention.

The name now wins the eye first; the preview reads as a subtitle.

https://claude.ai/code/session_01NufduPfZvYQVYwLkbCjCUo
This commit is contained in:
Claude
2026-04-24 16:31:01 +00:00
parent b69224433c
commit a59358f888
@@ -342,7 +342,10 @@ private fun ConversationCard(
Spacer(Modifier.width(10.dp)) Spacer(Modifier.width(10.dp))
// Name, preview, timestamp // Name, preview, timestamp — vertical hierarchy: name = medium-weight
// primary text (titleSmall), preview = muted secondary. Prior styling had
// both lines at the same weight / near-same color and stacked flush,
// making them blur into each other.
Column(modifier = Modifier.weight(1f)) { Column(modifier = Modifier.weight(1f)) {
Row( Row(
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
@@ -351,7 +354,7 @@ private fun ConversationCard(
) { ) {
Text( Text(
text = item.displayName, text = item.displayName,
style = MaterialTheme.typography.bodyMedium, style = MaterialTheme.typography.titleSmall,
color = MaterialTheme.colorScheme.onSurface, color = MaterialTheme.colorScheme.onSurface,
maxLines = 1, maxLines = 1,
overflow = TextOverflow.Ellipsis, overflow = TextOverflow.Ellipsis,
@@ -359,30 +362,34 @@ private fun ConversationCard(
) )
if (item.lastMessageTimestamp > 0) { if (item.lastMessageTimestamp > 0) {
Spacer(Modifier.width(8.dp))
Text( Text(
text = item.lastMessageTimestamp.toTimeAgo(withDot = false), text = item.lastMessageTimestamp.toTimeAgo(withDot = false),
style = MaterialTheme.typography.labelSmall, style = MaterialTheme.typography.labelSmall,
color = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.7f), color = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.6f),
) )
} }
} }
if (item.lastMessagePreview.isNotEmpty()) { if (item.lastMessagePreview.isNotEmpty()) {
Spacer(Modifier.height(2.dp))
Text( Text(
text = item.lastMessagePreview, text = item.lastMessagePreview,
style = MaterialTheme.typography.bodySmall, style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurfaceVariant, color = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.7f),
maxLines = 1, maxLines = 1,
overflow = TextOverflow.Ellipsis, overflow = TextOverflow.Ellipsis,
) )
} }
// Group indicator // Group indicator — labelSmall with muted tertiary so the name line
// still wins the eye even when a group badge is present.
if (item.isGroup) { if (item.isGroup) {
Spacer(Modifier.height(2.dp))
Text( Text(
text = "Group (${item.users.size + 1})", text = "Group (${item.users.size + 1})",
style = MaterialTheme.typography.labelSmall, style = MaterialTheme.typography.labelSmall,
color = MaterialTheme.colorScheme.primary.copy(alpha = 0.7f), color = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.5f),
) )
} }
} }