Masonry grid

Free · MITReact Native · Expo

Pinterest-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.

View as Markdown
Try it on your phone
Scan to open this demo in your phone's browser and use it with your fingers.

Installation

$ npx shadcn@latest add https://goodui.dev/native/r/masonry-grid.json

Then 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

Use it for
  • A browsable set of pictures with mixed proportions, such as styles or templates.
  • A gallery of a person's results.
Reach for something else
  • Long or endless feeds: it renders every item, so use a virtualized list.
  • Pictures of one size: use a plain grid.

API reference

MasonryGrid

PropTypeDefault
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—
columnsnumber2
gapnumber10
style
Style for the outer container.
StyleProp<ViewStyle>—
testID
Identifier for end-to-end tests.
string—

MasonryTile

PropTypeDefault
image*ImageSourcePropType—
title*string—
subtitlestring—
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—
labelsPartial<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.