Skip to content

Commit b7393ac

Browse files
authored
[combobox] New Combobox and Autocomplete components (#2105)
1 parent f480adb commit b7393ac

File tree

215 files changed

+20898
-822
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

215 files changed

+20898
-822
lines changed

docs/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
"@next/mdx": "^15.5.0",
2626
"@react-spring/web": "^10.0.1",
2727
"@stefanprobst/rehype-extract-toc": "^3.0.0",
28+
"@tanstack/react-virtual": "^3.13.12",
2829
"@types/mdx": "^2.0.13",
2930
"clipboard-copy": "^4.0.1",
3031
"clsx": "^2.1.1",
@@ -36,6 +37,7 @@
3637
"hast-util-to-string": "^3.0.1",
3738
"lodash": "^4.17.21",
3839
"lz-string": "^1.5.0",
40+
"match-sorter": "^8.0.3",
3941
"next": "15.5.0",
4042
"postcss": "^8.5.6",
4143
"postcss-custom-media": "^11.0.6",
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
{
2+
"name": "AutocompleteRoot",
3+
"description": "Groups all parts of the autocomplete.\nDoesn't render its own HTML element.",
4+
"props": {
5+
"name": {
6+
"type": "string",
7+
"description": "Identifies the field when a form is submitted.",
8+
"detailedType": "string | undefined"
9+
},
10+
"defaultValue": {
11+
"type": "string | number | string[]",
12+
"description": "The uncontrolled input value of the autocomplete when it's initially rendered.\n\nTo render a controlled autocomplete, use the `value` prop instead.",
13+
"detailedType": "string | number | string[] | undefined"
14+
},
15+
"value": {
16+
"type": "string | number | string[]",
17+
"description": "The input value of the autocomplete. Use when controlled.",
18+
"detailedType": "string | number | string[] | undefined"
19+
},
20+
"onValueChange": {
21+
"type": "((value: string, eventDetails: Autocomplete.Root.ChangeEventDetails) => void)",
22+
"description": "Callback fired when the input value of the autocomplete changes.",
23+
"detailedType": "| ((\n value: string,\n eventDetails: Autocomplete.Root.ChangeEventDetails,\n ) => void)\n| undefined"
24+
},
25+
"defaultOpen": {
26+
"type": "boolean",
27+
"default": "false",
28+
"description": "Whether the popup is initially open.\n\nTo render a controlled popup, use the `open` prop instead.",
29+
"detailedType": "boolean | undefined"
30+
},
31+
"open": {
32+
"type": "boolean",
33+
"description": "Whether the popup is currently open.",
34+
"detailedType": "boolean | undefined"
35+
},
36+
"onOpenChange": {
37+
"type": "((open: boolean, eventDetails: Autocomplete.Root.ChangeEventDetails) => void)",
38+
"description": "Event handler called when the popup is opened or closed.",
39+
"detailedType": "| ((\n open: boolean,\n eventDetails: Autocomplete.Root.ChangeEventDetails,\n ) => void)\n| undefined"
40+
},
41+
"actionsRef": {
42+
"type": "RefObject<Autocomplete.Root.Actions>",
43+
"description": "A ref to imperative actions.\n- `unmount`: When specified, the autocomplete will not be unmounted when closed.\nInstead, the `unmount` function must be called to unmount the autocomplete manually.\nUseful when the autocomplete's animation is controlled by an external library.",
44+
"detailedType": "| React.RefObject<Autocomplete.Root.Actions>\n| undefined"
45+
},
46+
"autoHighlight": {
47+
"type": "boolean",
48+
"default": "false",
49+
"description": "Whether to automatically highlight the first item when the popup opens.",
50+
"detailedType": "boolean | undefined"
51+
},
52+
"cols": {
53+
"type": "number",
54+
"default": "1",
55+
"description": "The maximum number of columns present when the items are rendered in grid layout.\nA value of more than `1` turns the listbox into a grid.",
56+
"detailedType": "number | undefined"
57+
},
58+
"filter": {
59+
"type": "((itemValue: Value, query: string, itemToStringLabel: ((itemValue: Value) => string) | undefined) => boolean) | null",
60+
"description": "Filter function used to match items vs input query.\nThe `itemToStringLabel` function is provided to help convert items to strings for comparison.",
61+
"detailedType": "| ((\n itemValue: Value,\n query: string,\n itemToStringLabel:\n | ((itemValue: Value) => string)\n | undefined,\n ) => boolean)\n| null\n| undefined"
62+
},
63+
"itemToStringValue": {
64+
"type": "((itemValue: Value) => string)",
65+
"description": "When items' values are objects, converts its value to a string representation for display in the input.",
66+
"detailedType": "((itemValue: Value) => string) | undefined"
67+
},
68+
"items": {
69+
"type": "Group<Value>[] | Value[]",
70+
"detailedType": "Group<Value>[] | Value[] | undefined"
71+
},
72+
"limit": {
73+
"type": "number",
74+
"default": "-1",
75+
"description": "The maximum number of items to display in the list.",
76+
"detailedType": "number | undefined"
77+
},
78+
"locale": {
79+
"type": "Intl.LocalesArgument",
80+
"description": "The locale to use for string comparison.\nDefaults to the user's runtime locale.",
81+
"detailedType": "Intl.LocalesArgument | undefined"
82+
},
83+
"modal": {
84+
"type": "boolean",
85+
"default": "false",
86+
"description": "Determines if the popup enters a modal state when open.\n- `true`: user interaction is limited to the popup: document page scroll is locked and pointer interactions on outside elements are disabled.\n- `false`: user interaction with the rest of the document is allowed.",
87+
"detailedType": "boolean | undefined"
88+
},
89+
"mode": {
90+
"type": "'none' | 'list' | 'inline' | 'both'",
91+
"default": "'list'",
92+
"description": "Controls how the autocomplete behaves with respect to list filtering and inline autocompletion.\n- `list` (default): items are dynamically filtered based on the input value. The input value does not change based on the active item.\n- `both`: items are dynamically filtered based on the input value, which will temporarily change based on the active item (inline autocompletion).\n- `inline`: items are static (not filtered), and the input value will temporarily change based on the active item (inline autocompletion).\n- `none`: items are static (not filtered), and the input value will not change based on the active item.",
93+
"detailedType": "'none' | 'list' | 'inline' | 'both' | undefined"
94+
},
95+
"onItemHighlighted": {
96+
"type": "((itemValue: Value | undefined, data: { type: 'none' | 'keyboard' | 'pointer', index: number }) => void)",
97+
"description": "Callback fired when the user navigates the list and highlights an item.\nPasses the item and the type of navigation or `undefined` when no item is highlighted.\n- `keyboard`: The item was highlighted via keyboard navigation.\n- `pointer`: The item was highlighted via pointer navigation.\n- `none`: The item was highlighted via programmatic navigation.",
98+
"detailedType": "| ((\n itemValue: Value | undefined,\n data: {\n type: 'none' | 'keyboard' | 'pointer'\n index: number\n },\n ) => void)\n| undefined"
99+
},
100+
"onOpenChangeComplete": {
101+
"type": "((open: boolean) => void)",
102+
"description": "Event handler called after any animations complete when the popup is opened or closed.",
103+
"detailedType": "((open: boolean) => void) | undefined"
104+
},
105+
"openOnInputClick": {
106+
"type": "boolean",
107+
"default": "true",
108+
"description": "Whether the popup opens when clicking the input.",
109+
"detailedType": "boolean | undefined"
110+
},
111+
"virtualized": {
112+
"type": "boolean",
113+
"default": "false",
114+
"description": "Whether the items are being externally virtualized.",
115+
"detailedType": "boolean | undefined"
116+
},
117+
"disabled": {
118+
"type": "boolean",
119+
"default": "false",
120+
"description": "Whether the component should ignore user interaction.",
121+
"detailedType": "boolean | undefined"
122+
},
123+
"readOnly": {
124+
"type": "boolean",
125+
"default": "false",
126+
"description": "Whether the user should be unable to choose a different option from the popup.",
127+
"detailedType": "boolean | undefined"
128+
},
129+
"required": {
130+
"type": "boolean",
131+
"default": "false",
132+
"description": "Whether the user must choose a value before submitting a form.",
133+
"detailedType": "boolean | undefined"
134+
},
135+
"inputRef": {
136+
"type": "RefObject<HTMLInputElement>",
137+
"description": "A ref to the hidden input element.",
138+
"detailedType": "React.RefObject<HTMLInputElement> | undefined"
139+
},
140+
"id": {
141+
"type": "string",
142+
"description": "The id of the component.",
143+
"detailedType": "string | undefined"
144+
},
145+
"children": {
146+
"type": "ReactNode",
147+
"detailedType": "React.ReactNode | undefined"
148+
}
149+
},
150+
"dataAttributes": {},
151+
"cssVariables": {}
152+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"name": "AutocompleteValue",
3+
"description": "The current value of the autocomplete.\nDoesn't render its own HTML element.",
4+
"props": {
5+
"children": {
6+
"type": "ReactNode | ((value: string) => ReactNode)",
7+
"detailedType": "React.ReactNode | ((value: string) => ReactNode)"
8+
}
9+
},
10+
"dataAttributes": {},
11+
"cssVariables": {}
12+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
{
2+
"name": "ComboboxArrow",
3+
"description": "Displays an element positioned against the anchor.\nRenders a `<div>` element.",
4+
"props": {
5+
"className": {
6+
"type": "string | ((state: Combobox.Arrow.State) => string)",
7+
"description": "CSS class applied to the element, or a function that\nreturns a class based on the component’s state."
8+
},
9+
"render": {
10+
"type": "ReactElement | ((props: HTMLProps, state: Combobox.Arrow.State) => ReactElement)",
11+
"description": "Allows you to replace the component’s HTML element\nwith a different tag, or compose it with another component.\n\nAccepts a `ReactElement` or a function that returns the element to render.",
12+
"detailedType": "| ReactElement\n| ((\n props: HTMLProps,\n state: Combobox.Arrow.State,\n ) => ReactElement)"
13+
}
14+
},
15+
"dataAttributes": {
16+
"data-open": {
17+
"description": "Present when the popup is open."
18+
},
19+
"data-closed": {
20+
"description": "Present when the popup is closed."
21+
},
22+
"data-uncentered": {
23+
"description": "Present when the arrow is uncentered."
24+
},
25+
"data-anchor-hidden": {
26+
"description": "Present when the anchor is hidden."
27+
},
28+
"data-align": {
29+
"description": "Indicates how the popup is aligned relative to specified side.",
30+
"type": "'start' | 'center' | 'end'"
31+
},
32+
"data-side": {
33+
"description": "Indicates which side the popup is positioned relative to the trigger.",
34+
"type": "'top' | 'bottom' | 'left' | 'right' | 'inline-end' | 'inline-start'"
35+
}
36+
},
37+
"cssVariables": {}
38+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
{
2+
"name": "ComboboxBackdrop",
3+
"description": "An overlay displayed beneath the popup.\nRenders a `<div>` element.",
4+
"props": {
5+
"className": {
6+
"type": "string | ((state: Combobox.Backdrop.State) => string)",
7+
"description": "CSS class applied to the element, or a function that\nreturns a class based on the component’s state.",
8+
"detailedType": "| string\n| ((state: Combobox.Backdrop.State) => string)"
9+
},
10+
"render": {
11+
"type": "ReactElement | ((props: HTMLProps, state: Combobox.Backdrop.State) => ReactElement)",
12+
"description": "Allows you to replace the component’s HTML element\nwith a different tag, or compose it with another component.\n\nAccepts a `ReactElement` or a function that returns the element to render.",
13+
"detailedType": "| ReactElement\n| ((\n props: HTMLProps,\n state: Combobox.Backdrop.State,\n ) => ReactElement)"
14+
}
15+
},
16+
"dataAttributes": {
17+
"data-open": {
18+
"description": "Present when the popup is open."
19+
},
20+
"data-closed": {
21+
"description": "Present when the popup is closed."
22+
},
23+
"data-starting-style": {
24+
"description": "Present when the popup is animating in."
25+
},
26+
"data-ending-style": {
27+
"description": "Present when the popup is animating out."
28+
}
29+
},
30+
"cssVariables": {}
31+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
{
2+
"name": "ComboboxChipRemove",
3+
"description": "A button to remove a chip.\nRenders a `<button>` element.",
4+
"props": {
5+
"nativeButton": {
6+
"type": "boolean",
7+
"default": "true",
8+
"description": "Whether the component renders a native `<button>` element when replacing it\nvia the `render` prop.\nSet to `false` if the rendered element is not a button (e.g. `<div>`).",
9+
"detailedType": "boolean | undefined"
10+
},
11+
"className": {
12+
"type": "string | ((state: Combobox.ChipRemove.State) => string)",
13+
"description": "CSS class applied to the element, or a function that\nreturns a class based on the component’s state.",
14+
"detailedType": "| string\n| ((state: Combobox.ChipRemove.State) => string)"
15+
},
16+
"render": {
17+
"type": "ReactElement | ((props: HTMLProps, state: Combobox.ChipRemove.State) => ReactElement)",
18+
"description": "Allows you to replace the component’s HTML element\nwith a different tag, or compose it with another component.\n\nAccepts a `ReactElement` or a function that returns the element to render.",
19+
"detailedType": "| ReactElement\n| ((\n props: HTMLProps,\n state: Combobox.ChipRemove.State,\n ) => ReactElement)"
20+
}
21+
},
22+
"dataAttributes": {},
23+
"cssVariables": {}
24+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"name": "ComboboxChip",
3+
"description": "An individual chip that represents a value in a multiselectable input.\nRenders a `<div>` element.",
4+
"props": {
5+
"className": {
6+
"type": "string | ((state: Combobox.Chip.State) => string)",
7+
"description": "CSS class applied to the element, or a function that\nreturns a class based on the component’s state."
8+
},
9+
"render": {
10+
"type": "ReactElement | ((props: HTMLProps, state: Combobox.Chip.State) => ReactElement)",
11+
"description": "Allows you to replace the component’s HTML element\nwith a different tag, or compose it with another component.\n\nAccepts a `ReactElement` or a function that returns the element to render.",
12+
"detailedType": "| ReactElement\n| ((\n props: HTMLProps,\n state: Combobox.Chip.State,\n ) => ReactElement)"
13+
}
14+
},
15+
"dataAttributes": {},
16+
"cssVariables": {}
17+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"name": "ComboboxChips",
3+
"description": "A container for the chips in a multiselectable input.\nRenders a `<div>` element.",
4+
"props": {
5+
"className": {
6+
"type": "string | ((state: Combobox.Chips.State) => string)",
7+
"description": "CSS class applied to the element, or a function that\nreturns a class based on the component’s state."
8+
},
9+
"render": {
10+
"type": "ReactElement | ((props: HTMLProps, state: Combobox.Chips.State) => ReactElement)",
11+
"description": "Allows you to replace the component’s HTML element\nwith a different tag, or compose it with another component.\n\nAccepts a `ReactElement` or a function that returns the element to render.",
12+
"detailedType": "| ReactElement\n| ((\n props: HTMLProps,\n state: Combobox.Chips.State,\n ) => ReactElement)"
13+
}
14+
},
15+
"dataAttributes": {},
16+
"cssVariables": {}
17+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
{
2+
"name": "ComboboxClear",
3+
"description": "Clears the value when clicked.\nRenders a `<button>` element.",
4+
"props": {
5+
"nativeButton": {
6+
"type": "boolean",
7+
"default": "true",
8+
"description": "Whether the component renders a native `<button>` element when replacing it\nvia the `render` prop.\nSet to `false` if the rendered element is not a button (e.g. `<div>`).",
9+
"detailedType": "boolean | undefined"
10+
},
11+
"disabled": {
12+
"type": "boolean",
13+
"default": "false",
14+
"description": "Whether the component should ignore user interaction.",
15+
"detailedType": "boolean | undefined"
16+
},
17+
"className": {
18+
"type": "string | ((state: Combobox.Clear.State) => string)",
19+
"description": "CSS class applied to the element, or a function that\nreturns a class based on the component’s state."
20+
},
21+
"keepMounted": {
22+
"type": "boolean",
23+
"default": "false",
24+
"description": "Whether the component should remain mounted in the DOM when not visible.",
25+
"detailedType": "boolean | undefined"
26+
},
27+
"render": {
28+
"type": "ReactElement | ((props: HTMLProps, state: Combobox.Clear.State) => ReactElement)",
29+
"description": "Allows you to replace the component’s HTML element\nwith a different tag, or compose it with another component.\n\nAccepts a `ReactElement` or a function that returns the element to render.",
30+
"detailedType": "| ReactElement\n| ((\n props: HTMLProps,\n state: Combobox.Clear.State,\n ) => ReactElement)"
31+
}
32+
},
33+
"dataAttributes": {},
34+
"cssVariables": {}
35+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"name": "ComboboxCollection",
3+
"description": "Renders filtered list items.\nDoesn't render its own HTML element.\n\nIf rendering a flat list, pass a function child to the `List` component instead, which implicitly wraps it.",
4+
"props": {
5+
"children": {
6+
"type": "((item: any, index: number) => ReactNode)",
7+
"required": true,
8+
"detailedType": "(item: any, index: number) => ReactNode"
9+
}
10+
},
11+
"dataAttributes": {},
12+
"cssVariables": {}
13+
}

0 commit comments

Comments
 (0)