React Native components for resizable panel groups/layouts, using react-native-reanimated
and react-native-gesture-handler
.
This library is a port of the popular react-resizable-panels
for web, and aims to provide the same powerful and flexible API for native applications.
Supported input methods include touch gestures.
This project is a direct translation of the great react-resizable-panels
library by Brian Vaughn. All credit for the API design and implementation goes to him. If you find this library useful, please consider supporting the original project.
# yarn
yarn add react-native-resizable-panels react-native-reanimated react-native-gesture-handler
# npm
npm install react-native-resizable-panels react-native-reanimated react-native-gesture-handler
You also need to ensure react-native-reanimated
and react-native-gesture-handler
are set up correctly. Please follow their respective installation instructions.
You can find a comprehensive example app in the apps/example
directory of this repository.
- Web apр: View the example application running in your browser.
- Expo Go: Open the example app on your device using the Expo Go app by scanning the QR code below.
prop | type | description |
---|---|---|
autoSaveId | ?string | Unique id used to auto-save group arrangement via AsyncStorage |
children | ReactNode | Arbitrary React element(s) |
direction | "horizontal" | "vertical" | Group orientation |
id | ?string | Group id; falls back to useId when not provided |
onLayout | ?(sizes: number[]) => void | Called when group layout changes |
style | ?ViewStyle | Style to attach to root element |
PanelGroup
components also expose an imperative API for manual resizing:
method | description |
---|---|
getId(): string |
Gets the panel group's ID. |
getLayout(): number[] |
Gets the panel group's current layout ([0 - 100, ...]). |
setLayout(number[]) |
Resize panel group to the specified layout ([0 - 100, ...]). |
prop | type | description |
---|---|---|
children | ReactNode | Arbitrary React element(s) |
collapsedSize | ?number=0 | Panel should collapse to this size |
collapsible | ?boolean=false | Panel should collapse when resized beyond its minSize |
defaultSize | ?number | Initial size of panel (numeric value between 0-100) |
id | ?string | Panel id (unique within group); falls back to useId when not provided |
maxSize | ?number = 100 | Maximum allowable size of panel (numeric value between 0-100) |
minSize | ?number = 10 | Minimum allowable size of panel (numeric value between 0-100) |
onCollapse | ?() => void | Called when panel is collapsed |
onExpand | ?() => void | Called when panel is expanded |
onResize | ?(size: number) => void | Called when panel is resized; size parameter is a numeric value between 0-100. |
order | ?number | Order of panel within group; required for groups with conditionally rendered panels |
style | ?ViewStyle | Style to attach to root element |
Panel
components also expose an imperative API for manual resizing:
method | description |
---|---|
collapse() |
If panel is collapsible, collapse it fully. |
expand() |
If panel is currently collapsed, expand it to its most recent size. |
getId(): string |
Gets the ID of the panel. |
getSize(): number |
Gets the current size of the panel as a percentage (0 - 100). |
isCollapsed(): boolean |
Returns true if the panel is currently collapsed (size === collapsedSize ). |
isExpanded(): boolean |
Returns true if the panel is currently not collapsed (!isCollapsed() ). |
resize(size: number) |
Resize panel to the specified percentage (0 - 100). |
prop | type | description |
---|---|---|
children | ?ReactNode | Custom drag UI; can be any arbitrary React element(s) |
disabled | ?boolean | Disable drag handle |
id | ?string | Resize handle id (unique within group) |
onDragging | ?(isDragging: boolean) => void | Called when group layout changes |
style | ?ViewStyle | Style to attach to root element |
No. Pixel-based constraints added significant complexity to the initialization and validation logic and so they are not supported.
The Panel
API doesn't require id
and order
props because they aren't necessary for static layouts. When panels are conditionally rendered though, it's best to supply these values.
import { Panel, PanelGroup, PanelResizeHandle } from 'react-native-resizable-panels';
<PanelGroup direction="horizontal">
{renderSideBar && (
<>
<Panel id="sidebar" minSize={25} order={1}>
<Sidebar />
</Panel>
<PanelResizeHandle />
</>
)}
<Panel minSize={25} order={2}>
<Main />
</Panel>
</PanelGroup>;
This likely means that you haven't applied any styling to the resize handles. By default, a resize handle is just an empty View
. To add styling, use the style
prop:
import { PanelResizeHandle } from 'react-native-resizable-panels';
import { StyleSheet } from 'react-native';
<PanelResizeHandle style={styles.resizeHandle} />;
const styles = StyleSheet.create({
resizeHandle: {
width: 4,
backgroundColor: '#888888',
},
});
Yes. Panel groups with an autoSaveId
prop will automatically save and restore their layouts on mount using AsyncStorage
.