diff --git a/.changeset/selfish-vans-sit.md b/.changeset/selfish-vans-sit.md
new file mode 100644
index 000000000..6f6d79bf6
--- /dev/null
+++ b/.changeset/selfish-vans-sit.md
@@ -0,0 +1,7 @@
+---
+'@lion/form-core': patch
+'@lion/switch': patch
+---
+
+- prevent toggle of checked state when disabled
+- dispatch checked-changed on label click
diff --git a/packages/form-core/src/choice-group/ChoiceInputMixin.js b/packages/form-core/src/choice-group/ChoiceInputMixin.js
index 68f581aa7..5c3694864 100644
--- a/packages/form-core/src/choice-group/ChoiceInputMixin.js
+++ b/packages/form-core/src/choice-group/ChoiceInputMixin.js
@@ -31,6 +31,13 @@ const ChoiceInputMixinImplementation = superclass =>
type: Boolean,
reflect: true,
},
+ /**
+ * Boolean indicating whether or not this element is disabled.
+ */
+ disabled: {
+ type: Boolean,
+ reflect: true,
+ },
/**
* Whereas 'normal' `.modelValue`s usually store a complex/typed version
* of a view value, choice inputs have a slightly different approach.
@@ -108,6 +115,7 @@ const ChoiceInputMixinImplementation = superclass =>
constructor() {
super();
this.modelValue = { value: '', checked: false };
+ this.disabled = false;
this.__toggleChecked = this.__toggleChecked.bind(this);
}
@@ -170,6 +178,9 @@ const ChoiceInputMixinImplementation = superclass =>
}
__toggleChecked() {
+ if (this.disabled) {
+ return;
+ }
this.checked = !this.checked;
}
diff --git a/packages/form-core/test/choice-group/ChoiceInputMixin.test.js b/packages/form-core/test/choice-group/ChoiceInputMixin.test.js
index 8c98e793f..dd43987c7 100644
--- a/packages/form-core/test/choice-group/ChoiceInputMixin.test.js
+++ b/packages/form-core/test/choice-group/ChoiceInputMixin.test.js
@@ -131,6 +131,14 @@ describe('ChoiceInputMixin', () => {
expect(el.checked).to.be.false;
});
+ it('can not toggle the checked state when disabled via user interaction', async () => {
+ const el = /** @type {ChoiceClass} */ (await fixture(
+ html``,
+ ));
+ el._inputNode.dispatchEvent(new CustomEvent('change', { bubbles: true }));
+ expect(el.checked).to.be.false;
+ });
+
it('synchronizes modelValue to checked state and vice versa', async () => {
const el = /** @type {ChoiceClass} */ (await fixture(
html``,
diff --git a/packages/switch/test/lion-switch.test.js b/packages/switch/test/lion-switch.test.js
index 0622c6094..c11156ced 100644
--- a/packages/switch/test/lion-switch.test.js
+++ b/packages/switch/test/lion-switch.test.js
@@ -16,6 +16,12 @@ describe('lion-switch', () => {
expect(el.checked).to.be.false;
});
+ it('clicking the label should not toggle the checked state when disabled', async () => {
+ const el = await fixture(html``);
+ el._labelNode.click();
+ expect(el.checked).to.be.false;
+ });
+
it('should sync its "disabled" state to child button', async () => {
const el = await fixture(html``);
expect(el._inputNode.disabled).to.be.true;