orn-ui
Molecule

SymmetricGrid

Requires <UIProvider> — Getting Started →

Installation

Install just this component (copies the source into your project, no npm dependency)

npx orn-ui add symmetric-grid

Or install the whole package and import it

pnpm add orn-ui
import { SymmetricGrid } from 'orn-ui/symmetric-grid';
Depends on:core (theme + icons)

Usage

  • when to use — A grid of cards or tiles where a short last row would otherwise read as a broken layout.
  • columns — `2` by default. Cell width is `100 / columns`, so the row still fills flush on any screen.
  • balanceLastRow — Centers an incomplete last row by default instead of leaving it flush left with a gap on the right.
  • gap — Applies to both axes. Leave it unset to inherit the theme's `spacing.md`.
Demo clip not recorded yet — see MEDIA.md

Variants

columns={2} — default, last row of 1 centered

<SymmetricGrid
  data={ITEMS}
  columns={2}
  keyExtractor={(item) => item.id}
  renderItem={(item) => <Tile name={item.name} />}
/>

columns={3} — same 5 items, different grid

<SymmetricGrid
  data={ITEMS}
  columns={3}
  keyExtractor={(item) => item.id}
  renderItem={(item) => <Tile name={item.name} />}
/>

balanceLastRow={false} — incomplete row left-aligned instead of centered

<SymmetricGrid
  data={ITEMS}
  columns={2}
  balanceLastRow={false}
  keyExtractor={(item) => item.id}
  renderItem={(item) => <Tile name={item.name} />}
/>
Full demo source
const variants: VariantDef[] = [
  {
    label: 'columns={2} — default, last row of 1 centered',
    content: (
      <SymmetricGrid
        data={ITEMS}
        columns={2}
        keyExtractor={(item) => item.id}
        renderItem={(item) => <Tile name={item.name} />}
      />
    ),
  },
  {
    label: 'columns={3} — same 5 items, different grid',
    content: (
      <SymmetricGrid
        data={ITEMS}
        columns={3}
        keyExtractor={(item) => item.id}
        renderItem={(item) => <Tile name={item.name} />}
      />
    ),
  },
  {
    label: 'balanceLastRow={false} — incomplete row left-aligned instead of centered',
    content: (
      <SymmetricGrid
        data={ITEMS}
        columns={2}
        balanceLastRow={false}
        keyExtractor={(item) => item.id}
        renderItem={(item) => <Tile name={item.name} />}
      />
    ),
  },
];
return <VariantList variants={variants} />;

Props

NameTypeDefaultDescription
dataT[]
renderItem(item: T, index: number) => ReactElement<unknown, string | JSXElementConstructor<any>>
keyExtractor(item: T, index: number) => string
columns?number2Columns per row.
gap?numbertheme.tokens.spacing.mdSpacing between cells, on both axes.
balanceLastRow?booleantrueIncomplete last row: centered (symmetric) instead of stuck to the left with a gap on the right.
style?StyleProp<ViewStyle>