rslabdocs

Gravity Stack

Any real component, dropped into a matter-js world, they fall, collide and pile up, tap one to blast it.

Reanimatedmatter-jsHapticsSource

Prerequisites

Gravity Stack needs a real 2D physics engine for the falling and colliding, plus haptics for the blast.


npx expo install matter-js expo-haptics react-native-reanimated

Install


npx @rslab/cli add gravity-stack

Usage

import { useRef } from 'react';

import { GravityStack, type GravityItem, type GravityStackHandle } from '@/components/ui/GravityStack';

import { Tag } from '@/components/ui/Tag';

import { Button } from '@/components/ui/Button';

const ref = useRef<GravityStackHandle>(null);

const items: GravityItem[] = ['Music', 'Coffee', 'Design'].map((label, i) => ({
  content: (
    <Pressable onPress={() => ref.current?.explodeAt(i)}>
      <Tag label={label} />
    </Pressable>
  ),
}));

<GravityStack ref={ref} items={items} height={340} />

<Button onPress={() => ref.current?.shake()}>Shake the pile</Button>;

items accepts any rendered content, a Tag, a Button, an Avatar, whatever should fall and pile up. Wrap each one in a Pressable calling explodeAt(index) to blast it on tap, GravityStack's own wrapper never intercepts touches so the inner content still gets them normally.

Props

PropTypeDefault
items
{ content: ReactNode }[]
-

The set of components to drop in. Treated as fixed for the component's lifetime, changing its length rebuilds the whole physics world.

height?
number
320

Container height in px.

gravity?
number
1

Downward acceleration passed straight to matter-js. Higher falls faster and lands harder.

className?
string
-

Extend or override the container.

Handle (via ref)

  • shake(): jolts every settled item with a random upward and angular impulse, so the pile bounces and resettles
  • explodeAt(index): a localized blast centered on items[index]'s current position, pushing it and anything nearby outward

See exactly how this works with an RSLAB subscription.

Get Pro

On this page