> Markdown version of [Switch](https://vaadin.com/docs/next/components/switch). Section index: [llms.txt](https://vaadin.com/docs/next/components/llms.txt)

# Switch (since V25.3)

Switch is an input field for toggling a single setting on or off.

**Lit** — `switch-basic.ts`

```html
<vaadin-switch label="Notifications"></vaadin-switch>
```

**Flow** — `SwitchBasic.java`

```java
Switch notifications = new Switch("Notifications");

add(notifications);
```

**React** — `switch-basic.tsx`

```tsx
<Switch label="Notifications" />
```

A Switch presents a single setting as a track with a sliding marker. It’s toggled by clicking the graphic or the label, or by pressing `Space` while it’s focused, and it defaults to off when no value is set.

## <a id="when-to-use"></a>When to Use

Use a Switch to show whether a setting, feature, or mode is on — "Notifications", "Autosave", "Two-factor authentication". Its state is meaningful on its own, independently of the other fields on the page, and users expect toggling it to take effect immediately.

Use a [Checkbox](https://vaadin.com/docs/next/components/checkbox.md) to mark a selection, such as picking an item, including a row, or agreeing to terms; those values are normally submitted with the rest of a form. A Checkbox also supports indeterminate state, which Switch doesn’t have.

## <a id="basic-features"></a>Basic Features

The following features, common to most input field components, are supported:

Label

The label is used to identify the input field. It supports plain-text content. In the Lumo theme its length is limited to the width of the field (and truncated with ellipsis), while in the Aura theme labels wrap to multiple lines. [Helpers](#helper) and [Tooltips](#tooltip) can be used to provide additional information that doesn’t fit into the label.

Visible labels are strongly recommended for all input fields. In cases where the built-in label cannot be used, an external element can be associated as the field’s label through the `aria-labelledby` attribute (`setAriaLabelledBy` in Flow). Fields without any visible label should include an invisible label for assistive technologies with the `aria-label` attribute (`setAriaLabel` in Flow).

Helper

Helpers are used to provide additional information that the user may need to enter in the field, such as format requirements or explanations of the field’s purpose below the field.

A [style variant](https://vaadin.com/docs/next/components/switch/styling.md#style-variants) is available for rendering the helper above the field.

In addition to plain text, helpers can contain components and HTML elements. However, complex and interactive content is likely to have accessibility issues.

Tooltip

Tooltips are small text pop-ups displayed on hover, and on keyboard-focus. They can be used to provide additional information about a field. This can be useful in situations where an always visible [Helper](#helper) is not appropriate. Helpers are generally recommended in favor of tooltips, though, as they provide much better discoverability and mobile support. See the [Tooltip](https://vaadin.com/docs/next/components/tooltip.md) documentation for more information.

External & Invisible Labels (ARIA)

Visible labels are strongly recommended for all input fields. In situations where the built-in label cannot be used, an external element can be associated as the field’s label through its element `id`. Fields without any visible label should be provided an invisible label for assistive technologies like screen readers.

```html
<!-- Associates external element as label: -->
<label id="external-label">This is the label</label>
<vaadin-switch accessible-name-ref="external-label">...

<!-- Invisible label for screen readers: -->
<vaadin-switch accessible-name="This is the label">...
```

```java
// Associates external element as label:
NativeLabel label = new NativeLabel("This is the label");
label.setId("external-label");
field.setAriaLabelledBy("external-label");

// Invisible label for screen readers:
field.setAriaLabel("This is the label");
```

**Lit** — `switch-basic-features.ts`

```typescript
<vaadin-switch label="Autosave" helper-text="Automatically save changes as you work">
  <vaadin-tooltip slot="tooltip" text="Last saved 5 minutes ago"></vaadin-tooltip>
</vaadin-switch>
```

**Flow** — `SwitchBasicFeatures.java`

```java
Switch autosave = new Switch("Autosave");
autosave.setHelperText("Automatically save changes as you work");
autosave.setTooltipText("Last saved 5 minutes ago");

add(autosave);
```

**React** — `switch-basic-features.tsx`

```tsx
<Switch label="Autosave" helperText="Automatically save changes as you work">
  <Tooltip slot="tooltip" text="Last saved 5 minutes ago" />
</Switch>
```

## <a id="read-only-disabled"></a>Read-Only & Disabled

Fields used to display values should be set to `read-only` mode to prevent editing. Read-only fields are focusable and visible to screen readers. They can display tooltips. Their values can be selected and copied.

Fields that are currently unavailable should be `disabled`. The reduced contrast of disabled fields makes them inappropriate for displaying information. They can’t be focused or display tooltips. They’re invisible to screen readers, and their values cannot be selected and copied.

Disabled fields can be useful in situations where they can become enabled based on some user action. Consider hiding fields entirely if there’s nothing the user can do to make them editable.

For a setting that the user can see but not change — one locked by a plan, a policy, or a parent setting — read-only is preferable to disabled. A read-only Switch remains focusable and announced, and it still accepts programmatic changes, so the application can toggle it for a system-driven update.

**Lit** — `switch-readonly-and-disabled.ts`

```typescript
<vaadin-switch
  label="Audit log retention (90 days)"
  helper-text="Included on the Business plan"
  readonly
  checked
></vaadin-switch>

<vaadin-switch label="Daily digest" disabled></vaadin-switch>
```

**Flow** — `SwitchReadonlyAndDisabled.java`

```java
Switch auditLog = new Switch("Audit log retention (90 days)");
auditLog.setValue(true);
auditLog.setReadOnly(true);
auditLog.setHelperText("Included on the Business plan");

Switch dailyDigest = new Switch("Daily digest");
dailyDigest.setEnabled(false);

add(auditLog, dailyDigest);
```

**React** — `switch-readonly-and-disabled.tsx`

```tsx
<Switch
  label="Audit log retention (90 days)"
  helperText="Included on the Business plan"
  readonly
  checked
/>

<Switch label="Daily digest" disabled />
```

## <a id="validation"></a>Validation

Switch supports a single constraint: it can be marked as required, in which case off is invalid and on is valid. This suits a setting that has to stay on, such as one enforced by a security policy. For a consent that the user has to accept before proceeding, use a [Checkbox](https://vaadin.com/docs/next/components/checkbox.md) instead.

Required

Required fields are marked with an indicator next to the label, and become invalid if their value is first entered and then cleared.

An instruction text at the top of the form explaining the required indicator is recommended. The indicator itself can be customized with the `--vaadin-input-field-required-indicator` style property.

A required Switch isn’t shown as invalid until the user has toggled it, or the application triggers validation, so no error appears before the user has acted. Toggling the switch back on clears the invalid state immediately. Turn off the switch to see the validation message.

**Lit** — `switch-validation.ts`

```typescript
<vaadin-switch
  label="Two-factor authentication"
  required
  checked
  error-message="Required by your workplace security policy"
></vaadin-switch>
```

**Flow** — `SwitchValidation.java`

```java
Switch twoFactor = new Switch("Two-factor authentication");
twoFactor.setValue(true);
twoFactor.setRequiredIndicatorVisible(true);
twoFactor.setI18n(new SwitchI18n().setRequiredErrorMessage(
        "Required by your workplace security policy"));
```

**React** — `switch-validation.tsx`

```tsx
<Switch
  label="Two-factor authentication"
  required
  checked
  errorMessage="Required by your workplace security policy"
/>
```

> **Note:** The required indicator is visible only when the Switch has a label.

> **Note: Data Binding & Custom Validation**
>
> Flow and Hilla offer an advanced API called Binder that allows you to bind data and add custom validation rules for multiple fields, creating forms. You can learn more about Binder from the corresponding [Flow](https://vaadin.com/docs/next/flow/binding-data/components-binder-validation.md) and [Hilla](https://vaadin.com/docs/next/hilla/guides/forms/binder-validation.md) articles.

## <a id="accessibility"></a>Accessibility

Switch uses the WAI-ARIA `switch` role, so screen readers announce it as a switch and read its state as on or off, rather than as a checkbox that is checked or unchecked. The accessible state is kept in sync with the visible state at all times, whether the user toggles the switch, the application updates it programmatically, or a form resets it.

The label, helper, and error message are all associated with the control for assistive technologies, and the read-only and required states are announced as well.

## <a id="best-practices"></a>Best Practices

Apply a switch’s change as soon as it’s toggled. A Switch can take part in a form that’s saved with a Save button — a settings form is a common case — but users expect a switch to apply right away.

Use short, descriptive labels with positive wording that name the setting being turned on — for example, "Notifications" rather than "Disable notifications". Negated labels make the off position ambiguous.

Avoid combining read-only with required on a switch that’s off, since that leaves the form in a state the user can’t correct.

## <a id="related-components"></a>Related Components

| Component                                                                     | Usage Recommendation                                                                                                                                                                                          |
| ----------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [Checkbox](https://vaadin.com/docs/next/components/checkbox.md)               | Marks a selection — picking an item, agreeing to terms, or including a row — and supports an indeterminate state. See [When to Use](#when-to-use) for choosing between the two.                               |
| [Radio Button Group](https://vaadin.com/docs/next/components/radio-button.md) | Picks one of two or more equal options. Use a Switch when one value is clearly the "off" state of a feature, and a two-option radio group when both values are equal labels, such as "Imperial" and "Metric". |
| [Select](https://vaadin.com/docs/next/components/select.md)                   | Presents options in an overlay. Prefer a Select over a Switch only when the two values need long labels; a Switch shows both states at once and toggles in a single click.                                    |
