orn-ui
Molecule

OptionCard

Requires <UIProvider> — Getting Started →

Installation

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

npx orn-ui add option-card

Or install the whole package and import it

pnpm add orn-ui
import { OptionCard } from 'orn-ui/option-card';
Depends on:core (theme + icons)pressable-scale

Usage

  • when to use — Choosing between a few options, each with an icon — a payment method, a shipping type.
  • layout — `horizontal` for a stacked list; `vertical` for a grid of two or three columns.
  • isSelected / onPress — Controlled selection: the parent decides which one is on.
Demo clip not recorded yet — see MEDIA.md

Variants

layout="horizontal"

<View style={{ flexDirection: 'row', gap: 8 }}>
  <OptionCard label="Cash" iconName="check" isSelected={selected === 'cash'} onPress={() => setSelected('cash')} />
  <OptionCard label="Card" iconName="info" isSelected={selected === 'card'} onPress={() => setSelected('card')} />
</View>

layout="vertical"

<View style={{ flexDirection: 'row', gap: 8 }}>
  <OptionCard
    label="Cash"
    iconName="check"
    layout="vertical"
    isSelected={selectedVertical === 'cash'}
    onPress={() => setSelectedVertical('cash')}
  />
  <OptionCard
    label="Card"
    iconName="info"
    layout="vertical"
    isSelected={selectedVertical === 'card'}
    onPress={() => setSelectedVertical('card')}
  />
  <OptionCard
    label="Transfer"
    iconName="search"
    layout="vertical"
    isSelected={selectedVertical === 'transfer'}
    onPress={() => setSelectedVertical('transfer')}
  />
</View>
Full demo source
const variants: VariantDef[] = [
  {
    label: 'layout="horizontal"',
    content: (
      <View style={{ flexDirection: 'row', gap: 8 }}>
        <OptionCard label="Cash" iconName="check" isSelected={selected === 'cash'} onPress={() => setSelected('cash')} />
        <OptionCard label="Card" iconName="info" isSelected={selected === 'card'} onPress={() => setSelected('card')} />
      </View>
    ),
  },
  {
    label: 'layout="vertical"',
    content: (
      <View style={{ flexDirection: 'row', gap: 8 }}>
        <OptionCard
          label="Cash"
          iconName="check"
          layout="vertical"
          isSelected={selectedVertical === 'cash'}
          onPress={() => setSelectedVertical('cash')}
        />
        <OptionCard
          label="Card"
          iconName="info"
          layout="vertical"
          isSelected={selectedVertical === 'card'}
          onPress={() => setSelectedVertical('card')}
        />
        <OptionCard
          label="Transfer"
          iconName="search"
          layout="vertical"
          isSelected={selectedVertical === 'transfer'}
          onPress={() => setSelectedVertical('transfer')}
        />
      </View>
    ),
  },
];
return <VariantList variants={variants} />;

Props

Also accepts testID, forwarded to the root node. It exists for end-to-end tests (Maestro drives the app by the accessibility tree) and has no effect on how the component looks or behaves.

NameTypeDefaultDescription
labelstring
description?stringSecondary line: the detail that decides the choice ("arrives in 3 days").
iconName?IconName
isSelectedboolean
onPress() => void
disabled?booleanfalse
layout?'vertical' | 'horizontal'horizontal'vertical': icon on top, text centered below. 'horizontal': icon and text in a row.
style?StyleProp<ViewStyle>