Radio
Import
import { Radio } from "@dr-max/ui/radio"
The entry carries its own precompiled CSS (including the styles of the Required and Spinner parts it composes) — no extra style imports needed.
Radios usually live inside a Radio group, which shares the name and selected value with its children — see that page for grouped usage.
Usage
value is required; the radio is checked while it equals the selected value. Bind the selection with v-model and share a name between radios of the same set:
<script setup lang="ts">
import { Radio } from "@dr-max/ui/radio"
import { ref } from "vue"
const delivery = ref("pickup")
</script>
<template>
<Radio v-model="delivery" name="delivery" value="pickup" label="Personal pickup" />
<Radio v-model="delivery" name="delivery" value="home" label="Home delivery" />
</template>
Disabled and loading
disabled disables the native input; loading shows a spinner and disables interaction:
<template>
<Radio v-model="delivery" name="delivery" value="unavailable" label="Unavailable option" disabled />
<Radio v-model="delivery" name="delivery" value="checking" label="Checking availability" loading />
</template>
Validation errors
On a lone radio, errors drive aria-invalid and the invalid visual state — the messages themselves render at group level, so pass them to the surrounding Radio group:
<template>
<Radio
v-model="choice"
name="terms"
value="accept"
label="I accept the terms"
:touched="true"
:errors="[{ label: 'Choose an option', param: 'required' }]"
/>
</template>
Custom label
The default slot takes precedence over the label prop when the label needs markup:
<template>
<Radio v-model="delivery" name="delivery" value="express">
Express delivery <strong>within 2 hours</strong>
</Radio>
</template>
Playground
<script setup lang="ts">
import { Radio } from '@dr-max/ui/radio'
</script>
<template>
<Radio label="Personal pickup" value="pickup" model-value="pickup" />
</template>