Gravity Stack
Any real component, dropped into a matter-js world, they fall, collide and pile up, tap one to blast it.
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
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?number320Container height in px.
gravity?number1Downward 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 resettlesexplodeAt(index): a localized blast centered onitems[index]'s current position, pushing it and anything nearby outward
See exactly how this works with an RSLAB subscription.
Get Pro