A flexible way to handle safe area insets in JS. Also works on Android and Web!
Installations
npm install react-native-safe-area-context
Releases
Developer
th3rdwave
Developer Guide
Module System
CommonJS
Min. Node Version
Typescript Support
Yes
Node Version
20.9.0
NPM Version
10.1.0
Statistics
2,183 Stars
442 Commits
201 Forks
12 Watching
5 Branches
79 Contributors
Updated on 27 Nov 2024
Bundle Size
5.03 kB
Minified
1.91 kB
Minified + Gzipped
Languages
TypeScript (38.46%)
Kotlin (20.93%)
Objective-C (17.75%)
Objective-C++ (7.54%)
C++ (6.27%)
Java (4.08%)
JavaScript (2.02%)
CMake (1.55%)
Ruby (1.34%)
Shell (0.06%)
Total Downloads
Cumulative downloads
Total Downloads
138,918,609
Last day
-6.1%
234,317
Compared to previous day
Last week
0.1%
1,243,956
Compared to previous week
Last month
11.3%
5,198,054
Compared to previous month
Last year
37.7%
48,813,805
Compared to previous year
Daily Downloads
Weekly Downloads
Monthly Downloads
Yearly Downloads
Peer Dependencies
2
Dev Dependencies
28
react-native-safe-area-context
A flexible way to handle safe area, also works on Android and Web!
Getting started
1npm install react-native-safe-area-context
1yarn add react-native-safe-area-context
You then need to link the native parts of the library for the platforms you are using.
-
iOS Platform:
$ npx pod-install
Supported react-native version
version | react-native version |
---|---|
4.0.0+ | 0.64.0+ |
New architecture support
This library currently has experimental support for the new react-native architecture. Note that there will be breaking changes and only the latest version of react-native will be supported.
You will need to be on 4.4.0 and react-native 0.70+.
Usage
This library has 2 important concepts, if you are familiar with React Context this is very similar.
Providers
The SafeAreaProvider component is a View
from where insets provided by Consumers are relative to. This means that if this view overlaps with any system elements (status bar, notches, etc.) these values will be provided to descendent consumers. Usually you will have one provider at the top of your app.
Consumers
Consumers are components and hooks that allow using inset values provided by the nearest parent Provider. Values are always relative to a provider and not to these components.
-
SafeAreaView is the preferred way to consume insets. This is a regular
View
with insets applied as extra padding or margin. It offers better performance by applying insets natively and avoids flickers that can happen with the other JS based consumers. -
useSafeAreaInsets offers more flexibility, but can cause some layout flicker in certain cases. Use this if you need more control over how insets are applied.
API
SafeAreaProvider
You should add SafeAreaProvider
in your app root component. You may need to add it in other places like the root of modals and routes when using react-native-screens
.
Note that providers should not be inside a View
that is animated with Animated
or inside a ScrollView
since it can cause very frequent updates.
Example
1import { SafeAreaProvider } from 'react-native-safe-area-context'; 2 3function App() { 4 return <SafeAreaProvider>...</SafeAreaProvider>; 5}
Props
Accepts all View props. Has a default style of {flex: 1}
.
initialMetrics
Optional, defaults to null
.
Can be used to provide the initial value for frame and insets, this allows rendering immediatly. See optimization for more information on how to use this prop.
SafeAreaView
SafeAreaView
is a regular View
component with the safe area insets applied as padding or margin.
Padding or margin styles are added to the insets, for example style={{paddingTop: 10}}
on a SafeAreaView
that has insets of 20 will result in a top padding of 30.
Example
1import { SafeAreaView } from 'react-native-safe-area-context'; 2 3function SomeComponent() { 4 return ( 5 <SafeAreaView style={{ flex: 1, backgroundColor: 'red' }}> 6 <View style={{ flex: 1, backgroundColor: 'blue' }} /> 7 </SafeAreaView> 8 ); 9}
Props
Accepts all View props.
edges
Optional, array of top
, right
, bottom
, and left
. Defaults to all.
Sets the edges to apply the safe area insets to.
For example if you don't want insets to apply to the top edge because the view does not touch the top of the screen you can use:
1<SafeAreaView edges={['right', 'bottom', 'left']} />
Optionally it can be set to an object { top?: EdgeMode, right?: EdgeMode, bottom?: EdgeMode, left?: EdgeMode }
where EdgeMode = 'off' | 'additive' | 'maximum'
. Additive is a default mode and is the same as passing and edge in the array: finalPadding = safeArea + padding
. Maximum mode will use safe area inset or padding/margin (depends on mode
) if safe area is less: finalPadding = max(safeArea, padding)
. For example if you want a floating UI element that should be at the bottom safe area edge on devices with safe area or 24px from the bottom of the screen on devices without safe area or if safe area is less than 24px:
1<SafeAreaView style={{paddingBottom: 24}} edges={{bottom: 'maximum'}} />
mode
Optional, padding
(default) or margin
.
Apply the safe area to either the padding or the margin.
This can be useful for example to create a safe area aware separator component:
1<SafeAreaView mode="margin" style={{ height: 1, backgroundColor: '#eee' }} />
useSafeAreaInsets
Returns the safe area insets of the nearest provider. This allows manipulating the inset values from JavaScript. Note that insets are not updated synchronously so it might cause a slight delay for example when rotating the screen.
Object with { top: number, right: number, bottom: number, left: number }
.
1import { useSafeAreaInsets } from 'react-native-safe-area-context'; 2 3function HookComponent() { 4 const insets = useSafeAreaInsets(); 5 6 return <View style={{ paddingBottom: Math.max(insets.bottom, 16) }} />; 7}
useSafeAreaFrame
Returns the frame of the nearest provider. This can be used as an alternative to the Dimensions
module.
Object with { x: number, y: number, width: number, height: number }
SafeAreaInsetsContext
React Context with the value of the safe area insets.
Can be used with class components:
1import { SafeAreaInsetsContext } from 'react-native-safe-area-context'; 2 3class ClassComponent extends React.Component { 4 render() { 5 return ( 6 <SafeAreaInsetsContext.Consumer> 7 {(insets) => <View style={{ paddingTop: insets.top }} />} 8 </SafeAreaInsetsContext.Consumer> 9 ); 10 } 11}
withSafeAreaInsets
Higher order component that provides safe area insets as the insets
prop.
1type Props = WithSafeAreaInsetsProps & { 2 someProp: number; 3}; 4 5class ClassComponent extends React.Component<Props> { 6 render() { 7 return <View style={{ paddingTop: this.props.insets.top }} />; 8 } 9} 10 11const ClassComponentWithInsets = withSafeAreaInsets(ClassComponent); 12 13<ClassComponentWithInsets someProp={1} />;
SafeAreaFrameContext
React Context with the value of the safe area frame.
initialWindowMetrics
Insets and frame of the window on initial render. This can be used with the initialMetrics
from SafeAreaProvider
. See optimization for more information.
Object with:
1{ 2 frame: { x: number, y: number, width: number, height: number }, 3 insets: { top: number, left: number, right: number, bottom: number }, 4}
NOTE: This value can be null or out of date as it is computed when the native module is created.
Deprecated apis
useSafeArea
Use useSafeAreaInsets
instead.
SafeAreaConsumer
Use SafeAreaInsetsContext.Consumer
instead.
SafeAreaContext
Use SafeAreaInsetsContext
instead.
initialWindowSafeAreaInsets
Use initialWindowMetrics
instead.
Web SSR
If you are doing server side rendering on the web you can use initialMetrics
to inject insets and frame value based on the device the user has, or simply pass zero values. Since insets measurement is async it will break rendering your page content otherwise.
Optimization
If you can, use SafeAreaView
. It's implemented natively so when rotating the device, there is no delay from the asynchronous bridge.
To speed up the initial render, you can import initialWindowMetrics
from this package and set as the initialMetrics
prop on the provider as described in Web SSR. You cannot do this if your provider remounts, or you are using react-native-navigation
.
1import { 2 SafeAreaProvider, 3 initialWindowMetrics, 4} from 'react-native-safe-area-context'; 5 6function App() { 7 return ( 8 <SafeAreaProvider initialMetrics={initialWindowMetrics}> 9 ... 10 </SafeAreaProvider> 11 ); 12}
Testing
This library includes a built in mock for Jest. It will use the following metrics by default:
1{ 2 frame: { 3 width: 320, 4 height: 640, 5 x: 0, 6 y: 0, 7 }, 8 insets: { 9 left: 0, 10 right: 0, 11 bottom: 0, 12 top: 0, 13 }, 14}
To use it, add the following code to the jest setup file:
1import mockSafeAreaContext from 'react-native-safe-area-context/jest/mock'; 2 3jest.mock('react-native-safe-area-context', () => mockSafeAreaContext);
To have more control over the test values it is also possible to pass initialMetrics
to
SafeAreaProvider
to provide mock data for frame and insets.
1export function TestSafeAreaProvider({ children }) { 2 return ( 3 <SafeAreaProvider 4 initialMetrics={{ 5 frame: { x: 0, y: 0, width: 0, height: 0 }, 6 insets: { top: 0, left: 0, right: 0, bottom: 0 }, 7 }} 8 > 9 {children} 10 </SafeAreaProvider> 11 ); 12}
Enabling Babel Parsing for Modules
While trying to use this mock, a frequently encountered error is:
1SyntaxError: Cannot use import statement outside a module.
This issue arises due to the use of the import statement. To resolve it, you need to permit Babel to parse the file.
By default, Jest does not parse files located within the node_modules folder.
However, you can modify this behavior as outlined in the Jest documentation on transformIgnorePatterns
customization.
If you're using a preset, like the one from react-native, you should update your Jest configuration to include react-native-safe-area-context
as shown below:
1transformIgnorePatterns: [ 2 'node_modules/(?!((jest-)?react-native|@react-native(-community)?|react-native-safe-area-context)/)', 3];
This adjustment ensures Babel correctly parses modules, avoiding the aforementioned syntax error.
Contributing
See the Contributing Guide
No vulnerabilities found.
Reason
no dangerous workflow patterns detected
Reason
13 commit(s) and 8 issue activity found in the last 90 days -- score normalized to 10
Reason
license file detected
Details
- Info: project has a license file: LICENSE:0
- Info: FSF or OSI recognized license: MIT License: LICENSE:0
Reason
binaries present in source code
Details
- Warn: binary detected: android/gradle/wrapper/gradle-wrapper.jar:1
- Warn: binary detected: example/android/gradle/wrapper/gradle-wrapper.jar:1
Reason
5 existing vulnerabilities detected
Details
- Warn: Project is vulnerable to: GHSA-3xgq-45jj-v275
- Warn: Project is vulnerable to: GHSA-mpg4-rc92-vx8v
- Warn: Project is vulnerable to: GHSA-952p-6rrq-rcjv
- Warn: Project is vulnerable to: GHSA-m6fv-jmcg-4jfg
- Warn: Project is vulnerable to: GHSA-cm22-4g7w-348p
Reason
Found 11/30 approved changesets -- score normalized to 3
Reason
detected GitHub workflow tokens with excessive permissions
Details
- Warn: no topLevel permission defined: .github/workflows/android.yml:1
- Warn: no topLevel permission defined: .github/workflows/ios.yml:1
- Warn: no topLevel permission defined: .github/workflows/js.yml:1
- Info: no jobLevel write permissions found
Reason
dependency not pinned by hash detected -- score normalized to 0
Details
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/android.yml:22: update your workflow using https://app.stepsecurity.io/secureworkflow/th3rdwave/react-native-safe-area-context/android.yml/main?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/android.yml:24: update your workflow using https://app.stepsecurity.io/secureworkflow/th3rdwave/react-native-safe-area-context/android.yml/main?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/android.yml:27: update your workflow using https://app.stepsecurity.io/secureworkflow/th3rdwave/react-native-safe-area-context/android.yml/main?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/android.yml:33: update your workflow using https://app.stepsecurity.io/secureworkflow/th3rdwave/react-native-safe-area-context/android.yml/main?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/android.yml:50: update your workflow using https://app.stepsecurity.io/secureworkflow/th3rdwave/react-native-safe-area-context/android.yml/main?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/android.yml:52: update your workflow using https://app.stepsecurity.io/secureworkflow/th3rdwave/react-native-safe-area-context/android.yml/main?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/android.yml:55: update your workflow using https://app.stepsecurity.io/secureworkflow/th3rdwave/react-native-safe-area-context/android.yml/main?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/android.yml:61: update your workflow using https://app.stepsecurity.io/secureworkflow/th3rdwave/react-native-safe-area-context/android.yml/main?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ios.yml:21: update your workflow using https://app.stepsecurity.io/secureworkflow/th3rdwave/react-native-safe-area-context/ios.yml/main?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ios.yml:23: update your workflow using https://app.stepsecurity.io/secureworkflow/th3rdwave/react-native-safe-area-context/ios.yml/main?enable=pin
- Warn: third-party GitHubAction not pinned by hash: .github/workflows/ios.yml:26: update your workflow using https://app.stepsecurity.io/secureworkflow/th3rdwave/react-native-safe-area-context/ios.yml/main?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ios.yml:45: update your workflow using https://app.stepsecurity.io/secureworkflow/th3rdwave/react-native-safe-area-context/ios.yml/main?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ios.yml:47: update your workflow using https://app.stepsecurity.io/secureworkflow/th3rdwave/react-native-safe-area-context/ios.yml/main?enable=pin
- Warn: third-party GitHubAction not pinned by hash: .github/workflows/ios.yml:50: update your workflow using https://app.stepsecurity.io/secureworkflow/th3rdwave/react-native-safe-area-context/ios.yml/main?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/js.yml:27: update your workflow using https://app.stepsecurity.io/secureworkflow/th3rdwave/react-native-safe-area-context/js.yml/main?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/js.yml:29: update your workflow using https://app.stepsecurity.io/secureworkflow/th3rdwave/react-native-safe-area-context/js.yml/main?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/js.yml:34: update your workflow using https://app.stepsecurity.io/secureworkflow/th3rdwave/react-native-safe-area-context/js.yml/main?enable=pin
- Info: 0 out of 15 GitHub-owned GitHubAction dependencies pinned
- Info: 0 out of 2 third-party GitHubAction dependencies pinned
Reason
no effort to earn an OpenSSF best practices badge detected
Reason
security policy file not detected
Details
- Warn: no security policy file detected
- Warn: no security file to analyze
- Warn: no security file to analyze
- Warn: no security file to analyze
Reason
project is not fuzzed
Details
- Warn: no fuzzer integrations found
Reason
SAST tool is not run on all commits -- score normalized to 0
Details
- Warn: 0 commits out of 11 are checked with a SAST tool
Score
4.4
/10
Last Scanned on 2024-11-18
The Open Source Security Foundation is a cross-industry collaboration to improve the security of open source software (OSS). The Scorecard provides security health metrics for open source projects.
Learn MoreOther packages similar to react-native-safe-area-context
@rescript-react-native/safe-area-context
ReScript bindings for react-native-safe-area-context.
@exodus/react-native-safe-area-context
A flexible way to handle safe area, also works on Android and web.
@reason-react-native/safe-area-context
ReScript bindings for react-native-safe-area-context.
react-native-static-safe-area-insets
React Native package that exposed the Safe Area insets as constants