feat(Android, Stack v5): toolbar menu item icon and icon tint color#4105
feat(Android, Stack v5): toolbar menu item icon and icon tint color#4105kligarski wants to merge 18 commits into
Conversation
92b5302 to
8105b22
Compare
There was a problem hiding this comment.
Pull request overview
Adds Android Stack v5 support for toolbar menu item icons (drawable resources or image sources) and per-state icon tinting, including correct “no change” vs “reset to default” semantics for view-command updates. This integrates new JS-to-native props, native icon/tint application in MaterialToolbar, and a Single Feature Test scenario to validate behavior.
Changes:
- Extend Stack v5 toolbar menu item API with
iconandiconTintColor*props, and plumb them through Fabric + view-command update paths. - Introduce native update/value wrappers (
StackHeaderToolbarUpdate) and icon resolution infrastructure (IconResolver, icon source maps) to support async image loading and diffing. - Add a new Android SFT scenario for toolbar menu icons/tints and wire it into the stack-v5 scenario group.
Reviewed changes
Copilot reviewed 20 out of 20 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| src/fabric/gamma/stack/StackHeaderConfigAndroidNativeComponent.ts | Adds native prop fields for menu item icon sources and processed tint colors. |
| src/components/tabs/screen/TabsScreen.android.tsx | Switches tabs icon parsing to use shared parseIconToNativeProps. |
| src/components/shared/index.ts | Adds shared parseIconToNativeProps helper (moved from tabs). |
| src/components/gamma/stack/header/StackHeaderConfig.android.types.ts | Extends public TS types/docs with menu item icon and iconTintColor* props. |
| src/components/gamma/stack/header/StackHeaderConfig.android.tsx | Converts toolbar menu item icon/tint props to native props; updates view-command option serialization. |
| apps/src/tests/single-feature-tests/tabs/test-tabs-item-title-ios/index.tsx | Formatting/line wrapping updates in an iOS SFT description component. |
| apps/src/tests/single-feature-tests/stack-v5/test-stack-toolbar-menu-icon-android/scenario.md | New manual test scenario documenting expected behavior for icon + tint props/commands. |
| apps/src/tests/single-feature-tests/stack-v5/test-stack-toolbar-menu-icon-android/scenario-descriptions.ts | Registers the new SFT scenario metadata. |
| apps/src/tests/single-feature-tests/stack-v5/test-stack-toolbar-menu-icon-android/index.tsx | Implements the interactive SFT screen for icon/tint prop + command flows. |
| apps/src/tests/single-feature-tests/stack-v5/index.ts | Adds the new scenario to the stack-v5 scenario group. |
| android/src/main/java/com/swmansion/rnscreens/gamma/stack/header/toolbar/StackHeaderToolbarUpdate.kt | Adds reset-vs-set wrapper to distinguish “reset default” from “no change”. |
| android/src/main/java/com/swmansion/rnscreens/gamma/stack/header/toolbar/StackHeaderToolbarMenuItemOptions.kt | Extends menu item option updates to include icon + per-state tint updates. |
| android/src/main/java/com/swmansion/rnscreens/gamma/stack/header/toolbar/StackHeaderToolbarMenuItemIconSource.kt | Adds a compact icon-source model (drawable name / image uri). |
| android/src/main/java/com/swmansion/rnscreens/gamma/stack/header/toolbar/StackHeaderToolbarMenuItemDefaults.kt | Adds defaults for icon/tint-related fields. |
| android/src/main/java/com/swmansion/rnscreens/gamma/stack/header/toolbar/StackHeaderToolbarMenuItemConfig.kt | Extends config model with resolved icon drawable and tint colors. |
| android/src/main/java/com/swmansion/rnscreens/gamma/stack/header/toolbar/StackHeaderToolbarMenuCoordinator.kt | Applies icon + tint updates to toolbar MenuItems and resizes drawables to 24dp. |
| android/src/main/java/com/swmansion/rnscreens/gamma/stack/header/StackHeaderCoordinator.kt | Updates coordinator call signature for menu item updates. |
| android/src/main/java/com/swmansion/rnscreens/gamma/stack/header/config/StackHeaderConfigViewManager.kt | Parses new icon/tint props/options and stages icon sources for async resolution. |
| android/src/main/java/com/swmansion/rnscreens/gamma/stack/header/config/StackHeaderConfig.kt | Adds icon resolution for back button + toolbar items and atomic command application. |
| android/src/main/java/com/swmansion/rnscreens/gamma/helpers/IconResolver.kt | Adds reusable icon resolver for drawable-name vs image-uri sources with diffing. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| return drawable | ||
| .toBitmap(width = targetWidthPx, height = targetHeightPx) | ||
| .toDrawable(toolbar.resources) |
There was a problem hiding this comment.
This doesn't resize drawable resources correctly. It will be fixed in follow-up PR with resizing & tint for back button.
| // Helpers for view commands: | ||
| // - not defined -> null (means "no update") | ||
| // - null -> default (means "reset to default value") | ||
| private fun ReadableMap.readColor( |
There was a problem hiding this comment.
wondering whether we shouldn't have a general helper file with all extensions rather than private parsers in the manager's source code (I did the same for TabsScreenManager) , unrelated to this PR, but do you think we should add a ticket to unify the approach or at least have a single file definitions for prop parsing?
| * @summary Specifies the icon for the menu item. | ||
| * | ||
| * Supported values: | ||
| * - `{ type: 'imageSource', imageSource }` |
There was a problem hiding this comment.
nit: shouldn't we mention what type imageSource is?
| import { Image, type ImageResolvedAssetSource } from 'react-native'; | ||
| import type { PlatformIconAndroid } from '../../types'; | ||
|
|
||
| export function parseIconToNativeProps(icon: PlatformIconAndroid | undefined): { |
There was a problem hiding this comment.
nit: parseAndroidIconToNativeProps
Description
Adds support for icons and icon tinting for toolbar menu items in Stack v5 on Android.
Closes https://github.com/software-mansion/react-native-screens-labs/issues/1207.
Details
normalleads to transparent icon - that's platform limitation. If you specify any tint, we can't use original appearance of the icon. You must specifynormalif you want to apply any tint color.Ctrl+Tab- this will move the focus to the toolbar.Changes
parseIconToNativePropstocomponents/sharedparseColor/resolveAssetSource)StackHeaderToolbarUpdateto handle props wherenullis the default value and "no change" needs different representation from "reset to default"IconResolverto handle icon-related logic (diffing, handling async updates)Before & after - visual documentation
toolbar_menu_icons.mp4
Test plan
Run
test-stack-toolbar-menu-icon-android. Check for regressions intest-stack-subviews-androidandtest-stack-back-button-android.Checklist