From 78b3980ceaab19b7c1af396abc29cde43457d26e Mon Sep 17 00:00:00 2001 From: Matthew Buckett Date: Tue, 9 Dec 2025 13:38:45 +0000 Subject: [PATCH] fix(ui-checkbox): warn CheckboxGroup onChange CheckboxGroup overrides the onChange value of contained Checkbox components. If a developer incorrectly sets an onChange property on the Checkbox contained within a CheckboxGroup we write a warning to the console in the standard way. The behaviour is also added to the documentation in the "Guidelines -> Don't" section. --- .../ui-checkbox/src/CheckboxGroup/README.md | 1 + .../__tests__/CheckboxGroup.test.tsx | 25 +++++++++++++++++++ .../ui-checkbox/src/CheckboxGroup/index.tsx | 5 ++++ 3 files changed, 31 insertions(+) diff --git a/packages/ui-checkbox/src/CheckboxGroup/README.md b/packages/ui-checkbox/src/CheckboxGroup/README.md index e47df09552..6c32e3b559 100644 --- a/packages/ui-checkbox/src/CheckboxGroup/README.md +++ b/packages/ui-checkbox/src/CheckboxGroup/README.md @@ -95,6 +95,7 @@ type: embed
Run more than two checkboxes horizontally + Attempt to set `onChange` on `Checkbox` contained within a `CheckboxGroup`
``` diff --git a/packages/ui-checkbox/src/CheckboxGroup/__tests__/CheckboxGroup.test.tsx b/packages/ui-checkbox/src/CheckboxGroup/__tests__/CheckboxGroup.test.tsx index 614d69251b..cd463acd72 100644 --- a/packages/ui-checkbox/src/CheckboxGroup/__tests__/CheckboxGroup.test.tsx +++ b/packages/ui-checkbox/src/CheckboxGroup/__tests__/CheckboxGroup.test.tsx @@ -83,6 +83,31 @@ describe('', () => { expect(checkboxes[1]).toHaveAttribute('name', TEST_NAME) }) + it('should not issue a warning/error by default', () => { + renderCheckboxGroup({ name: TEST_NAME }) + + expect(consoleWarningMock).not.toHaveBeenCalled() + expect(consoleErrorMock).not.toHaveBeenCalled() + }) + + it('should issue a warning when a child Checkbox has an onChange prop', () => { + const changeSpy = vi.fn() + render( + + + + ) + + expect(consoleErrorMock).toHaveBeenCalled() + expect(consoleErrorMock.mock.calls[0][0]).toBe( + 'Warning: [CheckboxGroup] When part of a CheckboxGroup, Checkbox components cannot have their own `onChange` prop.' + ) + }) + it('links the messages to the fieldset via aria-describedby', () => { const { container } = renderCheckboxGroup({ messages: [{ text: TEST_ERROR_MESSAGE, type: 'error' }] diff --git a/packages/ui-checkbox/src/CheckboxGroup/index.tsx b/packages/ui-checkbox/src/CheckboxGroup/index.tsx index 3e59c76e02..72ba9c03dd 100644 --- a/packages/ui-checkbox/src/CheckboxGroup/index.tsx +++ b/packages/ui-checkbox/src/CheckboxGroup/index.tsx @@ -41,6 +41,7 @@ import type { CheckboxGroupState, CheckboxChild } from './props' +import { error } from '@instructure/console' /** --- @@ -117,6 +118,10 @@ class CheckboxGroup extends Component { return Children.map(children, (child) => { if (matchComponentTypes(child, [Checkbox])) { + error( + typeof child.props.onChange === 'undefined', + '[CheckboxGroup] When part of a CheckboxGroup, Checkbox components cannot have their own `onChange` prop.' + ) return safeCloneElement(child, { key: `${child.props.name}`, name,