v17

Radio Group

A component that allows the user to select one of several choices. Multiple radio buttons grouped together.

Tori Day
Epic Crazy Designer
Ishaan Martinez
Natural Born Computer-Human
Alvin Bailey
Common Layer
import { Component } from '@angular/core';
import {
  HeadwindRadioButtonComponent,
  HeadwindRadioComponent,
  HeadwindRadioGroupComponent,
  HeadwindRadioSelectedDirective,
} from '@favian/headwind-ui';
import { animate, state, style, transition, trigger } from '@angular/animations';

@Component({
  selector: 'app-basic-radio-group-example',
  standalone: true,
  imports: [
    HeadwindRadioComponent,
    HeadwindRadioGroupComponent,
    HeadwindRadioButtonComponent,
    HeadwindRadioSelectedDirective,
  ],
  template: `
    <div class="w-full max-w-[400px] space-y-2 rounded-2xl bg-white p-8 shadow-xl">
      <label class="text-lg font-semibold"> Choose your partner </label>

      <headwind-radio-group class="block space-y-2">
        @for (option of options; track option.name) {
          <headwind-radio
            #radio
            [value]="option.name"
            class="flex cursor-pointer select-none items-center justify-between rounded-md border border-zinc-200 p-3 transition-colors hover:bg-rose-50"
          >
            <div>
              <div class="text-sm font-semibold">
                {{ option.name }}
              </div>

              <div class="text-xs text-zinc-400">
                {{ option.description }}
              </div>
            </div>

            <headwind-radio-button
              class="relative flex h-5 w-5 items-center justify-center rounded-full border border-zinc-300 transition-colors"
            >
              <ng-template headwindRadioSelected>
                <div [@scaleUp] class="absolute h-2 w-2 rounded-full bg-rose-500"></div>
              </ng-template>
            </headwind-radio-button>
          </headwind-radio>
        }
      </headwind-radio-group>
    </div>
  `,
  styles: [
    `
      @tailwind components;

      @layer components {
        .headwind-radio-group:focus {
          .headwind-radio.headwind-selected {
            .headwind-radio-button {
              @apply bg-rose-100;
            }
          }
        }

        .headwind-radio.headwind-selected {
          .headwind-radio-button {
            @apply border-rose-500;
          }
        }
      }
    `,
  ],
  animations: [
    trigger('scaleUp', [
      state(
        'void',
        style({
          transform: 'scale(0)',
        }),
      ),
      transition(
        'void => *',
        animate(
          '.1s',
          style({
            transform: 'scale(1)',
          }),
        ),
      ),
      transition('* => void', animate('.1s')),
    ]),
  ],
})
export class BasicRadioGroupExampleComponent {
  options = [
    {
      name: 'Tori Day',
      description: 'Epic Crazy Designer',
    },
    {
      name: 'Ishaan Martinez',
      description: 'Natural Born Computer-Human',
    },
    {
      name: 'Alvin Bailey',
      description: 'Common Layer',
    },
  ];
}

Radio Group Classes

Basic Classes

Each component used to implement Radio Group has the same class name as its name. You can set styles using the class name as a selector in a style file.

Tori Day
Ishaan Martinez
Alvin Bailey
import { Component } from '@angular/core';
import {
  HeadwindRadioButtonComponent,
  HeadwindRadioComponent,
  HeadwindRadioGroupComponent,
  HeadwindRadioSelectedDirective,
} from '@favian/headwind-ui';

@Component({
  selector: 'app-radio-group-classes-example',
  standalone: true,
  imports: [
    HeadwindRadioGroupComponent,
    HeadwindRadioComponent,
    HeadwindRadioButtonComponent,
    HeadwindRadioSelectedDirective,
  ],
  template: `
    <headwind-radio-group>
      @for (option of options; track option) {
        <headwind-radio [value]="option">
          <headwind-radio-button>
            <ng-template headwindRadioSelected>
              <div class="absolute h-2 w-2 rounded-full bg-rose-500"></div>
            </ng-template>
          </headwind-radio-button>

          <div class="text-sm">
            {{ option }}
          </div>
        </headwind-radio>
      }
    </headwind-radio-group>
  `,
  styles: [
    `
      @tailwind components;

      @layer components {
        .headwind-radio-group {
          @apply block w-full max-w-[300px] space-y-2 rounded-xl bg-white p-6 shadow-xl;
        }

        .headwind-radio {
          @apply flex cursor-pointer select-none items-center space-x-2;
        }

        .headwind-radio-button {
          @apply relative flex h-5 w-5 items-center justify-center rounded-full border border-zinc-300;
        }
      }
    `,
  ],
})
export class RadioGroupClassesExampleComponent {
  options = ['Tori Day', 'Ishaan Martinez', 'Alvin Bailey'];
}

Selected Class

When a Radio is selected, the <headwind-radio> component has the class .headwind-selected.

Tori Day
Ishaan Martinez
Alvin Bailey
import { Component } from '@angular/core';
import {
  HeadwindRadioButtonComponent,
  HeadwindRadioComponent,
  HeadwindRadioGroupComponent,
  HeadwindRadioSelectedDirective,
} from '@favian/headwind-ui';

@Component({
  selector: 'app-radio-group-selected-class-example',
  standalone: true,
  imports: [
    HeadwindRadioGroupComponent,
    HeadwindRadioComponent,
    HeadwindRadioButtonComponent,
    HeadwindRadioSelectedDirective,
  ],
  template: `
    <headwind-radio-group>
      @for (option of options; track option) {
        <headwind-radio [value]="option">
          <headwind-radio-button>
            <ng-template headwindRadioSelected>
              <div class="absolute h-2 w-2 rounded-full bg-rose-500"></div>
            </ng-template>
          </headwind-radio-button>

          <div class="text-sm">
            {{ option }}
          </div>
        </headwind-radio>
      }
    </headwind-radio-group>
  `,
  styles: [
    `
      @tailwind components;

      @layer components {
        .headwind-radio-group {
          @apply block w-full max-w-[300px] space-y-2 rounded-xl bg-white p-6 shadow-xl;
        }

        .headwind-radio {
          @apply flex cursor-pointer select-none items-center space-x-2;

          &.headwind-selected {
            .headwind-radio-button {
              @apply border-rose-500;
            }
          }
        }

        .headwind-radio-button {
          @apply relative flex h-5 w-5 items-center justify-center rounded-full border border-zinc-300;
        }
      }
    `,
  ],
})
export class RadioGroupSelectedClassExampleComponent {
  options = ['Tori Day', 'Ishaan Martinez', 'Alvin Bailey'];
}

Value

Radio Group can bind value to property using value input and valueChange output.

Selected Value: Ishaan Martinez
Tori Day
Ishaan Martinez
Alvin Bailey
import { Component } from '@angular/core';
import {
  HeadwindRadioButtonComponent,
  HeadwindRadioComponent,
  HeadwindRadioGroupComponent,
  HeadwindRadioSelectedDirective,
} from '@favian/headwind-ui';

@Component({
  selector: 'app-radio-group-value-example',
  standalone: true,
  imports: [
    HeadwindRadioGroupComponent,
    HeadwindRadioComponent,
    HeadwindRadioButtonComponent,
    HeadwindRadioSelectedDirective,
  ],
  template: `
    <div class="w-full max-w-[300px] space-y-2">
      <div class="text-sm">Selected Value: {{ value }}</div>

      <headwind-radio-group [(value)]="value" class="block space-y-2 rounded-xl bg-white p-6 shadow-xl">
        @for (option of options; track option) {
          <headwind-radio [value]="option" class="flex cursor-pointer select-none items-center space-x-2">
            <headwind-radio-button
              class="relative flex h-5 w-5 items-center justify-center rounded-full border border-zinc-300"
            >
              <ng-template headwindRadioSelected>
                <div class="absolute h-2 w-2 rounded-full bg-rose-500"></div>
              </ng-template>
            </headwind-radio-button>

            <div class="text-sm">
              {{ option }}
            </div>
          </headwind-radio>
        }
      </headwind-radio-group>
    </div>
  `,
})
export class RadioGroupValueExampleComponent {
  value = 'Ishaan Martinez';

  options = ['Tori Day', 'Ishaan Martinez', 'Alvin Bailey'];
}

NgModel, FormControl

The <headwind-radio-group> component can bind value using NgModel or FormControl.

Selected NgModel: Ishaan Martinez
Tori Day
Ishaan Martinez
Alvin Bailey
Selected FormControl: Tori Day
Tori Day
Ishaan Martinez
Alvin Bailey
import { Component } from '@angular/core';
import {
  HeadwindRadioButtonComponent,
  HeadwindRadioComponent,
  HeadwindRadioGroupComponent,
  HeadwindRadioSelectedDirective,
} from '@favian/headwind-ui';
import { FormControl, FormsModule, ReactiveFormsModule } from '@angular/forms';

@Component({
  selector: 'app-radio-group-model-binding-example',
  standalone: true,
  imports: [
    HeadwindRadioGroupComponent,
    HeadwindRadioComponent,
    HeadwindRadioButtonComponent,
    HeadwindRadioSelectedDirective,
    FormsModule,
    ReactiveFormsModule,
  ],
  template: `
    <div class="w-full max-w-[300px] space-y-2">
      <div class="text-sm">Selected NgModel: {{ value }}</div>

      <headwind-radio-group [(ngModel)]="value" class="block space-y-2 rounded-xl bg-white p-6 shadow-xl">
        @for (option of options; track option) {
          <headwind-radio [value]="option" class="flex cursor-pointer select-none items-center space-x-2">
            <headwind-radio-button
              class="relative flex h-5 w-5 items-center justify-center rounded-full border border-zinc-300"
            >
              <ng-template headwindRadioSelected>
                <div class="absolute h-2 w-2 rounded-full bg-rose-500"></div>
              </ng-template>
            </headwind-radio-button>

            <div class="text-sm">
              {{ option }}
            </div>
          </headwind-radio>
        }
      </headwind-radio-group>

      <div class="text-sm">Selected FormControl: {{ formControl.value }}</div>

      <headwind-radio-group [formControl]="formControl" class="block space-y-2 rounded-xl bg-white p-6 shadow-xl">
        @for (option of options; track option) {
          <headwind-radio [value]="option" class="flex cursor-pointer select-none items-center space-x-2">
            <headwind-radio-button
              class="relative flex h-5 w-5 items-center justify-center rounded-full border border-zinc-300"
            >
              <ng-template headwindRadioSelected>
                <div class="absolute h-2 w-2 rounded-full bg-rose-500"></div>
              </ng-template>
            </headwind-radio-button>

            <div class="text-sm">
              {{ option }}
            </div>
          </headwind-radio>
        }
      </headwind-radio-group>
    </div>
  `,
})
export class RadioGroupModelBindingExampleComponent {
  value = 'Ishaan Martinez';
  formControl = new FormControl('Tori Day');

  options = ['Tori Day', 'Ishaan Martinez', 'Alvin Bailey'];
}

Disabled State

Setting the disabled attribute will disable the Radio Group. Styling for the disabled state uses the [disabled] CSS selector instead of :disabled.

Tori Day
Ishaan Martinez
Alvin Bailey
import { Component } from '@angular/core';
import {
  HeadwindRadioButtonComponent,
  HeadwindRadioComponent,
  HeadwindRadioGroupComponent,
  HeadwindRadioSelectedDirective,
} from '@favian/headwind-ui';

@Component({
  selector: 'app-radio-group-disabled-example',
  standalone: true,
  imports: [
    HeadwindRadioGroupComponent,
    HeadwindRadioComponent,
    HeadwindRadioButtonComponent,
    HeadwindRadioSelectedDirective,
  ],
  template: `
    <headwind-radio-group
      value="Tori Day"
      disabled
      class="block w-full max-w-[300px] space-y-2 rounded-xl bg-white p-6 shadow-xl"
    >
      @for (option of options; track option) {
        <headwind-radio [value]="option" class="flex cursor-pointer select-none items-center space-x-2">
          <headwind-radio-button
            class="relative flex h-5 w-5 items-center justify-center rounded-full border border-zinc-300"
          >
            <ng-template headwindRadioSelected>
              <div class="selected absolute h-2 w-2 rounded-full bg-rose-500"></div>
            </ng-template>
          </headwind-radio-button>

          <div class="label text-sm">
            {{ option }}
          </div>
        </headwind-radio>
      }
    </headwind-radio-group>
  `,
  styles: [
    `
      @tailwind components;

      @layer components {
        .headwind-radio-group[disabled] {
          .headwind-radio {
            @apply cursor-not-allowed;
          }

          .headwind-radio-button {
            @apply bg-zinc-100;

            .selected {
              @apply bg-zinc-300;
            }
          }

          .label {
            @apply text-zinc-300;
          }
        }
      }
    `,
  ],
})
export class RadioGroupDisabledExampleComponent {
  options = ['Tori Day', 'Ishaan Martinez', 'Alvin Bailey'];
}

Animation

Bind an animation trigger to the content of [headwindRadioSelected] to play animation when selected state is toggled.

Tori Day
Ishaan Martinez
Alvin Bailey
import { Component } from '@angular/core';
import {
  HeadwindRadioButtonComponent,
  HeadwindRadioComponent,
  HeadwindRadioGroupComponent,
  HeadwindRadioSelectedDirective,
} from '@favian/headwind-ui';
import { animate, state, style, transition, trigger } from '@angular/animations';

@Component({
  selector: 'app-radio-group-animation-example',
  standalone: true,
  imports: [
    HeadwindRadioGroupComponent,
    HeadwindRadioComponent,
    HeadwindRadioButtonComponent,
    HeadwindRadioSelectedDirective,
  ],
  template: `
    <headwind-radio-group class="block w-full max-w-[300px] space-y-2 rounded-xl bg-white p-6 shadow-xl">
      @for (option of options; track option) {
        <headwind-radio [value]="option" class="flex cursor-pointer select-none items-center space-x-2">
          <headwind-radio-button
            class="relative flex h-5 w-5 items-center justify-center rounded-full border border-zinc-300"
          >
            <ng-template headwindRadioSelected>
              <div [@scaleUp] class="absolute h-2 w-2 rounded-full bg-rose-500"></div>
            </ng-template>
          </headwind-radio-button>

          <div class="text-sm">
            {{ option }}
          </div>
        </headwind-radio>
      }
    </headwind-radio-group>
  `,
  animations: [
    trigger('scaleUp', [
      state(
        'void',
        style({
          transform: 'scale(0)',
        }),
      ),
      transition(
        'void => *',
        animate(
          '.1s',
          style({
            transform: 'scale(1)',
          }),
        ),
      ),
      transition('* => void', animate('.1s')),
    ]),
  ],
})
export class RadioGroupAnimationExampleComponent {
  options = ['Tori Day', 'Ishaan Martinez', 'Alvin Bailey'];
}

Accessibility

Mouse Interaction

Clicking on <headwind-radio> selects the option.

Keyboard Interaction

Command Target Description
ArrowDown, ArrowRight <headwind-radio-group> Select the next option.
ArrowUp, ArrowLeft <headwind-radio-group> Select the previous option.

API

HeadwindRadioGroupComponent

A component containing multiple <headwind-radio>.

Selector

<headwind-radio-group>

Host Class

.headwind-radio-group

Inputs

Name Description
@Input() set value(value: any) Set the selected value of Radio Group.
@Input() set disabled(value: boolean) Set the disabled state of Radio Group.

Outputs

Name Description
@Output() valueChange: EventEmitter<any> Emits the changed value of Radio Group.

Methods

Name Description
toPreviousOption() Select the previous option.
toNextOption() Select the next option.

HeadwindRadioComponent

Components for selectable radio options. Must be used with <headwind-radio-button>

Selector

<headwind-radio>

Host Class

.headwind-radio<br/> .headwind-selected when Radio selected.

Inputs

Name Description
@Input() value: any Set the value of Radio option.

Properties

Name Description
get selected(): boolean Selected state of radio.

HeadwindRadioButtonComponent

Radio button to display selected state.

Selector

&lt;headwind-radio-button&gt;

Host Class

.headwind-radio-button

HeadwindRadioSelectedDirective

A directive for a template that wraps a selected indicator.

Selector

[headwindRadioSelected]