Radio Group

The radio group component provides a way to select one option from a list of options.

It is presented as a group of radio buttons, only one of which can be selected at a time.

WAI-ARIA: Radio Group Pattern

Example

You have selected the unknown power plan.

Sources

+page.svelte

<script lang="ts">
  import RadioGroup from './RadioGroup.svelte'
  import Radio from './Radio.svelte'

  let value: string = ''
</script>

<p class="mb-4 text-sm opacity-60">
  You have selected the <b>{value || 'unknown'}</b> power plan.
</p>

<RadioGroup bind:value>
  <Radio value="balanced">
    <h3>⚖️ Balanced</h3>
    <p>
      Provides a balance between performance and energy efficiency by adjusting
      CPU speed and power settings based on system load.
    </p>
  </Radio>
  <Radio value="high-performance">
    <h3>⚡ High Performance</h3>
    <p>
      Prioritizes performance over power savings, keeping the CPU running at
      higher frequencies for faster response times.
    </p>
  </Radio>
  <Radio value="power-saver">
    <h3>🔋 Power Saver</h3>
    <p>
      Maximizes battery life on laptops and mobile devices by reducing CPU
      speed, lowering screen brightness, and applying power-saving measures.
    </p>
  </Radio>
</RadioGroup>

<style lang="postcss">
  h3 {
    @apply font-semibold;
  }

  p {
    @apply mt-1 text-xs;
  }
</style>

Radio.svelte

<script lang="ts">
  import type { RadioGroup } from 'louisette'
  import { getContext } from 'svelte'
  import { CheckCircle, Circle } from 'lucide-svelte'

  export let value: string

  const { radioAttrs, selected } = getContext<RadioGroup>('radioGroup')
</script>

<div
  {...$radioAttrs(value)}
  class="flex cursor-pointer items-center rounded-md p-4 text-neutral-900 transition-colors hover:bg-neutral-200 focus:outline-none focus-visible:bg-neutral-200 focus-visible:ring focus-visible:ring-accent-500 focus-visible:ring-opacity-50 dark:border-neutral-600 dark:text-neutral-100 dark:hover:bg-neutral-700 dark:focus-visible:bg-neutral-700"
  class:is-selected={$selected === value}
>
  <svelte:component
    this={$selected === value ? CheckCircle : Circle}
    class="mr-4 h-4 w-4 flex-shrink-0"
  />
  <span>
    <slot />
  </span>
</div>

<style lang="postcss">
  .is-selected {
    @apply bg-accent-200 dark:bg-accent-500 dark:text-neutral-100 !important;
  }
</style>

RadioGroup.svelte

<script lang="ts">
  import { createRadioGroup } from 'louisette'
  import { setContext } from 'svelte'

  export let value: string = ''

  const { radioGroupAttrs, ...radioGroupContext } = createRadioGroup({
    selected: value,
  })

  setContext('radioGroup', radioGroupContext)

  const { selected } = radioGroupContext
  $: value = $selected
</script>

<div {...$radioGroupAttrs} class="max-w-xl space-y-2">
  <slot />
</div>