Toggle
This library is a work-in-progress. We are releasing it early to gather feedback, but it is not ready for production.
The Toggle component provides an accessible binary switch for on/off states, implementing the WAI-ARIA Switch pattern.
Examples
Live Preview
Default Toggles
Sizes
Variants
Interactive Examples
Demonstrates event handling with @toggle-change and v-model:checked
Notifications: Disabled
Dark mode: Off
Form data: name="", value="", checked=false
Labels, Helper Text, and Validation
The Toggle component supports labels, helper text, required fields, and validation states.
Label Positioning
Control label position with label-position: 'top' (default), 'start', 'end', or 'bottom'.
CSS Shadow Parts Customization
View Vue Code
<template>
<section>
<div class="mbe2">
<h2>Default Toggles</h2>
</div>
<div class="stacked-mobile mbe4">
<VueToggle label="Default toggle" />
<VueToggle
label="Checked by default"
:checked="true"
/>
<VueToggle
label="Disabled"
disabled
/>
<VueToggle
label="Disabled and checked"
:checked="true"
disabled
/>
</div>
<div class="mbe2">
<h2>Sizes</h2>
</div>
<div class="stacked-mobile mbe4">
<VueToggle
label="Extra small"
size="xs"
/>
<VueToggle
label="Small"
size="sm"
/>
<VueToggle
label="Medium (default)"
size="md"
/>
<VueToggle
label="Large"
size="lg"
/>
<VueToggle
label="Extra large"
size="xl"
/>
</div>
<div class="mbe2">
<h2>Variants</h2>
</div>
<div class="stacked-mobile mbe4">
<VueToggle
label="Default variant"
:checked="true"
/>
<VueToggle
label="Success"
variant="success"
:checked="true"
/>
<VueToggle
label="Warning"
variant="warning"
:checked="true"
/>
<VueToggle
label="Danger"
variant="danger"
:checked="true"
/>
<VueToggle
label="Monochrome"
variant="monochrome"
:checked="true"
/>
</div>
<div class="mbe2">
<h2>Interactive Examples</h2>
<p class="mbs2 mbe3">
Demonstrates event handling with @toggle-change and v-model:checked
</p>
</div>
<div class="stacked-mobile mbe4">
<!-- Pattern 1: @toggle-change event -->
<div>
<VueToggle
label="Notifications (@toggle-change)"
:checked="notificationsEnabled"
@toggle-change="handleToggleChange"
/>
<p style="margin-top: 0.5rem">
Notifications: <strong>{{ notificationsEnabled ? 'Enabled' : 'Disabled' }}</strong>
</p>
</div>
<!-- Pattern 2: v-model:checked (two-way binding) -->
<div>
<VueToggle
label="Dark Mode (v-model:checked)"
v-model:checked="darkModeEnabled"
/>
<p style="margin-top: 0.5rem">
Dark mode: <strong>{{ darkModeEnabled ? 'On' : 'Off' }}</strong>
</p>
</div>
<!-- Pattern 3: Form integration with event detail -->
<div>
<VueToggle
label="Newsletter Subscription"
name="newsletter"
value="subscribed"
:checked="formData.newsletter"
@toggle-change="handleFormToggle"
/>
<p style="margin-top: 0.5rem; font-size: 0.875rem; color: var(--ag-text-secondary);">
Form data: name="{{ formData.name }}", value="{{ formData.value }}", checked={{ formData.newsletter }}
</p>
</div>
</div>
<div class="mbe4 flex justify-center">
<VueButton
@click="darkModeEnabled = !darkModeEnabled"
mode="primary"
size="small"
>
Toggle above programmatically
</VueButton>
</div>
<div class="mbe4">
<h2>Labels, Helper Text, and Validation</h2>
<p class="mbs2 mbe3">
The Toggle component supports labels, helper text, required fields, and validation states.
</p>
</div>
<div
class="mbe4"
style="max-width: 600px;"
>
<div class="mbe3">
<VueToggle label="Enable notifications" />
</div>
<div class="mbe3">
<VueToggle
label="Dark mode"
help-text="Reduces eye strain in low-light environments"
/>
</div>
<div class="mbe3">
<VueToggle
label="Two-factor authentication"
:required="true"
help-text="This setting is required for account security"
/>
</div>
<div class="mbe3">
<VueToggle
label="Email notifications"
:required="true"
:invalid="true"
error-message="You must enable email notifications to continue"
/>
</div>
</div>
<div class="mbe4">
<h2>Label Positioning</h2>
<p class="mbs2 mbe3">
Control label position with <code>label-position</code>: 'top' (default), 'start', 'end', or 'bottom'.
</p>
</div>
<div
class="mbe4"
style="max-width: 600px;"
>
<div class="mbe3">
<VueToggle
label="Top Label (Default)"
label-position="top"
/>
</div>
<div class="mbe3">
<VueToggle
label="Start Position"
label-position="start"
/>
</div>
<div class="mbe3">
<VueToggle
label="End Position"
label-position="end"
/>
</div>
<div class="mbe3">
<VueToggle
label="Bottom Position"
label-position="bottom"
help-text="Bottom label position for alternative layouts"
/>
</div>
</div>
<div class="mbe2">
<h2>CSS Shadow Parts Customization</h2>
</div>
<div class="stacked-mobile mbe4">
<div v-html="customToggleStyles"></div>
<VueToggle
class="custom-toggle"
label="Customized Toggle"
:checked="true"
/>
</div>
</section>
</template>
<script>
import VueToggle from "agnosticui-core/toggle/vue";
import VueButton from "agnosticui-core/button/vue";
export default {
name: "ToggleExamples",
components: { VueToggle, VueButton },
data() {
return {
notificationsEnabled: false,
darkModeEnabled: false,
formData: {
newsletter: false,
name: "",
value: "",
},
customToggleStyles: `
<style>
.custom-toggle::part(ag-toggle-button) {
border: 2px solid var(--ag-coral-50);
border-radius: 9999px;
padding: var(--ag-space-2) var(--ag-space-3);
}
.custom-toggle::part(ag-toggle-track) {
background-color: #f0f0f0;
}
.custom-toggle::part(ag-toggle-handle) {
background-color: var(--ag-coral-200);
border: 2px solid #fff;
box-shadow: 0 0 5px var(--ag-coral-200);
}
.custom-toggle[checked]::part(ag-toggle-track) {
background-color:var(--ag-coral-300);
}
.custom-toggle[checked]::part(ag-toggle-handle) {
background-color: #fff;
}
</style>
`,
};
},
methods: {
handleToggleChange(event) {
this.notificationsEnabled = event.checked;
console.log("Toggle changed:", event);
},
handleFormToggle(event) {
this.formData.newsletter = event.checked;
this.formData.name = event.name;
this.formData.value = event.value;
console.log("Form toggle changed:", event);
},
},
};
</script>
Live Preview
View Lit / Web Component Code
import { LitElement, html } from 'lit';
import 'agnosticui-core/toggle';
import 'agnosticui-core/button';
export class ToggleLitExamples extends LitElement {
createRenderRoot() {
return this;
}
static get properties() {
return {
notificationsEnabled: { type: Boolean, state: true },
darkModeEnabled: { type: Boolean, state: true },
formData: { type: Object, state: true },
};
}
constructor() {
super();
this.notificationsEnabled = false;
this.darkModeEnabled = false;
this.formData = {
newsletter: false,
name: "",
value: "",
};
this.customToggleStyles = html`
<style>
.custom-toggle::part(ag-toggle-button) {
border: 2px solid var(--ag-coral-50);
border-radius: 9999px;
padding: var(--ag-space-2) var(--ag-space-3);
}
.custom-toggle::part(ag-toggle-track) {
background-color: #f0f0f0;
}
.custom-toggle::part(ag-toggle-handle) {
background-color: var(--ag-coral-200);
border: 2px solid #fff;
box-shadow: 0 0 5px var(--ag-coral-200);
}
.custom-toggle[checked]::part(ag-toggle-track) {
background-color: var(--ag-coral-300);
}
.custom-toggle[checked]::part(ag-toggle-handle) {
background-color: #fff;
}
</style>
`;
}
handleToggleChange(event) {
this.notificationsEnabled = event.detail.checked;
console.log("Toggle changed:", event.detail);
}
handleDarkModeToggle(event) {
this.darkModeEnabled = event.detail.checked;
}
handleFormToggle(event) {
this.formData = {
newsletter: event.detail.checked,
name: event.detail.name,
value: event.detail.value,
};
console.log("Form toggle changed:", event.detail);
}
toggleDarkModeProgrammatically() {
this.darkModeEnabled = !this.darkModeEnabled;
}
render() {
return html`
<section>
<div class="mbe2">
<h2>Default Toggles</h2>
</div>
<div class="stacked-mobile mbe4">
<ag-toggle label="Default toggle"></ag-toggle>
<ag-toggle label="Checked by default" checked></ag-toggle>
<ag-toggle label="Disabled" disabled></ag-toggle>
<ag-toggle label="Disabled and checked" checked disabled></ag-toggle>
</div>
<div class="mbe2">
<h2>Sizes</h2>
</div>
<div class="stacked-mobile mbe4">
<ag-toggle label="Extra small" size="xs"></ag-toggle>
<ag-toggle label="Small" size="sm"></ag-toggle>
<ag-toggle label="Medium (default)" size="md"></ag-toggle>
<ag-toggle label="Large" size="lg"></ag-toggle>
<ag-toggle label="Extra large" size="xl"></ag-toggle>
</div>
<div class="mbe2">
<h2>Variants</h2>
</div>
<div class="stacked-mobile mbe4">
<ag-toggle label="Default variant" checked></ag-toggle>
<ag-toggle label="Success" variant="success" checked></ag-toggle>
<ag-toggle label="Warning" variant="warning" checked></ag-toggle>
<ag-toggle label="Danger" variant="danger" checked></ag-toggle>
<ag-toggle label="Monochrome" variant="monochrome" checked></ag-toggle>
</div>
<div class="mbe2">
<h2>Interactive Examples</h2>
<p class="mbs2 mbe3">
Demonstrates event handling with @toggle-change.
</p>
</div>
<div class="stacked-mobile mbe4">
<div>
<ag-toggle
label="Notifications (@toggle-change)"
.checked=${this.notificationsEnabled}
@toggle-change=${this.handleToggleChange}
></ag-toggle>
<p style="margin-top: 0.5rem">
Notifications: <strong>${this.notificationsEnabled ? 'Enabled' : 'Disabled'}</strong>
</p>
</div>
<div>
<ag-toggle
label="Dark Mode"
.checked=${this.darkModeEnabled}
@toggle-change=${this.handleDarkModeToggle}
></ag-toggle>
<p style="margin-top: 0.5rem">
Dark mode: <strong>${this.darkModeEnabled ? 'On' : 'Off'}</strong>
</p>
</div>
<div>
<ag-toggle
label="Newsletter Subscription"
name="newsletter"
value="subscribed"
.checked=${this.formData.newsletter}
@toggle-change=${this.handleFormToggle}
></ag-toggle>
<p style="margin-top: 0.5rem; font-size: 0.875rem; color: var(--ag-text-secondary);">
Form data: name="${this.formData.name}", value="${this.formData.value}", checked=${this.formData.newsletter}
</p>
</div>
</div>
<div class="mbe4 flex justify-center">
<ag-button
@click=${this.toggleDarkModeProgrammatically}
mode="primary"
size="small"
>
Toggle above programmatically
</ag-button>
</div>
<div class="mbe4">
<h2>Labels, Helper Text, and Validation</h2>
<p class="mbs2 mbe3">
The Toggle component supports labels, helper text, required fields, and validation states.
</p>
</div>
<div class="mbe4" style="max-width: 600px;">
<div class="mbe3">
<ag-toggle label="Enable notifications"></ag-toggle>
</div>
<div class="mbe3">
<ag-toggle
label="Dark mode"
help-text="Reduces eye strain in low-light environments"
></ag-toggle>
</div>
<div class="mbe3">
<ag-toggle
label="Two-factor authentication"
required
help-text="This setting is required for account security"
></ag-toggle>
</div>
<div class="mbe3">
<ag-toggle
label="Email notifications"
required
invalid
error-message="You must enable email notifications to continue"
></ag-toggle>
</div>
</div>
<div class="mbe4">
<h2>Label Positioning</h2>
<p class="mbs2 mbe3">
Control label position with <code>label-position</code>: 'top' (default), 'start', 'end', or 'bottom'.
</p>
</div>
<div class="mbe4" style="max-width: 600px;">
<div class="mbe3">
<ag-toggle label="Top Label (Default)" label-position="top"></ag-toggle>
</div>
<div class="mbe3">
<ag-toggle label="Start Position" label-position="start"></ag-toggle>
</div>
<div class="mbe3">
<ag-toggle label="End Position" label-position="end"></ag-toggle>
</div>
<div class="mbe3">
<ag-toggle
label="Bottom Position"
label-position="bottom"
help-text="Bottom label position for alternative layouts"
></ag-toggle>
</div>
</div>
<div class="mbe2">
<h2>CSS Shadow Parts Customization</h2>
</div>
<div class="stacked-mobile mbe4">
${this.customToggleStyles}
<ag-toggle
class="custom-toggle"
label="Customized Toggle"
checked
></ag-toggle>
</div>
</section>
`;
}
}
customElements.define('toggle-lit-examples', ToggleLitExamples);
Interactive Preview: Click the "Open in StackBlitz" button below to see this example running live in an interactive playground.
View React Code
import { useState } from "react";
import { ReactToggle } from "agnosticui-core/toggle/react";
import { ReactButton } from "agnosticui-core/button/react";
export default function ToggleReactExamples() {
const [notificationsEnabled, setNotificationsEnabled] = useState(false);
const [darkModeEnabled, setDarkModeEnabled] = useState(false);
const [formData, setFormData] = useState({
newsletter: false,
name: "",
value: "",
});
const handleToggleChange = (event) => {
setNotificationsEnabled(event.checked);
console.log("Toggle changed:", event);
};
const handleFormToggle = (event) => {
setFormData({
newsletter: event.checked,
name: event.name,
value: event.value,
});
console.log("Form toggle changed:", event);
};
const customToggleStyles = `
<style>
.custom-toggle::part(ag-toggle-button) {
border: 2px solid var(--ag-coral-50);
border-radius: 9999px;
padding: var(--ag-space-2) var(--ag-space-3);
}
.custom-toggle::part(ag-toggle-track) {
background-color: #f0f0f0;
}
.custom-toggle::part(ag-toggle-handle) {
background-color: var(--ag-coral-200);
border: 2px solid #fff;
box-shadow: 0 0 5px var(--ag-coral-200);
}
.custom-toggle[checked]::part(ag-toggle-track) {
background-color:var(--ag-coral-300);
}
.custom-toggle[checked]::part(ag-toggle-handle) {
background-color: #fff;
}
</style>
`;
return (
<section>
<div className="mbe2">
<h2>Default Toggles</h2>
</div>
<div className="stacked-mobile mbe4">
<ReactToggle label="Default toggle" />
<ReactToggle
label="Checked by default"
checked={true}
/>
<ReactToggle
label="Disabled"
disabled
/>
<ReactToggle
label="Disabled and checked"
checked={true}
disabled
/>
</div>
<div className="mbe2">
<h2>Sizes</h2>
</div>
<div className="stacked-mobile mbe4">
<ReactToggle
label="Extra small"
size="xs"
/>
<ReactToggle
label="Small"
size="sm"
/>
<ReactToggle
label="Medium (default)"
size="md"
/>
<ReactToggle
label="Large"
size="lg"
/>
<ReactToggle
label="Extra large"
size="xl"
/>
</div>
<div className="mbe2">
<h2>Variants</h2>
</div>
<div className="stacked-mobile mbe4">
<ReactToggle
label="Default variant"
checked={true}
/>
<ReactToggle
label="Success"
variant="success"
checked={true}
/>
<ReactToggle
label="Warning"
variant="warning"
checked={true}
/>
<ReactToggle
label="Danger"
variant="danger"
checked={true}
/>
<ReactToggle
label="Monochrome"
variant="monochrome"
checked={true}
/>
</div>
<div className="mbe2">
<h2>Interactive Examples</h2>
<p className="mbs2 mbe3">
Demonstrates event handling with onToggleChange.
</p>
</div>
<div className="stacked-mobile mbe4">
<div>
<ReactToggle
label="Notifications (onToggleChange)"
checked={notificationsEnabled}
onToggleChange={handleToggleChange}
/>
<p style={{ marginTop: "0.5rem" }}>
Notifications: <strong>{notificationsEnabled ? 'Enabled' : 'Disabled'}</strong>
</p>
</div>
<div>
<ReactToggle
label="Dark Mode"
checked={darkModeEnabled}
onToggleChange={(e) => setDarkModeEnabled(e.checked)}
/>
<p style={{ marginTop: "0.5rem" }}>
Dark mode: <strong>{darkModeEnabled ? 'On' : 'Off'}</strong>
</p>
</div>
<div>
<ReactToggle
label="Newsletter Subscription"
name="newsletter"
value="subscribed"
checked={formData.newsletter}
onToggleChange={handleFormToggle}
/>
<p style={{ marginTop: "0.5rem", fontSize: "0.875rem", color: "var(--ag-text-secondary)" }}>
Form data: name="{formData.name}", value="{formData.value}", checked={String(formData.newsletter)}
</p>
</div>
</div>
<div className="mbe4 flex justify-center">
<ReactButton
onClick={() => setDarkModeEnabled(!darkModeEnabled)}
mode="primary"
size="small"
>
Toggle above programmatically
</ReactButton>
</div>
<div className="mbe4">
<h2>Labels, Helper Text, and Validation</h2>
<p className="mbs2 mbe3">
The Toggle component supports labels, helper text, required fields, and validation states.
</p>
</div>
<div
className="mbe4"
style={{ maxWidth: "600px" }}
>
<div className="mbe3">
<ReactToggle label="Enable notifications" />
</div>
<div className="mbe3">
<ReactToggle
label="Dark mode"
helpText="Reduces eye strain in low-light environments"
/>
</div>
<div className="mbe3">
<ReactToggle
label="Two-factor authentication"
required={true}
helpText="This setting is required for account security"
/>
</div>
<div className="mbe3">
<ReactToggle
label="Email notifications"
required={true}
invalid={true}
errorMessage="You must enable email notifications to continue"
/>
</div>
</div>
<div className="mbe4">
<h2>Label Positioning</h2>
<p className="mbs2 mbe3">
Control label position with <code>labelPosition</code>: 'top' (default), 'start', 'end', or 'bottom'.
</p>
</div>
<div
className="mbe4"
style={{ maxWidth: "600px" }}
>
<div className="mbe3">
<ReactToggle
label="Top Label (Default)"
labelPosition="top"
/>
</div>
<div className="mbe3">
<ReactToggle
label="Start Position"
labelPosition="start"
/>
</div>
<div className="mbe3">
<ReactToggle
label="End Position"
labelPosition="end"
/>
</div>
<div className="mbe3">
<ReactToggle
label="Bottom Position"
labelPosition="bottom"
helpText="Bottom label position for alternative layouts"
/>
</div>
</div>
<div className="mbe2">
<h2>CSS Shadow Parts Customization</h2>
</div>
<div className="stacked-mobile mbe4">
<div dangerouslySetInnerHTML={{ __html: customToggleStyles }}></div>
<ReactToggle
className="custom-toggle"
label="Customized Toggle"
checked={true}
/>
</div>
</section>
);
}
Props
| Prop | Type | Default | Description |
|---|---|---|---|
label | string | '' | Label text for the toggle |
labelPosition | 'top' | 'start' | 'end' | 'bottom' | 'top' | Position of the label relative to the toggle |
labelHidden | boolean | false | Visually hide the label (still accessible to screen readers) |
noLabel | boolean | false | Remove label completely |
checked | boolean | false | Whether the toggle is checked/on |
size | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'md' | Size of the toggle switch |
variant | 'default' | 'success' | 'warning' | 'danger' | 'monochrome' | 'default' | Color variant when checked |
disabled | boolean | false | Whether the toggle is disabled |
readonly | boolean | false | Toggle appears interactive but cannot be changed |
required | boolean | false | Required field indicator |
invalid | boolean | false | Invalid state for validation feedback |
errorMessage | string | '' | Error message text displayed when invalid |
helpText | string | '' | Helper text displayed below toggle |
name | string | '' | Name for form integration |
value | string | '' | Value when toggle is checked (for forms) |
Events
| Event | Framework | Detail | Description |
|---|---|---|---|
click | Vue: @clickReact: onClickLit: @click | MouseEvent | Fired when the toggle is clicked. |
toggle-change | Vue: @toggle-changeReact: onToggleChangeLit: @toggle-change | { checked: boolean, name: string, value: string } | Fired when toggle state changes. Contains the new checked state and form integration data. |
Note: The Toggle component supports dual-dispatch event propagation: it dispatches both DOM CustomEvents (usable with addEventListener) and invokes callback props (.onToggleChange), giving you flexibility in how you handle events.
Type:
export type ToggleChangeEvent = CustomEvent<ToggleChangeEventDetail>;
export interface ToggleChangeEventDetail {
checked: boolean; // New checked state
name: string; // Form name (if provided)
value: string; // Form value (if provided)
}Event Handling Patterns
Lit / Web Components
// Pattern 1: addEventListener (DOM event)
const toggle = document.querySelector('ag-toggle');
toggle.addEventListener('toggle-change', (e) => {
console.log('Checked:', e.detail.checked);
console.log('Form name:', e.detail.name);
console.log('Form value:', e.detail.value);
});
// Pattern 2: Callback prop
html`<ag-toggle
label="Enable feature"
.onToggleChange=${(e: CustomEvent) => {
console.log('Callback fired:', e.detail);
}}
></ag-toggle>`
// Pattern 3: Both (dual-dispatch)
html`<ag-toggle
label="With both"
@toggle-change=${(e) => console.log('DOM event')}
.onToggleChange=${(e) => console.log('Callback')}
></ag-toggle>`React
import { ReactToggle } from 'agnosticui-core/toggle/react';
// React automatically maps toggle-change to onToggleChange
<ReactToggle
label="Enable notifications"
onToggleChange={(e) => {
console.log('Checked:', e.detail.checked);
console.log('Name:', e.detail.name);
console.log('Value:', e.detail.value);
}}
onClick={(e) => {
console.log('Native click also available:', e);
}}
/>Vue
<template>
<!-- Pattern 1: @toggle-change event -->
<VueToggle
label="Enable feature"
@toggle-change="handleToggle"
/>
<!-- Pattern 2: v-model:checked (two-way binding) -->
<VueToggle
label="Dark mode"
v-model:checked="isDarkMode"
/>
<!-- Pattern 3: Both together -->
<VueToggle
label="With both"
v-model:checked="isEnabled"
@toggle-change="handleToggle"
/>
</template>
<script setup>
import { ref } from 'vue';
const isDarkMode = ref(false);
const isEnabled = ref(false);
// Event emits detail object (not full CustomEvent)
const handleToggle = (detail) => {
console.log('Checked:', detail.checked);
console.log('Name:', detail.name);
console.log('Value:', detail.value);
};
</script>Event Detail Structure
The toggle-change event provides the following detail payload:
interface ToggleChangeEventDetail {
checked: boolean; // New checked state
name: string; // Form name (if provided)
value: string; // Form value (if provided)
}Accessibility
The Toggle component implements the WAI-ARIA Switch pattern:
- Uses semantic
<button>element withrole="switch" - Communicates state via
aria-checked - Requires accessible name via
labeloraria-labelprop - Keyboard accessible (Space/Enter to toggle)
- Screen reader announces "On"/"Off" state
- Minimum 44px touch target for mobile accessibility
- Clear focus indicators for keyboard navigation
Form Integration
Use the name and value props to integrate with forms:
Vue
<template>
<form @submit.prevent="handleSubmit">
<VueToggle
label="Subscribe to newsletter"
name="newsletter"
value="yes"
:checked="formData.newsletter"
@toggle-change="handleChange"
/>
<VueButton type="submit">Submit</VueButton>
</form>
</template>
<script>
export default {
data() {
return {
formData: {
newsletter: false,
},
};
},
methods: {
handleChange(event) {
this.formData.newsletter = event.checked;
},
handleSubmit() {
console.log('Submit:', this.formData);
},
},
};
</script>React
import { useState } from 'react';
export default function Form() {
const [formData, setFormData] = useState({ newsletter: false });
const handleChange = (event: CustomEvent) => {
setFormData({ newsletter: event.detail.checked });
};
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
console.log('Submit:', formData);
};
return (
<form onSubmit={handleSubmit}>
<ReactToggle
label="Subscribe to newsletter"
name="newsletter"
value="yes"
checked={formData.newsletter}
onToggleChange={handleChange}
/>
<button type="submit">Submit</button>
</form>
);
}Lit (Web Components)
<form id="myForm">
<ag-toggle
id="newsletter-toggle"
label="Subscribe to newsletter"
name="newsletter"
value="yes"
></ag-toggle>
<button type="submit">Submit</button>
</form>
<script type="module">
let formData = { newsletter: false };
const toggle = document.querySelector('#newsletter-toggle');
toggle?.addEventListener('toggle-change', (event) => {
formData.newsletter = event.detail.checked;
});
document.querySelector('#myForm')?.addEventListener('submit', (e) => {
e.preventDefault();
console.log('Submit:', formData);
});
</script>CSS Shadow Parts
| Part | Description |
|---|---|
ag-toggle-button | The main button element for the toggle. |
ag-toggle-track | The track of the toggle switch. |
ag-toggle-handle | The handle of the toggle switch. |
Example
.custom-toggle::part(ag-toggle-button) {
border: 2px solid #bada55;
border-radius: 9999px;
}
.custom-toggle::part(ag-toggle-track) {
background-color: #f0f0f0;
}
.custom-toggle::part(ag-toggle-handle) {
background-color: #bada55;
border: 2px solid #fff;
box-shadow: 0 0 5px #bada55;
}
.custom-toggle[checked]::part(ag-toggle-track) {
background-color: #bada55;
}
.custom-toggle[checked]::part(ag-toggle-handle) {
background-color: #fff;
}