Skip to content

prototype: toggle-switch web component specs and implementation#11760

Draft
web-padawan wants to merge 25 commits into
mainfrom
proto/sdd-switch
Draft

prototype: toggle-switch web component specs and implementation#11760
web-padawan wants to merge 25 commits into
mainfrom
proto/sdd-switch

Conversation

@web-padawan
Copy link
Copy Markdown
Member

Description

This is a PR containing all changes for toggle-switch component: specs, tasks, implementation.
It's opened to make it easy to browse those things together and collect feedback.

If we decide to proceed with implementation, I will split individual commits into separate PRs.

Type of change

  • Prototype

Comment thread packages/toggle-switch/src/vaadin-toggle-switch.js Outdated
web-padawan and others added 25 commits May 19, 2026 11:25
Make CheckboxMixin reusable for binary-input field components beyond
Checkbox itself (e.g. the upcoming vaadin-toggle-switch). Move the
indeterminate property declaration, its delegateProps entry, and the
_toggleChecked override from CheckboxMixin to the Checkbox element
class. Indeterminate is checkbox-specific per the WHATWG spec; toggle
switches don't have it.

Subclasses extending CheckboxMixin can set element-specific attributes
on the inner input (e.g. role="switch") by overriding
_inputElementChanged from InputMixin — same convention as combo-box
and date-picker.

Behavior for Checkbox is unchanged: 44 unit tests + 9 snapshot tests
pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Move packages/switch/spec/ to packages/toggle-switch/spec/ and rewrite
references throughout: tag <vaadin-toggle-switch>, Java class ToggleSwitch
in package com.vaadin.flow.component.toggleswitch, ToggleSwitchI18n,
ToggleSwitchVariant, --vaadin-toggle-switch-* CSS custom properties.

Avoids the Java reserved-keyword collision that the previous "Switch"
naming required to work around (com.vaadin.flow.component.switch_).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…spec

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…mer observer

The prototype's vaadin-toggle-switch-mixin.js handles readonly via Lit's
updated(changed) hook (per guidelines/04-coding-conventions.md, which prefers
this over `static get observers()` for new components). The spec and the
read-only task previously described the handler with observer-style language.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The CheckboxMixin refactor (refactor/checkbox-mixin) extracts indeterminate
to the Checkbox element class and leaves the mixin as a generic binary-input
field plumbing layer. The toggle switch now reuses CheckboxMixin as-is and
only adds an _inputElementChanged override on the element class to set
role="switch" — same convention vaadin-combo-box and vaadin-date-picker
use for inner-input role attributes.

Spec changes:

- requirements.md: Req 3 narrowed to anchors only (button-in-label is not
  a supported use case, matching the inherited <a>-only label-click rule).
  Discussion entry added.

- web-component-spec.md: Key Design Decisions trimmed from 14 to 9 by
  collapsing decisions about readonly, validation, Safari tabindex, slot
  styles, and label-click broadening into one "reuse CheckboxMixin"
  decision. New decision describes the _inputElementChanged override.
  Internal Behavior section collapses to a single "inherited from
  CheckboxMixin" bullet plus the toggle-specific role and tooltip
  bullets. Reuse section reduces to the six modules actually imported.
  Discussion entry added explaining the deferral.

- web-component-tasks.md: shrinks from 13 tasks to 7 — feature-by-feature
  tasks (disabled, readonly, validation, helper/error/label/tooltip,
  form integration, a11y/keyboard) collapse into a single "behavioral
  verification through CheckboxMixin" test task. Implementation work
  reduces to one element-wiring task with the role="switch" override
  and tooltip controller setup.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…xMixin

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Picked up `guidelines/12-testing.md` from origin/main (which also moved
the previous `12-checklist.md` to `13-checklist.md`). The new chapter
codifies the rule "don't test mixin / controller internals in components
that consume them" — exactly the rule Task 3 already settled on.

- web-component-spec.md: Decision 9 (Guideline alignment) now
  references `guidelines/12-testing.md`. Added a Discussion entry
  explaining why Task 3's coverage is intentionally minimal.

- web-component-tasks.md: Task 7's "Spec sections" updated from
  `guidelines/12-checklist.md` to both `guidelines/12-testing.md` and
  the renamed `guidelines/13-checklist.md`.

- implementation-notes.md: post-Task 3 entry recording the rebase, the
  spec adjustments, and a follow-up note that the existing `.test.js`
  files predate the new "write new tests in .ts" recommendation —
  conversion is a small, pure-renaming change worth doing in Task 7
  alongside the TypeScript typings file.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Computed-style assertions for --vaadin-toggle-switch-* overrides test the
CSS engine, not the component. The visual regression suite already covers
the styling layer.
The local stylesheet was suppressing checkable()'s [part='switch']::after
with content: none, which removed the em-space that anchors the flex
container's first baseline. Without that anchor, :host { align-items:
baseline } collapsed to the track's bottom edge and the label drifted up.
Clear background and mask instead so the em-space content (and therefore
the centred baseline) is preserved.
The only candidate variant was helper-above-field, and that theme
attribute is not actually supported by the web component (see
#11750). Defer introducing the enum until a real
variant lands. flow-api.md and flow-spec.md drop the variant section,
the HasThemeVariant<…> mixin, and the corresponding class layout
entries, and each grows a Discussion entry explaining the deferral.
The component does not expose a theme attribute and does not register
theme-scoped CSS via registerStyles. Lumo styles ship through
LumoInjectionMixin and Aura styles ship document-side via ::part,
so ThemableMixin's style registry was never read.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@sonarqubecloud
Copy link
Copy Markdown

Copy link
Copy Markdown
Contributor

@rolfsmeds rolfsmeds left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Name should be just vaadin-switch / Switch IMO.
  • Styles definitely need some work, e.g. switch outline has insufficient contrast (esp. in dark mode) and the readonly state's dashed border is... not pretty.

@@ -0,0 +1,264 @@
# Toggle Switch Developer API

The component is exposed as `<vaadin-toggle-switch>`, following the Vaadin convention where the kebab-cased ComponentName becomes the tag (`ToggleSwitch` → `vaadin-toggle-switch`). All examples below are minimal — no extra wiring needed beyond what the snippet shows.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The name <vaadin-toggle-switch> with both toggle and switch seems redundant. Most component libraries seem to call this simply a switch, with toggle coming in second place. Propose we go with vaadin-switch to make it more distinguished from a potential future vaadin-toggle-button-group.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd be ok to use vaadin-switch but then we'd need to have it in vaadin-checkbox-flow package like so:

import com.vaadin.flow.component.checkbox.Switch;

That's because we can't use .switch.Switch as switch is a reserved Java keyword.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Having it in checkbox package would be fine IMO – they are very closely related, after all.

Alternatively we could call it just vaadin-toggle / Toggle.

I'd be fine with either.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer Switch to avoid confusion if we use Toggle for the standalone toggle button / toggle button group.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking the same, but then I started thinking that maybe a standalone toggle button isn't really a thing even? ToggleButtonGroup is sufficiently different to not be an issue.

But we can of course the problem by going with Switch in checkbox pacakge.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO we could use standalone toggle button for some cases like the icon-only "favorites" button in Starpass - in this particular case toggle button feels more appropriate than a switch.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok yeah that's a good example of a toggle-button.
Let's go with checkbox.Switch then.

Comment thread packages/toggle-switch/spec/web-component-api.md
@web-padawan
Copy link
Copy Markdown
Member Author

Name should be just vaadin-switch / Switch IMO.

This introduces a problem of not being able to use com.vaadin.component.switch because switch is a reserved Java keyword. Claude initially suggested switch_ for the package name as a workaround but it feels weird.

If we want Switch, then maybe we could use com.vaadin.flow.component.checkbox.Switch and therefore place it in vaadin-checkbox-flow-parent as the component is conceptually related to Checkbox?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants