Skip to content

refactor(ui): improve chat and node list row layout#236

Draft
mikewren wants to merge 4 commits intoAvi0n:devfrom
mikewren:refactor/chat-list-row-layout
Draft

refactor(ui): improve chat and node list row layout#236
mikewren wants to merge 4 commits intoAvi0n:devfrom
mikewren:refactor/chat-list-row-layout

Conversation

@mikewren
Copy link
Contributor

Summary

  • Move favorite star to appear immediately after name, enlarged to 110%
  • Standardize timestamp formatting across Chats and Nodes tabs (clock time today, "Yesterday", full weekday, abbreviated date, year for old dates)
  • Replace system NavigationLink chevrons with custom positioned chevrons aligned to the top row, consistent with Apple Messages UI
  • Move unread message count to a red badge overlay on the avatar top-right, matching iOS app icon badge style

Changes

  • ConversationRow.swift, ChannelConversationRow.swift, RoomConversationRow.swift — star position, unread badge on avatar, chevron alignment
  • ContactRowView.swift — star position and size
  • ConversationTimestamp.swift — new date formatting rules
  • RelativeTimestampText.swift — matching date formatting, removed fuzzy relative times
  • ConversationListContent.swift — hidden NavigationLink pattern for custom chevron positioning
  • ContactsCompactList.swift — same hidden NavigationLink pattern
  • View+ListChevron.swift (new) — shared chevron modifier with configurable offset
  • UnreadCountBadge.swift (new) — red avatar badge component with white border
  • RelativeTimestampTextTests.swift — updated tests for new formatting

Test plan

  • Verified all changes in iPhone and iPad simulators
  • Chats tab: star position, timestamp formatting, chevron alignment, unread badge on avatar
  • Nodes tab: star position, timestamp formatting, chevron alignment
  • iPad split view: layout correct, no unwanted chevrons
  • Unread badge renders with white border fully covering avatar
  • swiftlint lint passes with no new warnings

🤖 Generated with Claude Code

mikewren and others added 4 commits February 26, 2026 15:30
- 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))
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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"
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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))
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here, use dynamic type.


UnreadBadges(
unreadCount: channel.unreadCount,
unreadMentionCount: channel.unreadMentionCount,
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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))
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use dynamic type

@Avi0n
Copy link
Owner

Avi0n commented Mar 8, 2026

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.

@Avi0n Avi0n marked this pull request as draft March 8, 2026 08:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants