Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
ad03dd3
refactor(checkbox): extract indeterminate to element class
web-padawan May 6, 2026
cec57af
docs(switch): add problem statement for switch component
web-padawan May 6, 2026
1ea4ac5
docs(switch): add behavioral requirements for switch component
web-padawan May 6, 2026
f3156d7
docs(switch): add web component API design for switch component
web-padawan May 6, 2026
0f82b73
docs(switch): add Flow API design for switch component
web-padawan May 6, 2026
68d1652
docs(toggle-switch): rename component specs from Switch to ToggleSwitch
web-padawan May 6, 2026
b608a70
docs(toggle-switch): add web component implementation spec
web-padawan May 6, 2026
de2795a
docs(toggle-switch): add Flow component implementation spec
web-padawan May 6, 2026
d91d443
docs(toggle-switch): drop deprecated theme variant aliases from Flow …
web-padawan May 6, 2026
210b14a
docs(toggle-switch): add web component implementation tasks
web-padawan May 6, 2026
ff2c2e2
docs(toggle-switch): clarify readonly handler uses updated() not Poly…
web-padawan May 6, 2026
476c74c
docs(toggle-switch): rebase specs on CheckboxMixin reuse
web-padawan May 6, 2026
5015d66
feat(toggle-switch): task 1 — package scaffolding and dev page
web-padawan May 15, 2026
889b6f1
feat(toggle-switch): task 2 — element class wiring — shadow DOM, role…
web-padawan May 15, 2026
8424afe
feat(toggle-switch): task 3 — behavioral verification through Checkbo…
web-padawan May 8, 2026
0993bac
docs(toggle-switch): align specs with new testing guideline
web-padawan May 8, 2026
3dff9e1
feat(toggle-switch): task 4 — base styles completion
web-padawan May 12, 2026
966e3a7
test(toggle-switch): drop CSS custom property override unit tests
web-padawan May 12, 2026
f7fdfec
fix(toggle-switch): restore label baseline alignment
web-padawan May 12, 2026
196ed25
feat(toggle-switch): task 5 — Lumo theme
web-padawan May 14, 2026
09da2e4
docs(toggle-switch): drop ToggleSwitchVariant from Flow specs
web-padawan May 14, 2026
c540786
feat(toggle-switch): task 6 — Aura theme
web-padawan May 15, 2026
8e8e3cd
feat(toggle-switch): task 7 — integration, snapshots, type tests, dev…
web-padawan May 15, 2026
02e64cb
test: use not-animated-styles.css to disable animations
web-padawan May 18, 2026
0c94188
refactor(toggle-switch): drop ThemableMixin from class chain
web-padawan May 18, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 80 additions & 0 deletions dev/playground/toggle-switch.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Toggle Switch</title>
<script type="module" src="../common.js"></script>

<script type="module">
// Enable feature flag
window.Vaadin ||= {};

Check warning on line 12 in dev/playground/toggle-switch.html

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Prefer `globalThis` over `window`.

See more on https://sonarcloud.io/project/issues?id=vaadin_web-components&issues=AZ4rR4CezgvZm-J9v7S1&open=AZ4rR4CezgvZm-J9v7S1&pullRequest=11760
window.Vaadin.featureFlags ||= {};

Check warning on line 13 in dev/playground/toggle-switch.html

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Prefer `globalThis` over `window`.

See more on https://sonarcloud.io/project/issues?id=vaadin_web-components&issues=AZ4rR4CezgvZm-J9v7S2&open=AZ4rR4CezgvZm-J9v7S2&pullRequest=11760
window.Vaadin.featureFlags.toggleSwitchComponent = true;

Check warning on line 14 in dev/playground/toggle-switch.html

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Prefer `globalThis` over `window`.

See more on https://sonarcloud.io/project/issues?id=vaadin_web-components&issues=AZ4rR4CezgvZm-J9v7S3&open=AZ4rR4CezgvZm-J9v7S3&pullRequest=11760

import '@vaadin/toggle-switch';
import '@vaadin/tooltip';
</script>
</head>

<body>
<section class="section">
<h2 class="heading">Label &amp; State</h2>
<vaadin-toggle-switch label="Notifications"></vaadin-toggle-switch>
<vaadin-toggle-switch label="Dark mode" checked></vaadin-toggle-switch>
</section>

<section class="section">
<h2 class="heading">Disabled</h2>
<vaadin-toggle-switch label="Daily digest" disabled></vaadin-toggle-switch>
<vaadin-toggle-switch label="Beta features" disabled checked></vaadin-toggle-switch>
</section>

<section class="section">
<h2 class="heading">Read-only</h2>
<vaadin-toggle-switch label="Audit log retention" readonly></vaadin-toggle-switch>
<vaadin-toggle-switch label="Account verified" readonly checked></vaadin-toggle-switch>
</section>

<section class="section">
<h2 class="heading">Required</h2>
<vaadin-toggle-switch label="I confirm the trip details are correct" required></vaadin-toggle-switch>
</section>

<section class="section">
<h2 class="heading">Invalid with error message</h2>
<vaadin-toggle-switch
label="Accept the terms"
required
invalid
error-message="You must accept the terms to continue"
></vaadin-toggle-switch>
</section>

<section class="section">
<h2 class="heading">Helper text</h2>
<vaadin-toggle-switch
label="Auto-save"
helper-text="Save changes automatically every 30 seconds"
></vaadin-toggle-switch>
</section>

<section class="section">
<h2 class="heading">With tooltip</h2>
<vaadin-toggle-switch label="Active">
<vaadin-tooltip slot="tooltip" text="Last delivery: 2 minutes ago"></vaadin-tooltip>
</vaadin-toggle-switch>
</section>

<section class="section">
<h2 class="heading">Label with link</h2>
<vaadin-toggle-switch>
<span slot="label">
Send anonymous usage data — <a href="https://vaadin.com/privacy">read our privacy policy</a>
</span>
</vaadin-toggle-switch>
</section>

</body>
</html>
22 changes: 22 additions & 0 deletions dev/toggle-switch.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Toggle Switch</title>
<script type="module" src="./common.js"></script>
<script type="module">
// Enable feature flag
window.Vaadin ||= {};

Check warning on line 11 in dev/toggle-switch.html

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Prefer `globalThis` over `window`.

See more on https://sonarcloud.io/project/issues?id=vaadin_web-components&issues=AZ4rR4CqzgvZm-J9v7S4&open=AZ4rR4CqzgvZm-J9v7S4&pullRequest=11760
window.Vaadin.featureFlags ||= {};

Check warning on line 12 in dev/toggle-switch.html

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Prefer `globalThis` over `window`.

See more on https://sonarcloud.io/project/issues?id=vaadin_web-components&issues=AZ4rR4CqzgvZm-J9v7S5&open=AZ4rR4CqzgvZm-J9v7S5&pullRequest=11760
window.Vaadin.featureFlags.toggleSwitchComponent = true;

Check warning on line 13 in dev/toggle-switch.html

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Prefer `globalThis` over `window`.

See more on https://sonarcloud.io/project/issues?id=vaadin_web-components&issues=AZ4rR4CqzgvZm-J9v7S6&open=AZ4rR4CqzgvZm-J9v7S6&pullRequest=11760

import '@vaadin/toggle-switch';
</script>
</head>

<body>
<vaadin-toggle-switch label="Notifications"></vaadin-toggle-switch>
</body>
</html>
1 change: 1 addition & 0 deletions packages/aura/aura.css
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
@import './src/components/side-nav.css';
@import './src/components/slider.css';
@import './src/components/tabs.css';
@import './src/components/toggle-switch.css';
@import './src/components/tooltip.css';
@import './src/components/upload.css';

Expand Down
71 changes: 71 additions & 0 deletions packages/aura/src/components/toggle-switch.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
:where(:root),
:where(:host) {
--vaadin-toggle-switch-size: round(1lh - 2px, 2px);
}

vaadin-toggle-switch::part(switch) {
transition:
background-color 100ms,
box-shadow 100ms;
}

vaadin-toggle-switch:not([disabled], [readonly])::part(switch) {
--aura-surface-level: 4;
background: var(--vaadin-toggle-switch-background, var(--aura-surface-color));
box-shadow: var(--aura-shadow-xs);
--_shade: color-mix(in srgb, var(--vaadin-border-color-secondary) 50%, transparent);
background-image: linear-gradient(
light-dark(transparent, var(--_shade)),
transparent 33%,
transparent 66%,
light-dark(var(--_shade), transparent)
);
}

vaadin-toggle-switch:not([checked])::part(switch) {
background-clip: padding-box;
}

vaadin-toggle-switch[checked]:not([readonly], [disabled])::part(switch) {
--vaadin-toggle-switch-background: var(--aura-accent-color);
--vaadin-toggle-switch-border-color: var(--vaadin-border-color-secondary);
--vaadin-toggle-switch-thumb-checked-color: var(--aura-accent-contrast-color);
background-image: none;
box-shadow: var(--aura-shadow-s);
}

vaadin-toggle-switch[invalid]:not([disabled], [readonly])::part(switch) {
--vaadin-toggle-switch-background: color-mix(in srgb, var(--aura-red) 10%, transparent);
--vaadin-toggle-switch-border-color: var(--aura-red-text);
background-image: none;
}

vaadin-toggle-switch[invalid][checked]:not([disabled], [readonly])::part(switch) {
--vaadin-toggle-switch-background: var(--aura-red);
--vaadin-toggle-switch-border-color: var(--vaadin-border-color-secondary);
--vaadin-toggle-switch-thumb-checked-color: var(--aura-accent-contrast-color);
}

vaadin-toggle-switch:not([disabled], [readonly])::part(switch)::before {
content: '';
position: absolute;
inset: calc(var(--vaadin-toggle-switch-border-width, var(--vaadin-input-field-border-width, 1px)) * -1);
border-radius: inherit;
background-color: currentColor;
opacity: 0;
transition:
opacity 100ms,
background-color 100ms;
pointer-events: none;
}

@media (any-hover: hover) {
vaadin-toggle-switch:hover:not([readonly], [disabled], [active])::part(switch)::before {
opacity: 0.04;
}
}

vaadin-toggle-switch[active]:not([readonly], [disabled])::part(switch)::before {
opacity: 0.1;
background: #000;
}
9 changes: 0 additions & 9 deletions packages/checkbox/src/vaadin-checkbox-mixin.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,6 @@ export declare function CheckboxMixin<T extends Constructor<HTMLElement>>(
T;

export declare class CheckboxMixinClass {
/**
* True if the checkbox is in the indeterminate state which means
* it is not possible to say whether it is checked or unchecked.
* The state is reset once the user switches the checkbox by hand.
*
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/checkbox#Indeterminate_state_checkboxes
*/
indeterminate: boolean;

/**
* The name of the checkbox.
*/
Expand Down
35 changes: 0 additions & 35 deletions packages/checkbox/src/vaadin-checkbox-mixin.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,20 +20,6 @@ export const CheckboxMixin = (superclass) =>
) {
static get properties() {
return {
/**
* True if the checkbox is in the indeterminate state which means
* it is not possible to say whether it is checked or unchecked.
* The state is reset once the user switches the checkbox by hand.
*
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/checkbox#Indeterminate_state_checkboxes
*/
indeterminate: {
type: Boolean,
notify: true,
value: false,
reflectToAttribute: true,
},

/**
* The name of the checkbox.
*/
Expand All @@ -60,11 +46,6 @@ export const CheckboxMixin = (superclass) =>
return ['__readonlyChanged(readonly, inputElement)'];
}

/** @override */
static get delegateProps() {
return [...super.delegateProps, 'indeterminate'];
}

/** @override */
static get delegateAttrs() {
return [...super.delegateAttrs, 'name', 'invalid', 'required'];
Expand Down Expand Up @@ -187,22 +168,6 @@ export const CheckboxMixin = (superclass) =>
}
}

/**
* Override method inherited from `CheckedMixin` to reset
* `indeterminate` state checkbox is toggled by the user.
*
* @param {boolean} checked
* @protected
* @override
*/
_toggleChecked(checked) {
if (this.indeterminate) {
this.indeterminate = false;
}

super._toggleChecked(checked);
}

/**
* @override
* @return {boolean}
Expand Down
9 changes: 9 additions & 0 deletions packages/checkbox/src/vaadin-checkbox.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,15 @@ export interface CheckboxEventMap extends HTMLElementEventMap, CheckboxCustomEve
* @fires {CustomEvent} validated - Fired whenever the field is validated.
*/
declare class Checkbox extends CheckboxMixin(ElementMixin(ThemableMixin(HTMLElement))) {
/**
* True if the checkbox is in the indeterminate state which means
* it is not possible to say whether it is checked or unchecked.
* The state is reset once the user switches the checkbox by hand.
*
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/checkbox#Indeterminate_state_checkboxes
*/
indeterminate: boolean;

addEventListener<K extends keyof CheckboxEventMap>(
type: K,
listener: (this: Checkbox, ev: CheckboxEventMap[K]) => void,
Expand Down
40 changes: 40 additions & 0 deletions packages/checkbox/src/vaadin-checkbox.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,30 @@ export class Checkbox extends CheckboxMixin(ElementMixin(ThemableMixin(PolylitMi
return checkboxStyles;
}

static get properties() {
return {
/**
* True if the checkbox is in the indeterminate state which means
* it is not possible to say whether it is checked or unchecked.
* The state is reset once the user switches the checkbox by hand.
*
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/checkbox#Indeterminate_state_checkboxes
*
*/
indeterminate: {
type: Boolean,
notify: true,
value: false,
reflectToAttribute: true,
},
};
}

/** @override */
static get delegateProps() {
return [...super.delegateProps, 'indeterminate'];
}

/** @protected */
render() {
return html`
Expand Down Expand Up @@ -125,6 +149,22 @@ export class Checkbox extends CheckboxMixin(ElementMixin(ThemableMixin(PolylitMi
this._tooltipController.setAriaTarget(this.inputElement);
this.addController(this._tooltipController);
}

/**
* Override method inherited from `CheckedMixin` to reset
* `indeterminate` when the checkbox is toggled by the user.
*
* @param {boolean} checked
* @protected
* @override
*/
_toggleChecked(checked) {
if (this.indeterminate) {
this.indeterminate = false;
}

super._toggleChecked(checked);
}
}

defineCustomElement(Checkbox);
Loading
Loading