Skip to content

Commit 1ce5d96

Browse files
authored
fix(CheckboxMultiSelect): change value on checkbox label click (#609)
1 parent 7a668ad commit 1ce5d96

File tree

4 files changed

+85
-15
lines changed

4 files changed

+85
-15
lines changed

src/components/Select/CheckboxMultiSelect.stories.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ const CheckboxMultiSelectExample = ({ childrenType, value, ...props }: Props) =>
2727
}
2828
return (
2929
<CheckboxMultiSelect
30-
value={value ? value.split(",") : undefined}
30+
value={selectedValues}
31+
onSelect={value => setSelectedValues(value)}
3132
selectLabel="Columns"
3233
{...props}
3334
>

src/components/Select/CheckboxMultiSelect.test.tsx

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ describe("CheckboxCheckboxMultiSelect", () => {
9090
expect(queryByTestingText(selectTrigger, "Content3")).not.toBeInTheDocument();
9191
});
9292

93-
it("shows allows checking and unchecking", async () => {
93+
it("allows checking and unchecking", async () => {
9494
const { getByTestId } = renderSelect({
9595
selectLabel: "Select columns",
9696
value: ["content0", "content1"],
@@ -119,6 +119,59 @@ describe("CheckboxCheckboxMultiSelect", () => {
119119
);
120120
});
121121

122+
it("reports onSelect by clicking on the label", () => {
123+
const handleSelect = vi.fn();
124+
const { queryByText, getByTestId } = renderSelect({
125+
selectLabel: "Select columns",
126+
value: ["content0", "content1"],
127+
onSelect: handleSelect,
128+
});
129+
130+
const selectTrigger = getByTestId("select-trigger");
131+
selectTrigger && fireEvent.click(selectTrigger);
132+
133+
expect(handleSelect).not.toHaveBeenCalled();
134+
const content0Label = queryByText("Content0");
135+
content0Label && fireEvent.click(content0Label);
136+
expect(handleSelect).toHaveBeenCalledTimes(1);
137+
});
138+
139+
it("reports onSelect by clicking on the checkbox", () => {
140+
const handleSelect = vi.fn();
141+
const { getByTestId } = renderSelect({
142+
selectLabel: "Select columns",
143+
value: ["content0", "content1"],
144+
onSelect: handleSelect,
145+
});
146+
147+
const selectTrigger = getByTestId("select-trigger");
148+
selectTrigger && fireEvent.click(selectTrigger);
149+
150+
expect(handleSelect).not.toHaveBeenCalled();
151+
const content0Checkbox = screen
152+
.getByTestId("multi-select-checkbox-content0")
153+
.querySelector("[role='checkbox']");
154+
fireEvent.click(content0Checkbox!);
155+
expect(handleSelect).toHaveBeenCalledTimes(1);
156+
});
157+
158+
it("reports onSelect by clicking on the menu item", () => {
159+
const handleSelect = vi.fn();
160+
const { getByTestId } = renderSelect({
161+
selectLabel: "Select columns",
162+
value: ["content0", "content1"],
163+
onSelect: handleSelect,
164+
});
165+
166+
const selectTrigger = getByTestId("select-trigger");
167+
selectTrigger && fireEvent.click(selectTrigger);
168+
169+
expect(handleSelect).not.toHaveBeenCalled();
170+
const content0MenuItem = screen.getByTestId("multi-select-checkbox-content0");
171+
content0MenuItem && fireEvent.click(content0MenuItem);
172+
expect(handleSelect).toHaveBeenCalledTimes(1);
173+
});
174+
122175
it("shows errors", () => {
123176
const { queryByText } = renderSelect({
124177
error: "Select Error",

src/components/Select/MultiSelect.stories.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ const MultiSelectExample = ({ childrenType, value, ...props }: Props) => {
2525
}
2626
return (
2727
<MultiSelect
28-
value={value ? value.split(",") : undefined}
28+
value={selectedValues}
29+
onSelect={value => setSelectedValues(value)}
2930
{...props}
3031
>
3132
<MultiSelect.Group heading="Group label">

src/components/Select/common/InternalSelect.tsx

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -629,15 +629,33 @@ export const MultiSelectCheckboxItem = forwardRef<
629629
) => {
630630
const { highlighted, updateHighlighted, isHidden, selectedValues, onSelect } =
631631
useOption();
632-
const onSelectValue = (evt: MouseEvent<HTMLElement>) => {
632+
633+
const handleSelect = (evt: MouseEvent<HTMLElement>) => {
633634
if (!disabled) {
634635
onSelect(value, undefined, evt);
635-
if (typeof onSelectProp == "function") {
636+
637+
if (typeof onSelectProp === "function") {
636638
onSelectProp(value, undefined, evt);
637639
}
638640
}
639641
};
640-
const onMouseOver = (e: MouseEvent<HTMLDivElement>) => {
642+
643+
const handleMenuItemClick = (evt: MouseEvent<HTMLElement>) => {
644+
// Clicking checkbox label fires another click event on the checkbox input.
645+
// They cancel each other out, so we handle checkbox clicks separately,
646+
// and this covers the outside area.
647+
if (evt.target !== evt.currentTarget) {
648+
return;
649+
}
650+
651+
handleSelect(evt);
652+
};
653+
654+
const handleCheckboxClick = (evt: MouseEvent<HTMLButtonElement>): void => {
655+
handleSelect(evt);
656+
};
657+
658+
const handleMenuItemMouseOver = (e: MouseEvent<HTMLDivElement>) => {
641659
if (onMouseOverProp) {
642660
onMouseOverProp(e);
643661
}
@@ -649,19 +667,16 @@ export const MultiSelectCheckboxItem = forwardRef<
649667
if (isHidden(value)) {
650668
return null;
651669
}
652-
const isChecked = selectedValues.includes(value);
653670

654-
const onChange = (): void => {
655-
onSelect(value);
656-
};
671+
const isChecked = selectedValues.includes(value);
657672

658673
return (
659674
<>
660675
<GenericMenuItem
661676
{...props}
662677
data-value={value}
663-
onClick={onSelectValue}
664-
onMouseOver={onMouseOver}
678+
onClick={handleMenuItemClick}
679+
onMouseOver={handleMenuItemMouseOver}
665680
ref={forwardedRef}
666681
data-disabled={disabled ? true : undefined}
667682
data-highlighted={highlighted == value ? "true" : undefined}
@@ -692,7 +707,7 @@ export const MultiSelectCheckboxItem = forwardRef<
692707
</div>
693708
)
694709
}
695-
onClick={onChange}
710+
onClick={handleCheckboxClick}
696711
variant={variant ?? "default"}
697712
/>
698713
)}
@@ -706,7 +721,7 @@ export const MultiSelectCheckboxItem = forwardRef<
706721
data-testid="multi-select-checkbox"
707722
disabled={disabled}
708723
label={label ?? children}
709-
onClick={onChange}
724+
onClick={handleCheckboxClick}
710725
variant={variant ?? "default"}
711726
/>
712727
</IconWrapper>
@@ -717,7 +732,7 @@ export const MultiSelectCheckboxItem = forwardRef<
717732
data-testid="multi-select-checkbox"
718733
disabled={disabled}
719734
label={label ?? children}
720-
onClick={onChange}
735+
onClick={handleCheckboxClick}
721736
variant={variant ?? "default"}
722737
/>
723738
)}

0 commit comments

Comments
 (0)