Skip to content

feat(ios): add largeTitleDisplayMode prop to native stack header#3817

Open
dacoto wants to merge 2 commits intosoftware-mansion:mainfrom
dacoto:copilot/implement-toolbar-title-display-mode
Open

feat(ios): add largeTitleDisplayMode prop to native stack header#3817
dacoto wants to merge 2 commits intosoftware-mansion:mainfrom
dacoto:copilot/implement-toolbar-title-display-mode

Conversation

@dacoto
Copy link
Copy Markdown

@dacoto dacoto commented Mar 28, 2026

Description

Exposes iOS's UINavigationItemLargeTitleDisplayMode to React Native via a new largeTitleDisplayMode prop on ScreenStackHeaderConfig. Previously, only a boolean largeTitle prop was available, mapping to Always/Never. This change provides granular control, including support for the iOS 17+ inlineLarge mode.

Changes

  • New LargeTitleDisplayMode type: 'none' | 'automatic' | 'always' | 'never' | 'inlineLarge'
  • ScreenStackHeaderConfigProps (src/types.tsx) — new optional largeTitleDisplayMode prop (iOS only)
  • Fabric codegen (ScreenStackHeaderConfigNativeComponent.ts) — prop added with default 'none'
  • RNSLargeTitleDisplayMode enum (RNSEnums.h) — native enum with None/Automatic/Always/Never/InlineLarge
  • Conversion layer — RNSConvert method for Fabric (C++ → ObjC); RCTConvert enum converter + RCT_EXPORT_VIEW_PROPERTY for Paper
  • updateViewController:withConfig:animated:'none' delegates to the existing largeTitle bool (fully backward-compatible); inlineLarge requires iOS 17+ with fallback to Always on older versions

Test plan

<ScreenStackHeaderConfig
  title="Settings"
  largeTitleDisplayMode="inlineLarge" // large title, compact inline layout (iOS 17+)
/>

largeTitleDisplayMode takes precedence over largeTitle when set to any value other than 'none'.

Steps to reproduce / verify:

  1. Set largeTitleDisplayMode="automatic" / "always" / "never" and confirm behavior matches UINavigationItemLargeTitleDisplayMode.
  2. Set largeTitleDisplayMode="inlineLarge" on iOS 17+ and verify compact inline large title renders correctly.
  3. Set largeTitleDisplayMode="inlineLarge" on iOS < 17 and confirm fallback to Always.
  4. Leave largeTitleDisplayMode unset and confirm existing largeTitle prop behavior is unchanged.

Checklist

  • Included code example that can be used to test this change.
  • Updated / created local changelog entries in relevant test files.
  • For visual changes, included screenshots / GIFs / recordings documenting the change.
  • For API changes, updated relevant public types.
  • Ensured that CI passes

@dacoto dacoto marked this pull request as ready for review March 28, 2026 00:32
Copilot AI review requested due to automatic review settings March 28, 2026 00:32
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds a new iOS-only largeTitleDisplayMode prop to ScreenStackHeaderConfig to expose UINavigationItemLargeTitleDisplayMode (including iOS 17+ inlineLarge) while keeping existing largeTitle behavior as the fallback when the new prop is unset/'none'.

Changes:

  • Adds LargeTitleDisplayMode union type and largeTitleDisplayMode?: LargeTitleDisplayMode to the public TS props.
  • Extends Fabric codegen props with largeTitleDisplayMode (default 'none').
  • Adds native enum + conversion/export plumbing and updates header configuration logic to apply the selected display mode (with iOS 17 fallback for inlineLarge).

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
src/types.tsx Exposes the new largeTitleDisplayMode prop/type to JS/TS consumers.
src/fabric/ScreenStackHeaderConfigNativeComponent.ts Adds Fabric codegen prop with default 'none'.
ios/RNSScreenStackHeaderConfig.mm Applies the new display mode (and keeps legacy largeTitle behavior for 'none'), adds Paper prop export + enum converter.
ios/RNSScreenStackHeaderConfig.h Adds native property and RCTConvert declaration for the new enum.
ios/RNSEnums.h Introduces RNSLargeTitleDisplayMode native enum.
ios/RNSConvert.mm Adds Fabric C++->ObjC enum conversion helper.
ios/RNSConvert.h Declares the new Fabric conversion helper.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

case Never:
return RNSLargeTitleDisplayModeNever;
case InlineLarge:
return RNSLargeTitleDisplayModeInlineLarge;
Copy link

Copilot AI Mar 28, 2026

Choose a reason for hiding this comment

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

RNSLargeTitleDisplayModeFromCppEquivalent has a non-void switch without a default branch or a fallback return. Even if the enum is currently exhaustive, this is undefined behavior if a new enum value is added (and may trigger compiler warnings / -Werror). Add a default case that logs and returns a safe fallback (e.g. RNSLargeTitleDisplayModeNone).

Suggested change
return RNSLargeTitleDisplayModeInlineLarge;
return RNSLargeTitleDisplayModeInlineLarge;
default:
RCTLogError(@"RNSLargeTitleDisplayModeFromCppEquivalent: unexpected largeTitleDisplayMode value (%d). Falling back to RNSLargeTitleDisplayModeNone.",
static_cast<int>(largeTitleDisplayMode));
return RNSLargeTitleDisplayModeNone;

Copilot uses AI. Check for mistakes.
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.

3 participants