Conversation
marius-ck
marked this pull request as ready for review
September 17, 2026 11:48
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
https://app.notion.com/p/callstack/Support-remaining-SF-Symbols-features-from-React-Navigation-3d65d027c0f880959beafda5c40e7643?v=3285d027c0f880a68ccb000c1ce3c56e&source=copy_link
PR Description
Feature. Adds full SF Symbol configuration to tab icons, closing the gap with React Navigation 8.
Until now
AppleIconwas literally{ sfSymbol: SFSymbol }and the native side calledUIImage(systemName:)with no configuration, so the symbol name was the only thing you could express. AlongsidesfSymbol, an icon object now acceptssize,color,weight,scale,variableValue,variableValueMode,renderingMode,colorsandcolorRenderingMode. Names, allowed values and defaults match React Navigation's SF Symbols options, so an icon configured for one behaves the same here.focusedIconandunfocusedIconeach carry their own options.The practical gain is that colored tab icons no longer require shipping a PNG or SVG. Previously every symbol was a flat monochrome template painted with the tab bar tint, so the only way to get color was an image asset, which costs the system symbol look, automatic weight and scale matching against the label font, and the automatic light/dark behavior.
Deliberately not supported. React Navigation's
effectandcontentTransitionanimate a symbol as it changes. A tab bar item renders a still image and the system never runs symbol animations on one, so both are omitted rather than accepted and silently dropped.styleis absent for the same reason: the tab bar lays the item out. The new guide says so explicitly.Two behaviors worth reviewing, both encoded in
preservesOwnColors:tabBarActiveTintColor/tabBarInactiveTintColor, since a tab item cannot hold a tint the way a live view can. This is visible in the Contacts screenshot below: the label turns blue on selection while the icon stays purple.hierarchicalorpalettewith no color at all stays tintable, so it keeps following the tab bar colors instead of falling back to black.How it flows.
TabView.tsxflattens the icon into scalar fields using sentinels for unset values, because a codegen struct cannot be null and a plain zero would otherwise read as configuration. The Fabric component view drops those sentinels into a dictionary, and the newSFSymbolOptions.swiftturns it into a configured symbol image for both the SwiftUI (TabItem) and UIKit (TabViewImpl) rendering paths.The second commit (
fix: template image color) is the part that only surfaced by running the app. The options reached native intact but the colors were still being flattened to the tab tint: a tab bar templates whatever image it is handed, and SwiftUI separately applies its ownsymbolRenderingModeto anything it recognises as a symbol. A colored symbol now rasterizes into a plain bitmap marked.alwaysOriginal, so neither recoloring applies. This mirrors how the library already handlesiconRenderingMode: 'original'for image icons.Fully backwards compatible: with no options set, symbols render exactly as before. Android is untouched, and the existing warning about SF Symbols there still applies. A changeset is included (minor for both packages).
Docs: new SF Symbols guide documenting every option, linked from the React Navigation, Expo Router and standalone guides.
How to test?
Open the SF Symbols example, which now exercises the new options:
weight: 'bold'withdocument.fillwhen focused,weight: 'light'withdocumentwhen not, so the icon visibly thickens and fills on selection.renderingMode: 'palette', keeping its own color instead of the tab tint.renderingMode: 'hierarchical'with a purple base color, which stays purple while selected.wifiatvariableValue: 0.6andscale: 'large', showing a dimmed outer arc.Worth also checking the Tint Colors example, since unconfigured symbols must still follow the active and inactive tints.
Screenshots