SplitViewUpdated

A vertical split layout with a draggable divider between a top and bottom section.

Import

import { SplitView } from 'heroui-native-pro';

Anatomy

<SplitView>
  <SplitView.TopSection>...</SplitView.TopSection>
  <SplitView.DragArea>
    <SplitView.DragHandle />
  </SplitView.DragArea>
  <SplitView.BottomSection>...</SplitView.BottomSection>
</SplitView>
  • SplitView: Root container that manages snap points, drag state, and layout. Exposes layout state and snap controls via useSplitView and render props.
  • SplitView.TopSection: Top pane with animated height driven by drag and snap state. Content should scroll internally when it exceeds the current height.
  • SplitView.DragArea: Pan gesture hit region with an extended touch target. Typically wraps SplitView.DragHandle.
  • SplitView.DragHandle: Visual pill handle. Scales slightly while dragging when animations are enabled.
  • SplitView.BottomSection: Bottom pane that fills remaining space below the drag area.

Usage

Basic usage

The SplitView uses compound parts to build a vertical split layout with a draggable divider.

<SplitView>
  <SplitView.TopSection>...</SplitView.TopSection>
  <SplitView.DragArea>
    <SplitView.DragHandle />
  </SplitView.DragArea>
  <SplitView.BottomSection>...</SplitView.BottomSection>
</SplitView>

Custom snap points

Pass snapPoints as ratios of container height (0..1) or absolute px (> 1). Combine with defaultSnapIndex and minHeight for uncontrolled layouts.

<SplitView snapPoints={[150, 0.5, 0.75]} defaultSnapIndex={1} minHeight={50}>
  <SplitView.TopSection>...</SplitView.TopSection>
  <SplitView.DragArea>
    <SplitView.DragHandle />
  </SplitView.DragArea>
  <SplitView.BottomSection>...</SplitView.BottomSection>
</SplitView>

Skip initial animation

By default (skipInitialAnimation is true) the divider appears already positioned at its starting snap point instead of animating into place on mount or screen focus. Subsequent snaps and drags still animate. Set skipInitialAnimation={false} to animate the divider into place on first render.

<SplitView skipInitialAnimation={false}>
  <SplitView.TopSection>...</SplitView.TopSection>
  <SplitView.DragArea>
    <SplitView.DragHandle />
  </SplitView.DragArea>
  <SplitView.BottomSection>...</SplitView.BottomSection>
</SplitView>

Controlled snap index

Control the active snap index externally with snapIndex and onSnapIndexChange.

const [snapIndex, setSnapIndex] = useState(1);

<SplitView snapIndex={snapIndex} onSnapIndexChange={setSnapIndex}>
  <SplitView.TopSection>...</SplitView.TopSection>
  <SplitView.DragArea>
    <SplitView.DragHandle />
  </SplitView.DragArea>
  <SplitView.BottomSection>...</SplitView.BottomSection>
</SplitView>;

Render function children

Use a render function to read layout state and drive animations inside children.

<SplitView>
  {({ topSectionHeight, minPx, maxPx }) => (
    <>
      <SplitView.TopSection>...</SplitView.TopSection>
      <SplitView.DragArea>
        <SplitView.DragHandle />
      </SplitView.DragArea>
      <SplitView.BottomSection>...</SplitView.BottomSection>
    </>
  )}
</SplitView>

Accessing context from children

Use the useSplitView hook inside any descendant to read animated layout values and trigger snap transitions.

const { topSectionHeight, minPx, snapTo } = useSplitView();

Disabled animation

Disable all animations for the subtree with animation="disable-all".

<SplitView animation="disable-all">
  <SplitView.TopSection>...</SplitView.TopSection>
  <SplitView.DragArea>
    <SplitView.DragHandle />
  </SplitView.DragArea>
  <SplitView.BottomSection>...</SplitView.BottomSection>
</SplitView>

Example

import { SplitView } from 'heroui-native-pro';
import { Text, View } from 'react-native';

export default function SplitViewExample() {
  return (
    <View className="flex-1 px-5 justify-center">
      <View
        className="h-3/5 w-full p-2 rounded-4xl overflow-hidden bg-surface-secondary"
        style={{ borderCurve: 'continuous' }}
      >
        <SplitView minHeight={50} maxHeight={1}>
          <SplitView.TopSection>
            <View
              className="flex-1 items-center justify-center p-4 bg-surface rounded-3xl"
              style={{ borderCurve: 'continuous' }}
            >
              <Text className="text-foreground">
                Top section — drag the handle to resize.
              </Text>
            </View>
          </SplitView.TopSection>
          <SplitView.DragArea className="h-5">
            <SplitView.DragHandle />
          </SplitView.DragArea>
          <SplitView.BottomSection>
            <View
              className="flex-1 items-center justify-center p-4 bg-surface rounded-3xl"
              style={{ borderCurve: 'continuous' }}
            >
              <Text className="text-foreground">
                Bottom section fills remaining space.
              </Text>
            </View>
          </SplitView.BottomSection>
        </SplitView>
      </View>
    </View>
  );
}

API Reference

SplitView

proptypedefaultdescription
childrenReact.ReactNode | ((props: SplitViewRenderProps) => React.ReactNode)-Child elements or render function receiving layout state
snapPointsreadonly number[][0.2, 0.5, 0.8]Snap points as ratios (0..1) of container height or absolute px (> 1)
minHeightnumber100Minimum height of the top section as px or ratio (0..1)
maxHeightnumber-Maximum height of the top section as px, ratio (0..1), or negative offset
defaultSnapIndexnumber1Default snap index for uncontrolled usage
skipInitialAnimationbooleantrueSkip the spring on the first snap so the divider starts already in place
snapIndexnumber-Controlled snap index
classNamestring-Additional CSS classes for the root container
onSnapIndexChange(index: number) => void-Callback fired when the snap index changes
onSnap(snapIndex: number, topHeightPx: number) => void-Callback fired after a snap completes with the resolved index and top height
animationSplitViewRootAnimation-Root animation configuration
asChildbooleanfalseMerge props onto the child element instead of rendering a wrapper
...ViewPropsViewProps-All standard React Native View props are supported

SplitViewSnapPoint

typedescription
numberRatio of container height when in [0, 1]; absolute px when > 1

SplitViewRenderProps

proptypedescription
topSectionHeightSharedValue<number>Animated height of the top section in px
isDraggingSharedValue<boolean>Whether the user is currently dragging the divider
containerHeightSharedValue<number>Measured container height in px
snapIndexnumberCurrent snap index into resolvedSnapPoints
resolvedSnapPointsreadonly number[]Snap heights in px, clamped and sorted
minPxnumberMinimum allowed top section height in px
maxPxnumberMaximum allowed top section height in px

SplitViewRootAnimation

Animation configuration for the root component. Can be:

  • false or "disabled": Disable only root animations
  • "disable-all": Disable all animations including children
  • true or undefined: Use default animations
  • object: Custom animation configuration
proptypedefaultdescription
snapSpringConfigWithSpringConfig{ damping: 25, stiffness: 300, mass: 0.8, overshootClamping: false, restDisplacementThreshold: 0.01, restSpeedThreshold: 0.01 }Spring used when snapping the top section after drag release or snapTo

SplitView.TopSection

proptypedefaultdescription
childrenReact.ReactNode-Content rendered inside the top pane
classNamestring-Additional CSS classes for the top section (the height style is reserved)
asChildbooleanfalseMerge props onto the child element instead of rendering a wrapper
...ViewPropsViewProps-All standard React Native View props are supported

SplitView.DragArea

proptypedefaultdescription
childrenReact.ReactNode-Content rendered inside the drag hit region
classNamestring-Additional CSS classes for the drag area
asChildbooleanfalseMerge props onto the child element instead of rendering a wrapper
...ViewPropsViewProps-All standard React Native View props are supported

SplitView.DragHandle

proptypedefaultdescription
childrenReact.ReactNode-Custom handle content. Defaults to a pill indicator
classNamestring-Additional CSS classes for the handle (the transform style is reserved)
isAnimatedStyleActivebooleantrueWhen false, animated scale styles are not applied
animationSplitViewDragHandleAnimation-Animation configuration for the handle scale
asChildbooleanfalseMerge props onto the child element instead of rendering a wrapper
...ViewPropsViewProps-All standard React Native View props are supported

SplitViewDragHandleAnimation

Animation configuration for the drag handle. Can be:

  • false or "disabled": Disable all handle animations
  • true or undefined: Use default animations
  • object: Custom animation configuration
proptypedescription
scaleSplitViewDragHandleScaleAnimationScale animation between idle and dragging states

SplitViewDragHandleScaleAnimation

proptypedefaultdescription
value[number, number][1, 1.15]Scale values [idle, dragging]
springConfigWithSpringConfig{ damping: 18, stiffness: 300, mass: 0.8 }Spring used when transitioning between idle and dragging scale

SplitView.BottomSection

proptypedefaultdescription
childrenReact.ReactNode-Content rendered inside the bottom pane
classNamestring-Additional CSS classes for the bottom section
asChildbooleanfalseMerge props onto the child element instead of rendering a wrapper
...ViewPropsViewProps-All standard React Native View props are supported

On this page