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

Radio Card

Radio cards for selection with enhanced visual presentation

Default

Radio cards arranged vertically in a group, each with an icon, title, and description.

Business plan

Includes up to 20 users, 40GB individual data and access to all features.

Business plan

Includes up to 20 users, 40GB individual data and access to all features.

vue
<template>
  <HLRadioGroup :value="value">
    <HLSpace vertical>
      <HLRadioCard
        @change="handleChange"
        value="card1"
        title="Business plan"
        description="Includes up to 20 users, 40GB individual data and access to all features."
      >
        <template #icon>
          <LayersThree01Icon />
        </template>
      </HLRadioCard>
      <HLRadioCard
        @change="handleChange"
        value="card2"
        title="Business plan"
        description="Includes up to 20 users, 40GB individual data and access to all features."
      >
        <template #icon>
          <LayersThree01Icon />
        </template>
      </HLRadioCard>
    </HLSpace>
  </HLRadioGroup>
</template>
<script setup lang="ts">
  import { HLRadioCard, HLRadioGroup, HLSpace } from '@platform-ui/highrise'
  import { LayersThree01Icon } from '@gohighlevel/ghl-icons/24/outline'
  import { ref } from 'vue'

  const value = ref('')
  const handleChange = (e: Event) => {
    value.value = (e.target as HTMLInputElement).value
  }
</script>

Without Icon

A radio card rendered with only a title and description, omitting the icon slot.

Business plan

Includes up to 20 users, 40GB individual data and access to all features.

vue
<template>
  <HLRadioGroup :value="value">
    <HLRadioCard
      @change="handleChange"
      value="card1"
      title="Business plan"
      description="Includes up to 20 users, 40GB individual data and access to all features."
    />
  </HLRadioGroup>
</template>
<script setup lang="ts">
  import { HLRadioCard, HLRadioGroup } from '@platform-ui/highrise'
  import { ref } from 'vue'

  const value = ref('')
  const handleChange = (e: Event) => {
    value.value = (e.target as HTMLInputElement).value
  }
</script>

Without Description

A radio card with an icon and title but no description text.

Business plan

vue
<template>
  <HLRadioGroup :value="value">
    <HLRadioCard @change="handleChange" value="card1" title="Business plan">
      <template #icon>
        <LayersThree01Icon />
      </template>
    </HLRadioCard>
  </HLRadioGroup>
</template>
<script setup lang="ts">
  import { HLRadioCard, HLRadioGroup } from '@platform-ui/highrise'
  import { LayersThree01Icon } from '@gohighlevel/ghl-icons/24/outline'
  import { ref } from 'vue'

  const value = ref('')
  const handleChange = (e: Event) => {
    value.value = (e.target as HTMLInputElement).value
  }
</script>

Compact Mode

The compact prop reduces the radio card's padding and spacing for denser layouts.

Business plan

Includes up to 20 users, 40GB individual data and access to all features.

vue
<template>
  <HLRadioGroup :value="value">
    <HLRadioCard
      @change="handleChange"
      value="card1"
      title="Business plan"
      description="Includes up to 20 users, 40GB individual data and access to all features."
      compact
    >
      <template #icon>
        <LayersThree01Icon />
      </template>
    </HLRadioCard>
  </HLRadioGroup>
</template>
<script setup lang="ts">
  import { HLRadioCard, HLRadioGroup } from '@platform-ui/highrise'
  import { LayersThree01Icon } from '@gohighlevel/ghl-icons/24/outline'
  import { ref } from 'vue'

  const value = ref('')
  const handleChange = (e: Event) => {
    value.value = (e.target as HTMLInputElement).value
  }
</script>

Custom Content

The default slot renders arbitrary content inside the radio card in place of the description.

Business icon
$99/monthBilled annually
Unlimited team members
Advanced analytics
24/7 priority support
Enterprise icon
$299/monthBilled annually
Custom integrations
Dedicated account manager
SLA guarantees
vue
<template>
  <HLRadioGroup :value="value">
    <HLSpace vertical>
      <HLRadioCard @change="handleChange" value="custom1" title="Business Plan">
        <div class="flex flex-col gap-4">
          <div class="flex items-center gap-4">
            <img src="https://api.dicebear.com/9.x/icons/svg?seed=plan" alt="Business icon" width="48" height="48" class="w-12 h-12 rounded-lg" />
            <div class="flex flex-col">
              <span class="text-lg font-semibold">$99/month</span>
              <span class="text-sm text-gray-500">Billed annually</span>
            </div>
          </div>
          <div class="flex flex-col gap-2">
            <div class="flex items-center gap-2">
              <span class="w-2 h-2 rounded-full bg-primary-500"></span>
              <span class="text-sm">Unlimited team members</span>
            </div>
            <div class="flex items-center gap-2">
              <span class="w-2 h-2 rounded-full bg-primary-500"></span>
              <span class="text-sm">Advanced analytics</span>
            </div>
            <div class="flex items-center gap-2">
              <span class="w-2 h-2 rounded-full bg-primary-500"></span>
              <span class="text-sm">24/7 priority support</span>
            </div>
          </div>
        </div>
      </HLRadioCard>

      <HLRadioCard @change="handleChange" value="custom2" title="Enterprise Plan">
        <div class="flex flex-col gap-4">
          <div class="flex items-center gap-4">
            <img src="https://api.dicebear.com/9.x/icons/svg?seed=plan" alt="Enterprise icon" width="48" height="48" class="w-12 h-12 rounded-lg" />
            <div class="flex flex-col">
              <span class="text-lg font-semibold">$299/month</span>
              <span class="text-sm text-gray-500">Billed annually</span>
            </div>
          </div>
          <div class="flex flex-col gap-2">
            <div class="flex items-center gap-2">
              <span class="w-2 h-2 rounded-full bg-primary-500"></span>
              <span class="text-sm">Custom integrations</span>
            </div>
            <div class="flex items-center gap-2">
              <span class="w-2 h-2 rounded-full bg-primary-500"></span>
              <span class="text-sm">Dedicated account manager</span>
            </div>
            <div class="flex items-center gap-2">
              <span class="w-2 h-2 rounded-full bg-primary-500"></span>
              <span class="text-sm">SLA guarantees</span>
            </div>
          </div>
        </div>
      </HLRadioCard>
    </HLSpace>
  </HLRadioGroup>
</template>
ts
<script setup lang="ts">
import { ref } from 'vue'
import { HLRadioCard, HLRadioGroup, HLSpace } from '@platform-ui/highrise'

const value = ref('')
const handleChange = (e: Event) => {
  value.value = (e.target as HTMLInputElement).value
}
</script>

Custom Icon Size

The iconSize prop overrides the default icon dimensions on the radio card.

Business Plan

Includes up to 20 users, 40GB individual data and access to all features.

vue
<template>
  <HLRadioGroup :value="value">
    <HLSpace vertical>
      <HLRadioCard
        @change="handleChange"
        value="custom1"
        title="Business Plan"
        iconSize="48px"
        description="Includes up to 20 users, 40GB individual data and access to all features."
      >
        <template #icon>
          <LayersThree01Icon />
        </template>
      </HLRadioCard>
    </HLSpace>
  </HLRadioGroup>
</template>
<script setup lang="ts">
  import { HLRadioCard, HLRadioGroup, HLSpace } from '@platform-ui/highrise'
  import { LayersThree01Icon } from '@gohighlevel/ghl-icons/24/outline'
  import { ref } from 'vue'

  const value = ref('')
  const handleChange = (e: Event) => {
    value.value = (e.target as HTMLInputElement).value
  }
</script>

Event Testing

This example logs the events the radio card emits as you select an option. @change fires with the native event (read the selected value from event.target.value), and @checked fires with the card's boolean checked state.

Business plan

Includes up to 20 users, 40GB individual data and access to all features.

Enterprise plan

Includes unlimited users, dedicated support, and SLA guarantees.

Event Log:

No events logged yet. Select a card above.
vue
<template>
  <HLRadioGroup :value="value">
    <HLSpace vertical>
      <HLRadioCard
        value="card1"
        title="Business plan"
        description="Includes up to 20 users, 40GB individual data and access to all features."
        @change="handleChange"
        @checked="val => addEventLog('@checked → ' + val)"
      >
        <template #icon>
          <LayersThree01Icon />
        </template>
      </HLRadioCard>
      <HLRadioCard
        value="card2"
        title="Enterprise plan"
        description="Includes unlimited users, dedicated support, and SLA guarantees."
        @change="handleChange"
        @checked="val => addEventLog('@checked → ' + val)"
      >
        <template #icon>
          <LayersThree01Icon />
        </template>
      </HLRadioCard>
    </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 a card 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 { HLRadioCard, HLRadioGroup, HLSpace } from '@platform-ui/highrise'
  import { LayersThree01Icon } from '@gohighlevel/ghl-icons/24/outline'
  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() })
    if (eventLog.value.length > 5) {
      eventLog.value.pop()
    }
  }
  const handleChange = (e: Event) => {
    value.value = (e.target as HTMLInputElement).value
    addEventLog('@change → ' + (e.target as HTMLInputElement).value)
  }
</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 { HLRadioCard, HLRadioGroup } from '@platform-ui/highrise'

Props

NameTypeDefaultDescription
idstringAuto (hr-radio-card-*)The id of the element. Generated automatically when omitted.
titlestringundefinedTitle text for the radio card
descriptionstringundefinedDescription text for the radio card
valuestringundefinedValue for the radio card
disabledbooleanfalseWhether the radio card is disabled, if disabled is passed to the HLRadioGroup this will be taken priority
compactbooleanfalseWhether to use compact mode
widthnumber | undefinedundefinedCustom width for the radio card
checkedboolean | undefinedundefinedWhether the radio is checked
iconSizestring32pxSize of the icon

Emits

NameParametersDescription
@change(event: Event) => voidWhen selection changes
@checked(event: Boolean) => voidWhen the radio is checked

Slots

NameParametersDescription
icon()Custom icon content
default()Default slot for custom content