Skip to content
RTL Support: Full
Accessibility: Full
Translations: Not Needed

Radio Group

Groups related radios so exactly one option can be selected at a time, with the chosen value bound via v-model:value.

Default

A horizontal radio group bound with v-model:value, using HLSpace to lay out the radios.

vue
<template>
  <HLRadioGroup id="radio-group-default" v-model:value="value">
    <HLSpace id="radio-space-default" size="md">
      <HLRadio id="radio-default-1" value="option1">Option 1</HLRadio>
      <HLRadio id="radio-default-2" value="option2">Option 2</HLRadio>
      <HLRadio id="radio-default-3" value="option3">Option 3</HLRadio>
    </HLSpace>
  </HLRadioGroup>
</template>
<script setup lang="ts">
  import { HLRadioGroup, HLRadio, HLSpace } from '@platform-ui/highrise'
  import { ref } from 'vue'

  const value = ref('option1')
</script>

Different Sizes

The size prop on HLRadioGroup accepts lg, md, sm, xs, 2xs, and 3xs.

LG Size
MD Size
SM Size
XS Size
2XS Size
3XS Size
vue
<template>
  <!-- size accepts: 'lg' | 'md' | 'sm' | 'xs' | '2xs' | '3xs' -->
  <HLRadioGroup v-model:value="value" size="md">
    <HLSpace size="md">
      <HLRadio value="option1">Option 1</HLRadio>
      <HLRadio value="option2">Option 2</HLRadio>
      <HLRadio value="option3">Option 3</HLRadio>
    </HLSpace>
  </HLRadioGroup>
</template>
<script setup lang="ts">
  import { HLRadioGroup, HLRadio, HLSpace } from '@platform-ui/highrise'
  import { ref } from 'vue'

  const value = ref('option1')
</script>

Vertical Layout

Adding the vertical prop to HLSpace stacks the radios in a column.

LG Size
MD Size
SM Size
XS Size
2XS Size
3XS Size
vue
<template>
  <HLRadioGroup id="radio-group" v-model:value="value" size="md">
    <HLSpace id="radio-space" vertical>
      <HLRadio id="radio-1" value="lg1">Option 1</HLRadio>
      <HLRadio id="radio-2" value="lg2">Option 2</HLRadio>
      <HLRadio id="radio-3" value="lg3">Option 3</HLRadio>
    </HLSpace>
  </HLRadioGroup>
</template>
<script setup lang="ts">
  import { HLRadioGroup, HLRadio, HLSpace } from '@platform-ui/highrise'
  import { ref } from 'vue'

  const value = ref('option1')
</script>

Disabled States

The disabled prop on HLRadioGroup disables all radios in the group.

vue
<template>
  <HLRadioGroup v-model:value="disabledValue" disabled>
    <HLSpace>
      <HLRadio value="option1">Option 1</HLRadio>
      <HLRadio value="option2">Option 2</HLRadio>
      <HLRadio value="option3">Option 3</HLRadio>
    </HLSpace>
  </HLRadioGroup>
</template>
<script setup lang="ts">
  import { HLRadioGroup, HLRadio, HLSpace } from '@platform-ui/highrise'
  import { ref } from 'vue'

  const disabledValue = ref('option1')
</script>

Error States

Wrapping the group in an HLFormItem with validation-status="error" renders the radios in their error state.

LG Size

MD Size

SM Size

XS Size

2XS Size

3XS Size

vue
<template>
  <HLFormItem id="radio-form-error-3xs" validation-status="error">
    <HLRadioGroup id="radio-group-error-3xs" v-model:value="value" size="3xs">
      <HLSpace id="radio-space-error-3xs">
        <HLRadio id="radio-error-3xs-1" value="option1">Option 1</HLRadio>
        <HLRadio id="radio-error-3xs-2" value="option2">Option 2</HLRadio>
        <HLRadio id="radio-error-3xs-3" value="option3">Option 3</HLRadio>
      </HLSpace>
    </HLRadioGroup>
  </HLFormItem>
</template>
<script setup lang="ts">
  import { HLRadioGroup, HLRadio, HLSpace, HLFormItem } from '@platform-ui/highrise'
  import { ref } from 'vue'

  const value = ref('option1')
</script>

Event Testing

@update:value fires with the newly selected value whenever the selection changes. This example logs each change.

Event Log:

No events logged yet. Select an option above.
vue
<template>
  <HLRadioGroup v-model:value="value" @update:value="val => addEventLog('@update:value → ' + val)">
    <HLSpace size="md">
      <HLRadio value="option1">Option 1</HLRadio>
      <HLRadio value="option2">Option 2</HLRadio>
      <HLRadio value="option3">Option 3</HLRadio>
    </HLSpace>
  </HLRadioGroup>
  <div class="text-sm">
    <p class="font-bold mb-2">Event Log:</p>
    <div v-if="eventLog.length === 0" class="text-gray-500">No events logged yet. Select an option above.</div>
    <div v-for="(log, index) in eventLog" :key="index" class="text-gray-700">{{ log.timestamp }}: {{ log.event }}</div>
  </div>
</template>
<script setup lang="ts">
  import { HLRadioGroup, HLRadio, HLSpace } from '@platform-ui/highrise'
  import { ref } from 'vue'

  const value = ref('option1')
  const eventLog = ref<{ event: string; timestamp: string }[]>([])
  const addEventLog = (event: string) => {
    eventLog.value.unshift({ event, timestamp: new Date().toLocaleTimeString() })
    if (eventLog.value.length > 5) {
      eventLog.value.pop()
    }
  }
</script>

Accessibility

  • Wrap radios with role="radiogroup" / fieldset and describe the question using aria-label / aria-labelledby.
  • Route shared helper or error messaging through aria-describedby, toggling aria-invalid on the group when needed.

Imports

ts
import { HLRadioGroup, HLRadio, HLSpace } from '@platform-ui/highrise'

Props

NameTypeDefaultDescription
id *stringundefinedThe id of the element
valuestring | number | booleanundefinedThe selected value (bind with v-model:value)
disabledbooleanfalseWhether to disable all radios in the group
size'lg' | 'md' | 'sm' | 'xs' | '2xs' | '3xs''md'Size of all radios in the group. Falls back to the surrounding HLForm size when omitted.
width'default' | 'equal' | 'full''default'Width distribution of the grouped items — default fits content, equal splits evenly, full spans the container
theme'primary' | 'neutral''primary'Visual theme. Only affects HLContentSwitcher children; plain radios ignore it.

Emits

NameParametersDescription
@update:value(value: string | number | boolean) => voidWhen the selection changes

Slots

NameParametersDescription
default()The content slot for radio items