Skip to content

Radio Group

When users must pick exactly one option from a small set of mutually exclusive choices, a radio group is the right tool. Each option is visible at a glance, unlike a select dropdown, which makes radios ideal when the list is short (roughly 2--5 items).

ts
import { CoarRadioGroup, CoarRadioButton } from '@cocoar/vue-ui';

Horizontal

Switch to orientation="horizontal" when labels are short and there are only a few choices.

Selected: m
vue
<template>
  <div style="display: flex; flex-direction: column; gap: 12px;">
    <CoarRadioGroup v-model="size" name="button-size" label="Button Size" orientation="horizontal">
      <CoarRadioButton value="xs">XS</CoarRadioButton>
      <CoarRadioButton value="s">S</CoarRadioButton>
      <CoarRadioButton value="m">M</CoarRadioButton>
      <CoarRadioButton value="l">L</CoarRadioButton>
    </CoarRadioGroup>
    <span style="font-size: 13px; color: #64748b;">Selected: {{ size }}</span>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue';
import { CoarRadioGroup, CoarRadioButton } from '@cocoar/vue-ui';

const size = ref('m');
</script>

Vertical (Default)

The default vertical layout stacks options for easy scanning -- works well with longer labels or more than 4 choices.

Selected: none
vue
<template>
  <div style="display: flex; flex-direction: column; gap: 12px;">
    <CoarRadioGroup v-model="color" name="preferred-color" label="Preferred Color">
      <CoarRadioButton value="red">Red — Passionate and energetic</CoarRadioButton>
      <CoarRadioButton value="blue">Blue — Calm and trustworthy</CoarRadioButton>
      <CoarRadioButton value="green">Green — Fresh and natural</CoarRadioButton>
      <CoarRadioButton value="purple">Purple — Creative and luxurious</CoarRadioButton>
    </CoarRadioGroup>
    <span style="font-size: 13px; color: #64748b;">Selected: {{ color || 'none' }}</span>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue';
import { CoarRadioGroup, CoarRadioButton } from '@cocoar/vue-ui';

const color = ref('');
</script>

States

Mark the group as required to show an asterisk. Wrap in CoarFormField to display validation messages.

Please select an option
vue
<template>
  <div style="display: flex; flex-direction: column; gap: 16px;">
    <CoarRadioGroup :model-value="'a'" name="required-group" label="Required Group" :required="true">
      <CoarRadioButton value="a">Option A</CoarRadioButton>
      <CoarRadioButton value="b">Option B</CoarRadioButton>
    </CoarRadioGroup>
    <CoarFormField error="Please select an option">
      <CoarRadioGroup :model-value="''" name="with-error" label="With Error">
        <CoarRadioButton value="a">Option A</CoarRadioButton>
        <CoarRadioButton value="b">Option B</CoarRadioButton>
      </CoarRadioGroup>
    </CoarFormField>
  </div>
</template>

<script setup lang="ts">
import { CoarRadioGroup, CoarRadioButton, CoarFormField } from '@cocoar/vue-ui';
</script>

Disabled Buttons

Individual CoarRadioButton options can be disabled while the rest of the group stays interactive -- useful for temporarily unavailable plans or tiers.

vue
<template>
  <div>
    <CoarRadioGroup v-model="plan" name="plan" label="Plan">
      <CoarRadioButton value="free">Free</CoarRadioButton>
      <CoarRadioButton value="pro">Pro</CoarRadioButton>
      <CoarRadioButton value="enterprise" :disabled="true">Enterprise (Coming Soon)</CoarRadioButton>
    </CoarRadioGroup>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue';
import { CoarRadioGroup, CoarRadioButton } from '@cocoar/vue-ui';

const plan = ref('free');
</script>

Sizes

Three sizes that stay in step with every other Cocoar form control.

vue
<template>
  <div style="display: flex; flex-direction: column; gap: 16px;">
    <CoarRadioGroup :model-value="'a'" name="size-s" label="Small" size="s">
      <CoarRadioButton value="a">Option A</CoarRadioButton>
      <CoarRadioButton value="b">Option B</CoarRadioButton>
    </CoarRadioGroup>
    <CoarRadioGroup :model-value="'a'" name="size-m" label="Medium (default)" size="m">
      <CoarRadioButton value="a">Option A</CoarRadioButton>
      <CoarRadioButton value="b">Option B</CoarRadioButton>
    </CoarRadioGroup>
    <CoarRadioGroup :model-value="'a'" name="size-l" label="Large" size="l">
      <CoarRadioButton value="a">Option A</CoarRadioButton>
      <CoarRadioButton value="b">Option B</CoarRadioButton>
    </CoarRadioGroup>
  </div>
</template>

<script setup lang="ts">
import { CoarRadioGroup, CoarRadioButton } from '@cocoar/vue-ui';
</script>

Accessibility

Keyboard Navigation

KeyAction
TabMove focus into / out of radio group
Arrow Left / Arrow UpSelect previous option
Arrow Right / Arrow DownSelect next option
SpaceSelect focused option

INFO

Only one radio button in a group receives tab focus. Arrow keys move selection between options within the group.

Screen Reader Support

  • Group label announced when entering the group
  • Each option's label announces on focus
  • Selected state properly communicated
  • Disabled options announced as unavailable

API

CoarRadioGroup Props

PropTypeDefaultDescription
v-modelunknownundefinedCurrently selected value
namestringRequired. HTML name for the radio inputs
labelstring''Group accessible label
orientation'horizontal' | 'vertical''vertical'Layout direction
size's' | 'm' | 'l''m'Radio button size
disabledbooleanfalseDisable all radio buttons
requiredbooleanfalseMark as required
errorbooleanfalseError state (auto-injected from CoarFormField)

CoarRadioButton Props

PropTypeDefaultDescription
valueunknown--Value emitted when selected
disabledbooleanfalseDisable this option

Released under the Apache-2.0 License.