Use radio button groups when users must choose one option from a set of 2-5. Use radio buttons in modals where users confirm decisions before changes take effect.
Use icon radio button groups when icons clearly communicate the options.
Use radio buttons to enable conditional inputs. For options that enable 1-3 inputs, disable the inputs until users select the radio buttons. For options that enable more inputs, hide the inputs until users select the radio buttons. If all options in a radio button group enable conditional inputs or significantly change the workflow, consider using action buttons instead. See the form layout guidelines for more information.
Don't use radio buttons when users must choose from more than five items. Use a different selection input instead.
Don't use radio buttons for two options that are exact opposites. Use a checkbox instead.
Don't use radio buttons when user selections significantly alter the workflow. Use action buttons instead, and place them at the beginning of the task.
By default, the labels for radio button groups aren't treated as HTML headings. To emphasize a label as an HTML heading in a form hierarchy, you can use headingLevel
headingStyle
In rare cases, you can hide radio button group label text and use other text to present the radio buttons.
In rare cases, you can make a radio button group required and leave every option unselected to force users to select an option. When a radio button group is required, a red asterisk appears to the right of the radio group label. It includes the appropriate ARIA attributes to support users of assistive technologies. For more information about required fields, see the form design guidelines.
You can't make individual radio buttons required.
When you need to supplement a radio button or radio button group label with additional information but don't require persistent inline help, you can place a help inline button beside the label to invoke contextual user assistance.
To highlight important considerations about a radio button or radio button group, use hint text. This persistent inline help can explain details such as:
Radio button groups automatically add vertical spacing between individual radio buttons. For consistent vertical spacing when a radio button group is immediately followed by another form input, use stacked
Don't use stacked
If a radio button group uses headingLevel
stacked
Make radio button group labels succinct and descriptive. In most cases, use nouns or noun phrases. When necessary, radio button group labels can use short sentences or sentence fragments.
For details about styling radio button group labels as headings, see the "Headings" section above.
Similarly, make radio button labels succinct and descriptive. But when necessary, radio button labels can use short sentences or sentence fragments.
Icon radio buttons use the icon component. For a list of common icons, see the SKY UX icon inventory. Don't display heading text or label text on icon radio button groups.
Don't wrap a radio button group inside a field group component if the radio button group is the only content.
In this example, “Payment processing mode” should be the heading of the radio button group, with headingLevel
headingStyle
Radio button groups will automatically create <fieldset>
<legend>
In most cases, radio button group labels are not treated as semantic h
headingLevel
3
headingStyle
sky-font-heading-3
SkyRadioModule
@skyux/forms
npm install --save-exact @skyux/forms
Organizes radio buttons into a group. It is required for radio
buttons on Angular reactive forms, and we recommend using it with all radio buttons.
On Angular forms, the component manages the selected values and keeps the forms up-to-date.
When users select a radio button, its value is driven through an ngModel
attribute that you specify on the sky-radio-group
element.
sky-radio-group
Input | Description |
---|---|
name: string | Danger: Required. The name for the collection of radio buttons that the component groups together.
This property overwrites the deprecated |
| Deprecated. Use The ARIA label for the radio button group. This sets the
radio button group's Optional. |
| Deprecated. Use The HTML element ID of the element that labels
the radio button group. This sets the radio button group's Optional. |
disabled?: boolean | Whether to disable the input on template-driven forms. Don't use this input on reactive forms because they may overwrite the input or leave the control out of sync.
To set the disabled state on reactive forms, use the Optional. Default is false |
headingHidden?: boolean | Indicates whether to hide the Optional. Default is false |
headingLevel?: SkyRadioGroupHeadingLevel | The semantic heading level in the document structure. By default, the heading text is not wrapped in a heading element. Optional. |
headingStyle?: SkyRadioGroupHeadingStyle | The heading font style. Optional. Default is 4 |
headingText?: string | The text to display as the radio group's heading. Optional. |
helpKey?: string | A help key that identifies the global help content to display. When specified, a help inline
button is placed beside the radio group heading. Clicking the button invokes global help
as configured by the application. This property only applies when Optional. |
helpPopoverContent?: string | TemplateRef<unknown> | The content of the help popover. When specified along with Optional. |
helpPopoverTitle?: string | The title of the help popover. This property only applies when Optional. |
hintText?: string | Persistent inline help text that provides additional context to the user. Optional. |
required?: boolean | Whether the input is required for form validation.
When you set this property to Optional. Default is false |
stacked?: boolean | Whether the radio button group is stacked on another form component. When specified, the appropriate vertical spacing is automatically added to the radio button group. Optional. |
tabIndex?: number | The index for all the radio buttons in the group. If the index is not defined, the indices for individual radio buttons are set to their positions on load. This property supports accessibility by placing focus on the currently selected radio button. If no radio button is selected, it places focus on the first or last button depending on how users navigate to the radio button group. Optional. |
value?: any | The value of the radio button to select by default when the group loads.
The value corresponds to the Optional. |
Renders a SKY UX-themed replacement for an HTML input
element
with type="radio"
. When users select a radio button, its value is driven through an
ngModel
attribute that you specify on the sky-radio
element or the parent sky-radio-group
element.
sky-radio
Input | Description |
---|---|
value: any | Danger: Required. The value bound to the radio button's |
checked?: boolean | Whether the radio button is selected. Optional. Default is false |
disabled?: boolean | Whether to disable the input on template-driven forms. Don't use this input on reactive forms because they may overwrite the input or leave the control out of sync.
To set the disabled state on reactive forms, use the Optional. Default is false |
helpKey?: string | A help key that identifies the global help content to display. When specified, a help inline
button is placed beside the radio button label. Clicking the button invokes global help
as configured by the application. This property only applies when Optional. |
helpPopoverContent?: string | TemplateRef<unknown> | The content of the help popover. When specified along with Optional. |
helpPopoverTitle?: string | The title of the help popover. This property only applies when Optional. |
hintText?: string | Persistent inline help text that provides additional context to the user. Optional. |
icon?: string | The icon to display in place of the radio button. To group radio buttons like in
the demo above, place the Optional. |
id?: string | The ID for the radio button. If a value is not provided, an autogenerated ID is used. Optional. |
| Deprecated. Use The ARIA label for the radio button. This sets the radio button's Optional. |
labelHidden?: boolean | Indicates whether to hide the Optional. Default is false |
labelText?: string | The text to display as the radio button's label. Use this instead of the Optional. |
| Deprecated. Use The HTML element ID of the element that labels
the radio button. This sets the radio button's Optional. |
| Deprecated. This property is deprecated in favor of the Optional. |
| Deprecated. radioType is no longer supported The background color type after users select an icon radio button.
The valid options correspond
the label component's
label types. Optional. Default is "info" |
| Deprecated. This property is deprecated in favor of
the Optional. |
Event | Description |
---|---|
change: EventEmitter<SkyRadioChange> | Fires when users select a radio button. |
checkedChange: EventEmitter<boolean> | Fires when the selected value changes. |
disabledChange: EventEmitter<boolean> | Fires when the selected value changes. |
Displays default and custom form field error messages for form field components.
Set labelText
on the form field component to automatically display required,
maximum length, minimum length, date, email, phone number, time, and URL errors.
To display custom errors, include sky-form-error elements in the form field component.
sky-form-error
Input | Description |
---|---|
errorName: string | Danger: Required. The name of the error. |
errorText: string | Danger: Required. The error message to display. |
<div class="sky-padding-even-lg">
<form [formGroup]="formGroup">
<sky-radio-group
formControlName="paymentMethod"
headingLevel="4"
headingText="Payment method"
[helpPopoverContent]="helpPopoverContent"
[helpPopoverTitle]="helpPopoverTitle"
[hintText]="hintText"
>
<ul class="sky-list-unstyled">
<li *ngFor="let option of paymentOptions">
<sky-radio
[disabled]="option.disabled"
[value]="option.value"
[labelText]="option.name"
[helpPopoverContent]="option.helpContent"
[hintText]="option.hintText"
/>
</li>
</ul>
<sky-form-error
*ngIf="paymentMethod.errors?.['processingIssue']"
errorName="processingIssue"
errorText="An error occurred with this payment method. Please contact us to resolve."
/>
</sky-radio-group>
</form>
</div>
import { CommonModule } from '@angular/common';
import { Component, inject } from '@angular/core';
import {
AbstractControl,
FormBuilder,
FormControl,
FormGroup,
FormsModule,
ReactiveFormsModule,
ValidationErrors,
} from '@angular/forms';
import { SkyRadioModule } from '@skyux/forms';
interface DemoForm {
paymentMethod: FormControl<string | null>;
}
interface Item {
name: string;
value: string;
disabled?: boolean;
hintText?: string;
helpContent?: string;
}
function validatePaymentMethod(
control: AbstractControl,
): ValidationErrors | null {
return control.value === 'check' ? { processingIssue: true } : null;
}
@Component({
standalone: true,
selector: 'app-demo',
templateUrl: './demo.component.html',
imports: [CommonModule, FormsModule, ReactiveFormsModule, SkyRadioModule],
})
export class DemoComponent {
protected formGroup: FormGroup<DemoForm>;
protected helpPopoverContent =
"We don't charge fees for any payment method. The only exception is when credit card payments are late, which incurs a 2% fee.";
protected helpPopoverTitle = 'Are there fees?';
protected hintText = 'Card methods require proof of identification.';
protected paymentMethod: FormControl<string | null>;
protected paymentOptions: Item[] = [
{
name: 'Cash',
value: 'cash',
helpContent:
'We accept cash at any of our locations and affiliated partners.',
},
{ name: 'Check', value: 'check' },
{ name: 'Apple pay', value: 'apple', disabled: true },
{
name: 'Credit',
value: 'credit',
hintText: 'A 2% late fee is applied to payments made after the due date.',
},
{ name: 'Debit', value: 'debit' },
];
readonly #formBuilder = inject(FormBuilder);
constructor() {
this.paymentMethod = this.#formBuilder.control(
this.paymentOptions[0].name,
{
validators: [validatePaymentMethod],
},
);
this.formGroup = this.#formBuilder.group({
paymentMethod: this.paymentMethod,
});
}
}
<div class="sky-padding-even-lg">
<form [formGroup]="formGroup">
<sky-radio-group
class="sky-switch-icon-group"
formControlName="myView"
headingHidden="true"
headingText="View"
>
<sky-radio
*ngFor="let view of views"
[icon]="view.icon"
[labelHidden]="true"
[labelText]="view.label"
[value]="view.name"
/>
</sky-radio-group>
</form>
</div>
import { CommonModule } from '@angular/common';
import { Component, inject } from '@angular/core';
import {
FormBuilder,
FormGroup,
FormsModule,
ReactiveFormsModule,
} from '@angular/forms';
import { SkyRadioModule } from '@skyux/forms';
interface Item {
icon: string;
label: string;
name: string;
}
@Component({
standalone: true,
selector: 'app-demo',
templateUrl: './demo.component.html',
imports: [CommonModule, FormsModule, ReactiveFormsModule, SkyRadioModule],
})
export class DemoComponent {
protected formGroup: FormGroup;
protected views: Item[] = [
{ icon: 'table', label: 'Table', name: 'table' },
{ icon: 'list', label: 'List', name: 'list' },
{ icon: 'map-marker', label: 'Map', name: 'map' },
];
constructor() {
this.formGroup = inject(FormBuilder).group({
myView: this.views[0].name,
});
}
}