Skip to content

Commit 62f88ec

Browse files
committed
fix: honor disabled prop in InputSearch list item
1 parent f4697d5 commit 62f88ec

File tree

3 files changed

+54
-4
lines changed

3 files changed

+54
-4
lines changed

packages/kit/src/input-search/InputSearchListItem.tsx

+19-3
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import React from "react";
22
import { Item } from "react-stately";
33
import { useOption } from "react-aria";
44
import { styled, theme } from "../theme";
5+
import { InputSearchContext } from "./InputSearchRoot";
56

67
import type { Node, ListState, ComboBoxState } from "react-stately";
78

@@ -75,6 +76,24 @@ interface ListItemProps {
7576
}
7677

7778
export const ListItem = ({ item, state }: ListItemProps) => {
79+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
80+
const { children, textValue, disabled, ...itemProps } = item.props;
81+
82+
const { setDisabledKeys } = React.useContext(InputSearchContext);
83+
React.useEffect(() => {
84+
if (disabled && !state.disabledKeys.has(item.key)) {
85+
setDisabledKeys((prev) => {
86+
if (prev) {
87+
const next = new Set(prev);
88+
next.add(item.key);
89+
return next;
90+
} else {
91+
return new Set([item.key]);
92+
}
93+
});
94+
}
95+
}, [disabled, setDisabledKeys, state.disabledKeys]);
96+
7897
const ref = React.useRef<HTMLLIElement>(null);
7998
const { optionProps, isDisabled, isSelected, isFocused } = useOption(
8099
{
@@ -97,9 +116,6 @@ export const ListItem = ({ item, state }: ListItemProps) => {
97116
);
98117
}
99118

100-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
101-
const { children, textValue, ...itemProps } = item.props;
102-
103119
return (
104120
<StyledListItem
105121
{...itemProps}

packages/kit/src/input-search/InputSearchRoot.tsx

+7-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { useComboBox } from "react-aria";
55
import { styled, theme } from "../theme";
66

77
import type * as WPDS from "../theme";
8-
import type { ComboBoxState } from "react-stately";
8+
import type { ComboBoxState, Key } from "react-stately";
99
import type { AriaListBoxOptions } from "react-aria";
1010
import type { CollectionChildren } from "@react-types/shared";
1111

@@ -20,6 +20,9 @@ type InputSearchContextProps = {
2020
setCollectionChildren: React.Dispatch<
2121
React.SetStateAction<CollectionChildren<object> | undefined>
2222
>;
23+
setDisabledKeys: React.Dispatch<
24+
React.SetStateAction<Iterable<Key> | undefined>
25+
>;
2326
isDisabled?: boolean;
2427
setUsePortal: React.Dispatch<React.SetStateAction<boolean | undefined>>;
2528
setPortalDomNode: React.Dispatch<React.SetStateAction<HTMLElement | null>>;
@@ -76,9 +79,11 @@ export const InputSearchRoot = ({
7679
}: InputSearchRootProps) => {
7780
const [collectionChildren, setCollectionChildren] =
7881
React.useState<CollectionChildren<object>>();
82+
const [disabledKeys, setDisabledKeys] = React.useState<Iterable<Key>>();
7983

8084
const state = useComboBoxState({
8185
children: collectionChildren,
86+
disabledKeys,
8287
allowsCustomValue: true,
8388
allowsEmptyCollection: true,
8489
menuTrigger: openOnFocus ? "focus" : "input",
@@ -132,6 +137,7 @@ export const InputSearchRoot = ({
132137
inputProps,
133138
listBoxProps,
134139
setCollectionChildren,
140+
setDisabledKeys,
135141
setUsePortal,
136142
setPortalDomNode,
137143
isDisabled: disabled,

packages/kit/src/input-search/play.stories.tsx

+28
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,34 @@ export const Grouping = {
192192
},
193193
};
194194

195+
const DisabledTemplate: StoryFn<typeof InputSearch.Root> = (args) => {
196+
return (
197+
<Box css={{ width: "275px", height: "340px" }}>
198+
<InputSearch.Root {...args} aria-label="Example-Search" openOnFocus>
199+
<InputSearch.Input name="fruit" id="fruit" />
200+
<InputSearch.Popover>
201+
<InputSearch.List>
202+
<InputSearch.ListItem value="Apple" />
203+
<InputSearch.ListItem value="Banana" disabled />
204+
<InputSearch.ListItem value="Orange" />
205+
<InputSearch.ListItem value="Kiwi" />
206+
<InputSearch.ListItem value="Pineapple" />
207+
</InputSearch.List>
208+
</InputSearch.Popover>
209+
</InputSearch.Root>
210+
</Box>
211+
);
212+
};
213+
214+
export const Disabled = {
215+
render: DisabledTemplate,
216+
args: {},
217+
218+
parameters: {
219+
chromatic: { disableSnapshot: true },
220+
},
221+
};
222+
195223
const ScrollTemplate: StoryFn<typeof InputSearch.Root> = (args) => {
196224
return (
197225
<Box css={{ width: "275px", height: "340px", marginBlockStart: "700px" }}>

0 commit comments

Comments
 (0)