diff --git a/dev/checkbox-group.html b/dev/checkbox-group.html
index 9106f7163e8..858c58c7a40 100644
--- a/dev/checkbox-group.html
+++ b/dev/checkbox-group.html
@@ -1,4 +1,4 @@
-
+
@@ -8,68 +8,113 @@
+
+
-
-
-
-
-
-
+
+ Plain Text Labels
+
+
+
+
+
+
+
+
+
+
+ Read Only & Disabled
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+ Bells & Whistles
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+ Content & Layout Variations
+ Resize the field to test how content flows.
+
+
+
+
+
+
+
+
+
+
diff --git a/dev/checkbox.html b/dev/checkbox.html
index 1a948638d3e..15e3e2ceb89 100644
--- a/dev/checkbox.html
+++ b/dev/checkbox.html
@@ -1,4 +1,4 @@
-
+
@@ -8,15 +8,39 @@
-
-
-
-
+
+ Label & Description
+
+
+
+
+
+
+
+
diff --git a/dev/common.js b/dev/common.js
index 697051b1e15..0aafba6e40a 100644
--- a/dev/common.js
+++ b/dev/common.js
@@ -26,5 +26,17 @@ addGlobalThemeStyles(
margin: 2em 0 1.25em;
text-box: cap alphabetic;
}
+
+ section {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 1lh 1.5lh;
+ margin: 2lh 0;
+ }
+
+ section > :is(h1, h2, h3, h4, h5, h6, p) {
+ width: 100%;
+ margin: 0;
+ }
`,
);
diff --git a/dev/radio-group.html b/dev/radio-group.html
index d76e47bf73a..161c4ed17b7 100644
--- a/dev/radio-group.html
+++ b/dev/radio-group.html
@@ -1,4 +1,4 @@
-
+
@@ -8,68 +8,122 @@
+
+
-
-
-
-
-
-
+
+ Plain Text Labels
+
+
+
+
+
+
+
+
-
-
+
+ Read Only & Disabled
+
+
+
+
+
-
-
-
+
+
+
+
+
+ Content & Layout Variations
+ Resize the field to test how content flows.
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/checkbox-group/src/vaadin-checkbox-group-styles.d.ts b/packages/checkbox-group/src/vaadin-checkbox-group-styles.d.ts
index e28da926571..04b9a18a59b 100644
--- a/packages/checkbox-group/src/vaadin-checkbox-group-styles.d.ts
+++ b/packages/checkbox-group/src/vaadin-checkbox-group-styles.d.ts
@@ -5,4 +5,4 @@
*/
import type { CSSResult } from 'lit';
-export const checkboxGroupStyles: CSSResult;
+export const checkboxGroupStyles: () => CSSResult;
diff --git a/packages/checkbox-group/src/vaadin-checkbox-group-styles.js b/packages/checkbox-group/src/vaadin-checkbox-group-styles.js
index d2f8bede567..1736163fdc4 100644
--- a/packages/checkbox-group/src/vaadin-checkbox-group-styles.js
+++ b/packages/checkbox-group/src/vaadin-checkbox-group-styles.js
@@ -3,35 +3,29 @@
* Copyright (c) 2018 - 2025 Vaadin Ltd.
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
*/
-import { css } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
+import { css, unsafeCSS } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
-export const checkboxGroupStyles = css`
+export const checkboxGroupStyles = (name = 'checkbox') => css`
:host {
- display: inline-flex;
+ width: fit-content;
}
- :host::before {
- content: '\\2003';
- width: 0;
- display: inline-block;
- }
-
- :host([hidden]) {
- display: none !important;
+ .vaadin-group-field-container {
+ display: contents;
}
- .vaadin-group-field-container {
+ :host,
+ [part='group-field'] {
display: flex;
flex-direction: column;
- width: 100%;
+ gap: var(--vaadin-${unsafeCSS(name)}-group-gap, var(--_vaadin-gap-container-block));
}
[part='group-field'] {
- display: flex;
- flex-wrap: wrap;
+ gap: 0.5lh 1.5em;
}
- :host(:not([has-label])) [part='label'] {
- display: none;
+ :host([theme~='horizontal']) [part='group-field'] {
+ flex-flow: row wrap;
}
`;
diff --git a/packages/checkbox-group/src/vaadin-lit-checkbox-group.js b/packages/checkbox-group/src/vaadin-lit-checkbox-group.js
index 462be6362f8..9f9eefb0ea6 100644
--- a/packages/checkbox-group/src/vaadin-lit-checkbox-group.js
+++ b/packages/checkbox-group/src/vaadin-lit-checkbox-group.js
@@ -8,6 +8,7 @@ import { html, LitElement } from 'lit';
import { defineCustomElement } from '@vaadin/component-base/src/define.js';
import { ElementMixin } from '@vaadin/component-base/src/element-mixin.js';
import { PolylitMixin } from '@vaadin/component-base/src/polylit-mixin.js';
+import { fieldShared } from '@vaadin/field-base/src/styles/field-shared-styles.js';
import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
import { CheckboxGroupMixin } from './vaadin-checkbox-group-mixin.js';
import { checkboxGroupStyles } from './vaadin-checkbox-group-styles.js';
@@ -27,7 +28,7 @@ class CheckboxGroup extends CheckboxGroupMixin(ElementMixin(ThemableMixin(Polyli
}
static get styles() {
- return checkboxGroupStyles;
+ return [fieldShared, checkboxGroupStyles()];
}
/** @protected */
diff --git a/packages/checkbox-group/test/visual/base/checkbox-group.test.js b/packages/checkbox-group/test/visual/base/checkbox-group.test.js
new file mode 100644
index 00000000000..1549e97248f
--- /dev/null
+++ b/packages/checkbox-group/test/visual/base/checkbox-group.test.js
@@ -0,0 +1,140 @@
+import { sendKeys } from '@vaadin/test-runner-commands';
+import { fixtureSync } from '@vaadin/testing-helpers/dist/fixture.js';
+import { visualDiff } from '@web/test-runner-visual-regression';
+import '../common.js';
+import '../../../src/vaadin-lit-checkbox-group.js';
+
+describe('checkbox-group', () => {
+ let div, element;
+
+ beforeEach(() => {
+ div = document.createElement('div');
+ div.style.display = 'inline-block';
+ div.style.padding = '10px';
+
+ element = fixtureSync(
+ `
+
+
+
+
+
+ `,
+ div,
+ );
+ });
+
+ describe('default', () => {
+ it('basic', async () => {
+ await visualDiff(div, 'basic');
+ });
+
+ it('disabled', async () => {
+ element.disabled = true;
+ await visualDiff(div, 'disabled');
+ });
+
+ it('horizontal', async () => {
+ element.setAttribute('theme', 'horizontal');
+ await visualDiff(div, 'horizontal');
+ });
+
+ it('label', async () => {
+ element.label = 'Label';
+ await visualDiff(div, 'label');
+ });
+
+ it('label focused', async () => {
+ element.label = 'Label';
+ await sendKeys({ press: 'Tab' });
+ await visualDiff(div, 'label-focused');
+ });
+
+ it('label focused readonly', async () => {
+ element.label = 'Label';
+ element.readonly = true;
+ await sendKeys({ press: 'Tab' });
+ await visualDiff(div, 'label-focused-readonly');
+ });
+
+ it('label disabled', async () => {
+ element.label = 'Label';
+ element.disabled = true;
+ await visualDiff(div, 'label-disabled');
+ });
+
+ it('value', async () => {
+ element.value = ['a', 'c'];
+ await visualDiff(div, 'value');
+ });
+
+ it('readonly', async () => {
+ element.readonly = true;
+ element.value = ['a', 'c'];
+ await visualDiff(div, 'readonly');
+ });
+
+ it('required', async () => {
+ element.label = 'Label';
+ element.required = true;
+ await visualDiff(div, 'required');
+ });
+
+ it('error message', async () => {
+ element.label = 'Label';
+ element.errorMessage = 'This field is required';
+ element.required = true;
+ element.validate();
+ await visualDiff(div, 'error-message');
+ });
+
+ it('helper text', async () => {
+ element.helperText = 'Helper text';
+ await visualDiff(div, 'helper-text');
+ });
+
+ it('helper above field', async () => {
+ element.label = 'Label';
+ element.errorMessage = 'This field is required';
+ element.required = true;
+ element.validate();
+ element.helperText = 'Helper text';
+ element.setAttribute('theme', 'helper-above-field');
+ await visualDiff(div, 'helper-above-field');
+ });
+
+ it('wrapped', async () => {
+ element.setAttribute('theme', 'horizontal');
+ element.style.width = '150px';
+ await visualDiff(div, 'wrapped');
+ });
+ });
+
+ describe('RTL', () => {
+ before(() => {
+ document.documentElement.setAttribute('dir', 'rtl');
+ });
+
+ after(() => {
+ document.documentElement.removeAttribute('dir');
+ });
+
+ it('RTL basic', async () => {
+ await visualDiff(div, 'rtl-basic');
+ });
+
+ it('RTL error message', async () => {
+ element.label = 'Label';
+ element.errorMessage = 'This field is required';
+ element.required = true;
+ element.validate();
+ await visualDiff(div, 'rtl-error-message');
+ });
+
+ it('RTL wrapped', async () => {
+ element.setAttribute('theme', 'horizontal');
+ element.style.width = '150px';
+ await visualDiff(div, 'rtl-wrapped');
+ });
+ });
+});
diff --git a/packages/checkbox-group/test/visual/base/screenshots/checkbox-group/baseline/basic.png b/packages/checkbox-group/test/visual/base/screenshots/checkbox-group/baseline/basic.png
new file mode 100644
index 00000000000..8df842b55cd
Binary files /dev/null and b/packages/checkbox-group/test/visual/base/screenshots/checkbox-group/baseline/basic.png differ
diff --git a/packages/checkbox-group/test/visual/base/screenshots/checkbox-group/baseline/disabled.png b/packages/checkbox-group/test/visual/base/screenshots/checkbox-group/baseline/disabled.png
new file mode 100644
index 00000000000..2bbec818414
Binary files /dev/null and b/packages/checkbox-group/test/visual/base/screenshots/checkbox-group/baseline/disabled.png differ
diff --git a/packages/checkbox-group/test/visual/base/screenshots/checkbox-group/baseline/error-message.png b/packages/checkbox-group/test/visual/base/screenshots/checkbox-group/baseline/error-message.png
new file mode 100644
index 00000000000..3c5780fd4d6
Binary files /dev/null and b/packages/checkbox-group/test/visual/base/screenshots/checkbox-group/baseline/error-message.png differ
diff --git a/packages/checkbox-group/test/visual/base/screenshots/checkbox-group/baseline/helper-above-field.png b/packages/checkbox-group/test/visual/base/screenshots/checkbox-group/baseline/helper-above-field.png
new file mode 100644
index 00000000000..8b447da21e5
Binary files /dev/null and b/packages/checkbox-group/test/visual/base/screenshots/checkbox-group/baseline/helper-above-field.png differ
diff --git a/packages/checkbox-group/test/visual/base/screenshots/checkbox-group/baseline/helper-text.png b/packages/checkbox-group/test/visual/base/screenshots/checkbox-group/baseline/helper-text.png
new file mode 100644
index 00000000000..8d9a2a8ba18
Binary files /dev/null and b/packages/checkbox-group/test/visual/base/screenshots/checkbox-group/baseline/helper-text.png differ
diff --git a/packages/checkbox-group/test/visual/base/screenshots/checkbox-group/baseline/horizontal.png b/packages/checkbox-group/test/visual/base/screenshots/checkbox-group/baseline/horizontal.png
new file mode 100644
index 00000000000..0f2d70d1855
Binary files /dev/null and b/packages/checkbox-group/test/visual/base/screenshots/checkbox-group/baseline/horizontal.png differ
diff --git a/packages/checkbox-group/test/visual/base/screenshots/checkbox-group/baseline/label-disabled.png b/packages/checkbox-group/test/visual/base/screenshots/checkbox-group/baseline/label-disabled.png
new file mode 100644
index 00000000000..d32e9966cb6
Binary files /dev/null and b/packages/checkbox-group/test/visual/base/screenshots/checkbox-group/baseline/label-disabled.png differ
diff --git a/packages/checkbox-group/test/visual/base/screenshots/checkbox-group/baseline/label-focused-readonly.png b/packages/checkbox-group/test/visual/base/screenshots/checkbox-group/baseline/label-focused-readonly.png
new file mode 100644
index 00000000000..ca23de58acf
Binary files /dev/null and b/packages/checkbox-group/test/visual/base/screenshots/checkbox-group/baseline/label-focused-readonly.png differ
diff --git a/packages/checkbox-group/test/visual/base/screenshots/checkbox-group/baseline/label-focused.png b/packages/checkbox-group/test/visual/base/screenshots/checkbox-group/baseline/label-focused.png
new file mode 100644
index 00000000000..4799c1c539c
Binary files /dev/null and b/packages/checkbox-group/test/visual/base/screenshots/checkbox-group/baseline/label-focused.png differ
diff --git a/packages/checkbox-group/test/visual/base/screenshots/checkbox-group/baseline/label.png b/packages/checkbox-group/test/visual/base/screenshots/checkbox-group/baseline/label.png
new file mode 100644
index 00000000000..768fc835bb3
Binary files /dev/null and b/packages/checkbox-group/test/visual/base/screenshots/checkbox-group/baseline/label.png differ
diff --git a/packages/checkbox-group/test/visual/base/screenshots/checkbox-group/baseline/readonly.png b/packages/checkbox-group/test/visual/base/screenshots/checkbox-group/baseline/readonly.png
new file mode 100644
index 00000000000..60163c7acae
Binary files /dev/null and b/packages/checkbox-group/test/visual/base/screenshots/checkbox-group/baseline/readonly.png differ
diff --git a/packages/checkbox-group/test/visual/base/screenshots/checkbox-group/baseline/required.png b/packages/checkbox-group/test/visual/base/screenshots/checkbox-group/baseline/required.png
new file mode 100644
index 00000000000..fa76c31d918
Binary files /dev/null and b/packages/checkbox-group/test/visual/base/screenshots/checkbox-group/baseline/required.png differ
diff --git a/packages/checkbox-group/test/visual/base/screenshots/checkbox-group/baseline/rtl-basic.png b/packages/checkbox-group/test/visual/base/screenshots/checkbox-group/baseline/rtl-basic.png
new file mode 100644
index 00000000000..597556baf54
Binary files /dev/null and b/packages/checkbox-group/test/visual/base/screenshots/checkbox-group/baseline/rtl-basic.png differ
diff --git a/packages/checkbox-group/test/visual/base/screenshots/checkbox-group/baseline/rtl-error-message.png b/packages/checkbox-group/test/visual/base/screenshots/checkbox-group/baseline/rtl-error-message.png
new file mode 100644
index 00000000000..84b23833f22
Binary files /dev/null and b/packages/checkbox-group/test/visual/base/screenshots/checkbox-group/baseline/rtl-error-message.png differ
diff --git a/packages/checkbox-group/test/visual/base/screenshots/checkbox-group/baseline/rtl-wrapped.png b/packages/checkbox-group/test/visual/base/screenshots/checkbox-group/baseline/rtl-wrapped.png
new file mode 100644
index 00000000000..3ed68de24c0
Binary files /dev/null and b/packages/checkbox-group/test/visual/base/screenshots/checkbox-group/baseline/rtl-wrapped.png differ
diff --git a/packages/checkbox-group/test/visual/base/screenshots/checkbox-group/baseline/value.png b/packages/checkbox-group/test/visual/base/screenshots/checkbox-group/baseline/value.png
new file mode 100644
index 00000000000..5e2714bb155
Binary files /dev/null and b/packages/checkbox-group/test/visual/base/screenshots/checkbox-group/baseline/value.png differ
diff --git a/packages/checkbox-group/test/visual/base/screenshots/checkbox-group/baseline/wrapped.png b/packages/checkbox-group/test/visual/base/screenshots/checkbox-group/baseline/wrapped.png
new file mode 100644
index 00000000000..d65c351d228
Binary files /dev/null and b/packages/checkbox-group/test/visual/base/screenshots/checkbox-group/baseline/wrapped.png differ
diff --git a/packages/checkbox/src/vaadin-checkbox-styles.js b/packages/checkbox/src/vaadin-checkbox-styles.js
index c4068595088..e603ea5eaf8 100644
--- a/packages/checkbox/src/vaadin-checkbox-styles.js
+++ b/packages/checkbox/src/vaadin-checkbox-styles.js
@@ -3,93 +3,20 @@
* Copyright (c) 2017 - 2025 Vaadin Ltd.
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
*/
-import { css } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
-
-export const checkboxStyles = css`
- :host {
- display: inline-block;
- }
-
- :host([hidden]) {
- display: none !important;
- }
-
- :host([disabled]) {
- -webkit-tap-highlight-color: transparent;
- }
-
- .vaadin-checkbox-container {
- display: grid;
- grid-template-columns: auto 1fr;
- align-items: baseline;
- }
-
- [part='checkbox'],
- ::slotted(input),
- [part='label'] {
- grid-row: 1;
- }
-
- [part='checkbox'],
- ::slotted(input) {
- grid-column: 1;
- }
-
- [part='helper-text'],
- [part='error-message'] {
- grid-column: 2;
- }
-
- :host(:not([has-helper])) [part='helper-text'],
- :host(:not([has-error-message])) [part='error-message'] {
- display: none;
- }
-
- [part='checkbox'] {
- width: var(--vaadin-checkbox-size, 1em);
- height: var(--vaadin-checkbox-size, 1em);
- --_input-border-width: var(--vaadin-input-field-border-width, 0);
- --_input-border-color: var(--vaadin-input-field-border-color, transparent);
- box-shadow: inset 0 0 0 var(--_input-border-width, 0) var(--_input-border-color);
- }
-
- [part='checkbox']::before {
- display: block;
- content: '\\202F';
- line-height: var(--vaadin-checkbox-size, 1em);
- contain: paint;
- }
-
- /* visually hidden */
- ::slotted(input) {
- cursor: inherit;
- margin: 0;
- align-self: stretch;
- -webkit-appearance: none;
- width: initial;
- height: initial;
- }
-
- @media (forced-colors: active) {
- [part='checkbox'] {
- outline: 1px solid;
- outline-offset: -1px;
- }
-
- :host([disabled]) [part='checkbox'],
- :host([disabled]) [part='checkbox']::after {
- outline-color: GrayText;
- }
-
- :host(:is([checked], [indeterminate])) [part='checkbox']::after {
- outline: 1px solid;
- outline-offset: -1px;
- border-radius: inherit;
+import { css } from 'lit';
+import { checkboxRadio } from '@vaadin/field-base/src/styles/checkbox-radio-styles.js';
+
+export const checkboxStyles = [
+ checkboxRadio('checkbox'),
+ css`
+ [part='checkbox']::after {
+ inset: 0;
+ mask-image: var(--_vaadin-icon-checkmark);
}
- :host([focused]) [part='checkbox'],
- :host([focused]) [part='checkbox']::after {
- outline-width: 2px;
+ :host([indeterminate]) [part='checkbox']::after {
+ inset: calc(var(--_border-width) * -1);
+ mask-image: var(--_vaadin-icon-minus);
}
- }
-`;
+ `,
+];
diff --git a/packages/checkbox/src/vaadin-lit-checkbox.js b/packages/checkbox/src/vaadin-lit-checkbox.js
index ab2dc97bdff..d2517936646 100644
--- a/packages/checkbox/src/vaadin-lit-checkbox.js
+++ b/packages/checkbox/src/vaadin-lit-checkbox.js
@@ -8,6 +8,7 @@ import { defineCustomElement } from '@vaadin/component-base/src/define.js';
import { ElementMixin } from '@vaadin/component-base/src/element-mixin.js';
import { PolylitMixin } from '@vaadin/component-base/src/polylit-mixin.js';
import { TooltipController } from '@vaadin/component-base/src/tooltip-controller.js';
+import { fieldShared } from '@vaadin/field-base/src/styles/field-shared-styles.js';
import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
import { CheckboxMixin } from './vaadin-checkbox-mixin.js';
import { checkboxStyles } from './vaadin-checkbox-styles.js';
@@ -27,7 +28,7 @@ export class Checkbox extends CheckboxMixin(ElementMixin(ThemableMixin(PolylitMi
}
static get styles() {
- return checkboxStyles;
+ return [fieldShared, checkboxStyles];
}
/** @protected */
diff --git a/packages/checkbox/test/checkbox.test.js b/packages/checkbox/test/checkbox.test.js
index 411b080d4b5..7f2025ac651 100644
--- a/packages/checkbox/test/checkbox.test.js
+++ b/packages/checkbox/test/checkbox.test.js
@@ -2,7 +2,7 @@ import { expect } from '@vaadin/chai-plugins';
import { resetMouse, sendKeys, sendMouseToElement } from '@vaadin/test-runner-commands';
import { fixtureSync, mousedown, mouseup, nextFrame, nextRender, nextUpdate } from '@vaadin/testing-helpers';
import sinon from 'sinon';
-import '../src/vaadin-checkbox.js';
+import '../src/vaadin-lit-checkbox.js';
describe('checkbox', () => {
let checkbox, input, label, link;
diff --git a/packages/checkbox/test/visual/base/checkbox.test.js b/packages/checkbox/test/visual/base/checkbox.test.js
new file mode 100644
index 00000000000..a71681c837e
--- /dev/null
+++ b/packages/checkbox/test/visual/base/checkbox.test.js
@@ -0,0 +1,137 @@
+import { sendKeys } from '@vaadin/test-runner-commands';
+import { fixtureSync } from '@vaadin/testing-helpers';
+import { visualDiff } from '@web/test-runner-visual-regression';
+import '../common.js';
+import '../../../src/vaadin-lit-checkbox.js';
+
+describe('checkbox', () => {
+ let div, element;
+
+ beforeEach(() => {
+ div = document.createElement('div');
+ div.style.display = 'inline-block';
+ div.style.padding = '10px';
+ element = fixtureSync('', div);
+ });
+
+ it('basic', async () => {
+ await visualDiff(div, 'basic');
+ });
+
+ it('empty', async () => {
+ element.label = null;
+ await visualDiff(div, 'empty');
+ });
+
+ it('checked', async () => {
+ element.checked = true;
+ await visualDiff(div, 'checked');
+ });
+
+ it('indeterminate', async () => {
+ element.indeterminate = true;
+ await visualDiff(div, 'indeterminate');
+ });
+
+ it('focus-ring', async () => {
+ await sendKeys({ press: 'Tab' });
+ await visualDiff(div, 'focus-ring');
+ });
+
+ it('checked focus-ring', async () => {
+ element.checked = true;
+ await sendKeys({ press: 'Tab' });
+ await visualDiff(div, 'checked-focus-ring');
+ });
+
+ it('required', async () => {
+ element.required = true;
+ await visualDiff(div, 'required');
+ });
+
+ it('error message', async () => {
+ element.errorMessage = 'This field is required';
+ element.required = true;
+ element.validate();
+ await visualDiff(div, 'error-message');
+ });
+
+ it('helper text', async () => {
+ element.helperText = 'Helper text';
+ await visualDiff(div, 'helper-text');
+ });
+
+ describe('disabled', () => {
+ beforeEach(() => {
+ element.disabled = true;
+ });
+
+ it('basic', async () => {
+ await visualDiff(div, 'disabled');
+ });
+
+ it('checked', async () => {
+ element.checked = true;
+ await visualDiff(div, 'disabled-checked');
+ });
+
+ it('indeterminate', async () => {
+ element.indeterminate = true;
+ await visualDiff(div, 'disabled-indeterminate');
+ });
+
+ it('required', async () => {
+ element.required = true;
+ await visualDiff(div, 'disabled-required');
+ });
+ });
+
+ describe('readonly', () => {
+ beforeEach(() => {
+ element.readonly = true;
+ });
+
+ it('basic', async () => {
+ await visualDiff(div, 'readonly');
+ });
+
+ it('checked', async () => {
+ element.checked = true;
+ await visualDiff(div, 'readonly-checked');
+ });
+
+ it('indeterminate', async () => {
+ element.indeterminate = true;
+ await visualDiff(div, 'readonly-indeterminate');
+ });
+
+ it('focus-ring', async () => {
+ await sendKeys({ press: 'Tab' });
+ await visualDiff(div, 'readonly-focus-ring');
+ });
+ });
+
+ describe('RTL', () => {
+ before(() => {
+ document.documentElement.setAttribute('dir', 'rtl');
+ });
+
+ after(() => {
+ document.documentElement.removeAttribute('dir');
+ });
+
+ it('basic', async () => {
+ await visualDiff(div, 'rtl');
+ });
+
+ it('empty', async () => {
+ element.label = '';
+ await visualDiff(div, 'rtl-empty');
+ });
+
+ it('required', async () => {
+ element.required = true;
+ await visualDiff(div, 'rtl-required');
+ });
+ });
+});
diff --git a/packages/checkbox/test/visual/base/screenshots/checkbox/baseline/basic.png b/packages/checkbox/test/visual/base/screenshots/checkbox/baseline/basic.png
new file mode 100644
index 00000000000..83d3a4fe513
Binary files /dev/null and b/packages/checkbox/test/visual/base/screenshots/checkbox/baseline/basic.png differ
diff --git a/packages/checkbox/test/visual/base/screenshots/checkbox/baseline/checked-focus-ring.png b/packages/checkbox/test/visual/base/screenshots/checkbox/baseline/checked-focus-ring.png
new file mode 100644
index 00000000000..9b6c227bad1
Binary files /dev/null and b/packages/checkbox/test/visual/base/screenshots/checkbox/baseline/checked-focus-ring.png differ
diff --git a/packages/checkbox/test/visual/base/screenshots/checkbox/baseline/checked.png b/packages/checkbox/test/visual/base/screenshots/checkbox/baseline/checked.png
new file mode 100644
index 00000000000..dde44b490c2
Binary files /dev/null and b/packages/checkbox/test/visual/base/screenshots/checkbox/baseline/checked.png differ
diff --git a/packages/checkbox/test/visual/base/screenshots/checkbox/baseline/disabled-checked.png b/packages/checkbox/test/visual/base/screenshots/checkbox/baseline/disabled-checked.png
new file mode 100644
index 00000000000..9883c373a9f
Binary files /dev/null and b/packages/checkbox/test/visual/base/screenshots/checkbox/baseline/disabled-checked.png differ
diff --git a/packages/checkbox/test/visual/base/screenshots/checkbox/baseline/disabled-indeterminate.png b/packages/checkbox/test/visual/base/screenshots/checkbox/baseline/disabled-indeterminate.png
new file mode 100644
index 00000000000..1958b0f2d24
Binary files /dev/null and b/packages/checkbox/test/visual/base/screenshots/checkbox/baseline/disabled-indeterminate.png differ
diff --git a/packages/checkbox/test/visual/base/screenshots/checkbox/baseline/disabled-required.png b/packages/checkbox/test/visual/base/screenshots/checkbox/baseline/disabled-required.png
new file mode 100644
index 00000000000..3624b5dac4c
Binary files /dev/null and b/packages/checkbox/test/visual/base/screenshots/checkbox/baseline/disabled-required.png differ
diff --git a/packages/checkbox/test/visual/base/screenshots/checkbox/baseline/disabled.png b/packages/checkbox/test/visual/base/screenshots/checkbox/baseline/disabled.png
new file mode 100644
index 00000000000..9b230c1e2c9
Binary files /dev/null and b/packages/checkbox/test/visual/base/screenshots/checkbox/baseline/disabled.png differ
diff --git a/packages/checkbox/test/visual/base/screenshots/checkbox/baseline/empty.png b/packages/checkbox/test/visual/base/screenshots/checkbox/baseline/empty.png
new file mode 100644
index 00000000000..f960c190b1e
Binary files /dev/null and b/packages/checkbox/test/visual/base/screenshots/checkbox/baseline/empty.png differ
diff --git a/packages/checkbox/test/visual/base/screenshots/checkbox/baseline/error-message.png b/packages/checkbox/test/visual/base/screenshots/checkbox/baseline/error-message.png
new file mode 100644
index 00000000000..f9b178c0c70
Binary files /dev/null and b/packages/checkbox/test/visual/base/screenshots/checkbox/baseline/error-message.png differ
diff --git a/packages/checkbox/test/visual/base/screenshots/checkbox/baseline/focus-ring.png b/packages/checkbox/test/visual/base/screenshots/checkbox/baseline/focus-ring.png
new file mode 100644
index 00000000000..f0f46a460d5
Binary files /dev/null and b/packages/checkbox/test/visual/base/screenshots/checkbox/baseline/focus-ring.png differ
diff --git a/packages/checkbox/test/visual/base/screenshots/checkbox/baseline/helper-text.png b/packages/checkbox/test/visual/base/screenshots/checkbox/baseline/helper-text.png
new file mode 100644
index 00000000000..e364ff3601d
Binary files /dev/null and b/packages/checkbox/test/visual/base/screenshots/checkbox/baseline/helper-text.png differ
diff --git a/packages/checkbox/test/visual/base/screenshots/checkbox/baseline/indeterminate.png b/packages/checkbox/test/visual/base/screenshots/checkbox/baseline/indeterminate.png
new file mode 100644
index 00000000000..1693b7e7b14
Binary files /dev/null and b/packages/checkbox/test/visual/base/screenshots/checkbox/baseline/indeterminate.png differ
diff --git a/packages/checkbox/test/visual/base/screenshots/checkbox/baseline/readonly-checked.png b/packages/checkbox/test/visual/base/screenshots/checkbox/baseline/readonly-checked.png
new file mode 100644
index 00000000000..ad4360924ec
Binary files /dev/null and b/packages/checkbox/test/visual/base/screenshots/checkbox/baseline/readonly-checked.png differ
diff --git a/packages/checkbox/test/visual/base/screenshots/checkbox/baseline/readonly-focus-ring.png b/packages/checkbox/test/visual/base/screenshots/checkbox/baseline/readonly-focus-ring.png
new file mode 100644
index 00000000000..7f6bb23f6e6
Binary files /dev/null and b/packages/checkbox/test/visual/base/screenshots/checkbox/baseline/readonly-focus-ring.png differ
diff --git a/packages/checkbox/test/visual/base/screenshots/checkbox/baseline/readonly-indeterminate.png b/packages/checkbox/test/visual/base/screenshots/checkbox/baseline/readonly-indeterminate.png
new file mode 100644
index 00000000000..b6d85cade2e
Binary files /dev/null and b/packages/checkbox/test/visual/base/screenshots/checkbox/baseline/readonly-indeterminate.png differ
diff --git a/packages/checkbox/test/visual/base/screenshots/checkbox/baseline/readonly.png b/packages/checkbox/test/visual/base/screenshots/checkbox/baseline/readonly.png
new file mode 100644
index 00000000000..abd06826f97
Binary files /dev/null and b/packages/checkbox/test/visual/base/screenshots/checkbox/baseline/readonly.png differ
diff --git a/packages/checkbox/test/visual/base/screenshots/checkbox/baseline/required.png b/packages/checkbox/test/visual/base/screenshots/checkbox/baseline/required.png
new file mode 100644
index 00000000000..14c635fb9dc
Binary files /dev/null and b/packages/checkbox/test/visual/base/screenshots/checkbox/baseline/required.png differ
diff --git a/packages/checkbox/test/visual/base/screenshots/checkbox/baseline/rtl-empty.png b/packages/checkbox/test/visual/base/screenshots/checkbox/baseline/rtl-empty.png
new file mode 100644
index 00000000000..08fcc1b5089
Binary files /dev/null and b/packages/checkbox/test/visual/base/screenshots/checkbox/baseline/rtl-empty.png differ
diff --git a/packages/checkbox/test/visual/base/screenshots/checkbox/baseline/rtl-required.png b/packages/checkbox/test/visual/base/screenshots/checkbox/baseline/rtl-required.png
new file mode 100644
index 00000000000..862052d6430
Binary files /dev/null and b/packages/checkbox/test/visual/base/screenshots/checkbox/baseline/rtl-required.png differ
diff --git a/packages/checkbox/test/visual/base/screenshots/checkbox/baseline/rtl.png b/packages/checkbox/test/visual/base/screenshots/checkbox/baseline/rtl.png
new file mode 100644
index 00000000000..2ef881c370b
Binary files /dev/null and b/packages/checkbox/test/visual/base/screenshots/checkbox/baseline/rtl.png differ
diff --git a/packages/component-base/src/style-props.js b/packages/component-base/src/style-props.js
index 74d6d32facf..115b9dc585e 100644
--- a/packages/component-base/src/style-props.js
+++ b/packages/component-base/src/style-props.js
@@ -44,11 +44,11 @@ addGlobalThemeStyles(
/* Focus outline */
--vaadin-focus-ring-width: 2px;
- --vaadin-focus-ring-color: var(--_vaadin-color);
+ --vaadin-focus-ring-color: var(--_vaadin-color-strong);
/* Icons, used as mask-image */
--_vaadin-icon-calendar: url('data:image/svg+xml,');
- --_vaadin-icon-checkmark: url('data:image/svg+xml;utf8,');
+ --_vaadin-icon-checkmark: url('data:image/svg+xml;utf8,');
--_vaadin-icon-chevron-down: url('data:image/svg+xml,');
--_vaadin-icon-clock: url('data:image/svg+xml,');
--_vaadin-icon-cross: url('data:image/svg+xml;utf8,');
diff --git a/packages/field-base/src/styles/checkbox-radio-styles.d.ts b/packages/field-base/src/styles/checkbox-radio-styles.d.ts
new file mode 100644
index 00000000000..63680914a4b
--- /dev/null
+++ b/packages/field-base/src/styles/checkbox-radio-styles.d.ts
@@ -0,0 +1,8 @@
+/**
+ * @license
+ * Copyright (c) 2021 - 2025 Vaadin Ltd.
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
+ */
+import type { CSSResult } from 'lit';
+
+export const checkboxRadio: CSSResult;
diff --git a/packages/field-base/src/styles/checkbox-radio-styles.js b/packages/field-base/src/styles/checkbox-radio-styles.js
new file mode 100644
index 00000000000..de3508cd9df
--- /dev/null
+++ b/packages/field-base/src/styles/checkbox-radio-styles.js
@@ -0,0 +1,152 @@
+/**
+ * @license
+ * Copyright (c) 2021 - 2025 Vaadin Ltd.
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
+ */
+import '@vaadin/component-base/src/style-props.js';
+import { css, unsafeCSS } from 'lit';
+
+export const checkboxRadio = (part, propName = part) => css`
+ :host {
+ align-items: center;
+ display: inline-grid;
+ gap: var(--vaadin-${unsafeCSS(propName)}-gap, 0.25lh var(--_vaadin-gap-container-inline));
+ grid-template-columns: auto 1fr;
+ -webkit-tap-highlight-color: transparent;
+ }
+
+ :host([disabled]) {
+ cursor: not-allowed;
+ }
+
+ .vaadin-${unsafeCSS(propName)}-container {
+ display: contents;
+ }
+
+ [part='${unsafeCSS(part)}'],
+ ::slotted(input),
+ [part='label'],
+ ::slotted(label) {
+ grid-row: 1;
+ }
+
+ [part='label'],
+ ::slotted(label) {
+ font-size: var(--vaadin-${unsafeCSS(propName)}-label-font-size, var(--vaadin-input-field-label-font-size, inherit));
+ line-height: var(--vaadin-${unsafeCSS(propName)}-label-line-height, var(--vaadin-input-field-label-line-height, inherit));
+ font-weight: var(--vaadin-${unsafeCSS(propName)}-font-weight, var(--vaadin-input-field-label-font-weight, 500));
+ color: var(--vaadin-${unsafeCSS(propName)}-label-color, var(--vaadin-input-field-label-color, var(--_vaadin-color-strong)));
+ }
+
+ [part='${unsafeCSS(part)}'],
+ ::slotted(input) {
+ grid-column: 1;
+ }
+
+ [part='helper-text'],
+ [part='error-message'] {
+ grid-column: 2;
+ }
+
+ /* Baseline vertical alignment */
+ :host::before {
+ content: '\\2003';
+ grid-column: 1;
+ grid-row: 1;
+ z-index: -1;
+ width: 0;
+ }
+
+ /* visually hidden */
+ ::slotted(input) {
+ cursor: inherit;
+ margin: 0;
+ align-self: stretch;
+ appearance: none;
+ width: 100%;
+ height: 100%;
+ }
+
+ /* Control container (checkbox, radio button) */
+ [part='${unsafeCSS(part)}'] {
+ background: var(--vaadin-${unsafeCSS(part)}-background, var(--_vaadin-background));
+ border-color: var(--vaadin-${unsafeCSS(propName)}-border-color, var(--vaadin-input-field-border-color, var(--_vaadin-border-color-strong)));
+ border-radius: var(--vaadin-${unsafeCSS(propName)}-border-radius, var(--_vaadin-radius-s));
+ border-style: solid;
+ --_border-width: var(--vaadin-${unsafeCSS(propName)}-border-width, var(--vaadin-input-field-border-width, 1px));
+ border-width: var(--_border-width);
+ box-sizing: border-box;
+ color: var(--vaadin-${unsafeCSS(propName)}-color, var(--vaadin-input-field-text-color, var(--_vaadin-color-strong)));
+ height: var(--vaadin-${unsafeCSS(propName)}-size, 1lh);
+ width: var(--vaadin-${unsafeCSS(propName)}-size, 1lh);
+ position: relative;
+ }
+
+ :host(:is([checked], [indeterminate])) {
+ --vaadin-${unsafeCSS(part)}-background: var(--_vaadin-color-strong);
+ --vaadin-${unsafeCSS(propName)}-border-color: transparent;
+ --vaadin-${unsafeCSS(propName)}-color: var(--_vaadin-background);
+ }
+
+ :host([readonly]) {
+ --vaadin-checkbox-background: transparent;
+ --vaadin-checkbox-border-color: var(--_vaadin-border-color-strong);
+ --vaadin-checkbox-color: var(--_vaadin-color-strong);
+ }
+
+ :host([readonly]) [part='${unsafeCSS(part)}'] {
+ border-style: dashed;
+ }
+
+ :host([disabled]) {
+ --vaadin-${unsafeCSS(part)}-background: var(--vaadin-input-field-disabled-background, var(--_vaadin-background-container-strong));
+ --vaadin-${unsafeCSS(propName)}-border-color: transparent;
+ --vaadin-${unsafeCSS(propName)}-color: var(--_vaadin-color-subtle);
+ }
+
+ /* Focus ring */
+ :host([focus-ring]) [part='${unsafeCSS(part)}'] {
+ outline: var(--vaadin-focus-ring-width) solid var(--vaadin-focus-ring-color);
+ outline-offset: calc(var(--_border-width) * -1);
+ }
+
+ :host([focus-ring]:is([checked], [indeterminate])) [part='${unsafeCSS(part)}'] {
+ outline-offset: 1px;
+ }
+
+ :host([readonly][focus-ring]) [part='${unsafeCSS(part)}'] {
+ --vaadin-${unsafeCSS(propName)}-border-color: transparent;
+ outline-offset: calc(var(--_border-width) * -1);
+ outline-style: dashed;
+ }
+
+ /* Checked indicator (checkmark, dot) */
+ [part='${unsafeCSS(part)}']::after {
+ content: '';
+ position: absolute;
+ background: currentColor;
+ border-radius: inherit;
+ }
+
+ :host(:not([checked], [indeterminate])) [part='${unsafeCSS(part)}']::after {
+ display: none;
+ }
+
+ @media (forced-colors: active) {
+ :host(:is([checked], [indeterminate])) {
+ --vaadin-${unsafeCSS(propName)}-border-color: CanvasText;
+ }
+
+ :host([readonly]) [part='${unsafeCSS(part)}']::after {
+ background: CanvasText;
+ }
+
+ :host([disabled]) {
+ --vaadin-${unsafeCSS(propName)}-border-color: GrayText;
+ }
+
+ :host([disabled]) [part='${unsafeCSS(part)}']::after {
+ background: GrayText;
+ }
+ }
+`;
diff --git a/packages/field-base/src/styles/field-shared-styles.js b/packages/field-base/src/styles/field-shared-styles.js
index b54ac92beae..0c033fa5279 100644
--- a/packages/field-base/src/styles/field-shared-styles.js
+++ b/packages/field-base/src/styles/field-shared-styles.js
@@ -10,14 +10,8 @@ export const fieldShared = css`
:host {
display: inline-flex;
outline: none;
- }
-
- :host::before {
- content: '\\2003';
- width: 0;
- display: inline-block;
- /* Size and position this element on the same vertical position as the input-field element
- to make vertical align for the host element work as expected */
+ cursor: default;
+ -webkit-tap-highlight-color: transparent;
}
:host([hidden]) {
@@ -30,16 +24,35 @@ export const fieldShared = css`
display: none;
}
- [part='label'] {
+ [part='label'],
+ ::slotted(label) {
font-size: var(--vaadin-input-field-label-font-size, inherit);
line-height: var(--vaadin-input-field-label-line-height, inherit);
font-weight: var(--vaadin-input-field-label-font-weight, 500);
color: var(--vaadin-input-field-label-color, var(--_vaadin-color-strong));
+ word-break: break-word;
+ }
+
+ ::slotted(label) {
+ cursor: inherit;
+ }
+
+ [part='label'] {
order: var(--vaadin-input-field-helper-order);
}
+ :host([disabled]) [part='label'],
+ :host([disabled]) ::slotted(label) {
+ opacity: 0.5;
+ }
+
+ :host([disabled]) [part='label'] ::slotted(label) {
+ opacity: 1;
+ }
+
[part='required-indicator'] {
- color: var(--vaadin-input-field-required-indicator-color, inherit);
+ display: inline-block;
+ color: var(--vaadin-input-field-required-indicator-color, var(--_vaadin-color));
}
[part='required-indicator']::after {
diff --git a/packages/radio-group/src/vaadin-lit-radio-button.js b/packages/radio-group/src/vaadin-lit-radio-button.js
index 8cda8bdccd2..8b73f5e1205 100644
--- a/packages/radio-group/src/vaadin-lit-radio-button.js
+++ b/packages/radio-group/src/vaadin-lit-radio-button.js
@@ -7,6 +7,7 @@ import { html, LitElement } from 'lit';
import { defineCustomElement } from '@vaadin/component-base/src/define.js';
import { ElementMixin } from '@vaadin/component-base/src/element-mixin.js';
import { PolylitMixin } from '@vaadin/component-base/src/polylit-mixin.js';
+import { fieldShared } from '@vaadin/field-base/src/styles/field-shared-styles.js';
import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
import { RadioButtonMixin } from './vaadin-radio-button-mixin.js';
import { radioButtonStyles } from './vaadin-radio-button-styles.js';
@@ -26,7 +27,7 @@ class RadioButton extends RadioButtonMixin(ElementMixin(ThemableMixin(PolylitMix
}
static get styles() {
- return radioButtonStyles;
+ return [fieldShared, radioButtonStyles];
}
/** @protected */
diff --git a/packages/radio-group/src/vaadin-lit-radio-group.js b/packages/radio-group/src/vaadin-lit-radio-group.js
index 4d1f8636706..43e28b225a1 100644
--- a/packages/radio-group/src/vaadin-lit-radio-group.js
+++ b/packages/radio-group/src/vaadin-lit-radio-group.js
@@ -8,6 +8,7 @@ import { html, LitElement } from 'lit';
import { defineCustomElement } from '@vaadin/component-base/src/define.js';
import { ElementMixin } from '@vaadin/component-base/src/element-mixin.js';
import { PolylitMixin } from '@vaadin/component-base/src/polylit-mixin.js';
+import { fieldShared } from '@vaadin/field-base/src/styles/field-shared-styles.js';
import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
import { RadioGroupMixin } from './vaadin-radio-group-mixin.js';
import { radioGroupStyles } from './vaadin-radio-group-styles.js';
@@ -27,7 +28,7 @@ class RadioGroup extends RadioGroupMixin(ElementMixin(ThemableMixin(PolylitMixin
}
static get styles() {
- return radioGroupStyles;
+ return [fieldShared, radioGroupStyles];
}
/** @protected */
diff --git a/packages/radio-group/src/vaadin-radio-button-styles.js b/packages/radio-group/src/vaadin-radio-button-styles.js
index 2f64b1aef29..3574e2642dc 100644
--- a/packages/radio-group/src/vaadin-radio-button-styles.js
+++ b/packages/radio-group/src/vaadin-radio-button-styles.js
@@ -3,75 +3,23 @@
* Copyright (c) 2017 - 2025 Vaadin Ltd.
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
*/
-import { css } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
+import { css } from 'lit';
+import { checkboxRadio } from '@vaadin/field-base/src/styles/checkbox-radio-styles';
-export const radioButtonStyles = css`
- :host {
- display: inline-block;
- }
-
- :host([hidden]) {
- display: none !important;
- }
-
- :host([disabled]) {
- -webkit-tap-highlight-color: transparent;
- }
-
- .vaadin-radio-button-container {
- display: grid;
- grid-template-columns: auto 1fr;
- align-items: baseline;
- }
-
- [part='radio'],
- ::slotted(input),
- ::slotted(label) {
- grid-row: 1;
- }
-
- [part='radio'],
- ::slotted(input) {
- grid-column: 1;
- }
-
- [part='radio'] {
- width: var(--vaadin-radio-button-size, 1em);
- height: var(--vaadin-radio-button-size, 1em);
- --_input-border-width: var(--vaadin-input-field-border-width, 0);
- --_input-border-color: var(--vaadin-input-field-border-color, transparent);
- box-shadow: inset 0 0 0 var(--_input-border-width, 0) var(--_input-border-color);
- }
-
- [part='radio']::before {
- display: block;
- content: '\\202F';
- line-height: var(--vaadin-radio-button-size, 1em);
- contain: paint;
- }
-
- /* visually hidden */
- ::slotted(input) {
- cursor: inherit;
- margin: 0;
- align-self: stretch;
- -webkit-appearance: none;
- width: initial;
- height: initial;
- }
-
- @media (forced-colors: active) {
+export const radioButtonStyles = [
+ checkboxRadio('radio', 'radio-button'),
+ css`
[part='radio'] {
- outline: 1px solid;
- outline-offset: -1px;
- }
-
- :host([focused]) [part='radio'] {
- outline-width: 2px;
+ border-radius: 50%;
}
- :host([disabled]) [part='radio'] {
- outline-color: GrayText;
+ [part='radio']::after {
+ top: 50%;
+ left: 50%;
+ translate: -50% -50%;
+ width: var(--vaadin-radio-button-dot-size, 50%);
+ height: var(--vaadin-radio-button-dot-size, 50%);
+ border-radius: 50%;
}
- }
-`;
+ `,
+];
diff --git a/packages/radio-group/src/vaadin-radio-group-styles.js b/packages/radio-group/src/vaadin-radio-group-styles.js
index 2269a27eda8..6d80078722e 100644
--- a/packages/radio-group/src/vaadin-radio-group-styles.js
+++ b/packages/radio-group/src/vaadin-radio-group-styles.js
@@ -3,35 +3,6 @@
* Copyright (c) 2017 - 2025 Vaadin Ltd.
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
*/
-import { css } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
+import { checkboxGroupStyles } from '@vaadin/checkbox-group/src/vaadin-checkbox-group-styles.js';
-export const radioGroupStyles = css`
- :host {
- display: inline-flex;
- }
-
- :host::before {
- content: '\\2003';
- width: 0;
- display: inline-block;
- }
-
- :host([hidden]) {
- display: none !important;
- }
-
- .vaadin-group-field-container {
- display: flex;
- flex-direction: column;
- width: 100%;
- }
-
- [part='group-field'] {
- display: flex;
- flex-wrap: wrap;
- }
-
- :host(:not([has-label])) [part='label'] {
- display: none;
- }
-`;
+export const radioGroupStyles = checkboxGroupStyles('radio-button');
diff --git a/packages/radio-group/test/visual/base/radio-button.test.js b/packages/radio-group/test/visual/base/radio-button.test.js
new file mode 100644
index 00000000000..cd973f635c4
--- /dev/null
+++ b/packages/radio-group/test/visual/base/radio-button.test.js
@@ -0,0 +1,74 @@
+import { sendKeys } from '@vaadin/test-runner-commands';
+import { fixtureSync } from '@vaadin/testing-helpers';
+import { visualDiff } from '@web/test-runner-visual-regression';
+import '../../../src/vaadin-lit-radio-button.js';
+
+describe('radio-button', () => {
+ let div, element;
+
+ beforeEach(() => {
+ div = document.createElement('div');
+ div.style.display = 'inline-block';
+ div.style.padding = '10px';
+ element = fixtureSync('', div);
+ });
+
+ it('basic', async () => {
+ await visualDiff(div, 'basic');
+ });
+
+ it('empty', async () => {
+ element.label = '';
+ await visualDiff(div, 'empty');
+ });
+
+ it('checked', async () => {
+ element.checked = true;
+ await visualDiff(div, 'checked');
+ });
+
+ it('focus-ring', async () => {
+ await sendKeys({ press: 'Tab' });
+ await visualDiff(div, 'focus-ring');
+ });
+
+ it('checked focus-ring', async () => {
+ element.checked = true;
+ await sendKeys({ press: 'Tab' });
+ await visualDiff(div, 'checked-focus-ring');
+ });
+
+ describe('disabled', () => {
+ beforeEach(() => {
+ element.disabled = true;
+ });
+
+ it('basic', async () => {
+ await visualDiff(div, 'disabled');
+ });
+
+ it('checked', async () => {
+ element.checked = true;
+ await visualDiff(div, 'disabled-checked');
+ });
+ });
+
+ describe('RTL', () => {
+ before(() => {
+ document.documentElement.setAttribute('dir', 'rtl');
+ });
+
+ after(() => {
+ document.documentElement.removeAttribute('dir');
+ });
+
+ it('basic', async () => {
+ await visualDiff(div, 'rtl');
+ });
+
+ it('empty', async () => {
+ element.label = '';
+ await visualDiff(div, 'rtl-empty');
+ });
+ });
+});
diff --git a/packages/radio-group/test/visual/base/radio-group.test.js b/packages/radio-group/test/visual/base/radio-group.test.js
new file mode 100644
index 00000000000..9b564fe3bb9
--- /dev/null
+++ b/packages/radio-group/test/visual/base/radio-group.test.js
@@ -0,0 +1,127 @@
+import { sendKeys } from '@vaadin/test-runner-commands';
+import { fixtureSync } from '@vaadin/testing-helpers/dist/fixture.js';
+import { visualDiff } from '@web/test-runner-visual-regression';
+import '../common.js';
+import '../../../src/vaadin-lit-radio-group.js';
+
+describe('radio-group', () => {
+ let div, element;
+
+ beforeEach(() => {
+ div = document.createElement('div');
+ div.style.display = 'inline-block';
+ div.style.padding = '10px';
+
+ element = fixtureSync(
+ `
+
+
+
+
+
+ `,
+ div,
+ );
+ });
+
+ describe('default', () => {
+ it('basic', async () => {
+ await visualDiff(div, 'basic');
+ });
+
+ it('disabled', async () => {
+ element.disabled = true;
+ await visualDiff(div, 'disabled');
+ });
+
+ it('horizontal', async () => {
+ element.setAttribute('theme', 'horizontal');
+ await visualDiff(div, 'horizontal');
+ });
+
+ it('label', async () => {
+ element.label = 'Label';
+ await visualDiff(div, 'label');
+ });
+
+ it('label focused', async () => {
+ element.label = 'Label';
+ await sendKeys({ press: 'Tab' });
+ await visualDiff(div, 'label-focused');
+ });
+
+ it('label disabled', async () => {
+ element.label = 'Label';
+ element.disabled = true;
+ await visualDiff(div, 'label-disabled');
+ });
+
+ it('value', async () => {
+ element.value = 'a';
+ await visualDiff(div, 'value');
+ });
+
+ it('required', async () => {
+ element.label = 'Label';
+ element.required = true;
+ await visualDiff(div, 'required');
+ });
+
+ it('error message', async () => {
+ element.label = 'Label';
+ element.errorMessage = 'This field is required';
+ element.required = true;
+ element.validate();
+ await visualDiff(div, 'error-message');
+ });
+
+ it('helper text', async () => {
+ element.helperText = 'Helper text';
+ await visualDiff(div, 'helper-text');
+ });
+
+ it('helper above field', async () => {
+ element.label = 'Label';
+ element.errorMessage = 'This field is required';
+ element.required = true;
+ element.validate();
+ element.helperText = 'Helper text';
+ element.setAttribute('theme', 'helper-above-field');
+ await visualDiff(div, 'helper-above-field');
+ });
+
+ it('wrapped', async () => {
+ element.setAttribute('theme', 'horizontal');
+ element.style.width = '150px';
+ await visualDiff(div, 'wrapped');
+ });
+ });
+
+ describe('RTL', () => {
+ before(() => {
+ document.documentElement.setAttribute('dir', 'rtl');
+ });
+
+ after(() => {
+ document.documentElement.removeAttribute('dir');
+ });
+
+ it('RTL basic', async () => {
+ await visualDiff(div, 'rtl-basic');
+ });
+
+ it('RTL error message', async () => {
+ element.label = 'Label';
+ element.errorMessage = 'This field is required';
+ element.required = true;
+ element.validate();
+ await visualDiff(div, 'rtl-error-message');
+ });
+
+ it('RTL wrapped', async () => {
+ element.setAttribute('theme', 'horizontal');
+ element.style.width = '150px';
+ await visualDiff(div, 'rtl-wrapped');
+ });
+ });
+});
diff --git a/packages/radio-group/test/visual/base/screenshots/radio-button/baseline/basic.png b/packages/radio-group/test/visual/base/screenshots/radio-button/baseline/basic.png
new file mode 100644
index 00000000000..785facfd1a7
Binary files /dev/null and b/packages/radio-group/test/visual/base/screenshots/radio-button/baseline/basic.png differ
diff --git a/packages/radio-group/test/visual/base/screenshots/radio-button/baseline/checked-focus-ring.png b/packages/radio-group/test/visual/base/screenshots/radio-button/baseline/checked-focus-ring.png
new file mode 100644
index 00000000000..7b3b67d95a7
Binary files /dev/null and b/packages/radio-group/test/visual/base/screenshots/radio-button/baseline/checked-focus-ring.png differ
diff --git a/packages/radio-group/test/visual/base/screenshots/radio-button/baseline/checked.png b/packages/radio-group/test/visual/base/screenshots/radio-button/baseline/checked.png
new file mode 100644
index 00000000000..e181edcdedb
Binary files /dev/null and b/packages/radio-group/test/visual/base/screenshots/radio-button/baseline/checked.png differ
diff --git a/packages/radio-group/test/visual/base/screenshots/radio-button/baseline/disabled-checked.png b/packages/radio-group/test/visual/base/screenshots/radio-button/baseline/disabled-checked.png
new file mode 100644
index 00000000000..efdd29bae66
Binary files /dev/null and b/packages/radio-group/test/visual/base/screenshots/radio-button/baseline/disabled-checked.png differ
diff --git a/packages/radio-group/test/visual/base/screenshots/radio-button/baseline/disabled.png b/packages/radio-group/test/visual/base/screenshots/radio-button/baseline/disabled.png
new file mode 100644
index 00000000000..784f8473089
Binary files /dev/null and b/packages/radio-group/test/visual/base/screenshots/radio-button/baseline/disabled.png differ
diff --git a/packages/radio-group/test/visual/base/screenshots/radio-button/baseline/empty.png b/packages/radio-group/test/visual/base/screenshots/radio-button/baseline/empty.png
new file mode 100644
index 00000000000..68cc55293dc
Binary files /dev/null and b/packages/radio-group/test/visual/base/screenshots/radio-button/baseline/empty.png differ
diff --git a/packages/radio-group/test/visual/base/screenshots/radio-button/baseline/focus-ring.png b/packages/radio-group/test/visual/base/screenshots/radio-button/baseline/focus-ring.png
new file mode 100644
index 00000000000..95ed60656fb
Binary files /dev/null and b/packages/radio-group/test/visual/base/screenshots/radio-button/baseline/focus-ring.png differ
diff --git a/packages/radio-group/test/visual/base/screenshots/radio-button/baseline/rtl-empty.png b/packages/radio-group/test/visual/base/screenshots/radio-button/baseline/rtl-empty.png
new file mode 100644
index 00000000000..bd1357334c7
Binary files /dev/null and b/packages/radio-group/test/visual/base/screenshots/radio-button/baseline/rtl-empty.png differ
diff --git a/packages/radio-group/test/visual/base/screenshots/radio-button/baseline/rtl.png b/packages/radio-group/test/visual/base/screenshots/radio-button/baseline/rtl.png
new file mode 100644
index 00000000000..0c727b0c330
Binary files /dev/null and b/packages/radio-group/test/visual/base/screenshots/radio-button/baseline/rtl.png differ
diff --git a/packages/radio-group/test/visual/base/screenshots/radio-group/baseline/basic.png b/packages/radio-group/test/visual/base/screenshots/radio-group/baseline/basic.png
new file mode 100644
index 00000000000..0eec2a1c5c2
Binary files /dev/null and b/packages/radio-group/test/visual/base/screenshots/radio-group/baseline/basic.png differ
diff --git a/packages/radio-group/test/visual/base/screenshots/radio-group/baseline/disabled.png b/packages/radio-group/test/visual/base/screenshots/radio-group/baseline/disabled.png
new file mode 100644
index 00000000000..dd60eefd65d
Binary files /dev/null and b/packages/radio-group/test/visual/base/screenshots/radio-group/baseline/disabled.png differ
diff --git a/packages/radio-group/test/visual/base/screenshots/radio-group/baseline/error-message.png b/packages/radio-group/test/visual/base/screenshots/radio-group/baseline/error-message.png
new file mode 100644
index 00000000000..201c371ad4d
Binary files /dev/null and b/packages/radio-group/test/visual/base/screenshots/radio-group/baseline/error-message.png differ
diff --git a/packages/radio-group/test/visual/base/screenshots/radio-group/baseline/helper-above-field.png b/packages/radio-group/test/visual/base/screenshots/radio-group/baseline/helper-above-field.png
new file mode 100644
index 00000000000..a5f4a940ed5
Binary files /dev/null and b/packages/radio-group/test/visual/base/screenshots/radio-group/baseline/helper-above-field.png differ
diff --git a/packages/radio-group/test/visual/base/screenshots/radio-group/baseline/helper-text.png b/packages/radio-group/test/visual/base/screenshots/radio-group/baseline/helper-text.png
new file mode 100644
index 00000000000..4e40fe798d7
Binary files /dev/null and b/packages/radio-group/test/visual/base/screenshots/radio-group/baseline/helper-text.png differ
diff --git a/packages/radio-group/test/visual/base/screenshots/radio-group/baseline/horizontal.png b/packages/radio-group/test/visual/base/screenshots/radio-group/baseline/horizontal.png
new file mode 100644
index 00000000000..34bdf312762
Binary files /dev/null and b/packages/radio-group/test/visual/base/screenshots/radio-group/baseline/horizontal.png differ
diff --git a/packages/radio-group/test/visual/base/screenshots/radio-group/baseline/label-disabled.png b/packages/radio-group/test/visual/base/screenshots/radio-group/baseline/label-disabled.png
new file mode 100644
index 00000000000..79d21a0e885
Binary files /dev/null and b/packages/radio-group/test/visual/base/screenshots/radio-group/baseline/label-disabled.png differ
diff --git a/packages/radio-group/test/visual/base/screenshots/radio-group/baseline/label-focused.png b/packages/radio-group/test/visual/base/screenshots/radio-group/baseline/label-focused.png
new file mode 100644
index 00000000000..86b8f9f5c62
Binary files /dev/null and b/packages/radio-group/test/visual/base/screenshots/radio-group/baseline/label-focused.png differ
diff --git a/packages/radio-group/test/visual/base/screenshots/radio-group/baseline/label.png b/packages/radio-group/test/visual/base/screenshots/radio-group/baseline/label.png
new file mode 100644
index 00000000000..f7a89e80390
Binary files /dev/null and b/packages/radio-group/test/visual/base/screenshots/radio-group/baseline/label.png differ
diff --git a/packages/radio-group/test/visual/base/screenshots/radio-group/baseline/required.png b/packages/radio-group/test/visual/base/screenshots/radio-group/baseline/required.png
new file mode 100644
index 00000000000..342c6e21e67
Binary files /dev/null and b/packages/radio-group/test/visual/base/screenshots/radio-group/baseline/required.png differ
diff --git a/packages/radio-group/test/visual/base/screenshots/radio-group/baseline/rtl-basic.png b/packages/radio-group/test/visual/base/screenshots/radio-group/baseline/rtl-basic.png
new file mode 100644
index 00000000000..0148cbe2c28
Binary files /dev/null and b/packages/radio-group/test/visual/base/screenshots/radio-group/baseline/rtl-basic.png differ
diff --git a/packages/radio-group/test/visual/base/screenshots/radio-group/baseline/rtl-error-message.png b/packages/radio-group/test/visual/base/screenshots/radio-group/baseline/rtl-error-message.png
new file mode 100644
index 00000000000..dd42ec97bbb
Binary files /dev/null and b/packages/radio-group/test/visual/base/screenshots/radio-group/baseline/rtl-error-message.png differ
diff --git a/packages/radio-group/test/visual/base/screenshots/radio-group/baseline/rtl-wrapped.png b/packages/radio-group/test/visual/base/screenshots/radio-group/baseline/rtl-wrapped.png
new file mode 100644
index 00000000000..ac1c27cdd4a
Binary files /dev/null and b/packages/radio-group/test/visual/base/screenshots/radio-group/baseline/rtl-wrapped.png differ
diff --git a/packages/radio-group/test/visual/base/screenshots/radio-group/baseline/value.png b/packages/radio-group/test/visual/base/screenshots/radio-group/baseline/value.png
new file mode 100644
index 00000000000..11d102c8033
Binary files /dev/null and b/packages/radio-group/test/visual/base/screenshots/radio-group/baseline/value.png differ
diff --git a/packages/radio-group/test/visual/base/screenshots/radio-group/baseline/wrapped.png b/packages/radio-group/test/visual/base/screenshots/radio-group/baseline/wrapped.png
new file mode 100644
index 00000000000..7b2b798c30b
Binary files /dev/null and b/packages/radio-group/test/visual/base/screenshots/radio-group/baseline/wrapped.png differ
diff --git a/test/integration/component-tooltip.test.js b/test/integration/component-tooltip.test.js
index b41e0b2ede2..386d8297026 100644
--- a/test/integration/component-tooltip.test.js
+++ b/test/integration/component-tooltip.test.js
@@ -36,7 +36,13 @@ before(() => {
[
{ tagName: Button.is },
{ tagName: Checkbox.is, ariaTargetSelector: 'input' },
- { tagName: CheckboxGroup.is },
+ {
+ tagName: CheckboxGroup.is,
+ children: `
+
+
+ `,
+ },
{
tagName: ComboBox.is,
position: 'top',