diff --git a/.changeset/fancy-papayas-battle.md b/.changeset/fancy-papayas-battle.md new file mode 100644 index 00000000..9211fcc5 --- /dev/null +++ b/.changeset/fancy-papayas-battle.md @@ -0,0 +1,5 @@ +--- +'react-native-bottom-tabs': patch +--- + +fix: adjust default font size on iOS diff --git a/packages/react-native-bottom-tabs/ios/PlatformAliases.swift b/packages/react-native-bottom-tabs/ios/PlatformAliases.swift index 5b508efd..dc8818d1 100644 --- a/packages/react-native-bottom-tabs/ios/PlatformAliases.swift +++ b/packages/react-native-bottom-tabs/ios/PlatformAliases.swift @@ -35,3 +35,9 @@ typealias PlatformViewRepresentable = NSViewRepresentable #else typealias PlatformViewRepresentable = UIViewRepresentable #endif + +#if os(macOS) +typealias PlatformFont = NSFont +#else +typealias PlatformFont = UIFont +#endif diff --git a/packages/react-native-bottom-tabs/ios/TabBarFontSize.swift b/packages/react-native-bottom-tabs/ios/TabBarFontSize.swift new file mode 100644 index 00000000..b8860424 --- /dev/null +++ b/packages/react-native-bottom-tabs/ios/TabBarFontSize.swift @@ -0,0 +1,82 @@ +import UIKit +import React + +enum TabBarFontSize { + /// Returns the default font size for tab bar item labels based on the current platform +#if os(tvOS) + static let defaultSize: CGFloat = 30.0 +#else + static let defaultSize: CGFloat = { + if UIDevice.current.userInterfaceIdiom == .pad { + return 13.0 + } + + return 10.0 + }() +#endif + + /// Creates font attributes for tab bar items + /// - Parameters: + /// - size: Font size in points + /// - family: Optional font family name + /// - weight: Optional font weight string + /// - color: Optional text color + /// - Returns: Dictionary of NSAttributedString attributes + static func createFontAttributes( + size: CGFloat, + family: String? = nil, + weight: String? = nil, + color: PlatformColor? = nil + ) -> [NSAttributedString.Key: Any] { + var attributes: [NSAttributedString.Key: Any] = [:] + + // Create font with React Native font handling if family or weight is specified + if family != nil || weight != nil { + attributes[.font] = RCTFont.update( + nil, + withFamily: family, + size: NSNumber(value: size), + weight: weight, + style: nil, + variant: nil, + scaleMultiplier: 1.0 + ) + } else { + // Fallback to system font + #if os(macOS) + attributes[.font] = NSFont.boldSystemFont(ofSize: size) + #else + attributes[.font] = UIFont.boldSystemFont(ofSize: size) + #endif + } + + // Add color if provided + if let color = color { + attributes[.foregroundColor] = color + } + + return attributes + } + + /// Creates font attributes specifically for normal (unselected) tab state + /// - Parameters: + /// - fontSize: Optional font size (uses default if nil) + /// - fontFamily: Optional font family + /// - fontWeight: Optional font weight + /// - inactiveColor: Optional color for inactive state + /// - Returns: Font attributes dictionary + static func createNormalStateAttributes( + fontSize: Int? = nil, + fontFamily: String? = nil, + fontWeight: String? = nil, + inactiveColor: PlatformColor? = nil + ) -> [NSAttributedString.Key: Any] { + let size = fontSize.map(CGFloat.init) ?? defaultSize + return createFontAttributes( + size: size, + family: fontFamily, + weight: fontWeight, + color: inactiveColor + ) + } +} diff --git a/packages/react-native-bottom-tabs/ios/TabViewImpl.swift b/packages/react-native-bottom-tabs/ios/TabViewImpl.swift index 4fb8050f..4f57dca2 100644 --- a/packages/react-native-bottom-tabs/ios/TabViewImpl.swift +++ b/packages/react-native-bottom-tabs/ios/TabViewImpl.swift @@ -117,36 +117,6 @@ struct TabViewImpl: View { } #endif -private func createFontAttributes( - size: CGFloat, - family: String?, - weight: String?, - inactiveTintColor: PlatformColor? -) -> [NSAttributedString.Key: Any] { - var attributes: [NSAttributedString.Key: Any] = [:] - - if family != nil || weight != nil { - attributes[.font] = RCTFont.update( - nil, - withFamily: family, - size: NSNumber(value: size), - weight: weight, - style: nil, - variant: nil, - scaleMultiplier: 1.0 - ) - } else { - attributes[.font] = UIFont.boldSystemFont(ofSize: size) - } - - return attributes -} - -#if os(tvOS) - let tabBarDefaultFontSize: CGFloat = 30.0 -#else - let tabBarDefaultFontSize: CGFloat = UIFont.smallSystemFontSize -#endif #if !os(macOS) private func configureTransparentAppearance(tabBar: UITabBar, props: TabViewProps) { @@ -158,12 +128,11 @@ private func createFontAttributes( guard let items = tabBar.items else { return } - let fontSize = props.fontSize != nil ? CGFloat(props.fontSize!) : tabBarDefaultFontSize - let attributes = createFontAttributes( - size: fontSize, - family: props.fontFamily, - weight: props.fontWeight, - inactiveTintColor: nil + let attributes = TabBarFontSize.createNormalStateAttributes( + fontSize: props.fontSize, + fontFamily: props.fontFamily, + fontWeight: props.fontWeight, + inactiveColor: nil ) items.forEach { item in @@ -192,19 +161,14 @@ private func createFontAttributes( // Configure item appearance let itemAppearance = UITabBarItemAppearance() - let fontSize = props.fontSize != nil ? CGFloat(props.fontSize!) : tabBarDefaultFontSize - var attributes = createFontAttributes( - size: fontSize, - family: props.fontFamily, - weight: props.fontWeight, - inactiveTintColor: props.inactiveTintColor + let attributes = TabBarFontSize.createNormalStateAttributes( + fontSize: props.fontSize, + fontFamily: props.fontFamily, + fontWeight: props.fontWeight, + inactiveColor: props.inactiveTintColor ) - if let inactiveTintColor = props.inactiveTintColor { - attributes[.foregroundColor] = inactiveTintColor - } - if let inactiveTintColor = props.inactiveTintColor { itemAppearance.normal.iconColor = inactiveTintColor }