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

Radio

Atomic radio element

Unchecked

A radio in its default unselected state.

vue
<template>
  <HLSpace justify="flex-start" align="center">
    <HLRadio id="radio-unchecked" v-model="uncheckedValue" value="unchecked">Radio Label</HLRadio>
  </HLSpace>
</template>

<script setup lang="ts">
  import { HLRadio, HLSpace } from '@platform-ui/highrise'
  import { ref } from 'vue'
  const uncheckedValue = ref(false)
</script>

Checked

A radio in its selected state.

vue
<template>
  <HLSpace justify="flex-start" align="center">
    <HLRadio id="radio-checked" v-model="checkedValue" value="checked" checked>Radio Label</HLRadio>
  </HLSpace>
</template>

<script setup lang="ts">
  import { HLRadio, HLSpace } from '@platform-ui/highrise'
  import { ref } from 'vue'
  const checkedValue = ref(true)
</script>

Disabled - Unchecked

A non-interactive radio that is unselected.

vue
<template>
  <HLSpace justify="flex-start" align="center">
    <HLRadio id="radio-disabled" disabled v-model="disabledValue" value="disabled">Radio Label</HLRadio>
  </HLSpace>
</template>

<script setup lang="ts">
  import { HLRadio, HLSpace } from '@platform-ui/highrise'
  import { ref } from 'vue'
  const disabledValue = ref(false)
</script>

Disabled - Checked

A non-interactive radio that is selected.

vue
<template>
  <HLSpace justify="flex-start" align="center">
    <HLRadio id="radio-disabled-checked" disabled v-model="disabledCheckedValue" value="disabled-checked" checked>Radio Label</HLRadio>
  </HLSpace>
</template>

<script setup lang="ts">
  import { HLRadio, HLSpace } from '@platform-ui/highrise'
  import { ref } from 'vue'
  const disabledCheckedValue = ref(true)
</script>

Error state

A radio wrapped in an HLFormItem with validation-status="error".

vue
<template>
  <HLFormItem validation-status="error">
    <HLRadio id="radio-error" v-model="errorValue" value="error">Remember me</HLRadio>
  </HLFormItem>
</template>

<script setup lang="ts">
  import { HLRadio, HLSpace, HLFormItem } from '@platform-ui/highrise'
  import { ref } from 'vue'
  const errorValue = ref(false)
</script>

Only Icon

A radio that renders the control without a label using the onlyIcon prop.

vue
<template>
  <HLSpace justify="flex-start" align="center">
    <HLRadio id="radio-icon" v-model="onlyIconValue" value="icon" onlyIcon></HLRadio>
  </HLSpace>
</template>

<script setup lang="ts">
  import { HLRadio, HLSpace } from '@platform-ui/highrise'
  import { ref } from 'vue'
  const onlyIconValue = ref(false)
</script>

Event Testing

The @change event fires with the native event when a radio is selected, and @update:checked fires with the new boolean checked state. This example logs the events as you select each option.

Event Log:

No events logged yet. Select an option above.
vue
<template>
  <HLSpace justify="flex-start" align="center">
    <HLRadio
      id="radio-events-a"
      name="events-group"
      value="a"
      :checked="value === 'a'"
      @update:checked="() => { value = 'a'; addEventLog('@update:checked → true (a)') }"
      @change="addEventLog('@change → a')"
    >
      Option A
    </HLRadio>
    <HLRadio
      id="radio-events-b"
      name="events-group"
      value="b"
      :checked="value === 'b'"
      @update:checked="() => { value = 'b'; addEventLog('@update:checked → true (b)') }"
      @change="addEventLog('@change → b')"
    >
      Option B
    </HLRadio>
  </HLSpace>
  <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 { HLRadio, HLSpace } from '@platform-ui/highrise'
  import { ref } from 'vue'

  const value = ref('')
  const eventLog = ref<{ event: string; timestamp: string }[]>([])

  const addEventLog = (event: string) => {
    eventLog.value.unshift({ event, timestamp: new Date().toLocaleTimeString() })
    // Keep only last 5 events
    if (eventLog.value.length > 5) {
      eventLog.value.pop()
    }
  }
</script>

Custom Input Attributes

Use radioInputProps to pass HTML attributes straight to the underlying input[type="radio"] element — useful for required, data-* hooks, or other form-related attributes.

vue
<template>
  <HLSpace justify="flex-start" align="center">
    <HLRadio id="radio-input-props" value="terms" :radioInputProps="{ required: true, 'data-testid': 'terms-radio' }">I accept the terms</HLRadio>
  </HLSpace>
</template>

<script setup lang="ts">
  import { HLRadio, HLSpace } from '@platform-ui/highrise'
</script>

Accessibility

  • Give each radio an id tied to its visible label and share a name so only one option is selectable.
  • Reflect the checked option with aria-checked / aria-disabled and mirror helper text through aria-describedby.

Imports

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

Props

NameTypeDefaultDescription
idstringAuto (hr-radio-*)The id of the element. Generated automatically when omitted.
checkedbooleanfalseWhether the radio is checked
disabledbooleanfalseWhether the radio is disabled
size'lg' | 'md' | 'sm' | 'xs' | '2xs' | '3xs''md'The size of the radio
valuestring | number | boolean | undefinedundefinedValue of the radio
namestring | undefinedundefinedSets the name attribute on the underlying input, grouping radios for native HTML form submission. For a managed single-select group, prefer HLRadioGroup.
onlyIconbooleanfalseShows only the radio button without label spacing
radioInputPropsInputHTMLAttributes{}HTML attributes that will be bound to the input[type='radio'] element internally

Emits

NameParametersDescription
@update:checked(value: boolean) => voidCallback when checked value changes
@change(event: Event) => voidWhen radio state changes

Slots

NameParametersDescription
default()The default content slot