UWC Components
  • Default
  • Material
  • Fluent

On this page

ToggleSwitch

An animated toggle switch (InputSwitch) for boolean values with label, three sizes, and validation support.

uwc-toggleswitch is an animated toggle switch for selecting boolean values. It supports a label, three sizes (small, medium, large), and fires uwc-change with { checked } on every toggle.

Import

All components

import '@uwc/components';

Selected component (Lit / Angular / Vue)

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

React

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

Usage

Lit

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

@customElement('app-demo')
export class AppDemo extends LitElement {
  render() {
    return html`
      <uwc-toggleswitch
        label="Notifications"
        @uwc-change=${(e) => console.log(e.detail.checked)}>
      </uwc-toggleswitch>
    `;
  }
}

React

import React from 'react';
import { UwcToggleSwitch } from '@uwc/components/react';

export default function App() {
  return (
    <UwcToggleSwitch
      label="Notifications"
      onUwcChange={(e) => console.log(e.detail.checked)}
    />
  );
}

Angular

import { Component } from '@angular/core';
import '@uwc/toggleswitch';

@Component({
  selector: 'app-root',
  standalone: true,
  template: `
    <uwc-toggleswitch
      label="Notifications"
      (uwc-change)="onToggle($event)">
    </uwc-toggleswitch>
  `,
})
export class AppComponent {
  onToggle(e: CustomEvent) { console.log(e.detail.checked); }
}

Vue

import '@uwc/toggleswitch';

export default {
  template: `
    <uwc-toggleswitch
      label="Notifications"
      @uwc-change="onToggle">
    </uwc-toggleswitch>
  `,
  methods: {
    onToggle(e) { console.log(e.detail.checked); },
  },
};

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;align-items:center;">
        <uwc-toggleswitch label="Off"></uwc-toggleswitch>
        <uwc-toggleswitch label="On" checked></uwc-toggleswitch>
        <uwc-toggleswitch label="Disabled" disabled></uwc-toggleswitch>
      </div>
    `;
  }
}
import React from 'react';
import { UwcToggleSwitch } from '@uwc/components/react';

export default function App() {
  return (
    <div style={{ display: 'flex', gap: '1.5rem', flexWrap: 'wrap', alignItems: 'center' }}>
      <UwcToggleSwitch label="Off" />
      <UwcToggleSwitch label="On" checked />
      <UwcToggleSwitch 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;align-items:center;">
      <uwc-toggleswitch label="Off"></uwc-toggleswitch>
      <uwc-toggleswitch label="On" checked></uwc-toggleswitch>
      <uwc-toggleswitch label="Disabled" disabled></uwc-toggleswitch>
    </div>
  `
})
export class AppComponent {}
export default {
  template: `
    <div style="display:flex;gap:1.5rem;flex-wrap:wrap;align-items:center;">
      <uwc-toggleswitch label="Off"></uwc-toggleswitch>
      <uwc-toggleswitch label="On" checked></uwc-toggleswitch>
      <uwc-toggleswitch label="Disabled" disabled></uwc-toggleswitch>
    </div>
  `
};

Basic

Toggle the switch to flip the boolean state. Listen to uwc-change for { checked }.

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

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

  @state() checked = false;

  render() {
    return html`
      <uwc-toggleswitch
        label="Notifications"
        ?checked=${this.checked}
        @uwc-change=${(e) => { this.checked = e.detail.checked; }}>
      </uwc-toggleswitch>
      <p>State: <strong>${this.checked ? 'on' : 'off'}</strong></p>
    `;
  }
}
import React, { useState } from 'react';
import { UwcToggleSwitch } from '@uwc/components/react';

export default function App() {
  const [checked, setChecked] = useState(false);
  return (
    <>
      <UwcToggleSwitch
        label="Notifications"
        checked={checked}
        onUwcChange={(e) => setChecked(e.detail.checked)}
      />
      <p style={{ marginTop: '.75rem', fontSize: '.875rem', color: '#374151' }}>
        State: <strong style={{ color: '#6366f1' }}>{checked ? 'on' : 'off'}</strong>
      </p>
    </>
  );
}
import { Component, signal } from '@angular/core';

@Component({
  selector: 'app-root',
  standalone: true,
  template: `
    <uwc-toggleswitch
      label="Notifications"
      [checked]="checked()"
      (uwc-change)="checked.set($event.detail.checked)">
    </uwc-toggleswitch>
    <p style="margin:.75rem 0 0;font-size:.875rem;color:#374151">
      State: <strong style="color:#6366f1">{{ checked() ? 'on' : 'off' }}</strong>
    </p>
  `
})
export class AppComponent {
  readonly checked = signal(false);
}
export default {
  data() {
    return { checked: false };
  },
  template: `
    <uwc-toggleswitch
      label="Notifications"
      :checked="checked"
      @uwc-change="checked = $event.detail.checked">
    </uwc-toggleswitch>
    <p style="margin:.75rem 0 0;font-size:.875rem;color:#374151">
      State: <strong style="color:#6366f1">{{ checked ? 'on' : 'off' }}</strong>
    </p>
  `
};

Sizes

Use size for small, medium (default), or large variants.

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

@customElement('toggleswitch-sizes-demo')
export class AppDemo extends LitElement {
  render() {
    return html`
      <div style="display:flex;gap:1.5rem;align-items:center;flex-wrap:wrap;">
        <uwc-toggleswitch size="small"  label="Small"  checked></uwc-toggleswitch>
        <uwc-toggleswitch size="medium" label="Medium" checked></uwc-toggleswitch>
        <uwc-toggleswitch size="large"  label="Large"  checked></uwc-toggleswitch>
      </div>
    `;
  }
}
import React from 'react';
import { UwcToggleSwitch } from '@uwc/components/react';

export default function App() {
  return (
    <div style={{ display: 'flex', gap: '1.5rem', alignItems: 'center', flexWrap: 'wrap' }}>
      <UwcToggleSwitch size="small"  label="Small"  checked />
      <UwcToggleSwitch size="medium" label="Medium" checked />
      <UwcToggleSwitch size="large"  label="Large"  checked />
    </div>
  );
}
import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  standalone: true,
  template: `
    <div style="display:flex;gap:1.5rem;align-items:center;flex-wrap:wrap;">
      <uwc-toggleswitch size="small"  label="Small"  checked></uwc-toggleswitch>
      <uwc-toggleswitch size="medium" label="Medium" checked></uwc-toggleswitch>
      <uwc-toggleswitch size="large"  label="Large"  checked></uwc-toggleswitch>
    </div>
  `
})
export class AppComponent {}
export default {
  template: `
    <div style="display:flex;gap:1.5rem;align-items:center;flex-wrap:wrap;">
      <uwc-toggleswitch size="small"  label="Small"  checked></uwc-toggleswitch>
      <uwc-toggleswitch size="medium" label="Medium" checked></uwc-toggleswitch>
      <uwc-toggleswitch size="large"  label="Large"  checked></uwc-toggleswitch>
    </div>
  `
};

Settings panel

Combine multiple switches to build a real-world settings form.

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

@customElement('toggleswitch-settings-demo')
export class AppDemo extends LitElement {
  static styles = css`
    :host { display: block; max-width: 320px; }
    .row { display: flex; justify-content: space-between; align-items: center; padding: .75rem 0; border-bottom: 1px solid #e5e7eb; }
    .row:last-child { border-bottom: none; }
    .label { font-size: .875rem; color: #374151; }
    .sublabel { font-size: .75rem; color: #9ca3af; margin-top: .125rem; }
  `;

  @state() settings = { email: true, push: false, sms: false };

  render() {
    return html`
      <div class="row">
        <div><div class="label">Email notifications</div><div class="sublabel">Daily digest</div></div>
        <uwc-toggleswitch ?checked=${this.settings.email} @uwc-change=${(e) => { this.settings = {...this.settings, email: e.detail.checked}; }}></uwc-toggleswitch>
      </div>
      <div class="row">
        <div><div class="label">Push notifications</div><div class="sublabel">Real-time alerts</div></div>
        <uwc-toggleswitch ?checked=${this.settings.push} @uwc-change=${(e) => { this.settings = {...this.settings, push: e.detail.checked}; }}></uwc-toggleswitch>
      </div>
      <div class="row">
        <div><div class="label">SMS notifications</div><div class="sublabel">Text messages</div></div>
        <uwc-toggleswitch ?checked=${this.settings.sms} @uwc-change=${(e) => { this.settings = {...this.settings, sms: e.detail.checked}; }}></uwc-toggleswitch>
      </div>
    `;
  }
}
import React, { useState } from 'react';
import { UwcToggleSwitch } from '@uwc/components/react';

export default function App() {
  const [settings, setSettings] = useState({ email: true, push: false, sms: false });
  const toggle = (key) => (e) => setSettings(s => ({ ...s, [key]: e.detail.checked }));
  const rowStyle = { display: 'flex', justifyContent: 'space-between', alignItems: 'center', padding: '.75rem 0', borderBottom: '1px solid #e5e7eb' };
  return (
    <div style={{ maxWidth: '320px' }}>
      {[
        { key: 'email', label: 'Email notifications',  sub: 'Daily digest'    },
        { key: 'push',  label: 'Push notifications',   sub: 'Real-time alerts' },
        { key: 'sms',   label: 'SMS notifications',    sub: 'Text messages'   },
      ].map(({ key, label, sub }, i, arr) => (
        <div key={key} style={{ ...rowStyle, borderBottom: i < arr.length - 1 ? '1px solid #e5e7eb' : 'none' }}>
          <div>
            <div style={{ fontSize: '.875rem', color: '#374151' }}>{label}</div>
            <div style={{ fontSize: '.75rem', color: '#9ca3af', marginTop: '.125rem' }}>{sub}</div>
          </div>
          <UwcToggleSwitch checked={settings[key]} onUwcChange={toggle(key)} />
        </div>
      ))}
    </div>
  );
}
import { Component, signal } from '@angular/core';

@Component({
  selector: 'app-root',
  standalone: true,
  template: `
    <div style="max-width:320px;">
      @for (item of items; track item.key; let last = $last) {
        <div style="display:flex;justify-content:space-between;align-items:center;padding:.75rem 0;"
             [style.border-bottom]="last ? 'none' : '1px solid #e5e7eb'">
          <div>
            <div style="font-size:.875rem;color:#374151">{{ item.label }}</div>
            <div style="font-size:.75rem;color:#9ca3af;margin-top:.125rem">{{ item.sub }}</div>
          </div>
          <uwc-toggleswitch [checked]="settings()[item.key]"
            (uwc-change)="toggle(item.key, $event.detail.checked)">
          </uwc-toggleswitch>
        </div>
      }
    </div>
  `
})
export class AppComponent {
  readonly settings = signal<Record<string, boolean>>({ email: true, push: false, sms: false });
  items = [
    { key: 'email', label: 'Email notifications',  sub: 'Daily digest'    },
    { key: 'push',  label: 'Push notifications',   sub: 'Real-time alerts' },
    { key: 'sms',   label: 'SMS notifications',    sub: 'Text messages'   },
  ];
  toggle(key: string, value: boolean) {
    this.settings.set({ ...this.settings(), [key]: value });
  }
}
export default {
  data() {
    return {
      settings: { email: true, push: false, sms: false },
      items: [
        { key: 'email', label: 'Email notifications',  sub: 'Daily digest'    },
        { key: 'push',  label: 'Push notifications',   sub: 'Real-time alerts' },
        { key: 'sms',   label: 'SMS notifications',    sub: 'Text messages'   },
      ],
    };
  },
  methods: {
    toggle(key, e) { this.settings[key] = e.detail.checked; },
  },
  template: `
    <div style="max-width:320px;">
      <div v-for="(item, i) in items" :key="item.key"
           style="display:flex;justify-content:space-between;align-items:center;padding:.75rem 0;"
           :style="{ borderBottom: i < items.length - 1 ? '1px solid #e5e7eb' : 'none' }">
        <div>
          <div style="font-size:.875rem;color:#374151">{{ item.label }}</div>
          <div style="font-size:.75rem;color:#9ca3af;margin-top:.125rem">{{ item.sub }}</div>
        </div>
        <uwc-toggleswitch :checked="settings[item.key]"
          @uwc-change="toggle(item.key, $event)">
        </uwc-toggleswitch>
      </div>
    </div>
  `
};

Disabled

Set disabled to block interaction.

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

@customElement('toggleswitch-disabled-demo')
export class AppDemo extends LitElement {
  render() {
    return html`
      <div style="display:flex;gap:1.5rem;align-items:center;flex-wrap:wrap;">
        <uwc-toggleswitch label="Disabled off" disabled></uwc-toggleswitch>
        <uwc-toggleswitch label="Disabled on" checked disabled></uwc-toggleswitch>
      </div>
    `;
  }
}
import React from 'react';
import { UwcToggleSwitch } from '@uwc/components/react';

export default function App() {
  return (
    <div style={{ display: 'flex', gap: '1.5rem', alignItems: 'center', flexWrap: 'wrap' }}>
      <UwcToggleSwitch label="Disabled off" disabled />
      <UwcToggleSwitch label="Disabled on" checked disabled />
    </div>
  );
}
import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  standalone: true,
  template: `
    <div style="display:flex;gap:1.5rem;align-items:center;flex-wrap:wrap;">
      <uwc-toggleswitch label="Disabled off" disabled></uwc-toggleswitch>
      <uwc-toggleswitch label="Disabled on" checked disabled></uwc-toggleswitch>
    </div>
  `
})
export class AppComponent {}
export default {
  template: `
    <div style="display:flex;gap:1.5rem;align-items:center;flex-wrap:wrap;">
      <uwc-toggleswitch label="Disabled off" disabled></uwc-toggleswitch>
      <uwc-toggleswitch label="Disabled on" checked disabled></uwc-toggleswitch>
    </div>
  `
};

Attributes

Name Type Default Description
checked Whether the switch is on.
label Label text rendered beside the switch.
size small | medium | large. Default: medium.
disabled Disable the switch.
invalid Mark as invalid.
name Name for form submission.

Properties

Name Type Default Description
styles CSSResultGroup [styles]
checked boolean false
label string | undefined
name string | undefined
size ToggleSwitchSize 'medium'
disabled boolean false
invalid boolean false

Slots

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

Events

Name Type Description
uwc-change CustomEvent Fired when the switch is toggled. Detail: { checked }.

CSS Custom Properties

Name Default Description
--uwc-switch-width Track width. Default: 2.75rem.
--uwc-switch-height Track height. Default: 1.5rem.
--uwc-switch-bg-off Track color when off. Default: #d1d5db.
--uwc-switch-bg-on Track color when on. Default: primary.
--uwc-switch-radius Track border radius. Default: full pill.

CSS Parts

Name Description
track The switch track.
dot The sliding thumb.
label The label element.