# Radio Group Field

A labeled fieldset of radio options with description and helper or error text.

## Installation

```tsx
import {
  RadioGroupField,
  RadioGroupFieldOption,
} from "@makeplane/propel/components/radio-group-field";
```
## Usage

```tsx
import {
  RadioGroupField,
  RadioGroupFieldOption,
} from "@makeplane/propel/components/radio-group-field";

export default function BasicDemo() {
  return (
    <RadioGroupField
      name="priority"
      label="Priority"
      description="Pick one default priority."
      density="comfortable"
      size="lg"
      defaultValue="medium"
      hint="You can change this later."
    >
      <RadioGroupFieldOption value="low" label="Low" />
      <RadioGroupFieldOption value="medium" label="Medium" description="Recommended." />
      <RadioGroupFieldOption value="high" label="High" />
    </RadioGroupField>
  );
}
```
## Examples

### Sizes

Legend, description, and option text scale together across `lg`, `xl`, and `2xl`.

```tsx
import {
  RadioGroupField,
  RadioGroupFieldOption,
} from "@makeplane/propel/components/radio-group-field";

export default function SizesDemo() {
  return (
    <div className="flex flex-wrap items-start gap-10">
      {(["lg", "xl", "2xl"] as const).map((size) => (
        <RadioGroupField
          key={size}
          name={`priority-${size}`}
          label={size}
          description="Pick one default priority."
          density="comfortable"
          size={size}
          defaultValue="medium"
        >
          <RadioGroupFieldOption value="low" label="Low" />
          <RadioGroupFieldOption value="medium" label="Medium" description="Recommended." />
          <RadioGroupFieldOption value="high" label="High" />
        </RadioGroupField>
      ))}
    </div>
  );
}
```

### Densities

`density` sets the row spacing between options: `comfortable` keeps a gap, `compact` stacks them flush.

```tsx
import {
  RadioGroupField,
  RadioGroupFieldOption,
} from "@makeplane/propel/components/radio-group-field";

export default function DensitiesDemo() {
  return (
    <div className="flex flex-wrap items-start gap-10">
      {(["comfortable", "compact"] as const).map((density) => (
        <RadioGroupField
          key={density}
          name={`priority-${density}`}
          label={density}
          description="Pick one default priority."
          density={density}
          size="lg"
          defaultValue="medium"
        >
          <RadioGroupFieldOption value="low" label="Low" />
          <RadioGroupFieldOption value="medium" label="Medium" description="Recommended." />
          <RadioGroupFieldOption value="high" label="High" />
        </RadioGroupField>
      ))}
    </div>
  );
}
```

### Orientations

`orientation` controls only the option rows. It defaults to `vertical`; `horizontal` lays the
options out in a wrapping row while the legend, description, and helper or error text keep their
normal vertical placement.

```tsx
import {
  RadioGroupField,
  RadioGroupFieldOption,
} from "@makeplane/propel/components/radio-group-field";

export default function OrientationsDemo() {
  return (
    <div className="flex flex-col items-start gap-10">
      <RadioGroupField
        name="priority-vertical"
        label="Vertical"
        description="The default option layout."
        density="comfortable"
        size="lg"
        defaultValue="medium"
      >
        <RadioGroupFieldOption value="low" label="Low" />
        <RadioGroupFieldOption value="medium" label="Medium" />
        <RadioGroupFieldOption value="high" label="High" />
      </RadioGroupField>
      <RadioGroupField
        name="priority-horizontal"
        label="Horizontal"
        description="Options wrap when the available width is limited."
        density="comfortable"
        size="lg"
        orientation="horizontal"
        defaultValue="medium"
      >
        <RadioGroupFieldOption value="low" label="Low" />
        <RadioGroupFieldOption value="medium" label="Medium" />
        <RadioGroupFieldOption value="high" label="High" />
      </RadioGroupField>
    </div>
  );
}
```

### Error

Setting `error` marks the fieldset invalid and replaces the helper text with the error message.
Every option in the group picks up the invalid state, but only the still-unanswered ones recolor
to danger — an option the user already picked keeps its normal accent color rather than also
reading as wrong.

```tsx
import {
  RadioGroupField,
  RadioGroupFieldOption,
} from "@makeplane/propel/components/radio-group-field";

export default function ErrorDemo() {
  return (
    <RadioGroupField
      name="visibility"
      label="Project visibility"
      description="Controls who can find and open this project."
      density="comfortable"
      size="lg"
      error="Select a visibility before creating the project."
    >
      <RadioGroupFieldOption value="private" label="Private" description="Only invited members." />
      <RadioGroupFieldOption
        value="workspace"
        label="Workspace"
        description="Everyone in the workspace."
      />
      <RadioGroupFieldOption value="public" label="Public" description="Anyone with the link." />
    </RadioGroupField>
  );
}
```

### Controlled

```tsx
import {
  RadioGroupField,
  RadioGroupFieldOption,
} from "@makeplane/propel/components/radio-group-field";
import * as React from "react";

export default function ControlledDemo() {
  const [value, setValue] = React.useState("medium");

  return (
    <RadioGroupField
      name="priority"
      label="Priority"
      description="Pick one default priority."
      density="comfortable"
      size="lg"
      value={value}
      onValueChange={(next) => setValue(next as string)}
      hint={`Selected: ${value}`}
    >
      <RadioGroupFieldOption value="low" label="Low" />
      <RadioGroupFieldOption value="medium" label="Medium" description="Recommended." />
      <RadioGroupFieldOption value="high" label="High" />
    </RadioGroupField>
  );
}
```
## API Reference

### RadioGroupField

Ready-to-use radio group field with legend, description, and helper/error text.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `children` (required) | `ReactNode` | — | Radio option rows, usually `RadioGroupFieldOption`. |
| `density` (required) | `"comfortable" \| "compact"` | — | Spacing between radio options. |
| `label` (required) | `string` | — | Visible fieldset legend. |
| `size` (required) | `"md" \| "lg" \| "xl" \| "2xl"` | — | Legend and helper text size. |
| `name` (required) | `string` | — | Submitted field name. |
| `render` | `ReactElement<unknown, string \| JSXElementConstructor<any>> \| ComponentRenderFn<HTMLProps, RadioGroupState>` | — | Allows you to replace the component's HTML element with a different tag, or compose it with another component. Accepts a `ReactElement` or a function that returns the element to render. |
| `description` | `ReactNode` | — | Supporting text shown below the legend. |
| `error` | `ReactNode` | — | Error text shown below the group. |
| `hint` | `ReactNode` | — | Helper text shown below the group. Replaced by `error` when an error is set. |
| `orientation` | `"horizontal" \| "vertical"` | `"vertical"` | Arrangement of the radio option rows. |

### RadioGroupFieldOption

A radio option row for use inside `RadioGroupField` or a custom `RadioGroup`.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `label` (required) | `string` | — | Visible option label. |
| `render` | `ReactElement<unknown, string \| JSXElementConstructor<any>> \| ComponentRenderFn<HTMLProps, RadioRootState>` | — | Allows you to replace the component's HTML element with a different tag, or compose it with another component. Accepts a `ReactElement` or a function that returns the element to render. |
| `description` | `ReactNode` | — | Optional supporting text announced as the radio description. |
| `size` | `"md" \| "lg" \| "xl" \| "2xl"` | — | Label and description size. Inherited from `RadioGroupField` when omitted. |
