refactor(ui): improve chat and node list row layout#236
refactor(ui): improve chat and node list row layout#236
Conversation
- Move favorite star to appear immediately after name across all row types
(Chats, Channels, Rooms, Contacts)
- Standardize timestamp formatting: clock time for today, "Yesterday",
full weekday name for 2-6 days, "Feb 8" for this year, "Dec 25, 2025"
for previous years
- Replace system NavigationLink chevrons with custom positioned chevrons
aligned to the top row, consistent with Apple Messages UI
- Remove fuzzy relative timestamps ("2 min ago") in favor of clock time
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Replace inline UnreadBadges with red count badge on avatar top-right, matching iOS app icon badge style - Increase favorite star size to 110% across all row types Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Align badge style with the tab bar badges in the Chats/Nodes selector for visual consistency across the app. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
| Image(systemName: "star.fill") | ||
| .foregroundStyle(.yellow) | ||
| .font(.caption) | ||
| .font(.system(size: 13.2)) |
There was a problem hiding this comment.
Don't use specific font sizes, stick with dynamic. To make it a little larger than .caption, try .footnote.
| } else if calendar.isDateInYesterday(date) { | ||
| return date.formatted(.relative(presentation: .named)) | ||
| } else { | ||
| return "Yesterday" |
There was a problem hiding this comment.
Don't hard code strings, use date.formatted(.relative(presentation: .named)) like it was before. It will handle translating "yesterday" for free.
| } else if contact.isFavorite { | ||
| Image(systemName: "star.fill") | ||
| .font(.caption) | ||
| .font(.system(size: 13.2)) |
|
|
||
| UnreadBadges( | ||
| unreadCount: channel.unreadCount, | ||
| unreadMentionCount: channel.unreadMentionCount, |
There was a problem hiding this comment.
Why was this removed? This will remove the "@" badge that appears when a user was mentioned in a chat/channel.
| UnreadBadges( | ||
| unreadCount: channel.unreadCount, | ||
| unreadMentionCount: channel.unreadMentionCount, | ||
| notificationLevel: channel.notificationLevel |
There was a problem hiding this comment.
Removing this will remove the ability to color the unread badge based on the set notification level
| Image(systemName: "star.fill") | ||
| .foregroundStyle(.yellow) | ||
| .font(.caption) | ||
| .font(.system(size: 13.2)) |
|
I like the chevron in the upper right of the row, but I don't think it's worth straying from the chevron we get for free from SwiftUI. Let's keep the middle chevron for now. What's your reasoning behind adding the red badge to the avatar? I don't believe I've seen this UI before. The change also created a regression in visuals. The color doesn't change when the conversation is muted (always stays red), and if the user is mentioned in the conversation they no longer see an "@" icon. |
Summary
Changes
ConversationRow.swift,ChannelConversationRow.swift,RoomConversationRow.swift— star position, unread badge on avatar, chevron alignmentContactRowView.swift— star position and sizeConversationTimestamp.swift— new date formatting rulesRelativeTimestampText.swift— matching date formatting, removed fuzzy relative timesConversationListContent.swift— hidden NavigationLink pattern for custom chevron positioningContactsCompactList.swift— same hidden NavigationLink patternView+ListChevron.swift(new) — shared chevron modifier with configurable offsetUnreadCountBadge.swift(new) — red avatar badge component with white borderRelativeTimestampTextTests.swift— updated tests for new formattingTest plan
swiftlint lintpasses with no new warnings🤖 Generated with Claude Code