---
title: YesNo
description: Two segmented buttons with radio semantics for yes_no fields.
preview: yes-no
---
# YesNo

A segmented control with two options. The value is a boolean; the words come from the schema's `options` (exactly two, yes first) when set, otherwise "Yes" and "No". `Field` renders it for `yes_no`.

## Preview
<!-- preview: yes-no -->

## Usage
```tsx
// { key: 'has_team', type: 'yes_no', label: 'Do you work with a team?', options: ['Yes, a team', 'Just me'], required: true }
import { Form } from '@trymirio/mirio';

<Form schema={intake} client={mirio} />

// by hand, overriding the words for this render only:
import { YesNo } from '@trymirio/mirio';
<YesNo name="has_team" yesLabel="Team" noLabel="Solo" />
```

## Props
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `name` | `string` | required | The field key. |
| `yesLabel` | `string` | `options[0]` label, else `"Yes"` | Overrides the text of the `true` segment. |
| `noLabel` | `string` | `options[1]` label, else `"No"` | Overrides the text of the `false` segment. |
| `className` | `string` | segmented group classes (`inline-flex w-full max-w-xs …`) | Merged onto the group element. |
| …`<div>` attributes | | | Spread on the group element (except `onChange`). |

Rendered: `<div id role="radiogroup" tabindex="-1" aria-labelledby data-mirio="yesno">` with two `<button type="button" role="radio" aria-checked data-value="true|false">`.

A `yes_no` field that is `required` must be answered; an unanswered optional field submits `null`. (For "must be yes", use a `consent` field.)

## Variants and states
- **Checked**: the segment lifts onto `--mirio-bg` with a small shadow; the other stays muted.
- **Error**: `aria-invalid` on the group plus the message below.
- **Prefill**: `defaultValue: true`.

## Customization
- Tokens: `--mirio-muted` (track), `--mirio-bg` (selected segment), `--mirio-fg` / `--mirio-muted-fg` (text), `--mirio-border`, `--mirio-ring`, `--mirio-radius` (segments use `radius - 2px`).
- `className="max-w-none"` makes it full width; `classNames={{ segment: '…' }}` on `Form` styles each button.
- CSS hooks: `[data-mirio="yesno"]`, `[data-mirio="yesno"] [role="radio"][aria-checked="true"]`, `[data-value="true"]`.

## Accessibility
Radio semantics without native radios: `role="radiogroup"` + `role="radio"`/`aria-checked`, roving `tabindex` (one segment is tabbable), and Left/Right/Up/Down/Home/End move the selection and focus.

## Related
[Choice](/docs/components/choice.md), [Consent](/docs/components/consent.md), [Rating](/docs/components/rating.md), [Schema: field types](/docs/schema.md)
