GridList

Tiled card grids for people directories, item collections, and image galleries.
The tiles are a list, as in Tailwind UI, and each tile is one of its items: a screen reader announces the list with its number of tiles and moves through it tile by tile. A tappable tile is a button inside its item. The label prop names the list (for example "Team members").
A virtualized grid with a bounded height scrolls its tiles on its own. On the web, while those tiles overflow, the grid is a keyboard tab stop (before the tiles themselves when onPressItem or tile actions make them buttons), the keyboard can scroll it, and while it has keyboard focus the grid, which has no card around it, draws the theme's focus ring around itself. Only the tiles near its viewport are mounted, and each says where it sits in the whole grid, so a screen reader still counts every tile. Give a windowed grid a label: focused, a list with no name is named in Chromium from the text of every tile it has rendered, so the kit warns in development when it has none.
  • RC
    Rachel Chen
    Engineering Lead
    Active
  • AL
    Ada Lovelace
    Staff Engineer
    Active
  • KT
    Kevin Turner
    Product Designer
    Away
iOS
  • RC
    Rachel Chen
    Engineering Lead
    Active
  • AL
    Ada Lovelace
    Staff Engineer
    Active
  • KT
    Kevin Turner
    Product Designer
    Away
Android
  • RC
    Rachel Chen
    Engineering Lead
    Active
  • AL
    Ada Lovelace
    Staff Engineer
    Active
  • KT
    Kevin Turner
    Product Designer
    Away
Web
tsx
<GridList
items={[
{ title: "Rachel Chen", subtitle: "Engineering Lead", avatar: "RC", badge: "Active", actions: [{ label: "Message", outline: true, onPress: () => {} }] },
{ title: "Ada Lovelace", subtitle: "Staff Engineer", avatar: "AL", badge: "Active", actions: [{ label: "Message", outline: true, onPress: () => {} }] },
{ title: "Kevin Turner", subtitle: "Product Designer", avatar: "KT", badge: "Away", actions: [{ label: "Message", outline: true, onPress: () => {} }] }
]}
/>
Each tile action carries its own onPress, so every button on a card fires your handler.

Props

Prop
Description
items
required
GridListItem[]
The tiles to render, one card per entry.
cols3
boolean
Columns (pick one; default is two-up).
cols2
boolean
Columns (pick one; default is two-up).
gallery
boolean
Gallery mode: render each tile as a borderless thumbnail (a square color block from `item.color`, with a left-aligned filename and size below). Avatars, badges, and actions are not shown in this mode. Omit for the default people/card tile.
compact
boolean
Density modifier: tighter gap and tile padding.
onPressItem
(index: number) => void
Make each tile a tappable target (open a detail, select a tile). When set, every tile renders as a Pressable with a button role and a pressed affordance, so a tappable grid needs no hand-rolled Pressable.
label
string
The grid's accessible name (e.g. "Team members"): a screen reader announces it with the list of tiles. A `virtualized` grid needs one: on the web its scroller is a keyboard stop while the tiles overflow, and Chromium names an unnamed stop from the text of every tile it has rendered.
virtualized
boolean
Render the tiles through a windowed `FlatList` instead of mounting every tile up front, for large grids. Give the grid a bounded height (via `style`, e.g. `{ maxHeight: 480 }`) so it can scroll; without one it warns and renders eagerly anyway. Default (omitted) mounts all tiles, unchanged. On the web, while the tiles overflow, the windowed grid is a keyboard tab stop the keyboard can scroll, and it draws the focus ring around itself while it has keyboard focus.
testID
string
E2E hook forwarded to the root element.
style
LayoutStyle
Composition within a parent only, never a restyle hook and never a width: the parent layout container provides the bounds.

Do & Don’t

People (card grid)

Don’t
RC
Rachel Chen
Engineering Lead
AL
Ada Lovelace
Staff Engineer
KT
Kevin Turner
Product Designer
A fixed column count with hard-width cards overflows the row on narrow viewports instead of reflowing.
Do
  • RC
    Rachel Chen
    Engineering Lead
  • AL
    Ada Lovelace
    Staff Engineer
  • KT
    Kevin Turner
    Product Designer
Let auto-fill minmax columns size to the available width so cards wrap cleanly at any breakpoint.

Image gallery

Don’t
hero-banner.png
icon-set.svg
product-shot.jpg
avatar-default.png
Letting each thumbnail keep its intrinsic height makes a ragged grid and shifts the layout as images load.
Do
  • hero-banner.png
    1.2 MB
  • icon-set.svg
    340 KB
  • product-shot.jpg
    2.8 MB
  • avatar-default.png
    96 KB
Lock a consistent aspect ratio so the grid stays even and nothing reflows once thumbnails load.