UWC Components
  • Default
  • Material
  • Fluent

On this page

RadioButton

A styled radio button with group support, labels, filled/outlined variants, and validation. Radio buttons sharing the same name form a mutually exclusive group.

uwc-radiobutton is a styled radio button. Group several with the same name attribute for mutually exclusive selection. It fires uwc-change with { value } when selected.

Import

All components

import '@uwc/components';

Selected component (Lit / Angular / Vue)

import { UwcRadioButton } from '@uwc/components/radiobutton';
customElements.define('uwc-radiobutton', UwcRadioButton);

React

import { UwcRadioButton } from '@uwc/components/react';

Usage

Lit

import { LitElement, html } from 'lit';
import { customElement, state } from 'lit/decorators.js';

@customElement('app-demo')
export class AppDemo extends LitElement {
  @state() value = '';
  render() {
    return html`
      <uwc-radiobutton name="city" value="NY" label="New York"
        @uwc-change=${(e) => { this.value = e.detail.value; }}></uwc-radiobutton>
      <uwc-radiobutton name="city" value="LA" label="Los Angeles"
        @uwc-change=${(e) => { this.value = e.detail.value; }}></uwc-radiobutton>
    `;
  }
}

React

import React, { useState } from 'react';
import { UwcRadioButton } from '@uwc/components/react';

export default function App() {
  const [value, setValue] = useState('');
  return (
    <>
      <UwcRadioButton name="city" value="NY" label="New York"
        onUwcChange={(e) => setValue(e.detail.value)} />
      <UwcRadioButton name="city" value="LA" label="Los Angeles"
        onUwcChange={(e) => setValue(e.detail.value)} />
    </>
  );
}

Angular

import { Component, signal } from '@angular/core';
import '@uwc/radiobutton';

@Component({
  selector: 'app-root',
  standalone: true,
  template: `
    <uwc-radiobutton name="city" value="NY" label="New York"
      (uwc-change)="value.set($event.detail.value)"></uwc-radiobutton>
    <uwc-radiobutton name="city" value="LA" label="Los Angeles"
      (uwc-change)="value.set($event.detail.value)"></uwc-radiobutton>
  `,
})
export class AppComponent {
  readonly value = signal('');
}

Vue

import '@uwc/radiobutton';

export default {
  data() {
    return { value: '' };
  },
  template: `
    <uwc-radiobutton name="city" value="NY" label="New York"
      @uwc-change="value = $event.detail.value"></uwc-radiobutton>
    <uwc-radiobutton name="city" value="LA" label="Los Angeles"
      @uwc-change="value = $event.detail.value"></uwc-radiobutton>
  `,
};

Basic Usage

import { LitElement, html } from 'lit';
import { customElement } from 'lit/decorators.js';

@customElement('app-demo')
export class AppDemo extends LitElement {
  render() {
    return html`
      <div style="display:flex;gap:1.5rem;flex-wrap:wrap;">
        <uwc-radiobutton name="demo" label="Unchecked"></uwc-radiobutton>
        <uwc-radiobutton name="demo" label="Checked" checked></uwc-radiobutton>
        <uwc-radiobutton name="demo" label="Disabled" disabled></uwc-radiobutton>
      </div>
    `;
  }
}
import React from 'react';
import { UwcRadioButton } from '@uwc/components/react';

export default function App() {
  return (
    <div style={{ display: 'flex', gap: '1.5rem', flexWrap: 'wrap' }}>
      <UwcRadioButton name="demo" label="Unchecked" />
      <UwcRadioButton name="demo" label="Checked" checked />
      <UwcRadioButton name="demo" label="Disabled" disabled />
    </div>
  );
}
import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  standalone: true,
  template: `
    <div style="display:flex;gap:1.5rem;flex-wrap:wrap;">
      <uwc-radiobutton name="demo" label="Unchecked"></uwc-radiobutton>
      <uwc-radiobutton name="demo" label="Checked" checked></uwc-radiobutton>
      <uwc-radiobutton name="demo" label="Disabled" disabled></uwc-radiobutton>
    </div>
  `
})
export class AppComponent {}
export default {
  template: `
    <div style="display:flex;gap:1.5rem;flex-wrap:wrap;">
      <uwc-radiobutton name="demo" label="Unchecked"></uwc-radiobutton>
      <uwc-radiobutton name="demo" label="Checked" checked></uwc-radiobutton>
      <uwc-radiobutton name="demo" label="Disabled" disabled></uwc-radiobutton>
    </div>
  `
};

Basic group

Radio buttons sharing the same name form a mutually exclusive group. Listen to uwc-change on each button to track the selected value.

import { LitElement, html, css } from 'lit';
import { customElement, state } from 'lit/decorators.js';

@customElement('radio-basic-demo')
export class AppDemo extends LitElement {
  static styles = css`
    :host { display: block; }
    .group { display: flex; gap: 1.5rem; flex-wrap: wrap; }
    p { margin: .75rem 0 0; font-size: .875rem; color: #374151; }
    strong { color: #6366f1; }
  `;

  @state() city = '';

  render() {
    return html`
      <div class="group">
        ${['New York', 'London', 'Tokyo', 'Paris'].map(c => html`
          <uwc-radiobutton
            name="city"
            value=${c}
            label=${c}
            ?checked=${this.city === c}
            @uwc-change=${() => { this.city = c; }}>
          </uwc-radiobutton>
        `)}
      </div>
      <p>Selected: <strong>${this.city || 'none'}</strong></p>
    `;
  }
}
import React, { useState } from 'react';
import { UwcRadioButton } from '@uwc/components/react';

export default function App() {
  const [city, setCity] = useState('');
  const cities = ['New York', 'London', 'Tokyo', 'Paris'];
  return (
    <>
      <div style={{ display: 'flex', gap: '1.5rem', flexWrap: 'wrap' }}>
        {cities.map(c => (
          <UwcRadioButton
            key={c}
            name="city"
            value={c}
            label={c}
            checked={city === c}
            onUwcChange={() => setCity(c)}
          />
        ))}
      </div>
      <p style={{ marginTop: '.75rem', fontSize: '.875rem', color: '#374151' }}>
        Selected: <strong style={{ color: '#6366f1' }}>{city || 'none'}</strong>
      </p>
    </>
  );
}
import { Component, signal } from '@angular/core';

@Component({
  selector: 'app-root',
  standalone: true,
  template: `
    <div style="display:flex;gap:1.5rem;flex-wrap:wrap;">
      @for (c of cities; track c) {
        <uwc-radiobutton
          name="city"
          [value]="c"
          [label]="c"
          [checked]="city() === c"
          (uwc-change)="city.set(c)">
        </uwc-radiobutton>
      }
    </div>
    <p style="margin:.75rem 0 0;font-size:.875rem;color:#374151">
      Selected: <strong style="color:#6366f1">{{ city() || 'none' }}</strong>
    </p>
  `
})
export class AppComponent {
  readonly city = signal('');
  cities = ['New York', 'London', 'Tokyo', 'Paris'];
}
export default {
  data() {
    return {
      city: '',
      cities: ['New York', 'London', 'Tokyo', 'Paris'],
    };
  },
  template: `
    <div style="display:flex;gap:1.5rem;flex-wrap:wrap;">
      <uwc-radiobutton
        v-for="c in cities"
        :key="c"
        name="city"
        :value="c"
        :label="c"
        :checked="city === c"
        @uwc-change="city = c">
      </uwc-radiobutton>
    </div>
    <p style="margin:.75rem 0 0;font-size:.875rem;color:#374151">
      Selected: <strong style="color:#6366f1">{{ city || 'none' }}</strong>
    </p>
  `
};

Filled variant

Set variant="filled" for a solid background instead of the default outlined circle.

import { LitElement, html } from 'lit';
import { customElement } from 'lit/decorators.js';

@customElement('radio-filled-demo')
export class AppDemo extends LitElement {
  render() {
    return html`
      <div style="display:flex;gap:2rem;flex-wrap:wrap;">
        <div>
          <p style="margin:0 0 .75rem;font-size:.8rem;font-weight:600;color:#6b7280;text-transform:uppercase;letter-spacing:.05em">Outlined</p>
          <div style="display:flex;flex-direction:column;gap:.75rem;">
            <uwc-radiobutton name="r-out" value="a" label="Option A"></uwc-radiobutton>
            <uwc-radiobutton name="r-out" value="b" label="Option B" checked></uwc-radiobutton>
          </div>
        </div>
        <div>
          <p style="margin:0 0 .75rem;font-size:.8rem;font-weight:600;color:#6b7280;text-transform:uppercase;letter-spacing:.05em">Filled</p>
          <div style="display:flex;flex-direction:column;gap:.75rem;">
            <uwc-radiobutton name="r-fill" value="a" label="Option A" variant="filled"></uwc-radiobutton>
            <uwc-radiobutton name="r-fill" value="b" label="Option B" variant="filled" checked></uwc-radiobutton>
          </div>
        </div>
      </div>
    `;
  }
}
import React from 'react';
import { UwcRadioButton } from '@uwc/components/react';

export default function App() {
  return (
    <div style={{ display: 'flex', gap: '2rem', flexWrap: 'wrap' }}>
      <div>
        <p style={{ margin: '0 0 .75rem', fontSize: '.8rem', fontWeight: 600, color: '#6b7280', textTransform: 'uppercase', letterSpacing: '.05em' }}>Outlined</p>
        <div style={{ display: 'flex', flexDirection: 'column', gap: '.75rem' }}>
          <UwcRadioButton name="r-out" value="a" label="Option A" />
          <UwcRadioButton name="r-out" value="b" label="Option B" checked />
        </div>
      </div>
      <div>
        <p style={{ margin: '0 0 .75rem', fontSize: '.8rem', fontWeight: 600, color: '#6b7280', textTransform: 'uppercase', letterSpacing: '.05em' }}>Filled</p>
        <div style={{ display: 'flex', flexDirection: 'column', gap: '.75rem' }}>
          <UwcRadioButton name="r-fill" value="a" label="Option A" variant="filled" />
          <UwcRadioButton name="r-fill" value="b" label="Option B" variant="filled" checked />
        </div>
      </div>
    </div>
  );
}
import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  standalone: true,
  template: `
    <div style="display:flex;gap:2rem;flex-wrap:wrap;">
      <div>
        <p style="margin:0 0 .75rem;font-size:.8rem;font-weight:600;color:#6b7280;text-transform:uppercase">Outlined</p>
        <div style="display:flex;flex-direction:column;gap:.75rem;">
          <uwc-radiobutton name="r-out" value="a" label="Option A"></uwc-radiobutton>
          <uwc-radiobutton name="r-out" value="b" label="Option B" checked></uwc-radiobutton>
        </div>
      </div>
      <div>
        <p style="margin:0 0 .75rem;font-size:.8rem;font-weight:600;color:#6b7280;text-transform:uppercase">Filled</p>
        <div style="display:flex;flex-direction:column;gap:.75rem;">
          <uwc-radiobutton name="r-fill" value="a" label="Option A" variant="filled"></uwc-radiobutton>
          <uwc-radiobutton name="r-fill" value="b" label="Option B" variant="filled" checked></uwc-radiobutton>
        </div>
      </div>
    </div>
  `
})
export class AppComponent {}
export default {
  template: `
    <div style="display:flex;gap:2rem;flex-wrap:wrap;">
      <div>
        <p style="margin:0 0 .75rem;font-size:.8rem;font-weight:600;color:#6b7280;text-transform:uppercase">Outlined</p>
        <div style="display:flex;flex-direction:column;gap:.75rem;">
          <uwc-radiobutton name="r-out" value="a" label="Option A"></uwc-radiobutton>
          <uwc-radiobutton name="r-out" value="b" label="Option B" checked></uwc-radiobutton>
        </div>
      </div>
      <div>
        <p style="margin:0 0 .75rem;font-size:.8rem;font-weight:600;color:#6b7280;text-transform:uppercase">Filled</p>
        <div style="display:flex;flex-direction:column;gap:.75rem;">
          <uwc-radiobutton name="r-fill" value="a" label="Option A" variant="filled"></uwc-radiobutton>
          <uwc-radiobutton name="r-fill" value="b" label="Option B" variant="filled" checked></uwc-radiobutton>
        </div>
      </div>
    </div>
  `
};

Outlined

Filled

Disabled

Set disabled on a radio button to prevent interaction.

import { LitElement, html } from 'lit';
import { customElement } from 'lit/decorators.js';

@customElement('radio-disabled-demo')
export class AppDemo extends LitElement {
  render() {
    return html`
      <div style="display:flex;gap:1.5rem;flex-wrap:wrap;">
        <uwc-radiobutton name="d" label="Enabled" value="a"></uwc-radiobutton>
        <uwc-radiobutton name="d" label="Disabled" value="b" disabled></uwc-radiobutton>
        <uwc-radiobutton name="d" label="Disabled checked" value="c" disabled checked></uwc-radiobutton>
      </div>
    `;
  }
}
import React from 'react';
import { UwcRadioButton } from '@uwc/components/react';

export default function App() {
  return (
    <div style={{ display: 'flex', gap: '1.5rem', flexWrap: 'wrap' }}>
      <UwcRadioButton name="d" label="Enabled" value="a" />
      <UwcRadioButton name="d" label="Disabled" value="b" disabled />
      <UwcRadioButton name="d" label="Disabled checked" value="c" disabled checked />
    </div>
  );
}
import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  standalone: true,
  template: `
    <div style="display:flex;gap:1.5rem;flex-wrap:wrap;">
      <uwc-radiobutton name="d" label="Enabled" value="a"></uwc-radiobutton>
      <uwc-radiobutton name="d" label="Disabled" value="b" disabled></uwc-radiobutton>
      <uwc-radiobutton name="d" label="Disabled checked" value="c" disabled checked></uwc-radiobutton>
    </div>
  `
})
export class AppComponent {}
export default {
  template: `
    <div style="display:flex;gap:1.5rem;flex-wrap:wrap;">
      <uwc-radiobutton name="d" label="Enabled" value="a"></uwc-radiobutton>
      <uwc-radiobutton name="d" label="Disabled" value="b" disabled></uwc-radiobutton>
      <uwc-radiobutton name="d" label="Disabled checked" value="c" disabled checked></uwc-radiobutton>
    </div>
  `
};

Attributes

Name Type Default Description
checked Whether this radio is selected.
value Value for this option.
name Group name — radio buttons with same name form a group.
label Label text rendered beside the radio.
disabled Disable the radio button.
invalid Mark as invalid (red border).
variant outlined | filled. Default: outlined.

Properties

Name Type Default Description
styles CSSResultGroup [styles]
checked boolean false
value string | undefined
name string | undefined
label string | undefined
disabled boolean false
invalid boolean false
variant RadioButtonVariant 'outlined'

Slots

Name Description
default Custom label content (overrides label attr).

Events

Name Type Description
uwc-change CustomEvent Fired when this radio becomes selected. Detail: { value }.

CSS Custom Properties

Name Default Description
--uwc-radio-size Circle size. Default: 1.125rem.
--uwc-radio-bg Background color (unchecked).
--uwc-radio-color Accent color for dot and border.
--uwc-radio-label-color Label text color.
--uwc-radio-font-size Label font size.

CSS Parts

Name Description
circle The visual circle.
label The label element.