Skip to content
v1.0.3

RadioGroup

A single-choice control rendered from an options array. Options can be plain strings or objects with a label, description, and per-option disabled flag. Stacks vertically by default or inline with direction="row".

bash
jlds add radio-group

Usage

html
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/jarooda/jlds@main/registry/css/index.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/jarooda/jlds@main/registry/css/radio-group.css">

<div class="jl-radiogroup" role="radiogroup">
  <label class="jl-radio">
    <input type="radio" class="jl-radio__input" name="plan" value="free" checked />
    <span class="jl-radio__dot"></span>
    <span class="jl-radio__body"><span class="jl-radio__label">Free</span></span>
  </label>
  <label class="jl-radio">
    <input type="radio" class="jl-radio__input" name="plan" value="pro" />
    <span class="jl-radio__dot"></span>
    <span class="jl-radio__body"><span class="jl-radio__label">Pro</span></span>
  </label>
</div>
vue
<script setup lang="ts">
import { ref } from "vue"
import { RadioGroup } from "@/components/ui/radio-group"

const plan = ref("free")
</script>

<template>
  <RadioGroup
    name="plan"
    v-model="plan"
    :options="['Free', 'Pro', 'Enterprise']"
  />
</template>
tsx
import { useState } from "react"
import { RadioGroup } from "@/components/ui/radio-group"

const [plan, setPlan] = useState("Free")

<RadioGroup
  name="plan"
  value={plan}
  onChange={setPlan}
  options={["Free", "Pro", "Enterprise"]}
/>

With descriptions

Pass option objects to add a description and per-option disabled.

html
<div class="jl-radiogroup" role="radiogroup">
  <label class="jl-radio">
    <input type="radio" class="jl-radio__input" name="tier" value="hobby" checked />
    <span class="jl-radio__dot"></span>
    <span class="jl-radio__body">
      <span class="jl-radio__label">Hobby</span>
      <span class="jl-radio__desc">For personal projects. 1 environment.</span>
    </span>
  </label>
  <label class="jl-radio" data-disabled="true">
    <input type="radio" class="jl-radio__input" name="tier" value="team" disabled />
    <span class="jl-radio__dot"></span>
    <span class="jl-radio__body">
      <span class="jl-radio__label">Team</span>
      <span class="jl-radio__desc">Coming soon.</span>
    </span>
  </label>
</div>
vue
<template>
  <RadioGroup
    name="tier"
    v-model="tier"
    :options="[
      { value: 'hobby', label: 'Hobby', description: 'For personal projects. 1 environment.' },
      { value: 'team', label: 'Team', description: 'Coming soon.', disabled: true },
    ]"
  />
</template>
tsx
<RadioGroup
  name="tier"
  value={tier}
  onChange={setTier}
  options={[
    { value: "hobby", label: "Hobby", description: "For personal projects. 1 environment." },
    { value: "team", label: "Team", description: "Coming soon.", disabled: true },
  ]}
/>

Inline

Set direction="row" (React/Vue) or add jl-radiogroup--row (HTML).

html
<div class="jl-radiogroup jl-radiogroup--row" role="radiogroup">
  <label class="jl-radio">
    <input type="radio" class="jl-radio__input" name="size" value="sm" checked />
    <span class="jl-radio__dot"></span>
    <span class="jl-radio__body"><span class="jl-radio__label">Small</span></span>
  </label>
  <!-- … -->
</div>
vue
<template>
  <RadioGroup name="size" v-model="size" direction="row" :options="['Small', 'Medium', 'Large']" />
</template>
tsx
<RadioGroup name="size" value={size} onChange={setSize} direction="row" options={["Small", "Medium", "Large"]} />

Props

RadioGroup is a controlled component — pass value/v-model and handle changes.

React

PropTypeDefaultDescription
namestringShared input name (required)
valuestringSelected value (controlled)
onChange(value, event) => voidCalled with the new value
optionsRadioOption[]Strings, or { value, label, description?, disabled? }
direction"column" | "row""column"Stack or inline
disabledbooleanfalseDisable the whole group

Vue

PropTypeDefaultDescription
namestringShared input name (required)
modelValuestringSelected value (v-model)
optionsRadioOption[]Strings, or { value, label, description?, disabled? }
direction"column" | "row""column"Stack or inline
disabledbooleanfalseDisable the whole group

CSS classes (HTML)

ClassPurpose
.jl-radiogroupGroup wrapper (role="radiogroup")
.jl-radiogroup--rowLay options out inline
.jl-radioPer-option <label>
.jl-radio__inputVisually-hidden <input type="radio">
.jl-radio__dotThe drawn radio dot
.jl-radio__body / __label / __descText column, label, and description
[data-disabled="true"]Disabled styling (on a .jl-radio)