# RadioGroup
> A set of checkable buttons where only one can be checked at a time.
The RadioGroup component is part of SummitUI, a Blazor component library focused on WCAG-compliant, fully customizable headless components.
## 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
Option 1
Option 2
```
## 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 | - | Callback when selected value changes |
| OnValueChange | EventCallback | - | 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 |
|----------|------|---------|-------------|
| Value | string | required | Unique value for this radio item |
| Disabled | bool | false | Disable this specific item |
| ChildContent | RenderFragment? | - | 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
Red
Green
Blue
```
### With Default Value
Set an initial selection using DefaultValue for uncontrolled mode.
```razor
Small
Medium
Large
```
### Controlled Mode
Control the selection state externally with two-way binding.
```razor
@code {
private string? selectedValue = "option1";
}
Option 1
Option 2
Selected: @selectedValue
```
### Horizontal Orientation
Use horizontal orientation for inline radio groups. Arrow Left/Right navigate between items.
```razor
Left
Center
Right
```
### Disabled Items
Individual items or the entire group can be disabled.
```razor
@* Disable entire group *@
Option A
Option B
@* Disable individual items *@
Available
Sold Out
Coming Soon
```
### Form Integration
Use the Name property to include the selection in form submissions.
```razor
```
## 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:hover {
background-color: #f5f5f5;
}
.radio-item:focus-visible {
outline: 2px solid #0066cc;
outline-offset: 2px;
}
.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;
}
.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.