---
title: Radio
url: "https://native-sdk.dev/docs/components/radio"
docs_index: /llms.txt
lastUpdated: 2026-10-16
---

> For an index of all documentation, see [/llms.txt](/llms.txt).

Use `radio` inside a `radio-group` to select one option. Give the group an accessible `label`, and provide each option’s visible label as content or `text`. Bind `checked` to the model’s choice.

Descendant radios form one group regardless of nesting depth. The group has one Tab stop; arrow keys wrap through choices, and Home/End move to the first or last option. Focus and selection move together. A selection change dispatches `on-change` when bound, otherwise `on-toggle` or `on-press`. Activating an already selected radio does not dispatch `on-change`; legacy fallback handlers still receive the activation.

## Markup

```html
<radio-group gap="12" label="Density">
  <radio checked="{density == 'default'}" on-change="set_default">Default</radio>
  <row>
    <radio checked="{density == 'comfortable'}" on-change="set_comfortable">Comfortable</radio>
  </row>
  <radio checked="{density == 'compact'}" disabled="true">Compact</radio>
</radio-group>
```

One field holds the group's choice — a string-literal union in a TypeScript core, an enum in a Zig core — and each radio's arm sets it:

```ts
// model: { readonly density: "default" | "comfortable" | "compact" }
case "set_comfortable":
  return { ...model, density: "comfortable" };
```

```zig
// model: density: enum { default, comfortable, compact } = .default,
.set_comfortable => model.density = .comfortable,
```

## Programmatic construction (Zig)

In a Zig view, the `canvas.Ui` builder constructs the same tree programmatically:

```zig
ui.el(.radio_group, .{ .gap = 12, .semantics = .{ .label = "Density" } }, .{
    ui.el(.radio, .{ .text = "Default", .checked = model.density == .default, .on_change = .set_default }, .{}),
    ui.row(.{}, .{
        ui.el(.radio, .{ .text = "Comfortable", .checked = model.density == .comfortable, .on_change = .set_comfortable }, .{}),
    }),
    ui.el(.radio, .{ .text = "Compact", .checked = model.density == .compact, .disabled = true }, .{}),
})
```

## Attributes

| Attribute   | Description                                                                                                                                                                                                                  |
| ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `text`      | Text value for text-bearing elements; a literal or one \{binding}.                                                                                                                                                           |
| `checked`   | Checked state for checkbox/toggle; true/false or a \{binding}.                                                                                                                                                               |
| `disabled`  | Disables the control; true/false or a \{binding}.                                                                                                                                                                            |
| `on-change` | Dispatch a Msg on change: tag or tag:\{payload}. Hit-target elements only. On a treeitem, Up/Down/Left/Right/Home/End focus movement prefers on-change over on-press, separating keyboard selection from pointer activation. |
| `on-toggle` | Dispatch a Msg on toggle: tag or tag:\{payload}. Hit-target elements only (checkbox, toggle, toggle-button, switch, accordion, ...).                                                                                         |
| `on-press`  | Dispatch a Msg on press: tag or tag:\{payload}. Legal on any element — a bound press handler makes it pressable, and presses on plain text/icons inside it fall through to it (dragging still selects text).                 |

---

For a semantic overview of all documentation, see [/sitemap.md](/sitemap.md)

For an index of all available documentation, see [/llms.txt](/llms.txt)

For agent-facing discovery, including API and MCP surfaces, see [/agents.md](/agents.md)