From aa8d9d56afb41720fc3faa7d00a81fa248a5e9d4 Mon Sep 17 00:00:00 2001 From: Albert Yu Date: Fri, 29 May 2026 19:24:05 +0800 Subject: [PATCH] [checkbox group] Fix parent checkbox with custom `validate` fn (#4912) --- .../src/checkbox-group/CheckboxGroup.test.tsx | 24 +++++++++++++++++++ .../react/src/checkbox/root/CheckboxRoot.tsx | 2 +- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/packages/react/src/checkbox-group/CheckboxGroup.test.tsx b/packages/react/src/checkbox-group/CheckboxGroup.test.tsx index 409e3f2ec..30062645c 100644 --- a/packages/react/src/checkbox-group/CheckboxGroup.test.tsx +++ b/packages/react/src/checkbox-group/CheckboxGroup.test.tsx @@ -326,6 +326,30 @@ describe('', () => { checkboxes.forEach((checkbox) => expect(checkbox).toHaveAttribute('aria-invalid', 'true')); }); + it('validates with the group value when toggling the parent checkbox', async () => { + const validateSpy = vi.fn((_value: unknown) => null); + + const { user } = render( + + + + + + + , + ); + + const parent = screen.getByTestId('parent'); + + await user.click(parent); + expect(validateSpy).toHaveBeenCalledTimes(1); + expect(validateSpy.mock.lastCall?.[0]).toEqual(['apple', 'orange']); + + await user.click(parent); + expect(validateSpy).toHaveBeenCalledTimes(2); + expect(validateSpy.mock.lastCall?.[0]).toEqual([]); + }); + it('revalidates when the controlled value changes externally', async () => { const validateSpy = vi.fn((value: unknown) => { const values = value as string[]; diff --git a/packages/react/src/checkbox/root/CheckboxRoot.tsx b/packages/react/src/checkbox/root/CheckboxRoot.tsx index e19fa973c..df84eb68a 100644 --- a/packages/react/src/checkbox/root/CheckboxRoot.tsx +++ b/packages/react/src/checkbox/root/CheckboxRoot.tsx @@ -191,7 +191,7 @@ export const CheckboxRoot = React.forwardRef(function CheckboxRoot( }, [checked, groupIndeterminate, setFilled]); useValueChanged(checked, () => { - if (groupContext && !parent) { + if (groupContext) { return; }