Repository navigation
fix: View, FloatingButton, Toast - keep content clear of the iOS 26 bottom tab bar - #4052
Merged
Merged
Conversation
…eArea on iOS react-native-safe-area-context's SafeAreaView pads every edge from the nearest SafeAreaProvider's insets regardless of where the view sits, so a header with useSafeArea gets bottom padding whenever the provider extends under a translucent tab bar (iOS 26 Liquid Glass). React Native's SafeAreaView insets only the edges the view actually touches, which is what useSafeArea means. Other platforms keep the safe-area-context SafeAreaView when it is installed.
Contributor
✅ PR Description Validation PassedAll required sections are properly filled out:
Your PR is good for review! 🚀 This validation ensures all sections from the PR template are properly filled. |
…and later Android, web and iOS < 26 keep react-native-safe-area-context's SafeAreaView when it is installed, exactly as before.
On iOS 26 and later the footer adds the bottom safe-area inset, so a FloatingButton on a screen that draws behind a translucent tab bar stays above it. Android, web and iOS < 26 are unchanged.
On iOS 26 and later the attachment rendered while the toast is hidden uses useSafeArea, so it stays inside the safe area instead of under a translucent tab bar. Android, web and iOS < 26 are unchanged.
… by default on iOS 26
…ngButton inset under the keyboard
…oast attachments flush, and drop the FloatingButton inset as the keyboard starts to show
…added later, and drop the FloatingButton inset only when hoisted
artald
approved these changes
Nov 11, 2026
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.
Description
On iOS 26 with the Liquid Glass tab bar, apps can draw screen content behind a floating translucent bottom tab bar. This PR fixes three components that misplace content in that layout.
Constants.isLiquidGlass. All three changes are gated on a newConstants.isLiquidGlassflag. It is on by default on iOS 26 and later, matching Xcode's default (apps built with the iOS 26 SDK get Liquid Glass unless they setUIDesignRequiresCompatibility, and Xcode 27 drops that opt-out), and always off on Android, web and iOS < 26 (setting it there has no effect). Apps that still opt out withUIDesignRequiresCompatibilitysetConstants.isLiquidGlass = falsebefore the first render to keep the previous layout. Android, web and iOS < 26 are unchanged throughout.View
useSafeArea.ViewwithuseSafeArearendersreact-native-safe-area-context'sSafeAreaViewwhenever that package is installed. That component pads every edge from the nearestSafeAreaProvider's insets regardless of where the view sits, so a header or spacer at the top of a screen gets bottom padding whenever the provider's view extends under the bar (provider bottom inset = tab bar + home indicator). AuseSafeAreaheader grows by the tab bar height and<View useSafeArea/>spacers become visible bands.With
Constants.isLiquidGlasson, auseSafeAreaview that sets no padding and noedges/moderenders React Native'sSafeAreaView, which UIKit insets only on the edges the view actually touches (a top header gets the status bar, a bottom footer gets the bar, a view in the middle gets nothing). Elsewhere it keeps thereact-native-safe-area-contextSafeAreaViewwhen installed, and React Native'sSafeAreaViewon iOS otherwise. Views that set padding (modifiers or style) or passedges/modekeepreact-native-safe-area-context'sSafeAreaViewexactly as before, because React Native'sSafeAreaViewreplaces the view's own padding with the insets and has noedges. With the flag on, a padding-freeuseSafeAreaview that does not touch an edge no longer gets padding for that edge. The container is chosen once, when the view mounts: padding added later does not remount it but is ignored by React Native'sSafeAreaView(a dev warning says so), and changing the flag after mount does not affect mounted views, and views withanimatedorreanimatedalso keepreact-native-safe-area-context'sSafeAreaView, since animated padding is not visible to the check.FloatingButton. It renders through
ScreenFooterand pads its content by a fixed spacing (orbottomMargin), so on a tab screen its buttons sit under the bar and can't be tapped. With the flag on it adds the bottom safe-area inset from the nearestreact-native-safe-area-contextprovider to the footer's bottom padding, with or without a custombottomMargin, and a hoisted button drops it as the keyboard starts to show (keyboardWillShow/keyboardWillHide, starting fromKeyboard.isVisible()), so it does not jump at the end of the keyboard animation. A sticky button keeps the inset. The inset comes from the nearest provider, so a FloatingButton inside a Modal or sheet opened from a tab screen should be wrapped in its ownSafeAreaProvider. Without a provider (or without the package) nothing is added, and a FloatingButton with no buttons still renders nothing outside a provider.Toast (incubator). While a
Toastis hidden, itsrenderAttachmentcontent (for example a bottom action bar) is rendered in a plain positionedViewat the bottom of the screen, so on a tab screen it sits under the bar. With the flag on that container usesuseSafeAreafor bottom-positioned toasts (top attachments stay flush with the top), so with the View change above it insets only the bottom edge it touches.No new props. New:
Constants.isLiquidGlass(getter and setter). Validated withyarn build:dev, lint (0 errors) and the fullreact-native-ui-libjest suite (982 passed). New tests coverConstants.isLiquidGlass, the View container choice (padding,edges,mode, flag changes after mount), the FloatingButton inset (keyboard, no provider,bottomMargin, no buttons) and the Toast attachment.What changes on iOS 26 by default
bottomMargin.useSafeAreaviews inset only the edges they touch, instead of every edge. This includes ui-lib's own users ofuseSafeArea: incubator and legacy Toast, ActionBar, Modal TopBar, ConnectionStatusBar, Dialog, Picker / PickerDialog spacers.useSafeAreaview logs React Native'sSafeAreaViewdeprecation warning in development.Apps that opt out of Liquid Glass set
Constants.isLiquidGlass = falsebefore the first render to keep today's layout. The default follows the OS version, so this also applies to binaries built with an SDK older than iOS 26 (which run without Liquid Glass) that receive new JavaScript over the air.Changelog
isLiquidGlassflag, on by default on iOS 26 and later; apps that opt out of Liquid Glass withUIDesignRequiresCompatibilityset it tofalse.useSafeAreainsets only the edges the view touches (React NativeSafeAreaView), so headers and spacers no longer pick up the bottom inset under translucent tab bars.Additional info
Needed for iOS 26 Liquid Glass tab bars in Wix apps; consumed by wix-react-native-ui-lib. Combines the former #4063 and #4064.