Masonry grid
Free · MITReact Native · ExpoPinterest-style columns: each item lands in the shortest column and the grid deals in with a stagger. Includes MasonryTile, a picture with its name on a scrim that presses down under the finger.
Installation
$ npx shadcn@latest add https://goodui.dev/native/r/masonry-grid.jsonThen run npx expo install --fix so react-native-reanimated match your Expo SDK. Files land in components/goodui-native/masonry-grid.
Usage
import { MasonryGrid, MasonryTile } from "@/components/goodui-native/masonry-grid/masonry-grid";
<MasonryGrid
items={styles}
keyOf={(s) => s.id}
aspect={(s) => s.aspect}
renderItem={(s) => <MasonryTile image={s.image} title={s.name} aspectRatio={s.aspect} onPress={() => pick(s.id)} />}
/>When to use
- A browsable set of pictures with mixed proportions, such as styles or templates.
- A gallery of a person's results.
- Long or endless feeds: it renders every item, so use a virtualized list.
- Pictures of one size: use a plain grid.
API reference
MasonryGrid
| Prop | Type | Default |
|---|---|---|
| items* | T[] | — |
| aspect* Width over height of an item. Items go to the shorter column. | (item: T) => number | — |
| renderItem* | (item: T, index: number) => ReactNode | — |
| keyOf* | (item: T) => string | — |
| columns | number | 2 |
| gap | number | 10 |
| style Style for the outer container. | StyleProp<ViewStyle> | — |
| testID Identifier for end-to-end tests. | string | — |
MasonryTile
| Prop | Type | Default |
|---|---|---|
| image* | ImageSourcePropType | — |
| title* | string | — |
| subtitle | string | — |
| aspectRatio* Width over height. | number | — |
| corner Something in the corner: a new badge, a cost. | ReactNode | — |
| cornerLabel What `corner` says, added to the spoken name: "4 credits". | string | — |
| onPress | () => void | — |
| labels | Partial<MasonryGridLabels> | — |
Motion and haptics
- Tiles rise in with a stagger capped at the tenth item.
- A tile springs to 95.5 percent under the finger.
- Reduced motion: tiles fade in and do not press down.
- Haptic: The tap cue on press.
- Not virtualized. Keep it to a few dozen items, and use appropriately sized thumbnails.
Accessibility
- MasonryTile is a button that reads its title and subtitle, with a hint from the labels.
- Screen readers follow column order, not the order of the array.
Notes for AI
- `aspect` must match the tile's aspectRatio, or the column balance is off.
- It has no scrolling of its own: put it in a ScrollView.
- The default hint says Opens this item. Override labels.open to name what opens.
Related
A snapping card carousel that follows the finger 1:1, shrinks and dims the neighbours, stretches its pagination pill with the drag, and turns that pill into a timer when it autoplays.
Tap a thumbnail and the photo flies out of it into a full-screen viewer, its crop opening up as it lands; pinch or double-tap to zoom at your fingers, drag to pan, swipe between photos, and drag down to send it back into its thumbnail while the background fades. On the web the wheel zooms toward the pointer.
Cards for long AI jobs: each one shows its status, a fill and a light sweep while running, a rolling percentage, and cancel, retry and open actions.