# RadioGroup (React Native)

> Single choice from a list, as rows or as cards.

GramproKit for React Native · Forms · Beta · Source: https://kit.gramproindia.com/native/docs/radio-group

> **Beta:** React Native support is in beta. APIs may change or break between prereleases (npm tag `native`).

_Interactive demo:_ [open the live example](https://kit.gramproindia.com/native/docs/radio-group). The example's source:

```tsx
import { useState } from "react";
import { Radio, RadioGroup } from "@/component-lib/radio-group";
import { Section } from "./layout"; // Section and Row: page layout for the demo

export function RadioGroupDemo() {
  const [plan, setPlan] = useState<string | null>("pro");
  return (
    <>
      <Section title="RadioGroup · options">
        <RadioGroup
          label="Billing cycle"
          description="You can change this later."
          defaultValue="monthly"
          clearable
          options={["Monthly", "Quarterly", "Yearly"].map((label) => ({ value: label.toLowerCase(), label }))}
        />
      </Section>

      <Section title="RadioGroup · cards">
        <RadioGroup
          label="Plan"
          variant="card"
          value={plan}
          onValueChange={setPlan}
          options={[
            { value: "free", label: "Free", description: "Up to 3 projects" },
            { value: "pro", label: "Pro", description: "₹499 / month, unlimited projects" },
            { value: "team", label: "Team", description: "Contact sales", disabled: true },
          ]}
        />
      </Section>

      <Section title="RadioGroup · horizontal, error, children">
        <RadioGroup label="Delivery" orientation="horizontal" required error="Choose a delivery option.">
          <Radio value="pickup" label="Pickup" />
          <Radio value="courier" label="Courier" />
          <Radio value="post" label="Post" disabled />
        </RadioGroup>
        <RadioGroup label="Sizes" orientation="horizontal" defaultValue="md">
          <Radio value="sm" size="sm" label="Small" />
          <Radio value="md" label="Medium" />
          <Radio value="lg" size="lg" label="Large" />
        </RadioGroup>
      </Section>
    </>
  );
}
```

## Install

```bash
npx @grampro/kit@native add RadioGroup
```

## Usage

```tsx
import { RadioGroup, Radio } from "@/component-lib/radio-group";

<RadioGroup label="Billing cycle" defaultValue="monthly">
  <Radio value="monthly" label="Monthly" />
  <Radio value="yearly" label="Yearly" />
</RadioGroup>
```

## Props

### RadioGroupProps

| Prop | Type | Description |
|---|---|---|
| `value` | `string \| null` | The chosen value (controlled). `null` for nothing chosen. |
| `defaultValue` | `string \| null` | The choice selected to begin with, when you are not controlling `value`. |
| `onValueChange` | `(value: string \| null) => void` | The chosen value, or `null` when the group was emptied with `clearable`. |
| `options` | `readonly (string \| RadioOption)[]` | Render these choices, or pass `<Radio value="…">` children. Plain strings work too. |
| `children` | `ReactNode` |   |
| `label` | `ReactNode` | The question the choices answer, shown as the group's legend. |
| `description` | `ReactNode` |   |
| `error` | `ReactNode` | The validation message for the question. Marks every radio invalid. |
| `required` | `boolean` |   |
| `disabled` | `boolean` |   |
| `size` | `RadioSize` | Default `md`. |
| `orientation` | `RadioOrientation` | Default `vertical`. |
| `variant` | `RadioVariant` | Default `default`. `card` draws each choice as a tile. |
| `clearable` | `boolean` | Offer a button that empties the group. |
| `style` | `StyleProp<ViewStyle>` |   |
| `styles` | `Partial<{ root: StyleProp<ViewStyle>; legend: StyleProp<TextStyle>; description: StyleP…` |   |
| `localeText` | `Partial<RadioGroupLocaleText>` |   |

### RadioProps

| Prop | Type | Description |
|---|---|---|
| `value` (required) | `string` | The value this choice contributes to its group. |
| `checked` | `boolean` | Selected (controlled). Inside a RadioGroup the group decides instead. |
| `defaultChecked` | `boolean` | Selected to begin with, for a standalone radio you are not controlling. |
| `onCheckedChange` | `(checked: boolean) => void` | This radio was chosen. Only ever fires with `true`. |
| `label` | `ReactNode` | The text beside the radio. Pressing it selects this choice. |
| `description` | `ReactNode` | A hint under the label. |
| `error` | `ReactNode` | The validation message for this one choice. |
| `size` | `RadioSize` | Default `md`, or the size of the RadioGroup it sits in. |
| `disabled` | `boolean` |   |
| `style` | `Styleable<ViewStyle>` |   |
| `styles` | `Partial<{ root: Styleable<ViewStyle>; control: Styleable<ViewStyle>; label: Styleable<T…` |   |

Also accepts the props of `Omit<PressableProps, "children" | "style" | "onPress" | "disabled">`.

## Native and web

- No arrow-key navigation on touch; each radio is its own target.
- Web version: [RadioGroup on the web](https://kit.gramproindia.com/radiogroup).
