Radiogroup
Component

RadioGroup

A set of checkable buttons where only one can be checked at a time.

Demo

Select a plan:
Selected: pro
Horizontal layout:

Features

  • Full keyboard navigation with roving tabindex
  • Vertical and horizontal orientation support
  • RTL (Right-to-Left) language support
  • Controlled and uncontrolled modes
  • Optional loop navigation (wrap from last to first)
  • Support for HTML forms (hidden input)
  • WCAG compliant with proper ARIA attributes

Installation

bash
dotnet add package SummitUI

Anatomy

Import the components and structure them as follows:

razor
<SmRadioGroupRoot>
    <SmRadioGroupItem Value="option1">
        <SmRadioGroupIndicator>
            <span class="dot"></span>
        </SmRadioGroupIndicator>
        <span>Option 1</span>
    </SmRadioGroupItem>
    <SmRadioGroupItem Value="option2">
        <SmRadioGroupIndicator>
            <span class="dot"></span>
        </SmRadioGroupIndicator>
        <span>Option 2</span>
    </SmRadioGroupItem>
</SmRadioGroupRoot>

Sub-components

RadioGroupRoot

Container component with radiogroup role. Manages selection state and provides context to child items.

RadioGroupItem

Individual radio button with role="radio". Handles keyboard navigation and selection.

RadioGroupIndicator

Visual indicator that renders when the item is checked. Supports ForceMount for animations.

API Reference

RadioGroupRoot

Property Type Default Description
Value string? null Controlled selected value
DefaultValue string? null Default selected value for uncontrolled mode
ValueChanged EventCallback<string?> - Callback when selected value changes
ValueExpression Expression<Func<string?>>? null Expression for EditForm binding and validation
OnValueChange EventCallback<string?> - Additional callback when value changes
Orientation RadioGroupOrientation Vertical Layout orientation (Vertical or Horizontal)
Loop bool true Whether navigation loops from last to first
Disabled bool false Disable the entire group
Required bool false Whether a selection is required
Name string? null Form field name for hidden input
AriaLabel string? null Accessible label for the group
AriaLabelledBy string? null ID of element that labels the group
AriaDescribedBy string? null ID of element that describes the group

RadioGroupItem

Property Type Default Description
Valuerequired string - Unique value for this radio item
Disabled bool false Disable this specific item
ChildContent RenderFragment<SmRadioGroupItemContext>? - Content with context providing Checked and Disabled state

RadioGroupIndicator

Property Type Default Description
ForceMount bool false Always render in DOM (useful for CSS animations)
ChildContent RenderFragment? - Content to render when checked

Examples

Basic Usage

razor
<SmRadioGroupRoot AriaLabel="Favorite color">
    <SmRadioGroupItem Value="red">
        <SmRadioGroupIndicator />
        <span>Red</span>
    </SmRadioGroupItem>
    <SmRadioGroupItem Value="green">
        <SmRadioGroupIndicator />
        <span>Green</span>
    </SmRadioGroupItem>
    <SmRadioGroupItem Value="blue">
        <SmRadioGroupIndicator />
        <span>Blue</span>
    </SmRadioGroupItem>
</SmRadioGroupRoot>

With Default Value

Set an initial selection using DefaultValue for uncontrolled mode.

razor
<SmRadioGroupRoot DefaultValue="medium" AriaLabel="Select size">
    <SmRadioGroupItem Value="small">
        <SmRadioGroupIndicator />
        <span>Small</span>
    </SmRadioGroupItem>
    <SmRadioGroupItem Value="medium">
        <SmRadioGroupIndicator />
        <span>Medium</span>
    </SmRadioGroupItem>
    <SmRadioGroupItem Value="large">
        <SmRadioGroupIndicator />
        <span>Large</span>
    </SmRadioGroupItem>
</SmRadioGroupRoot>

Controlled Mode

Control the selection state externally with two-way binding.

razor
@code {
    private string? selectedValue = "option1";
}

<SmRadioGroupRoot @bind-Value="selectedValue" AriaLabel="Select option">
    <SmRadioGroupItem Value="option1">
        <SmRadioGroupIndicator />
        <span>Option 1</span>
    </SmRadioGroupItem>
    <SmRadioGroupItem Value="option2">
        <SmRadioGroupIndicator />
        <span>Option 2</span>
    </SmRadioGroupItem>
</SmRadioGroupRoot>

<p>Selected: @selectedValue</p>

Horizontal Orientation

Use horizontal orientation for inline radio groups. Arrow Left/Right navigate between items.

razor
<SmRadioGroupRoot Orientation="RadioGroupOrientation.Horizontal" AriaLabel="Text alignment">
    <SmRadioGroupItem Value="left">
        <SmRadioGroupIndicator />
        <span>Left</span>
    </SmRadioGroupItem>
    <SmRadioGroupItem Value="center">
        <SmRadioGroupIndicator />
        <span>Center</span>
    </SmRadioGroupItem>
    <SmRadioGroupItem Value="right">
        <SmRadioGroupIndicator />
        <span>Right</span>
    </SmRadioGroupItem>
</SmRadioGroupRoot>

Disabled Items

Individual items or the entire group can be disabled.

razor
@* Disable entire group *@
<SmRadioGroupRoot Disabled="true" AriaLabel="Disabled group">
    <SmRadioGroupItem Value="a"><SmRadioGroupIndicator /><span>Option A</span></SmRadioGroupItem>
    <SmRadioGroupItem Value="b"><SmRadioGroupIndicator /><span>Option B</span></SmRadioGroupItem>
</SmRadioGroupRoot>

@* Disable individual items *@
<SmRadioGroupRoot AriaLabel="Partially disabled">
    <SmRadioGroupItem Value="available"><SmRadioGroupIndicator /><span>Available</span></SmRadioGroupItem>
    <SmRadioGroupItem Value="sold-out" Disabled="true"><SmRadioGroupIndicator /><span>Sold Out</span></SmRadioGroupItem>
    <SmRadioGroupItem Value="coming-soon" Disabled="true"><SmRadioGroupIndicator /><span>Coming Soon</span></SmRadioGroupItem>
</SmRadioGroupRoot>

Form Integration

Use the Name property to include the selection in form submissions.

razor
<form method="post">
    <SmRadioGroupRoot Name="subscription" Required="true" AriaLabel="Subscription plan">
        <SmRadioGroupItem Value="monthly">
            <SmRadioGroupIndicator />
            <span>Monthly - $9/month</span>
        </SmRadioGroupItem>
        <SmRadioGroupItem Value="yearly">
            <SmRadioGroupIndicator />
            <span>Yearly - $99/year</span>
        </SmRadioGroupItem>
    </SmRadioGroupRoot>
    <button type="submit">Subscribe</button>
</form>

EditForm Integration

Use with Blazor EditForm for model binding and validation support.

razor
@using System.ComponentModel.DataAnnotations

<EditForm Model="model" OnValidSubmit="HandleSubmit">
    <DataAnnotationsValidator />
    
    <div class="form-group">
        <label>Select a subscription plan:</label>
        <SmRadioGroupRoot @bind-Value="model.Plan" AriaLabel="Subscription plan">
            <SmRadioGroupItem Value="starter" Context="itemContext">
                <SmRadioGroupIndicator />
                <span>Starter - $9/month</span>
            </SmRadioGroupItem>
            <SmRadioGroupItem Value="pro" Context="itemContext">
                <SmRadioGroupIndicator />
                <span>Pro - $29/month</span>
            </SmRadioGroupItem>
            <SmRadioGroupItem Value="enterprise" Context="itemContext">
                <SmRadioGroupIndicator />
                <span>Enterprise - $99/month</span>
            </SmRadioGroupItem>
        </SmRadioGroupRoot>
        <ValidationMessage For="@(() => model.Plan)" />
    </div>
    
    <button type="submit">Subscribe</button>
</EditForm>

@code {
    private FormModel model = new();

    public class FormModel
    {
        [Required(ErrorMessage = "Please select a subscription plan")]
        public string? Plan { get; set; }
    }

    private void HandleSubmit()
    {
        // Handle form submission
    }
}

Styling

Data Attributes

Attribute Values Description
data-summit-radio-group Present on root Identifies the radio group root element
data-summit-radio-group-item Present on items Identifies radio group item elements
data-state "checked" | "unchecked" Current selection state of the item
data-orientation "vertical" | "horizontal" Current orientation of the group/item
data-disabled Present when disabled Indicates disabled state

CSS Example

css
/* Radio group container */
.radio-group {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

.radio-group[data-orientation="horizontal"] {
    flex-direction: row;
}

/* Radio item */
.radio-item {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.5rem;
    border-radius: 0.375rem;
    cursor: pointer;
}

.radio-item[data-disabled] {
    opacity: 0.5;
    cursor: not-allowed;
}

/* Radio indicator (circle) */
.radio-indicator {
    width: 1.25rem;
    height: 1.25rem;
    border: 2px solid #d4d4d8;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: border-color 0.15s ease;
}

/* Hover state on indicator */
.radio-item:hover:not([data-disabled]) .radio-indicator {
    border-color: #0066cc80;
}

/* Focus ring on indicator */
.radio-item:focus-visible .radio-indicator {
    outline: 2px solid #0066cc;
    outline-offset: 2px;
}

.radio-item[data-state="checked"] .radio-indicator {
    border-color: #0066cc;
}

/* Radio dot */
.radio-dot {
    width: 0.625rem;
    height: 0.625rem;
    background-color: #0066cc;
    border-radius: 50%;
}

Accessibility

Keyboard Navigation

Key Action
Tab Moves focus to the selected item, or first item if none selected
Space Selects the focused item
ArrowDown Moves to and selects the next item (vertical orientation)
ArrowUp Moves to and selects the previous item (vertical orientation)
ArrowRight Moves to and selects the next item (horizontal orientation, RTL-aware)
ArrowLeft Moves to and selects the previous item (horizontal orientation, RTL-aware)

ARIA Attributes

  • role: radiogroup on the root element, radio on each item
  • aria-checked: Reflects the current selection state on each item (true or false)
  • aria-orientation: Set on root to indicate vertical or horizontal layout
  • aria-label / aria-labelledby: Provides an accessible name for the group
  • aria-disabled: Set when an item or the group is disabled
  • aria-required: Set when a selection is required

RTL Support

The component automatically detects RTL mode and adjusts horizontal navigation accordingly. In RTL mode, Arrow Right moves to the previous item and Arrow Left moves to the next item.

An unhandled error has occurred. Reload X