Skip to content

fix: forward style prop to Modal inner container View#56181

Closed
AnuMessi10 wants to merge 2 commits into
react:mainfrom
AnuMessi10:fix/modal-style-prop-forwarding
Closed

fix: forward style prop to Modal inner container View#56181
AnuMessi10 wants to merge 2 commits into
react:mainfrom
AnuMessi10:fix/modal-style-prop-forwarding

Conversation

@AnuMessi10

@AnuMessi10 AnuMessi10 commented Mar 21, 2026

Copy link
Copy Markdown
Contributor

Summary:

Modal accepts a style prop via ViewProps (since ModalProps spreads ...ViewProps) but silently discards it. The inner container <View> only applies styles.container and containerStyles (which handles backdropColor/transparent), so any style passed by the consumer has no effect.

For example, <Modal style={{ padding: 20 }}> compiles without errors but the padding is never applied.

This PR forwards this.props.style to the inner container View with a carefully designed precedence chain:

styles.container (layout defaults + white background)
  → this.props.style (consumer overrides)
    → containerStyles (explicit transparent / backdropColor always win)

containerStyles now only sets backgroundColor when transparent or backdropColor are explicitly passed, ensuring these Modal-specific API props always take precedence over the generic style prop while still allowing consumers to customize other style properties.

Precedence examples:

Usage Result
<Modal style={{ backgroundColor: 'red' }}> Red (user overrides default white)
<Modal transparent> Transparent (explicit prop wins)
<Modal transparent style={{ backgroundColor: 'red' }}> Transparent wins
<Modal backdropColor="blue" style={{ backgroundColor: 'red' }}> Blue wins
<Modal style={{ padding: 20 }}> Works, no conflicts

Changelog:

[GENERAL] [FIXED] - Forward style prop to Modal's inner container View with correct precedence so consumer styles are applied without overriding transparent or backdropColor

Test Plan:

  1. Render a Modal with a custom style prop:

    <Modal visible style={{ padding: 40, backgroundColor: 'red' }}>
      <View style={{ flex: 1, backgroundColor: 'white' }}>
        <Text>Hello</Text>
      </View>
    </Modal>
  2. Before fix: padding and backgroundColor are silently ignored

  3. After fix: The modal container has 40px padding and a red background

Also verified that:

  • transparent={true} always produces a transparent background, even if style={{ backgroundColor }} is set
  • backdropColor always takes precedence over style.backgroundColor
  • Default behavior (no style prop) is unchanged — white background
  • Non-backgroundColor style properties (padding, margin, etc.) work without conflicts

Modal accepts `style` via ViewProps but silently discards it.
The inner container View only applies `styles.container` and
`containerStyles` (which handles `backdropColor`/`transparent`),
ignoring any style prop passed by the consumer.

This means `<Modal style={{ padding: 20 }}>` has no effect even
though the types allow it.

Forward `this.props.style` as the last element in the style array
so consumer styles are applied and can override defaults.
@meta-cla

meta-cla Bot commented Mar 21, 2026

Copy link
Copy Markdown

Hi @AnuMessi10!

Thank you for your pull request and welcome to our community.

Action Required

In order to merge any pull request (code, docs, etc.), we require contributors to sign our Contributor License Agreement, and we don't seem to have one on file for you.

Process

In order for us to review and merge your suggested changes, please sign at https://code.facebook.com/cla. If you are contributing on behalf of someone else (eg your employer), the individual CLA may not be sufficient and your employer may need to sign the corporate CLA.

Once the CLA is signed, our tooling will perform checks and validations. Afterwards, the pull request will be tagged with CLA signed. The tagging process may take up to 1 hour after signing. Please give it that time before contacting us about it.

If you have received this in error or have any questions, please contact us at cla@meta.com. Thanks!

@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Mar 21, 2026
@meta-cla

meta-cla Bot commented Mar 21, 2026

Copy link
Copy Markdown

Thank you for signing our Contributor License Agreement. We can now accept your code for this (and any) Meta Open Source project. Thanks!

@facebook-github-tools facebook-github-tools Bot added the Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team. label Mar 21, 2026
@zeyap

zeyap commented Mar 23, 2026

Copy link
Copy Markdown
Contributor

@AnuMessi10 would it be able to achieve something similar by wrapping Modal under View and set style on the view? Since this.props.style is appended last, it can silently override backdropColor and transparent={true}. Someone passing style={{ backgroundColor: 'blue' }} would unintentionally break their transparent modal.

…prop

Reorder the style array so explicit Modal API props (transparent,
backdropColor) always win over the generic style prop. Move the
default backgroundColor into styles.container so user styles can
override the default but not the explicit props.

Precedence: styles.container (default white) → this.props.style → containerStyles
- <Modal style={{ backgroundColor: 'red' }}> → red (user overrides default)
- <Modal transparent> → transparent (explicit prop wins over style)
- <Modal transparent style={{ backgroundColor: 'red' }}> → transparent wins
- <Modal backdropColor="blue" style={{ backgroundColor: 'red' }}> → blue wins
- <Modal style={{ padding: 20 }}> → works, no conflicts
@AnuMessi10

Copy link
Copy Markdown
Contributor Author

@zeyap Good catch — thanks for the feedback!

On wrapping Modal in a View: That won't work because Modal renders its children in a separate native overlay/window, not within the normal view hierarchy. A parent <View style={...}> around <Modal> has no effect on the modal's content.

On the override concern: You're right — the initial implementation had this.props.style last, which could silently break transparent or backdropColor. I've updated the approach in 88b45be to fix this.

The new precedence chain is:

styles.container (layout defaults + white background)
  → this.props.style (consumer overrides)
    → containerStyles (explicit transparent / backdropColor always win)

Key changes:

  • containerStyles now only sets backgroundColor when transparent or backdropColor are explicitly passed (the default white moved to styles.container)
  • Style array reordered to [styles.container, this.props.style, containerStyles]

This means:

  • <Modal transparent style={{ backgroundColor: 'red' }}>transparent wins (explicit API prop takes precedence)
  • <Modal backdropColor="blue" style={{ backgroundColor: 'red' }}>blue wins
  • <Modal style={{ backgroundColor: 'red' }}>red (user overrides the default white, which is fine since no explicit prop was set)
  • <Modal style={{ padding: 20 }}> → works, no conflicts

@github-actions

Copy link
Copy Markdown

Warning

JavaScript API change detected

This PR commits an update to ReactNativeApi.d.ts, indicating a change to React Native's public JavaScript API.

  • Please include a clear changelog message.
  • This change will be subject to additional review.

This change was flagged as: POTENTIALLY_BREAKING

@AnuMessi10

Copy link
Copy Markdown
Contributor Author

The POTENTIALLY_BREAKING flag was triggered by moving the default backgroundColor: 'white' from a runtime object (containerStyles) into styles.container. The rendered output is identical — this is a refactor of where the default is applied, not a change in behavior.

The only new behavior is that this.props.style is now forwarded to the inner container View, which was previously silently ignored despite being accepted by the types.

@meta-codesync

meta-codesync Bot commented Apr 16, 2026

Copy link
Copy Markdown

@zeyap has imported this pull request. If you are a Meta employee, you can view this in D101170804.

@meta-codesync meta-codesync Bot closed this in f8fa76f Apr 16, 2026
@react-native-bot

Copy link
Copy Markdown
Collaborator

This pull request was successfully merged by @AnuMessi10 in f8fa76f

When will my fix make it into a release? | How to file a pick request?

@react-native-bot react-native-bot added the Merged This PR has been merged. label Apr 16, 2026
@meta-codesync

meta-codesync Bot commented Apr 16, 2026

Copy link
Copy Markdown

@zeyap merged this pull request in f8fa76f.

@AnuMessi10 AnuMessi10 deleted the fix/modal-style-prop-forwarding branch April 16, 2026 19:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. Merged This PR has been merged. Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants