Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions Flipcash/Core/Screens/Main/Home/HomeTabBar.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ import FlipcashUI
/// The floating pill tab bar for the v2 UI. A Liquid Glass capsule holds one
/// button per ``HomeTab``, with a white selection pill that slides to the active
/// tab. Ported from Android's `NavigationBarV2` (Figma frame 9013-5434):
/// translucent capsule, white-20% sliding indicator, icons at full/half opacity.
/// translucent capsule, white-20% sliding indicator, white icons and labels in
/// both states. Only the profile photo dims when unselected.
struct HomeTabBar: View {

@Binding var selection: HomeTab
Expand Down Expand Up @@ -80,7 +81,6 @@ struct HomeTabBar: View {
.frame(height: Self.labelLineHeight)
.accessibilityHidden(true)
}
.opacity(selection == tab ? 1 : 0.5)
.frame(width: itemWidth, height: Self.itemHeight)
.contentShape(Capsule())
}
Expand Down Expand Up @@ -110,6 +110,7 @@ struct HomeTabBar: View {
private func icon(for tab: HomeTab) -> some View {
if tab == .tipCard, let profileSlot {
ProfileTabIcon(photo: profileSlot.preview, isSelected: tab == selection)
.opacity(tab == selection ? 1 : 0.5)
.scaleEffect(Self.iconSize / ProfileTabIcon.slotSize)
.frame(width: Self.iconSize, height: Self.iconSize)
} else {
Expand Down
11 changes: 6 additions & 5 deletions Flipcash/Core/Screens/Main/Home/HomeTabView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,18 +38,19 @@ struct HomeTabView: View {
_selection = State(initialValue: initialTab)
_hasOpenedChat = State(initialValue: initialTab == .chat)

// Color the tab glyphs per state: selected white, the rest secondary.
// The iOS 26 tab bar ignores UITabBar.unselectedItemTintColor, so drive
// it through a full item appearance instead. A transparent background
// Color the tab glyphs white in both states, as iOS 27 already does; the
// outline-vs-filled glyph carries the selection. The iOS 26 tab bar
// ignores UITabBar.unselectedItemTintColor, so drive it through a full
// item appearance instead. A transparent background
// keeps the system's Liquid Glass. No-op on the legacy pill path, which
// draws its own buttons rather than a `UITabBar`.
if #available(iOS 26, *) {
let items = UITabBarItemAppearance()
items.normal.iconColor = UIColor(Color.textSecondary)
items.normal.iconColor = UIColor(Color.textMain)
items.selected.iconColor = UIColor(Color.textMain)
// Labels per node 10642:1325: 10pt Avenir Demi, colored like the glyph above.
let titleFont = UIFont.default(size: 10, weight: .semibold)
items.normal.titleTextAttributes = [.font: titleFont, .foregroundColor: UIColor(Color.textSecondary)]
items.normal.titleTextAttributes = [.font: titleFont, .foregroundColor: UIColor(Color.textMain)]
items.selected.titleTextAttributes = [.font: titleFont, .foregroundColor: UIColor(Color.textMain)]

let appearance = UITabBarAppearance()
Expand Down
11 changes: 1 addition & 10 deletions Flipcash/Core/Screens/Main/Home/TabBarBadgedIcon.swift
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ enum TabBarBadgedIcon {
.renderingMode(.template)
.resizable()
.scaledToFit()
.foregroundStyle(glyphColor(isSelected: isSelected))
.foregroundStyle(Color.textMain)
.frame(width: glyphSize, height: glyphSize)
.overlay(alignment: .topTrailing) {
Bubble(size: .regular, count: count, color: .unreadIndicator)
Expand All @@ -59,15 +59,6 @@ enum TabBarBadgedIcon {
.padding(.trailing, bubbleOverhang)
}

/// The color the bar paints its template glyphs in for the state. iOS 27
/// ignores the unselected `iconColor` from `HomeTabView` and paints every
/// glyph in the main text color, so the Chat glyph follows suit there.
private static func glyphColor(isSelected: Bool) -> Color {
if isSelected { return .textMain }
if #available(iOS 27, *) { return .textMain }
return .textSecondary
}

private static func image(of icon: some View) -> UIImage? {
let renderer = ImageRenderer(content: icon)
renderer.scale = UIScreen.main.scale
Expand Down
4 changes: 2 additions & 2 deletions Flipcash/Core/Screens/Main/Home/TabBarProfilePhoto.swift
Original file line number Diff line number Diff line change
Expand Up @@ -160,8 +160,8 @@ final class TabBarProfilePhoto {
///
/// The bar tints template glyphs per state, but a photo has to render as its
/// own colours — so the unselected state is baked in here instead: the
/// thinner half-opacity ring, and the half opacity the pill applies to every
/// other icon.
/// thinner half-opacity ring, and the half opacity the pill draws the photo
/// at.
static func render(_ photo: UIImage?) -> ItemImages? {
guard let selected = image(of: ProfileTabIcon(photo: photo, isSelected: true)),
let normal = image(of: ProfileTabIcon(photo: photo, isSelected: false).opacity(0.5))
Expand Down
Loading