@patternfly/react-docs 7.6.0-prerelease.6 → 7.6.0-prerelease.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (163) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/package.json +12 -13
  3. package/patternfly-docs/generated/components/about-modal/react.js +149 -0
  4. package/patternfly-docs/generated/components/accordion/react.js +262 -0
  5. package/patternfly-docs/generated/components/action-list/react.js +144 -0
  6. package/patternfly-docs/generated/components/alert/react-demos.js +56 -0
  7. package/patternfly-docs/generated/components/alert/react.js +1433 -0
  8. package/patternfly-docs/generated/components/avatar/react.js +166 -0
  9. package/patternfly-docs/generated/components/back-to-top/react-demos.js +60 -0
  10. package/patternfly-docs/generated/components/back-to-top/react.js +77 -0
  11. package/patternfly-docs/generated/components/backdrop/react.js +64 -0
  12. package/patternfly-docs/generated/components/background-image/react.js +62 -0
  13. package/patternfly-docs/generated/components/badge/react.js +97 -0
  14. package/patternfly-docs/generated/components/banner/react-demos.js +57 -0
  15. package/patternfly-docs/generated/components/banner/react.js +148 -0
  16. package/patternfly-docs/generated/components/brand/react.js +142 -0
  17. package/patternfly-docs/generated/components/breadcrumb/react.js +206 -0
  18. package/patternfly-docs/generated/components/button/react-demos.js +57 -0
  19. package/patternfly-docs/generated/components/button/react.js +826 -0
  20. package/patternfly-docs/generated/components/card/react-demos.js +201 -0
  21. package/patternfly-docs/generated/components/card/react.js +1015 -0
  22. package/patternfly-docs/generated/components/charts/area-chart/-Victory.js +1350 -0
  23. package/patternfly-docs/generated/components/charts/bar-chart/-Victory.js +1334 -0
  24. package/patternfly-docs/generated/components/charts/box-plot-chart/-Victory.js +1282 -0
  25. package/patternfly-docs/generated/components/charts/bullet-chart/-Victory.js +848 -0
  26. package/patternfly-docs/generated/components/charts/colors-for-charts/-Victory.js +192 -0
  27. package/patternfly-docs/generated/components/charts/donut-chart/-Victory.js +426 -0
  28. package/patternfly-docs/generated/components/charts/donut-utilization-chart/-Victory.js +804 -0
  29. package/patternfly-docs/generated/components/charts/legends/-Victory.js +3230 -0
  30. package/patternfly-docs/generated/components/charts/line-chart/-Victory.js +1178 -0
  31. package/patternfly-docs/generated/components/charts/line-chart/ECharts.js +525 -0
  32. package/patternfly-docs/generated/components/charts/patterns/-Victory.js +3382 -0
  33. package/patternfly-docs/generated/components/charts/pie-chart/-Victory.js +377 -0
  34. package/patternfly-docs/generated/components/charts/resize-observer/-Victory.js +2475 -0
  35. package/patternfly-docs/generated/components/charts/sankey-chart/ECharts.js +538 -0
  36. package/patternfly-docs/generated/components/charts/scatter-chart/-Victory.js +1551 -0
  37. package/patternfly-docs/generated/components/charts/skeletons/-Victory.js +4115 -0
  38. package/patternfly-docs/generated/components/charts/sparkline-chart/-Victory.js +955 -0
  39. package/patternfly-docs/generated/components/charts/stack-chart/-Victory.js +1173 -0
  40. package/patternfly-docs/generated/components/charts/threshold-chart/-Victory.js +1166 -0
  41. package/patternfly-docs/generated/components/charts/tooltips/-Victory.js +413 -0
  42. package/patternfly-docs/generated/components/chip/react-deprecated.js +323 -0
  43. package/patternfly-docs/generated/components/clipboard-copy/react.js +373 -0
  44. package/patternfly-docs/generated/components/code-block/react.js +148 -0
  45. package/patternfly-docs/generated/components/code-editor/react.js +659 -0
  46. package/patternfly-docs/generated/components/compass/react-demos.js +147 -0
  47. package/patternfly-docs/generated/components/compass/react.js +440 -0
  48. package/patternfly-docs/generated/components/content/react.js +248 -0
  49. package/patternfly-docs/generated/components/data-list/react-demos.js +90 -0
  50. package/patternfly-docs/generated/components/data-list/react.js +709 -0
  51. package/patternfly-docs/generated/components/date-and-time/calendar-month/react.js +283 -0
  52. package/patternfly-docs/generated/components/date-and-time/date-and-time-picker/react-demos.js +64 -0
  53. package/patternfly-docs/generated/components/date-and-time/date-picker/react-demos.js +83 -0
  54. package/patternfly-docs/generated/components/date-and-time/date-picker/react.js +395 -0
  55. package/patternfly-docs/generated/components/date-and-time/time-picker/react.js +241 -0
  56. package/patternfly-docs/generated/components/description-list/react-demos.js +58 -0
  57. package/patternfly-docs/generated/components/description-list/react.js +743 -0
  58. package/patternfly-docs/generated/components/divider/react.js +126 -0
  59. package/patternfly-docs/generated/components/drag-and-drop/react-demos.js +351 -0
  60. package/patternfly-docs/generated/components/drag-and-drop/react-deprecated.js +184 -0
  61. package/patternfly-docs/generated/components/drag-and-drop/react.js +137 -0
  62. package/patternfly-docs/generated/components/drawer/react.js +598 -0
  63. package/patternfly-docs/generated/components/dual-list-selector/react-deprecated.js +772 -0
  64. package/patternfly-docs/generated/components/dual-list-selector/react.js +594 -0
  65. package/patternfly-docs/generated/components/empty-state/react.js +199 -0
  66. package/patternfly-docs/generated/components/expandable-section/react-demos.js +65 -0
  67. package/patternfly-docs/generated/components/expandable-section/react.js +408 -0
  68. package/patternfly-docs/generated/components/file-upload/multiple-file-upload/react-demos.js +52 -0
  69. package/patternfly-docs/generated/components/file-upload/multiple-file-upload/react.js +398 -0
  70. package/patternfly-docs/generated/components/file-upload/simple-file-upload/react.js +749 -0
  71. package/patternfly-docs/generated/components/forms/checkbox/react.js +222 -0
  72. package/patternfly-docs/generated/components/forms/form/react.js +1106 -0
  73. package/patternfly-docs/generated/components/forms/form-select/react.js +208 -0
  74. package/patternfly-docs/generated/components/forms/radio/react.js +212 -0
  75. package/patternfly-docs/generated/components/forms/text-area/react.js +160 -0
  76. package/patternfly-docs/generated/components/forms/text-input/react.js +216 -0
  77. package/patternfly-docs/generated/components/helper-text/react-demos.js +180 -0
  78. package/patternfly-docs/generated/components/helper-text/react.js +164 -0
  79. package/patternfly-docs/generated/components/hero/react.js +88 -0
  80. package/patternfly-docs/generated/components/hint/react.js +169 -0
  81. package/patternfly-docs/generated/components/icon/react.js +215 -0
  82. package/patternfly-docs/generated/components/input-group/react.js +182 -0
  83. package/patternfly-docs/generated/components/jump-links/react-demos.js +154 -0
  84. package/patternfly-docs/generated/components/jump-links/react.js +212 -0
  85. package/patternfly-docs/generated/components/label/react-demos.js +57 -0
  86. package/patternfly-docs/generated/components/label/react.js +417 -0
  87. package/patternfly-docs/generated/components/list/react.js +175 -0
  88. package/patternfly-docs/generated/components/login-page/react.js +587 -0
  89. package/patternfly-docs/generated/components/masthead/react-demos.js +79 -0
  90. package/patternfly-docs/generated/components/masthead/react.js +291 -0
  91. package/patternfly-docs/generated/components/menus/application-launcher/react-demos.js +769 -0
  92. package/patternfly-docs/generated/components/menus/context-selector/react-demos.js +665 -0
  93. package/patternfly-docs/generated/components/menus/custom-menus/react-demos.js +187 -0
  94. package/patternfly-docs/generated/components/menus/dropdown/react-templates.js +163 -0
  95. package/patternfly-docs/generated/components/menus/dropdown/react.js +998 -0
  96. package/patternfly-docs/generated/components/menus/menu/react.js +1540 -0
  97. package/patternfly-docs/generated/components/menus/menu-toggle/react.js +747 -0
  98. package/patternfly-docs/generated/components/menus/options-menu/react-demos.js +508 -0
  99. package/patternfly-docs/generated/components/menus/select/react-templates.js +257 -0
  100. package/patternfly-docs/generated/components/menus/select/react.js +998 -0
  101. package/patternfly-docs/generated/components/modal/react-deprecated.js +554 -0
  102. package/patternfly-docs/generated/components/modal/react.js +597 -0
  103. package/patternfly-docs/generated/components/navigation/react-demos.js +356 -0
  104. package/patternfly-docs/generated/components/navigation/react.js +409 -0
  105. package/patternfly-docs/generated/components/notification-badge/react.js +196 -0
  106. package/patternfly-docs/generated/components/notification-drawer/react-demos.js +107 -0
  107. package/patternfly-docs/generated/components/notification-drawer/react.js +394 -0
  108. package/patternfly-docs/generated/components/number-input/react.js +210 -0
  109. package/patternfly-docs/generated/components/overflow-menu/react.js +274 -0
  110. package/patternfly-docs/generated/components/page/react-demos.js +149 -0
  111. package/patternfly-docs/generated/components/page/react.js +1352 -0
  112. package/patternfly-docs/generated/components/pagination/react.js +492 -0
  113. package/patternfly-docs/generated/components/panel/react.js +236 -0
  114. package/patternfly-docs/generated/components/popover/react.js +390 -0
  115. package/patternfly-docs/generated/components/progress/react-demos.js +59 -0
  116. package/patternfly-docs/generated/components/progress/react.js +283 -0
  117. package/patternfly-docs/generated/components/progress-stepper/react-demos.js +45 -0
  118. package/patternfly-docs/generated/components/progress-stepper/react.js +219 -0
  119. package/patternfly-docs/generated/components/search-input/react-demos.js +113 -0
  120. package/patternfly-docs/generated/components/search-input/react.js +263 -0
  121. package/patternfly-docs/generated/components/sidebar/react.js +236 -0
  122. package/patternfly-docs/generated/components/simple-list/react.js +200 -0
  123. package/patternfly-docs/generated/components/skeleton/react-demos.js +44 -0
  124. package/patternfly-docs/generated/components/skeleton/react.js +122 -0
  125. package/patternfly-docs/generated/components/skip-to-content/react.js +73 -0
  126. package/patternfly-docs/generated/components/slider/react.js +309 -0
  127. package/patternfly-docs/generated/components/spinner/react.js +111 -0
  128. package/patternfly-docs/generated/components/switch/react.js +163 -0
  129. package/patternfly-docs/generated/components/table/react-demos.js +355 -0
  130. package/patternfly-docs/generated/components/table/react-deprecated.js +1350 -0
  131. package/patternfly-docs/generated/components/table/react.js +3241 -0
  132. package/patternfly-docs/generated/components/tabs/react-demos.js +108 -0
  133. package/patternfly-docs/generated/components/tabs/react.js +1359 -0
  134. package/patternfly-docs/generated/components/text-input-group/react-demos.js +152 -0
  135. package/patternfly-docs/generated/components/text-input-group/react.js +278 -0
  136. package/patternfly-docs/generated/components/tile/react-deprecated.js +242 -0
  137. package/patternfly-docs/generated/components/timestamp/react.js +283 -0
  138. package/patternfly-docs/generated/components/title/react.js +94 -0
  139. package/patternfly-docs/generated/components/toggle-group/react.js +299 -0
  140. package/patternfly-docs/generated/components/toolbar/react-demos.js +66 -0
  141. package/patternfly-docs/generated/components/toolbar/react.js +932 -0
  142. package/patternfly-docs/generated/components/tooltip/react.js +241 -0
  143. package/patternfly-docs/generated/components/tree-view/react.js +429 -0
  144. package/patternfly-docs/generated/components/truncate/react.js +211 -0
  145. package/patternfly-docs/generated/components/wizard/react-demos.js +87 -0
  146. package/patternfly-docs/generated/components/wizard/react-deprecated.js +788 -0
  147. package/patternfly-docs/generated/components/wizard/react.js +986 -0
  148. package/patternfly-docs/generated/developer-guides/open-ui-automation/react.js +285 -0
  149. package/patternfly-docs/generated/foundations-and-styles/layouts/bullseye/react.js +70 -0
  150. package/patternfly-docs/generated/foundations-and-styles/layouts/flex/react.js +506 -0
  151. package/patternfly-docs/generated/foundations-and-styles/layouts/gallery/react.js +94 -0
  152. package/patternfly-docs/generated/foundations-and-styles/layouts/grid/react.js +272 -0
  153. package/patternfly-docs/generated/foundations-and-styles/layouts/level/react.js +87 -0
  154. package/patternfly-docs/generated/foundations-and-styles/layouts/split/react.js +124 -0
  155. package/patternfly-docs/generated/foundations-and-styles/layouts/stack/react.js +112 -0
  156. package/patternfly-docs/generated/index.js +1769 -0
  157. package/patternfly-docs/generated/patterns/card-view/react-demos.js +78 -0
  158. package/patternfly-docs/generated/patterns/filters/react-demos.js +141 -0
  159. package/patternfly-docs/generated/patterns/password-generator/react-demos.js +51 -0
  160. package/patternfly-docs/generated/patterns/password-strength/react-demos.js +61 -0
  161. package/patternfly-docs/generated/patterns/primary-detail/react-demos.js +124 -0
  162. package/patternfly-docs/generated/patterns/right-to-left/react-demos.js +81 -0
  163. package/LICENSE +0 -21
@@ -0,0 +1,998 @@
1
+ import React from 'react';
2
+ import { AutoLinkHeader, Example, Link as PatternflyThemeLink } from '@patternfly/documentation-framework/components';
3
+ import { Fragment, useEffect, useRef, useState } from 'react';
4
+ import RhMicronsCloseIcon from '@patternfly/react-icons/dist/esm/icons/rh-microns-close-icon';
5
+ import RhUiNotificationFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-notification-fill-icon';
6
+ const pageData = {
7
+ "id": "Select",
8
+ "section": "components",
9
+ "subsection": "menus",
10
+ "deprecated": false,
11
+ "template": false,
12
+ "beta": false,
13
+ "demo": false,
14
+ "newImplementationLink": false,
15
+ "source": "react",
16
+ "tabName": null,
17
+ "slug": "/components/menus/select/react",
18
+ "sourceLink": "https://github.com/patternfly/patternfly-react/blob/main/packages/react-core/src/components/Select/examples/Select.md",
19
+ "relPath": "packages/react-core/src/components/Select/examples/Select.md",
20
+ "propComponents": [
21
+ {
22
+ "name": "Select",
23
+ "description": "See the Menu documentation for additional props that may be passed.",
24
+ "props": [
25
+ {
26
+ "name": "activeItemId",
27
+ "type": "string | number",
28
+ "description": "itemId of the currently active item. You can also specify isActive on the MenuItem."
29
+ },
30
+ {
31
+ "name": "activeMenu",
32
+ "type": "string",
33
+ "description": "ID of the currently active menu for the drilldown variant"
34
+ },
35
+ {
36
+ "name": "children",
37
+ "type": "React.ReactNode",
38
+ "description": "Anything that can be rendered inside of the Menu"
39
+ },
40
+ {
41
+ "name": "className",
42
+ "type": "string",
43
+ "description": "Additional classes added to the Menu"
44
+ },
45
+ {
46
+ "name": "containsDrilldown",
47
+ "type": "boolean",
48
+ "description": "Indicates if menu contains a drilldown menu"
49
+ },
50
+ {
51
+ "name": "containsFlyout",
52
+ "type": "boolean",
53
+ "description": "Indicates if menu contains a flyout menu"
54
+ },
55
+ {
56
+ "name": "drilldownItemPath",
57
+ "type": "string[]",
58
+ "description": "Indicates the path of drilled in menu itemIds"
59
+ },
60
+ {
61
+ "name": "drilledInMenus",
62
+ "type": "string[]",
63
+ "description": "Array of menus that are drilled in"
64
+ },
65
+ {
66
+ "name": "focusTimeoutDelay",
67
+ "type": "number",
68
+ "description": "Time in ms to wait before firing the toggles' focus event. Defaults to 0"
69
+ },
70
+ {
71
+ "name": "id",
72
+ "type": "string",
73
+ "description": "ID of the menu"
74
+ },
75
+ {
76
+ "name": "isMenuDrilledIn",
77
+ "type": "boolean",
78
+ "description": "Indicates if a menu is drilled into"
79
+ },
80
+ {
81
+ "name": "isNavFlyout",
82
+ "type": "boolean",
83
+ "description": "Indicating that the menu should have nav flyout styling"
84
+ },
85
+ {
86
+ "name": "isOpen",
87
+ "type": "boolean",
88
+ "description": "Flag to indicate if select is open"
89
+ },
90
+ {
91
+ "name": "isPlain",
92
+ "type": "boolean",
93
+ "description": "Indicates if the menu should be without the outer box-shadow"
94
+ },
95
+ {
96
+ "name": "isRootMenu",
97
+ "type": "boolean",
98
+ "description": "Internal flag indicating if the Menu is the root of a menu tree"
99
+ },
100
+ {
101
+ "name": "isScrollable",
102
+ "type": "boolean",
103
+ "description": "Indicates if the menu should be srollable"
104
+ },
105
+ {
106
+ "name": "maxMenuHeight",
107
+ "type": "string",
108
+ "description": "Maximum height of select menu"
109
+ },
110
+ {
111
+ "name": "menuHeight",
112
+ "type": "string",
113
+ "description": "Height of the select menu"
114
+ },
115
+ {
116
+ "name": "onActionClick",
117
+ "type": "(event?: any, itemId?: any, actionId?: any) => void",
118
+ "description": "Callback called when an MenuItems's action button is clicked. You can also specify it within a MenuItemAction."
119
+ },
120
+ {
121
+ "name": "onDrillIn",
122
+ "type": "(\n event: React.KeyboardEvent | React.MouseEvent,\n fromItemId: string,\n toItemId: string,\n itemId: string\n) => void",
123
+ "description": "Callback for drilling into a submenu"
124
+ },
125
+ {
126
+ "name": "onDrillOut",
127
+ "type": "(event: React.KeyboardEvent | React.MouseEvent, toItemId: string, itemId: string) => void",
128
+ "description": "Callback for drilling out of a submenu"
129
+ },
130
+ {
131
+ "name": "onGetMenuHeight",
132
+ "type": "(menuId: string, height: number) => void",
133
+ "description": "Callback for collecting menu heights"
134
+ },
135
+ {
136
+ "name": "onOpenChange",
137
+ "type": "(isOpen: boolean) => void",
138
+ "description": "Callback to allow the select component to change the open state of the menu.\nTriggered by clicking outside of the menu, or by pressing any keys specified in onOpenChangeKeys."
139
+ },
140
+ {
141
+ "name": "onOpenChangeKeys",
142
+ "type": "string[]",
143
+ "description": "Keys that trigger onOpenChange, defaults to tab and escape. It is highly recommended to include Escape in the array, while Tab may be omitted if the menu contains non-menu items that are focusable."
144
+ },
145
+ {
146
+ "name": "onSelect",
147
+ "type": "(event?: React.MouseEvent<Element, MouseEvent>, value?: SelectOptionProps['value']) => void",
148
+ "description": "Callback for updating when item selection changes. You can also specify onClick on the MenuItem."
149
+ },
150
+ {
151
+ "name": "onToggleKeydown",
152
+ "type": "(event: KeyboardEvent) => void",
153
+ "description": "Callback to override the toggle keydown behavior. By default, when the toggle has focus and the menu is open, pressing the up/down arrow keys will focus a valid non-disabled menu item - the first item for the down arrow key and last item for the up arrow key."
154
+ },
155
+ {
156
+ "name": "ouiaId",
157
+ "type": "number | string",
158
+ "description": "Value to overwrite the randomly generated data-ouia-component-id."
159
+ },
160
+ {
161
+ "name": "ouiaSafe",
162
+ "type": "boolean",
163
+ "description": "Set the value of data-ouia-safe. Only set to true when the component is in a static state, i.e. no animations are occurring. At all other times, this value must be false."
164
+ },
165
+ {
166
+ "name": "parentMenu",
167
+ "type": "string",
168
+ "description": "ID of parent menu for drilldown menus"
169
+ },
170
+ {
171
+ "name": "popperProps",
172
+ "type": "PopperOptions",
173
+ "description": "Additional properties to pass to the popper"
174
+ },
175
+ {
176
+ "name": "role",
177
+ "type": "string",
178
+ "description": "Determines the accessible role of the menu. For a non-checkbox menu that can have\none or more items selected, pass in \"listbox\"."
179
+ },
180
+ {
181
+ "name": "selected",
182
+ "type": "any | any[]",
183
+ "description": "Single itemId for single select menus, or array of itemIds for multi select. You can also specify isSelected on the MenuItem."
184
+ },
185
+ {
186
+ "name": "shouldFocusFirstItemOnOpen",
187
+ "type": "boolean",
188
+ "description": "Flag indicating the first menu item should be focused after opening the menu.",
189
+ "beta": true
190
+ },
191
+ {
192
+ "name": "shouldFocusToggleOnSelect",
193
+ "type": "boolean",
194
+ "description": "Flag indicating the toggle should be focused after a selection. If this use case is too restrictive, the optional toggleRef property with a node toggle may be used to control focus."
195
+ },
196
+ {
197
+ "name": "shouldPreventScrollOnItemFocus",
198
+ "type": "boolean",
199
+ "description": "Flag indicating if scroll on focus of the first menu item should occur."
200
+ },
201
+ {
202
+ "name": "toggle",
203
+ "type": "SelectToggleProps | ((toggleRef: React.RefObject<any>) => React.ReactNode)",
204
+ "description": "Select toggle. The toggle should either be a renderer function which forwards the given toggle ref, or a direct ReactNode that should be passed along with the toggleRef property.",
205
+ "required": true
206
+ },
207
+ {
208
+ "name": "variant",
209
+ "type": "'default' | 'typeahead'",
210
+ "description": "Select variant. For typeahead variant focus won't shift to menu items when pressing up/down arrows."
211
+ },
212
+ {
213
+ "name": "zIndex",
214
+ "type": "number",
215
+ "description": "z-index of the select menu"
216
+ }
217
+ ]
218
+ },
219
+ {
220
+ "name": "SelectOption",
221
+ "description": "See the MenuItem section of the Menu documentation for additional props that may be passed.",
222
+ "props": [
223
+ {
224
+ "name": "children",
225
+ "type": "React.ReactNode",
226
+ "description": "Anything which can be rendered in a select option"
227
+ },
228
+ {
229
+ "name": "className",
230
+ "type": "string",
231
+ "description": "Classes applied to root element of select option"
232
+ },
233
+ {
234
+ "name": "description",
235
+ "type": "React.ReactNode",
236
+ "description": "Description of the option"
237
+ },
238
+ {
239
+ "name": "hasCheckbox",
240
+ "type": "boolean",
241
+ "description": "Indicates the option has a checkbox"
242
+ },
243
+ {
244
+ "name": "icon",
245
+ "type": "React.ReactNode",
246
+ "description": "Render option with icon"
247
+ },
248
+ {
249
+ "name": "isDisabled",
250
+ "type": "boolean",
251
+ "description": "Indicates the option is disabled"
252
+ },
253
+ {
254
+ "name": "isExternalLink",
255
+ "type": "boolean",
256
+ "description": "Render an external link icon on focus or hover, and set the link's\n\"target\" attribute to a value of \"_blank\"."
257
+ },
258
+ {
259
+ "name": "isFocused",
260
+ "type": "boolean",
261
+ "description": "Indicates the option is focused"
262
+ },
263
+ {
264
+ "name": "isSelected",
265
+ "type": "boolean",
266
+ "description": "Indicates the option is selected"
267
+ },
268
+ {
269
+ "name": "value",
270
+ "type": "any",
271
+ "description": "Identifies the component in the Select onSelect callback"
272
+ }
273
+ ]
274
+ },
275
+ {
276
+ "name": "SelectGroup",
277
+ "description": "See the MenuGroup section of the Menu documentation for additional props that may be passed.",
278
+ "props": [
279
+ {
280
+ "name": "children",
281
+ "type": "React.ReactNode",
282
+ "description": "Anything which can be rendered in a select group",
283
+ "required": true
284
+ },
285
+ {
286
+ "name": "className",
287
+ "type": "string",
288
+ "description": "Classes applied to root element of select group"
289
+ },
290
+ {
291
+ "name": "label",
292
+ "type": "React.ReactNode",
293
+ "description": "Label of the select group"
294
+ }
295
+ ]
296
+ },
297
+ {
298
+ "name": "SelectList",
299
+ "description": "",
300
+ "props": [
301
+ {
302
+ "name": "aria-label",
303
+ "type": "string",
304
+ "description": "Adds an accessible name to the menu."
305
+ },
306
+ {
307
+ "name": "children",
308
+ "type": "React.ReactNode",
309
+ "description": "Anything that can be rendered inside of menu list",
310
+ "required": true
311
+ },
312
+ {
313
+ "name": "className",
314
+ "type": "string",
315
+ "description": "Additional classes added to the menu list"
316
+ },
317
+ {
318
+ "name": "isAriaMultiselectable",
319
+ "type": "boolean",
320
+ "description": "Indicates to assistive technologies whether more than one item can be selected\nfor a non-checkbox menu. Only applies when the menu's role is \"listbox\".",
321
+ "defaultValue": "false"
322
+ }
323
+ ]
324
+ },
325
+ {
326
+ "name": "MenuToggle",
327
+ "description": "",
328
+ "props": [
329
+ {
330
+ "name": "badge",
331
+ "type": "BadgeProps | React.ReactNode",
332
+ "description": "Optional badge rendered inside the toggle, after the children content"
333
+ },
334
+ {
335
+ "name": "children",
336
+ "type": "React.ReactNode",
337
+ "description": "Content rendered inside the toggle"
338
+ },
339
+ {
340
+ "name": "className",
341
+ "type": "string",
342
+ "description": "Additional classes added to the toggle"
343
+ },
344
+ {
345
+ "name": "icon",
346
+ "type": "React.ReactNode",
347
+ "description": "Optional icon or image rendered inside the toggle, before the children content. It is\nrecommended to wrap most basic icons in our icon component."
348
+ },
349
+ {
350
+ "name": "isCircle",
351
+ "type": "boolean",
352
+ "description": "Flag indicating the toggle has circular styling. Can only be applied to plain toggles.",
353
+ "beta": true
354
+ },
355
+ {
356
+ "name": "isDisabled",
357
+ "type": "boolean",
358
+ "description": "Flag indicating the toggle is disabled"
359
+ },
360
+ {
361
+ "name": "isDocked",
362
+ "type": "boolean",
363
+ "description": "Flag indicating the menu toggle is a docked variant. For use in docked navigation.",
364
+ "beta": true
365
+ },
366
+ {
367
+ "name": "isExpanded",
368
+ "type": "boolean",
369
+ "description": "Flag indicating the toggle has expanded styling"
370
+ },
371
+ {
372
+ "name": "isFullHeight",
373
+ "type": "boolean",
374
+ "description": "Flag indicating the toggle is full height"
375
+ },
376
+ {
377
+ "name": "isFullWidth",
378
+ "type": "boolean",
379
+ "description": "Flag indicating the toggle takes up the full width of its parent"
380
+ },
381
+ {
382
+ "name": "isInForm",
383
+ "type": "boolean",
384
+ "description": "Flag indicating the toggle is placed inside a form",
385
+ "beta": true
386
+ },
387
+ {
388
+ "name": "isPlaceholder",
389
+ "type": "boolean",
390
+ "description": "Flag indicating the toggle contains placeholder text"
391
+ },
392
+ {
393
+ "name": "isSettings",
394
+ "type": "boolean",
395
+ "description": "Flag indicating whether the toggle is a settings toggle. This will override the icon property"
396
+ },
397
+ {
398
+ "name": "isTextExpanded",
399
+ "type": "boolean",
400
+ "description": "Flag indicating the docked toggle should display text. Only applies when isDocked is true.",
401
+ "beta": true
402
+ },
403
+ {
404
+ "name": "ouiaId",
405
+ "type": "number | string",
406
+ "description": "Value to overwrite the randomly generated data-ouia-component-id. It will always target the toggle button."
407
+ },
408
+ {
409
+ "name": "ouiaSafe",
410
+ "type": "boolean",
411
+ "description": "Set the value of data-ouia-safe. Only set to true when the component is in a static state, i.e. no animations are occurring. At all other times, this value must be false."
412
+ },
413
+ {
414
+ "name": "size",
415
+ "type": "'default' | 'sm'",
416
+ "description": "Adds styling which affects the size of the menu toggle"
417
+ },
418
+ {
419
+ "name": "splitButtonItems",
420
+ "type": "React.ReactNode[]",
421
+ "description": "Elements to display before the toggle button. When included, renders the menu toggle as a split button."
422
+ },
423
+ {
424
+ "name": "status",
425
+ "type": "'success' | 'warning' | 'danger'",
426
+ "description": "Status styles of the menu toggle"
427
+ },
428
+ {
429
+ "name": "statusIcon",
430
+ "type": "React.ReactNode",
431
+ "description": "Overrides the status icon"
432
+ },
433
+ {
434
+ "name": "variant",
435
+ "type": "'default' | 'plain' | 'primary' | 'plainText' | 'secondary' | 'typeahead'",
436
+ "description": "Variant styles of the menu toggle"
437
+ }
438
+ ]
439
+ },
440
+ {
441
+ "name": "SelectToggleProps",
442
+ "description": "",
443
+ "props": [
444
+ {
445
+ "name": "toggleNode",
446
+ "type": "React.ReactNode",
447
+ "description": "Select toggle node.",
448
+ "required": true
449
+ },
450
+ {
451
+ "name": "toggleRef",
452
+ "type": "React.RefObject<HTMLButtonElement | null>",
453
+ "description": "Reference to the toggle."
454
+ }
455
+ ]
456
+ },
457
+ {
458
+ "name": "PopperOptions",
459
+ "description": "Properties of Popper that can be used to customize its behavior.",
460
+ "props": [
461
+ {
462
+ "name": "animationDuration",
463
+ "type": "number",
464
+ "description": "The duration of the CSS fade transition animation."
465
+ },
466
+ {
467
+ "name": "appendTo",
468
+ "type": "HTMLElement | (() => HTMLElement) | 'inline'",
469
+ "description": "The container to append the popper to. Defaults to 'inline'."
470
+ },
471
+ {
472
+ "name": "direction",
473
+ "type": "'up' | 'down'",
474
+ "description": "popper direction"
475
+ },
476
+ {
477
+ "name": "distance",
478
+ "type": "number",
479
+ "description": "Distance of the popper to the trigger"
480
+ },
481
+ {
482
+ "name": "enableFlip",
483
+ "type": "boolean",
484
+ "description": "Enable to flip the popper when it reaches the boundary"
485
+ },
486
+ {
487
+ "name": "entryDelay",
488
+ "type": "number",
489
+ "description": "Delay in ms before the popper appears"
490
+ },
491
+ {
492
+ "name": "exitDelay",
493
+ "type": "number",
494
+ "description": "Delay in ms before the popper disappears"
495
+ },
496
+ {
497
+ "name": "flipBehavior",
498
+ "type": "| 'flip'\n | (\n | 'top'\n | 'bottom'\n | 'left'\n | 'right'\n | 'top-start'\n | 'top-end'\n | 'bottom-start'\n | 'bottom-end'\n | 'left-start'\n | 'left-end'\n | 'right-start'\n | 'right-end'\n )[]",
499
+ "description": "The behavior of how the popper flips when it reaches the boundary"
500
+ },
501
+ {
502
+ "name": "maxWidth",
503
+ "type": "string | 'trigger'",
504
+ "description": "Maximum width of the popper. If the value is \"trigger\", it will set the max width to the trigger element's width"
505
+ },
506
+ {
507
+ "name": "minWidth",
508
+ "type": "string | 'trigger'",
509
+ "description": "Minimum width of the popper. If the value is \"trigger\", it will set the min width to the trigger element's width"
510
+ },
511
+ {
512
+ "name": "offset",
513
+ "type": "OffsetOptions['offset']",
514
+ "description": "Override for the popper's offset"
515
+ },
516
+ {
517
+ "name": "onBlur",
518
+ "type": "(event?: FocusEvent) => void",
519
+ "description": "Callback function when trigger is blurred (focus leaves)"
520
+ },
521
+ {
522
+ "name": "onDocumentClick",
523
+ "type": "(event?: MouseEvent, triggerElement?: HTMLElement, popperElement?: HTMLElement) => void",
524
+ "description": "Callback function when document is clicked"
525
+ },
526
+ {
527
+ "name": "onDocumentKeyDown",
528
+ "type": "(event?: KeyboardEvent) => void",
529
+ "description": "Callback function when keydown event occurs on document"
530
+ },
531
+ {
532
+ "name": "onFocus",
533
+ "type": "(event?: FocusEvent) => void",
534
+ "description": "Callback function when trigger is focused"
535
+ },
536
+ {
537
+ "name": "onHidden",
538
+ "type": "() => void",
539
+ "description": "Callback when popper's hide transition has finished executing"
540
+ },
541
+ {
542
+ "name": "onHide",
543
+ "type": "() => void",
544
+ "description": "Lifecycle function invoked when the popper begins to transition out."
545
+ },
546
+ {
547
+ "name": "onMount",
548
+ "type": "() => void",
549
+ "description": "Lifecycle function invoked when the popper has been mounted to the DOM."
550
+ },
551
+ {
552
+ "name": "onMouseEnter",
553
+ "type": "(event?: MouseEvent) => void",
554
+ "description": "Callback function when mouse enters trigger"
555
+ },
556
+ {
557
+ "name": "onMouseLeave",
558
+ "type": "(event?: MouseEvent) => void",
559
+ "description": "Callback function when mouse leaves trigger"
560
+ },
561
+ {
562
+ "name": "onPopperClick",
563
+ "type": "(event?: MouseEvent) => void",
564
+ "description": "Callback function when popper is clicked"
565
+ },
566
+ {
567
+ "name": "onPopperMouseEnter",
568
+ "type": "(event?: MouseEvent) => void",
569
+ "description": "Callback function when mouse enters popper content"
570
+ },
571
+ {
572
+ "name": "onPopperMouseLeave",
573
+ "type": "(event?: MouseEvent) => void",
574
+ "description": "Callback function when mouse leaves popper content"
575
+ },
576
+ {
577
+ "name": "onShow",
578
+ "type": "() => void",
579
+ "description": "Lifecycle function invoked when the popper begins to transition in."
580
+ },
581
+ {
582
+ "name": "onShown",
583
+ "type": "() => void",
584
+ "description": "Lifecycle function invoked when the popper has fully transitioned in."
585
+ },
586
+ {
587
+ "name": "onTriggerClick",
588
+ "type": "(event?: MouseEvent) => void",
589
+ "description": "Callback function when trigger is clicked"
590
+ },
591
+ {
592
+ "name": "onTriggerEnter",
593
+ "type": "(event?: KeyboardEvent) => void",
594
+ "description": "Callback function when Enter key is used on trigger"
595
+ },
596
+ {
597
+ "name": "placement",
598
+ "type": "Placement",
599
+ "description": "Instead of direction and position can set the placement of the popper"
600
+ },
601
+ {
602
+ "name": "position",
603
+ "type": "'right' | 'left' | 'center' | 'start' | 'end'",
604
+ "description": "Horizontal position of the popper. Use the additional prop preventOverflow if seeing clipping."
605
+ },
606
+ {
607
+ "name": "positionModifiers",
608
+ "type": "{\n top?: string;\n right?: string;\n bottom?: string;\n left?: string;\n topStart?: string;\n topEnd?: string;\n bottomStart?: string;\n bottomEnd?: string;\n leftStart?: string;\n leftEnd?: string;\n rightStart?: string;\n rightEnd?: string;\n }",
609
+ "description": "Map class names to positions, for example:\n{\n top: styles.modifiers.top,\n bottom: styles.modifiers.bottom,\n left: styles.modifiers.left,\n right: styles.modifiers.right\n}"
610
+ },
611
+ {
612
+ "name": "preventOverflow",
613
+ "type": "boolean",
614
+ "description": "Flag to prevent the popper from overflowing its container and becoming partially obscured."
615
+ },
616
+ {
617
+ "name": "width",
618
+ "type": "string | 'trigger'",
619
+ "description": "Custom width of the popper. If the value is \"trigger\", it will set the width to the trigger element's width"
620
+ },
621
+ {
622
+ "name": "zIndex",
623
+ "type": "number",
624
+ "description": "z-index of the popper element"
625
+ }
626
+ ]
627
+ }
628
+ ],
629
+ "cssPrefix": [
630
+ "pf-v6-c-select"
631
+ ],
632
+ "examples": [
633
+ "Single select",
634
+ "Select option variants",
635
+ "With grouped items",
636
+ "With validation",
637
+ "Checkbox select",
638
+ "Typeahead",
639
+ "Typeahead with create option",
640
+ "Multiple typeahead with labels",
641
+ "Multiple typeahead with create option",
642
+ "Multiple typeahead with checkboxes",
643
+ "With view more",
644
+ "With a footer"
645
+ ]
646
+ };
647
+ pageData.liveContext = {
648
+ Fragment,
649
+ useEffect,
650
+ useRef,
651
+ useState,
652
+ RhMicronsCloseIcon,
653
+ RhUiNotificationFillIcon
654
+ };
655
+ pageData.examples = {
656
+ 'Single select': props =>
657
+ <Example {...pageData} {...props} {...{"code":"import { Fragment, useState } from 'react';\nimport { Select, SelectOption, SelectList, MenuToggle, MenuToggleElement, Checkbox } from '@patternfly/react-core';\n\nexport const SelectBasic: React.FunctionComponent = () => {\n const [isOpen, setIsOpen] = useState(false);\n const [selected, setSelected] = useState<string>('Select a value');\n const [isDisabled, setIsDisabled] = useState<boolean>(false);\n\n const onToggleClick = () => {\n setIsOpen(!isOpen);\n };\n\n const onSelect = (_event: React.MouseEvent<Element, MouseEvent> | undefined, value: string | number | undefined) => {\n // eslint-disable-next-line no-console\n console.log('selected', value);\n\n setSelected(value as string);\n setIsOpen(false);\n };\n\n const toggle = (toggleRef: React.Ref<MenuToggleElement>) => (\n <MenuToggle\n ref={toggleRef}\n onClick={onToggleClick}\n isExpanded={isOpen}\n isDisabled={isDisabled}\n style={\n {\n width: '200px'\n } as React.CSSProperties\n }\n >\n {selected}\n </MenuToggle>\n );\n\n return (\n <Fragment>\n <Checkbox\n id=\"toggle-disabled\"\n label=\"isDisabled\"\n isChecked={isDisabled}\n onChange={(_event, checked) => setIsDisabled(checked)}\n style={{ marginBottom: 20 }}\n />\n <Select\n id=\"single-select\"\n isOpen={isOpen}\n selected={selected}\n onSelect={onSelect}\n onOpenChange={(isOpen) => setIsOpen(isOpen)}\n toggle={toggle}\n shouldFocusToggleOnSelect\n >\n <SelectList>\n <SelectOption value=\"Option 1\">Option 1</SelectOption>\n <SelectOption value=\"Option 2\">Option 2</SelectOption>\n <SelectOption value=\"Option 3\">Option 3</SelectOption>\n </SelectList>\n </Select>\n </Fragment>\n );\n};\n","title":"Single select","lang":"ts","className":""}}>
658
+
659
+ <p {...{"className":"pf-v6-c-content--p pf-m-editorial ws-p "}}>
660
+ {`To let users select a single item from a list, use a single select menu.`}
661
+ </p>
662
+
663
+ <p {...{"className":"pf-v6-c-content--p pf-m-editorial ws-p "}}>
664
+ {`You can add multiple `}
665
+
666
+ <code {...{"className":"ws-code "}}>
667
+ {`<SelectOption>`}
668
+ </code>
669
+ {` components to build out a list of menu items. For each select option, pass a relevant option label to the `}
670
+
671
+ <code {...{"className":"ws-code "}}>
672
+ {`value`}
673
+ </code>
674
+ {` property.`}
675
+ </p>
676
+
677
+ <p {...{"className":"pf-v6-c-content--p pf-m-editorial ws-p "}}>
678
+ {`To disable the select menu toggle, use the `}
679
+
680
+ <code {...{"className":"ws-code "}}>
681
+ {`isDisabled`}
682
+ </code>
683
+ {` property. In the following example, select the checkbox to observe this behavior.`}
684
+ </p>
685
+ </Example>,
686
+ 'Select option variants': props =>
687
+ <Example {...pageData} {...props} {...{"code":"import { useState } from 'react';\nimport { Select, SelectOption, SelectList, MenuToggle, MenuToggleElement } from '@patternfly/react-core';\nimport RhUiNotificationFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-notification-fill-icon';\n\nexport const SelectOptionVariations: React.FunctionComponent = () => {\n const [isOpen, setIsOpen] = useState(false);\n const [selected, setSelected] = useState<string>('Select a value');\n\n const onToggleClick = () => {\n setIsOpen(!isOpen);\n };\n\n const onSelect = (_event: React.MouseEvent<Element, MouseEvent> | undefined, value: string | number | undefined) => {\n // eslint-disable-next-line no-console\n console.log('selected', value);\n\n setSelected(value as string);\n setIsOpen(false);\n };\n\n const toggle = (toggleRef: React.Ref<MenuToggleElement>) => (\n <MenuToggle\n ref={toggleRef}\n onClick={onToggleClick}\n isExpanded={isOpen}\n style={\n {\n width: '200px'\n } as React.CSSProperties\n }\n >\n {selected}\n </MenuToggle>\n );\n\n return (\n <Select\n id=\"option-variations-select\"\n isOpen={isOpen}\n selected={selected}\n onSelect={onSelect}\n onOpenChange={(isOpen) => setIsOpen(isOpen)}\n toggle={toggle}\n shouldFocusToggleOnSelect\n >\n <SelectList>\n <SelectOption value=\"Basic option\">Basic option</SelectOption>\n <SelectOption value=\"Option with description\" description=\"This is a description\">\n Option with description\n </SelectOption>\n <SelectOption\n to=\"#\"\n // Prevent default clicking functionality for example purposes only\n onClick={(event) => event.preventDefault()}\n value=\"Option with link\"\n isExternalLink\n >\n Option with link\n </SelectOption>\n <SelectOption value=\"Option with icon\" icon={<RhUiNotificationFillIcon />}>\n Option with icon\n </SelectOption>\n <SelectOption value=\"Disabled option\" isDisabled>\n Disabled option\n </SelectOption>\n <SelectOption value=\"See Menu for additional variations!\">See Menu for additional variations!</SelectOption>\n </SelectList>\n </Select>\n );\n};\n","title":"Select option variants","lang":"ts","className":""}}>
688
+
689
+ <p {...{"className":"pf-v6-c-content--p pf-m-editorial ws-p "}}>
690
+ {`The following example showcases different option variants and customizations that are commonly used in a select menu.`}
691
+ </p>
692
+
693
+ <p {...{"className":"pf-v6-c-content--p pf-m-editorial ws-p "}}>
694
+ {`To create these variants, you can pass different properties into a `}
695
+
696
+ <code {...{"className":"ws-code "}}>
697
+ {`<SelectOption>`}
698
+ </code>
699
+ {` component.`}
700
+ </p>
701
+
702
+ <p {...{"className":"pf-v6-c-content--p pf-m-editorial ws-p "}}>
703
+ {`This example provides examples of:`}
704
+ </p>
705
+
706
+ <ul {...{"className":"pf-v6-c-content--ul pf-m-editorial ws-ul "}}>
707
+
708
+
709
+
710
+ <li {...{"className":"pf-v6-c-content--li pf-m-editorial ws-li "}}>
711
+ {`An option with a description, which is created by using the `}
712
+
713
+ <code {...{"className":"ws-code "}}>
714
+ {`description`}
715
+ </code>
716
+ {` property.`}
717
+ </li>
718
+
719
+
720
+
721
+ <li {...{"className":"pf-v6-c-content--li pf-m-editorial ws-li "}}>
722
+ {`An option with a link, which is created by passing a URL into the `}
723
+
724
+ <code {...{"className":"ws-code "}}>
725
+ {`to`}
726
+ </code>
727
+ {` property. For external links, use the `}
728
+
729
+ <code {...{"className":"ws-code "}}>
730
+ {`isExternalLink`}
731
+ </code>
732
+ {` property so that the option is styled with an outbound link icon.`}
733
+ </li>
734
+
735
+
736
+
737
+ <li {...{"className":"pf-v6-c-content--li pf-m-editorial ws-li "}}>
738
+ {`An option with an icon, which is created by using the `}
739
+
740
+ <code {...{"className":"ws-code "}}>
741
+ {`icon`}
742
+ </code>
743
+ {` property.`}
744
+ </li>
745
+
746
+
747
+
748
+ <li {...{"className":"pf-v6-c-content--li pf-m-editorial ws-li "}}>
749
+ {`An option that is disabled by using the `}
750
+
751
+ <code {...{"className":"ws-code "}}>
752
+ {`isDisabled`}
753
+ </code>
754
+ {` property.`}
755
+ </li>
756
+
757
+
758
+ </ul>
759
+ </Example>,
760
+ 'With grouped items': props =>
761
+ <Example {...pageData} {...props} {...{"code":"import { useState } from 'react';\nimport {\n Select,\n SelectOption,\n SelectList,\n SelectGroup,\n MenuToggle,\n MenuToggleElement,\n Divider\n} from '@patternfly/react-core';\n\nexport const SelectGrouped: React.FunctionComponent = () => {\n const [isOpen, setIsOpen] = useState(false);\n const [selected, setSelected] = useState<string>('Select a value');\n\n const onToggleClick = () => {\n setIsOpen(!isOpen);\n };\n\n const onSelect = (_event: React.MouseEvent<Element, MouseEvent> | undefined, value: string | number | undefined) => {\n // eslint-disable-next-line no-console\n console.log('selected', value);\n\n setSelected(value as string);\n setIsOpen(false);\n };\n\n const toggle = (toggleRef: React.Ref<MenuToggleElement>) => (\n <MenuToggle\n ref={toggleRef}\n onClick={onToggleClick}\n isExpanded={isOpen}\n style={\n {\n width: '200px'\n } as React.CSSProperties\n }\n >\n {selected}\n </MenuToggle>\n );\n\n return (\n <Select\n id=\"single-grouped-select\"\n isOpen={isOpen}\n selected={selected}\n onSelect={onSelect}\n onOpenChange={(isOpen) => setIsOpen(isOpen)}\n toggle={toggle}\n shouldFocusToggleOnSelect\n >\n <SelectGroup label=\"Group 1\">\n <SelectList>\n <SelectOption value=\"Option 1\">Option 1</SelectOption>\n <SelectOption value=\"Option 2\">Option 2</SelectOption>\n <SelectOption value=\"Option 3\">Option 3</SelectOption>\n </SelectList>\n </SelectGroup>\n <Divider />\n <SelectGroup label=\"Group 2\">\n <SelectList>\n <SelectOption value=\"Option 4\">Option 4</SelectOption>\n <SelectOption value=\"Option 5\">Option 5</SelectOption>\n <SelectOption value=\"Option 6\">Option 6</SelectOption>\n </SelectList>\n </SelectGroup>\n </Select>\n );\n};\n","title":"With grouped items","lang":"ts","className":""}}>
762
+
763
+ <p {...{"className":"pf-v6-c-content--p pf-m-editorial ws-p "}}>
764
+ {`To group related select options together, use 1 or more `}
765
+
766
+ <code {...{"className":"ws-code "}}>
767
+ {`<SelectGroup>`}
768
+ </code>
769
+ {` components and title each group using the `}
770
+
771
+ <code {...{"className":"ws-code "}}>
772
+ {`label`}
773
+ </code>
774
+ {` property.`}
775
+ </p>
776
+ </Example>,
777
+ 'With validation': props =>
778
+ <Example {...pageData} {...props} {...{"code":"import { Fragment, useState } from 'react';\nimport {\n Select,\n SelectOption,\n SelectList,\n MenuToggle,\n MenuToggleElement,\n MenuToggleStatus,\n HelperText,\n HelperTextItem\n} from '@patternfly/react-core';\n\nexport const SelectValidated: React.FunctionComponent = () => {\n const [isOpen, setIsOpen] = useState(false);\n const [selected, setSelected] = useState<string>('Select a value');\n const [status, setStatus] = useState<MenuToggleStatus>();\n\n const onToggleClick = () => {\n setIsOpen(!isOpen);\n };\n\n const onSelect = (_event: React.MouseEvent<Element, MouseEvent> | undefined, value: string | number | undefined) => {\n // eslint-disable-next-line no-console\n console.log('selected', value);\n\n setSelected(value as string);\n setStatus((value as string).toLowerCase() as MenuToggleStatus);\n setIsOpen(false);\n };\n\n const toggle = (toggleRef: React.Ref<MenuToggleElement>) => (\n <MenuToggle\n ref={toggleRef}\n onClick={onToggleClick}\n isExpanded={isOpen}\n style={\n {\n width: '200px'\n } as React.CSSProperties\n }\n status={status}\n >\n {selected}\n </MenuToggle>\n );\n\n return (\n <Fragment>\n <Select\n id=\"single-select\"\n isOpen={isOpen}\n selected={selected}\n onSelect={onSelect}\n onOpenChange={(isOpen) => setIsOpen(isOpen)}\n toggle={toggle}\n shouldFocusToggleOnSelect\n >\n <SelectList>\n <SelectOption value=\"Success\">Success</SelectOption>\n <SelectOption value=\"Warning\">Warning</SelectOption>\n <SelectOption value=\"Danger\">Danger</SelectOption>\n </SelectList>\n </Select>\n {(status === MenuToggleStatus.warning || status === MenuToggleStatus.danger) && (\n <HelperText isLiveRegion>\n <HelperTextItem variant={status === MenuToggleStatus.warning ? 'warning' : 'error'}>\n {status === MenuToggleStatus.warning && 'Warning text that explains the issue.'}\n {status === MenuToggleStatus.danger && 'Danger text that explains the issue.'}\n </HelperTextItem>\n </HelperText>\n )}\n </Fragment>\n );\n};\n","title":"With validation","lang":"ts","className":""}}>
779
+
780
+ <p {...{"className":"pf-v6-c-content--p pf-m-editorial ws-p "}}>
781
+ {`To create a toggle with a status, pass in `}
782
+
783
+ <code {...{"className":"ws-code "}}>
784
+ {`status`}
785
+ </code>
786
+ {` to the `}
787
+
788
+ <code {...{"className":"ws-code "}}>
789
+ {`MenuToggle`}
790
+ </code>
791
+ {`. The default icon associated with each status may be overridden by using the `}
792
+
793
+ <code {...{"className":"ws-code "}}>
794
+ {`statusIcon`}
795
+ </code>
796
+ {` property.`}
797
+ </p>
798
+
799
+ <p {...{"className":"pf-v6-c-content--p pf-m-editorial ws-p "}}>
800
+ {`When the status value is "warning" or "danger", you must include helper text that conveys what is causing the warning/error.`}
801
+ </p>
802
+ </Example>,
803
+ 'Checkbox select': props =>
804
+ <Example {...pageData} {...props} {...{"code":"import { useState } from 'react';\nimport { Select, SelectOption, SelectList, MenuToggle, MenuToggleElement, Badge } from '@patternfly/react-core';\n\nexport const SelectCheckbox: React.FunctionComponent = () => {\n const [isOpen, setIsOpen] = useState(false);\n const [selectedItems, setSelectedItems] = useState<number[]>([]);\n\n const onToggleClick = () => {\n setIsOpen(!isOpen);\n };\n\n const onSelect = (_event: React.MouseEvent<Element, MouseEvent> | undefined, value: string | number | undefined) => {\n // eslint-disable-next-line no-console\n console.log('selected', value);\n\n if (selectedItems.includes(value as number)) {\n setSelectedItems(selectedItems.filter((id) => id !== value));\n } else {\n setSelectedItems([...selectedItems, value as number]);\n }\n };\n\n const toggle = (toggleRef: React.Ref<MenuToggleElement>) => (\n <MenuToggle\n ref={toggleRef}\n onClick={onToggleClick}\n isExpanded={isOpen}\n style={\n {\n width: '200px'\n } as React.CSSProperties\n }\n >\n Filter by status\n {selectedItems.length > 0 && <Badge isRead>{selectedItems.length}</Badge>}\n </MenuToggle>\n );\n\n return (\n <Select\n role=\"menu\"\n id=\"checkbox-select\"\n isOpen={isOpen}\n selected={selectedItems}\n onSelect={onSelect}\n onOpenChange={(nextOpen: boolean) => setIsOpen(nextOpen)}\n toggle={toggle}\n >\n <SelectList>\n <SelectOption hasCheckbox value={0} isSelected={selectedItems.includes(0)}>\n Debug\n </SelectOption>\n <SelectOption hasCheckbox value={1} isSelected={selectedItems.includes(1)}>\n Info\n </SelectOption>\n <SelectOption hasCheckbox value={2} isSelected={selectedItems.includes(2)}>\n Warn\n </SelectOption>\n <SelectOption hasCheckbox isDisabled value={4} isSelected={selectedItems.includes(4)}>\n Error\n </SelectOption>\n </SelectList>\n </Select>\n );\n};\n","title":"Checkbox select","lang":"ts","className":""}}>
805
+
806
+ <p {...{"className":"pf-v6-c-content--p pf-m-editorial ws-p "}}>
807
+ {`To let users select multiple list options via checkbox input, use a checkbox select.`}
808
+ </p>
809
+
810
+ <p {...{"className":"pf-v6-c-content--p pf-m-editorial ws-p "}}>
811
+ {`To create a checkbox select, pass `}
812
+
813
+ <code {...{"className":"ws-code "}}>
814
+ {`role="menu"`}
815
+ </code>
816
+ {` to the `}
817
+
818
+ <code {...{"className":"ws-code "}}>
819
+ {`<Select>`}
820
+ </code>
821
+ {`, and `}
822
+
823
+ <code {...{"className":"ws-code "}}>
824
+ {`hasCheckbox`}
825
+ </code>
826
+ {` into each `}
827
+
828
+ <code {...{"className":"ws-code "}}>
829
+ {`<SelectOption>`}
830
+ </code>
831
+ {` component. To indicate that an option is selected, use the `}
832
+
833
+ <code {...{"className":"ws-code "}}>
834
+ {`isSelected`}
835
+ </code>
836
+ {` property.`}
837
+ </p>
838
+
839
+ <p {...{"className":"pf-v6-c-content--p pf-m-editorial ws-p "}}>
840
+ {`By default, the menu toggle will display a badge to indicate the number of items that a user has selected.`}
841
+ </p>
842
+ </Example>,
843
+ 'Typeahead': props =>
844
+ <Example {...pageData} {...props} {...{"code":"import { useEffect, useRef, useState } from 'react';\nimport {\n Select,\n SelectOption,\n SelectList,\n SelectOptionProps,\n MenuToggle,\n MenuToggleElement,\n TextInputGroup,\n TextInputGroupMain,\n TextInputGroupUtilities,\n Button\n} from '@patternfly/react-core';\nimport RhMicronsCloseIcon from '@patternfly/react-icons/dist/esm/icons/rh-microns-close-icon';\n\nconst initialSelectOptions: SelectOptionProps[] = [\n { value: 'Alabama', children: 'Alabama' },\n { value: 'Florida', children: 'Florida' },\n { value: 'New Jersey', children: 'New Jersey' },\n { value: 'New Mexico', children: 'New Mexico' },\n { value: 'New York', children: 'New York' },\n { value: 'North Carolina', children: 'North Carolina' }\n];\n\nexport const SelectTypeahead: React.FunctionComponent = () => {\n const [isOpen, setIsOpen] = useState(false);\n const [selected, setSelected] = useState<string>('');\n const [inputValue, setInputValue] = useState<string>('');\n const [filterValue, setFilterValue] = useState<string>('');\n const [selectOptions, setSelectOptions] = useState<SelectOptionProps[]>(initialSelectOptions);\n const [focusedItemIndex, setFocusedItemIndex] = useState<number | null>(null);\n const [activeItemId, setActiveItemId] = useState<string | null>(null);\n const textInputRef = useRef<HTMLInputElement>(undefined);\n\n const NO_RESULTS = 'no results';\n\n useEffect(() => {\n let newSelectOptions: SelectOptionProps[] = initialSelectOptions;\n\n // Filter menu items based on the text input value when one exists\n if (filterValue) {\n newSelectOptions = initialSelectOptions.filter((menuItem) =>\n String(menuItem.children).toLowerCase().includes(filterValue.toLowerCase())\n );\n\n // When no options are found after filtering, display 'No results found'\n if (!newSelectOptions.length) {\n newSelectOptions = [\n { isAriaDisabled: true, children: `No results found for \"${filterValue}\"`, value: NO_RESULTS }\n ];\n }\n\n // Open the menu when the input value changes and the new value is not empty\n if (!isOpen) {\n setIsOpen(true);\n }\n }\n\n setSelectOptions(newSelectOptions);\n }, [filterValue]);\n\n const createItemId = (value: any) => `select-typeahead-${value.replace(' ', '-')}`;\n\n const setActiveAndFocusedItem = (itemIndex: number) => {\n setFocusedItemIndex(itemIndex);\n const focusedItem = selectOptions[itemIndex];\n setActiveItemId(createItemId(focusedItem.value));\n };\n\n const resetActiveAndFocusedItem = () => {\n setFocusedItemIndex(null);\n setActiveItemId(null);\n };\n\n const closeMenu = () => {\n setIsOpen(false);\n resetActiveAndFocusedItem();\n };\n\n const onInputClick = () => {\n if (!isOpen) {\n setIsOpen(true);\n } else if (!inputValue) {\n closeMenu();\n }\n };\n\n const selectOption = (value: string | number, content: string | number) => {\n // eslint-disable-next-line no-console\n console.log('selected', content);\n\n setInputValue(String(content));\n setFilterValue('');\n setSelected(String(value));\n\n closeMenu();\n };\n\n const onSelect = (_event: React.MouseEvent<Element, MouseEvent> | undefined, value: string | number | undefined) => {\n if (value && value !== NO_RESULTS) {\n const optionText = selectOptions.find((option) => option.value === value)?.children;\n selectOption(value, optionText as string);\n }\n };\n\n const onTextInputChange = (_event: React.FormEvent<HTMLInputElement>, value: string) => {\n setInputValue(value);\n setFilterValue(value);\n\n resetActiveAndFocusedItem();\n\n if (value !== selected) {\n setSelected('');\n }\n };\n\n const handleMenuArrowKeys = (key: string) => {\n let indexToFocus = 0;\n\n if (!isOpen) {\n setIsOpen(true);\n }\n\n if (selectOptions.every((option) => option.isDisabled)) {\n return;\n }\n\n if (key === 'ArrowUp') {\n // When no index is set or at the first index, focus to the last, otherwise decrement focus index\n if (focusedItemIndex === null || focusedItemIndex === 0) {\n indexToFocus = selectOptions.length - 1;\n } else {\n indexToFocus = focusedItemIndex - 1;\n }\n\n // Skip disabled options\n while (selectOptions[indexToFocus].isDisabled) {\n indexToFocus--;\n if (indexToFocus === -1) {\n indexToFocus = selectOptions.length - 1;\n }\n }\n }\n\n if (key === 'ArrowDown') {\n // When no index is set or at the last index, focus to the first, otherwise increment focus index\n if (focusedItemIndex === null || focusedItemIndex === selectOptions.length - 1) {\n indexToFocus = 0;\n } else {\n indexToFocus = focusedItemIndex + 1;\n }\n\n // Skip disabled options\n while (selectOptions[indexToFocus].isDisabled) {\n indexToFocus++;\n if (indexToFocus === selectOptions.length) {\n indexToFocus = 0;\n }\n }\n }\n\n setActiveAndFocusedItem(indexToFocus);\n };\n\n const onInputKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {\n const focusedItem = focusedItemIndex !== null ? selectOptions[focusedItemIndex] : null;\n\n switch (event.key) {\n case 'Enter':\n if (isOpen && focusedItem && focusedItem.value !== NO_RESULTS && !focusedItem.isAriaDisabled) {\n selectOption(focusedItem.value, focusedItem.children as string);\n }\n\n if (!isOpen) {\n setIsOpen(true);\n }\n\n break;\n case 'ArrowUp':\n case 'ArrowDown':\n event.preventDefault();\n handleMenuArrowKeys(event.key);\n break;\n }\n };\n\n const onToggleClick = () => {\n setIsOpen(!isOpen);\n textInputRef?.current?.focus();\n };\n\n const onClearButtonClick = () => {\n setSelected('');\n setInputValue('');\n setFilterValue('');\n resetActiveAndFocusedItem();\n textInputRef?.current?.focus();\n };\n\n const toggle = (toggleRef: React.Ref<MenuToggleElement>) => (\n <MenuToggle\n ref={toggleRef}\n variant=\"typeahead\"\n aria-label=\"Typeahead menu toggle\"\n onClick={onToggleClick}\n isExpanded={isOpen}\n isFullWidth\n >\n <TextInputGroup isPlain>\n <TextInputGroupMain\n value={inputValue}\n onClick={onInputClick}\n onChange={onTextInputChange}\n onKeyDown={onInputKeyDown}\n id=\"typeahead-select-input\"\n autoComplete=\"off\"\n innerRef={textInputRef}\n placeholder=\"Select a state\"\n {...(activeItemId && { 'aria-activedescendant': activeItemId })}\n role=\"combobox\"\n isExpanded={isOpen}\n aria-controls=\"select-typeahead-listbox\"\n />\n\n <TextInputGroupUtilities {...(!inputValue ? { style: { display: 'none' } } : {})}>\n <Button\n variant=\"plain\"\n onClick={onClearButtonClick}\n aria-label=\"Clear input value\"\n icon={<RhMicronsCloseIcon />}\n />\n </TextInputGroupUtilities>\n </TextInputGroup>\n </MenuToggle>\n );\n\n return (\n <Select\n id=\"typeahead-select\"\n isOpen={isOpen}\n selected={selected}\n onSelect={onSelect}\n onOpenChange={(isOpen) => {\n !isOpen && closeMenu();\n }}\n toggle={toggle}\n variant=\"typeahead\"\n >\n <SelectList id=\"select-typeahead-listbox\">\n {selectOptions.map((option, index) => (\n <SelectOption\n key={option.value || option.children}\n isFocused={focusedItemIndex === index}\n className={option.className}\n id={createItemId(option.value)}\n {...option}\n ref={null}\n />\n ))}\n </SelectList>\n </Select>\n );\n};\n","title":"Typeahead","lang":"ts","className":""}}>
845
+
846
+ <p {...{"className":"pf-v6-c-content--p pf-m-editorial ws-p "}}>
847
+ {`Typeahead is a select variant that replaces the typical button toggle for opening the select menu with a text input and button toggle combo. As a user enters characters into the text input, the menu options will be filtered to match.`}
848
+ </p>
849
+
850
+ <p {...{"className":"pf-v6-c-content--p pf-m-editorial ws-p "}}>
851
+ {`To make a typeahead, pass `}
852
+
853
+ <code {...{"className":"ws-code "}}>
854
+ {`variant=typeahead`}
855
+ </code>
856
+ {` into the `}
857
+
858
+ <code {...{"className":"ws-code "}}>
859
+ {`<MenuToggle>`}
860
+ </code>
861
+ {` component and link an `}
862
+
863
+ <code {...{"className":"ws-code "}}>
864
+ {`onClick`}
865
+ </code>
866
+ {` function to the `}
867
+
868
+ <code {...{"className":"ws-code "}}>
869
+ {`<TextInputGroupMain>`}
870
+ </code>
871
+ {` component.`}
872
+ </p>
873
+ </Example>,
874
+ 'Typeahead with create option': props =>
875
+ <Example {...pageData} {...props} {...{"code":"import { useEffect, useRef, useState } from 'react';\nimport {\n Select,\n SelectOption,\n SelectList,\n SelectOptionProps,\n MenuToggle,\n MenuToggleElement,\n TextInputGroup,\n TextInputGroupMain,\n TextInputGroupUtilities,\n Button\n} from '@patternfly/react-core';\nimport RhMicronsCloseIcon from '@patternfly/react-icons/dist/esm/icons/rh-microns-close-icon';\n\nlet initialSelectOptions: SelectOptionProps[] = [\n { value: 'Alabama', children: 'Alabama' },\n { value: 'Florida', children: 'Florida' },\n { value: 'New Jersey', children: 'New Jersey' },\n { value: 'New Mexico', children: 'New Mexico' },\n { value: 'New York', children: 'New York' },\n { value: 'North Carolina', children: 'North Carolina' }\n];\n\nexport const SelectTypeaheadCreatable: React.FunctionComponent = () => {\n const [isOpen, setIsOpen] = useState(false);\n const [selected, setSelected] = useState<string>('');\n const [inputValue, setInputValue] = useState<string>('');\n const [filterValue, setFilterValue] = useState<string>('');\n const [selectOptions, setSelectOptions] = useState<SelectOptionProps[]>(initialSelectOptions);\n const [focusedItemIndex, setFocusedItemIndex] = useState<number | null>(null);\n const [activeItemId, setActiveItemId] = useState<string | null>(null);\n const textInputRef = useRef<HTMLInputElement>(undefined);\n\n const CREATE_NEW = 'create';\n\n useEffect(() => {\n let newSelectOptions: SelectOptionProps[] = initialSelectOptions;\n\n // Filter menu items based on the text input value when one exists\n if (filterValue) {\n newSelectOptions = initialSelectOptions.filter((menuItem) =>\n String(menuItem.children).toLowerCase().includes(filterValue.toLowerCase())\n );\n\n // If no option matches the filter exactly, display creation option\n if (!initialSelectOptions.some((option) => option.value === filterValue)) {\n newSelectOptions = [...newSelectOptions, { children: `Create new option \"${filterValue}\"`, value: CREATE_NEW }];\n }\n\n // Open the menu when the input value changes and the new value is not empty\n if (!isOpen) {\n setIsOpen(true);\n }\n }\n\n setSelectOptions(newSelectOptions);\n }, [filterValue]);\n\n const createItemId = (value: any) => `select-typeahead-${value.replace(' ', '-')}`;\n\n const setActiveAndFocusedItem = (itemIndex: number) => {\n setFocusedItemIndex(itemIndex);\n const focusedItem = selectOptions[itemIndex];\n setActiveItemId(createItemId(focusedItem.value));\n };\n\n const resetActiveAndFocusedItem = () => {\n setFocusedItemIndex(null);\n setActiveItemId(null);\n };\n\n const closeMenu = () => {\n setIsOpen(false);\n resetActiveAndFocusedItem();\n };\n\n const onInputClick = () => {\n if (!isOpen) {\n setIsOpen(true);\n } else if (!inputValue) {\n closeMenu();\n }\n };\n\n const selectOption = (value: string | number, content: string | number) => {\n // eslint-disable-next-line no-console\n console.log('selected', content);\n\n setInputValue(String(content));\n setFilterValue('');\n setSelected(String(value));\n\n closeMenu();\n };\n\n const onSelect = (_event: React.MouseEvent<Element, MouseEvent> | undefined, value: string | number | undefined) => {\n if (value) {\n if (value === CREATE_NEW) {\n if (!initialSelectOptions.some((item) => item.children === filterValue)) {\n initialSelectOptions = [...initialSelectOptions, { value: filterValue, children: filterValue }];\n }\n setSelected(filterValue);\n setFilterValue('');\n closeMenu();\n } else {\n const optionText = selectOptions.find((option) => option.value === value)?.children;\n selectOption(value, optionText as string);\n }\n }\n };\n\n const onTextInputChange = (_event: React.FormEvent<HTMLInputElement>, value: string) => {\n setInputValue(value);\n setFilterValue(value);\n\n resetActiveAndFocusedItem();\n\n if (value !== selected) {\n setSelected('');\n }\n };\n\n const handleMenuArrowKeys = (key: string) => {\n let indexToFocus = 0;\n\n if (!isOpen) {\n setIsOpen(true);\n }\n\n if (selectOptions.every((option) => option.isDisabled)) {\n return;\n }\n\n if (key === 'ArrowUp') {\n // When no index is set or at the first index, focus to the last, otherwise decrement focus index\n if (focusedItemIndex === null || focusedItemIndex === 0) {\n indexToFocus = selectOptions.length - 1;\n } else {\n indexToFocus = focusedItemIndex - 1;\n }\n\n // Skip disabled options\n while (selectOptions[indexToFocus].isDisabled) {\n indexToFocus--;\n if (indexToFocus === -1) {\n indexToFocus = selectOptions.length - 1;\n }\n }\n }\n\n if (key === 'ArrowDown') {\n // When no index is set or at the last index, focus to the first, otherwise increment focus index\n if (focusedItemIndex === null || focusedItemIndex === selectOptions.length - 1) {\n indexToFocus = 0;\n } else {\n indexToFocus = focusedItemIndex + 1;\n }\n\n // Skip disabled options\n while (selectOptions[indexToFocus].isDisabled) {\n indexToFocus++;\n if (indexToFocus === selectOptions.length) {\n indexToFocus = 0;\n }\n }\n }\n\n setActiveAndFocusedItem(indexToFocus);\n };\n\n const onInputKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {\n const focusedItem = focusedItemIndex !== null ? selectOptions[focusedItemIndex] : null;\n\n switch (event.key) {\n case 'Enter':\n if (isOpen && focusedItem && !focusedItem.isAriaDisabled) {\n onSelect(undefined, focusedItem.value as string);\n }\n\n if (!isOpen) {\n setIsOpen(true);\n }\n\n break;\n case 'ArrowUp':\n case 'ArrowDown':\n event.preventDefault();\n handleMenuArrowKeys(event.key);\n break;\n }\n };\n\n const onToggleClick = () => {\n setIsOpen(!isOpen);\n textInputRef?.current?.focus();\n };\n\n const onClearButtonClick = () => {\n setSelected('');\n setInputValue('');\n setFilterValue('');\n resetActiveAndFocusedItem();\n textInputRef?.current?.focus();\n };\n\n const toggle = (toggleRef: React.Ref<MenuToggleElement>) => (\n <MenuToggle\n ref={toggleRef}\n variant=\"typeahead\"\n aria-label=\"Typeahead creatable menu toggle\"\n onClick={onToggleClick}\n isExpanded={isOpen}\n isFullWidth\n >\n <TextInputGroup isPlain>\n <TextInputGroupMain\n value={inputValue}\n onClick={onInputClick}\n onChange={onTextInputChange}\n onKeyDown={onInputKeyDown}\n id=\"create-typeahead-select-input\"\n autoComplete=\"off\"\n innerRef={textInputRef}\n placeholder=\"Select a state\"\n {...(activeItemId && { 'aria-activedescendant': activeItemId })}\n role=\"combobox\"\n isExpanded={isOpen}\n aria-controls=\"select-create-typeahead-listbox\"\n />\n\n <TextInputGroupUtilities {...(!inputValue ? { style: { display: 'none' } } : {})}>\n <Button\n variant=\"plain\"\n onClick={onClearButtonClick}\n aria-label=\"Clear input value\"\n icon={<RhMicronsCloseIcon />}\n />\n </TextInputGroupUtilities>\n </TextInputGroup>\n </MenuToggle>\n );\n\n return (\n <Select\n id=\"create-typeahead-select\"\n isOpen={isOpen}\n selected={selected}\n onSelect={onSelect}\n onOpenChange={(isOpen) => {\n !isOpen && closeMenu();\n }}\n toggle={toggle}\n variant=\"typeahead\"\n >\n <SelectList id=\"select-create-typeahead-listbox\">\n {selectOptions.map((option, index) => (\n <SelectOption\n key={option.value || option.children}\n isFocused={focusedItemIndex === index}\n className={option.className}\n id={createItemId(option.value)}\n {...option}\n ref={null}\n />\n ))}\n </SelectList>\n </Select>\n );\n};\n","title":"Typeahead with create option","lang":"ts","className":""}}>
876
+
877
+ <p {...{"className":"pf-v6-c-content--p pf-m-editorial ws-p "}}>
878
+ {`If a user enters a value into a typeahead select menu that does not exist, you can allow them to create an option of that value.`}
879
+ </p>
880
+
881
+ <p {...{"className":"pf-v6-c-content--p pf-m-editorial ws-p "}}>
882
+ {`To enable the creation ability, pass a predetermined `}
883
+
884
+ <code {...{"className":"ws-code "}}>
885
+ {`value`}
886
+ </code>
887
+ {` into a `}
888
+
889
+ <code {...{"className":"ws-code "}}>
890
+ {`<SelectOption>`}
891
+ </code>
892
+ {` component. You can use the `}
893
+
894
+ <code {...{"className":"ws-code "}}>
895
+ {`placeholder`}
896
+ </code>
897
+ {` property to change the default text shown in the text input.`}
898
+ </p>
899
+
900
+ <p {...{"className":"pf-v6-c-content--p pf-m-editorial ws-p "}}>
901
+ {`The following example outlines the code implementation required to create a working typeahead menu that allows for creation.`}
902
+ </p>
903
+ </Example>,
904
+ 'Multiple typeahead with labels': props =>
905
+ <Example {...pageData} {...props} {...{"code":"import { useEffect, useRef, useState } from 'react';\nimport {\n Select,\n SelectOption,\n SelectList,\n SelectOptionProps,\n MenuToggle,\n MenuToggleElement,\n TextInputGroup,\n TextInputGroupMain,\n TextInputGroupUtilities,\n Label,\n LabelGroup,\n Button\n} from '@patternfly/react-core';\nimport RhMicronsCloseIcon from '@patternfly/react-icons/dist/esm/icons/rh-microns-close-icon';\n\nconst initialSelectOptions: SelectOptionProps[] = [\n { value: 'Alabama', children: 'Alabama' },\n { value: 'Florida', children: 'Florida' },\n { value: 'New Jersey', children: 'New Jersey' },\n { value: 'New Mexico', children: 'New Mexico' },\n { value: 'New York', children: 'New York' },\n { value: 'North Carolina', children: 'North Carolina' }\n];\n\nexport const SelectMultiTypeahead: React.FunctionComponent = () => {\n const [isOpen, setIsOpen] = useState(false);\n const [inputValue, setInputValue] = useState<string>('');\n const [selected, setSelected] = useState<string[]>([]);\n const [selectOptions, setSelectOptions] = useState<SelectOptionProps[]>(initialSelectOptions);\n const [focusedItemIndex, setFocusedItemIndex] = useState<number | null>(null);\n const [activeItemId, setActiveItemId] = useState<string | null>(null);\n const textInputRef = useRef<HTMLInputElement>(undefined);\n\n const NO_RESULTS = 'no results';\n\n useEffect(() => {\n let newSelectOptions: SelectOptionProps[] = initialSelectOptions;\n\n // Filter menu items based on the text input value when one exists\n if (inputValue) {\n newSelectOptions = initialSelectOptions.filter((menuItem) =>\n String(menuItem.children).toLowerCase().includes(inputValue.toLowerCase())\n );\n\n // When no options are found after filtering, display 'No results found'\n if (!newSelectOptions.length) {\n newSelectOptions = [\n { isAriaDisabled: true, children: `No results found for \"${inputValue}\"`, value: NO_RESULTS }\n ];\n }\n\n // Open the menu when the input value changes and the new value is not empty\n if (!isOpen) {\n setIsOpen(true);\n }\n }\n\n setSelectOptions(newSelectOptions);\n }, [inputValue]);\n\n const createItemId = (value: any) => `select-multi-typeahead-${value.replace(' ', '-')}`;\n\n const setActiveAndFocusedItem = (itemIndex: number) => {\n setFocusedItemIndex(itemIndex);\n const focusedItem = selectOptions[itemIndex];\n setActiveItemId(createItemId(focusedItem.value));\n };\n\n const resetActiveAndFocusedItem = () => {\n setFocusedItemIndex(null);\n setActiveItemId(null);\n };\n\n const closeMenu = () => {\n setIsOpen(false);\n resetActiveAndFocusedItem();\n };\n\n const onInputClick = () => {\n if (!isOpen) {\n setIsOpen(true);\n } else if (!inputValue) {\n closeMenu();\n }\n };\n\n const onSelect = (value: string) => {\n if (value && value !== NO_RESULTS) {\n // eslint-disable-next-line no-console\n console.log('selected', value);\n\n setSelected(\n selected.includes(value) ? selected.filter((selection) => selection !== value) : [...selected, value]\n );\n }\n\n textInputRef.current?.focus();\n };\n\n const onTextInputChange = (_event: React.FormEvent<HTMLInputElement>, value: string) => {\n setInputValue(value);\n resetActiveAndFocusedItem();\n };\n\n const handleMenuArrowKeys = (key: string) => {\n let indexToFocus = 0;\n\n if (!isOpen) {\n setIsOpen(true);\n }\n\n if (selectOptions.every((option) => option.isDisabled)) {\n return;\n }\n\n if (key === 'ArrowUp') {\n // When no index is set or at the first index, focus to the last, otherwise decrement focus index\n if (focusedItemIndex === null || focusedItemIndex === 0) {\n indexToFocus = selectOptions.length - 1;\n } else {\n indexToFocus = focusedItemIndex - 1;\n }\n\n // Skip disabled options\n while (selectOptions[indexToFocus].isDisabled) {\n indexToFocus--;\n if (indexToFocus === -1) {\n indexToFocus = selectOptions.length - 1;\n }\n }\n }\n\n if (key === 'ArrowDown') {\n // When no index is set or at the last index, focus to the first, otherwise increment focus index\n if (focusedItemIndex === null || focusedItemIndex === selectOptions.length - 1) {\n indexToFocus = 0;\n } else {\n indexToFocus = focusedItemIndex + 1;\n }\n\n // Skip disabled options\n while (selectOptions[indexToFocus].isDisabled) {\n indexToFocus++;\n if (indexToFocus === selectOptions.length) {\n indexToFocus = 0;\n }\n }\n }\n\n setActiveAndFocusedItem(indexToFocus);\n };\n\n const onInputKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {\n const focusedItem = focusedItemIndex !== null ? selectOptions[focusedItemIndex] : null;\n\n switch (event.key) {\n case 'Enter':\n if (isOpen && focusedItem && focusedItem.value !== NO_RESULTS && !focusedItem.isAriaDisabled) {\n onSelect(focusedItem.value);\n }\n\n if (!isOpen) {\n setIsOpen(true);\n }\n\n break;\n case 'ArrowUp':\n case 'ArrowDown':\n event.preventDefault();\n handleMenuArrowKeys(event.key);\n break;\n }\n };\n\n const onToggleClick = () => {\n setIsOpen(!isOpen);\n textInputRef?.current?.focus();\n };\n\n const onClearButtonClick = () => {\n setSelected([]);\n setInputValue('');\n resetActiveAndFocusedItem();\n textInputRef?.current?.focus();\n };\n\n const toggle = (toggleRef: React.Ref<MenuToggleElement>) => (\n <MenuToggle\n variant=\"typeahead\"\n aria-label=\"Multi typeahead menu toggle\"\n onClick={onToggleClick}\n innerRef={toggleRef}\n isExpanded={isOpen}\n isFullWidth\n >\n <TextInputGroup isPlain>\n <TextInputGroupMain\n value={inputValue}\n onClick={onInputClick}\n onChange={onTextInputChange}\n onKeyDown={onInputKeyDown}\n id=\"multi-typeahead-select-input\"\n autoComplete=\"off\"\n innerRef={textInputRef}\n placeholder=\"Select a state\"\n {...(activeItemId && { 'aria-activedescendant': activeItemId })}\n role=\"combobox\"\n isExpanded={isOpen}\n aria-controls=\"select-multi-typeahead-listbox\"\n >\n <LabelGroup aria-label=\"Current selections\">\n {selected.map((selection, index) => (\n <Label\n key={index}\n variant=\"outline\"\n onClose={(ev) => {\n ev.stopPropagation();\n onSelect(selection);\n }}\n >\n {selection}\n </Label>\n ))}\n </LabelGroup>\n </TextInputGroupMain>\n <TextInputGroupUtilities {...(selected.length === 0 ? { style: { display: 'none' } } : {})}>\n <Button\n variant=\"plain\"\n onClick={onClearButtonClick}\n aria-label=\"Clear input value\"\n icon={<RhMicronsCloseIcon />}\n />\n </TextInputGroupUtilities>\n </TextInputGroup>\n </MenuToggle>\n );\n\n return (\n <Select\n id=\"multi-typeahead-select\"\n isOpen={isOpen}\n selected={selected}\n onSelect={(_event, selection) => onSelect(selection as string)}\n onOpenChange={(isOpen) => {\n !isOpen && closeMenu();\n }}\n toggle={toggle}\n variant=\"typeahead\"\n >\n <SelectList isAriaMultiselectable id=\"select-multi-typeahead-listbox\">\n {selectOptions.map((option, index) => (\n <SelectOption\n key={option.value || option.children}\n isFocused={focusedItemIndex === index}\n className={option.className}\n id={createItemId(option.value)}\n {...option}\n ref={null}\n />\n ))}\n </SelectList>\n </Select>\n );\n};\n","title":"Multiple typeahead with labels","lang":"ts","className":""}}>
906
+
907
+ <p {...{"className":"pf-v6-c-content--p pf-m-editorial ws-p "}}>
908
+ {`A multiple typeahead can be used to allow users to select multiple options from a list. Additionally, you can render a label group to be placed in the select toggle.`}
909
+ </p>
910
+
911
+ <p {...{"className":"pf-v6-c-content--p pf-m-editorial ws-p "}}>
912
+ {`When more items than the allowed limit are selected, overflowing items will be hidden under a "more" button. The following example hides items after more than 3 are selected. To show hidden items, select the “more” button. Select "show less" to hide extra items again.`}
913
+ </p>
914
+ </Example>,
915
+ 'Multiple typeahead with create option': props =>
916
+ <Example {...pageData} {...props} {...{"code":"import { useEffect, useRef, useState } from 'react';\nimport {\n Select,\n SelectOption,\n SelectList,\n SelectOptionProps,\n MenuToggle,\n MenuToggleElement,\n TextInputGroup,\n TextInputGroupMain,\n TextInputGroupUtilities,\n Label,\n LabelGroup,\n Button\n} from '@patternfly/react-core';\nimport RhMicronsCloseIcon from '@patternfly/react-icons/dist/esm/icons/rh-microns-close-icon';\n\nlet initialSelectOptions: SelectOptionProps[] = [\n { value: 'Alabama', children: 'Alabama' },\n { value: 'Florida', children: 'Florida' },\n { value: 'New Jersey', children: 'New Jersey' },\n { value: 'New Mexico', children: 'New Mexico' },\n { value: 'New York', children: 'New York' },\n { value: 'North Carolina', children: 'North Carolina' }\n];\n\nexport const SelectMultiTypeaheadCreatable: React.FunctionComponent = () => {\n const [isOpen, setIsOpen] = useState(false);\n const [inputValue, setInputValue] = useState<string>('');\n const [selected, setSelected] = useState<string[]>([]);\n const [selectOptions, setSelectOptions] = useState<SelectOptionProps[]>(initialSelectOptions);\n const [focusedItemIndex, setFocusedItemIndex] = useState<number | null>(null);\n const [activeItemId, setActiveItemId] = useState<string | null>(null);\n const [onCreation, setOnCreation] = useState<boolean>(false); // Boolean to refresh filter state after new option is created\n const textInputRef = useRef<HTMLInputElement>(undefined);\n\n const CREATE_NEW = 'create';\n\n useEffect(() => {\n let newSelectOptions: SelectOptionProps[] = initialSelectOptions;\n\n // Filter menu items based on the text input value when one exists\n if (inputValue) {\n newSelectOptions = initialSelectOptions.filter((menuItem) =>\n String(menuItem.children).toLowerCase().includes(inputValue.toLowerCase())\n );\n\n // If no option matches the filter exactly, display creation option\n if (!initialSelectOptions.some((option) => option.value === inputValue)) {\n newSelectOptions = [...newSelectOptions, { children: `Create new option \"${inputValue}\"`, value: CREATE_NEW }];\n }\n\n // Open the menu when the input value changes and the new value is not empty\n if (!isOpen) {\n setIsOpen(true);\n }\n }\n\n setSelectOptions(newSelectOptions);\n }, [inputValue, onCreation]);\n\n const createItemId = (value: any) => `select-multi-create-typeahead-${value.replace(' ', '-')}`;\n\n const setActiveAndFocusedItem = (itemIndex: number) => {\n setFocusedItemIndex(itemIndex);\n const focusedItem = selectOptions[itemIndex];\n setActiveItemId(createItemId(focusedItem.value));\n };\n\n const resetActiveAndFocusedItem = () => {\n setFocusedItemIndex(null);\n setActiveItemId(null);\n };\n\n const closeMenu = () => {\n setIsOpen(false);\n resetActiveAndFocusedItem();\n };\n\n const onInputClick = () => {\n if (!isOpen) {\n setIsOpen(true);\n } else if (!inputValue) {\n closeMenu();\n }\n };\n\n const onSelect = (value: string) => {\n if (value) {\n if (value === CREATE_NEW) {\n if (!initialSelectOptions.some((item) => item.value === inputValue)) {\n initialSelectOptions = [...initialSelectOptions, { value: inputValue, children: inputValue }];\n }\n setSelected(\n selected.includes(inputValue)\n ? selected.filter((selection) => selection !== inputValue)\n : [...selected, inputValue]\n );\n setOnCreation(!onCreation);\n resetActiveAndFocusedItem();\n } else {\n // eslint-disable-next-line no-console\n console.log('selected', value);\n setSelected(\n selected.includes(value) ? selected.filter((selection) => selection !== value) : [...selected, value]\n );\n }\n }\n\n textInputRef.current?.focus();\n };\n\n const onTextInputChange = (_event: React.FormEvent<HTMLInputElement>, value: string) => {\n setInputValue(value);\n resetActiveAndFocusedItem();\n };\n\n const handleMenuArrowKeys = (key: string) => {\n let indexToFocus = 0;\n\n if (!isOpen) {\n setIsOpen(true);\n }\n\n if (selectOptions.every((option) => option.isDisabled)) {\n return;\n }\n\n if (key === 'ArrowUp') {\n // When no index is set or at the first index, focus to the last, otherwise decrement focus index\n if (focusedItemIndex === null || focusedItemIndex === 0) {\n indexToFocus = selectOptions.length - 1;\n } else {\n indexToFocus = focusedItemIndex - 1;\n }\n\n // Skip disabled options\n while (selectOptions[indexToFocus].isDisabled) {\n indexToFocus--;\n if (indexToFocus === -1) {\n indexToFocus = selectOptions.length - 1;\n }\n }\n }\n\n if (key === 'ArrowDown') {\n // When no index is set or at the last index, focus to the first, otherwise increment focus index\n if (focusedItemIndex === null || focusedItemIndex === selectOptions.length - 1) {\n indexToFocus = 0;\n } else {\n indexToFocus = focusedItemIndex + 1;\n }\n\n // Skip disabled options\n while (selectOptions[indexToFocus].isDisabled) {\n indexToFocus++;\n if (indexToFocus === selectOptions.length) {\n indexToFocus = 0;\n }\n }\n }\n\n setActiveAndFocusedItem(indexToFocus);\n };\n\n const onInputKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {\n const focusedItem = focusedItemIndex !== null ? selectOptions[focusedItemIndex] : null;\n\n switch (event.key) {\n case 'Enter':\n if (isOpen && focusedItem && !focusedItem.isAriaDisabled) {\n onSelect(focusedItem.value as string);\n }\n\n if (!isOpen) {\n setIsOpen(true);\n }\n\n break;\n case 'ArrowUp':\n case 'ArrowDown':\n event.preventDefault();\n handleMenuArrowKeys(event.key);\n break;\n }\n };\n\n const onToggleClick = () => {\n setIsOpen(!isOpen);\n textInputRef?.current?.focus();\n };\n\n const onClearButtonClick = () => {\n setSelected([]);\n setInputValue('');\n resetActiveAndFocusedItem();\n textInputRef?.current?.focus();\n };\n\n const getChildren = (value: string) => initialSelectOptions.find((option) => option.value === value)?.children;\n\n const toggle = (toggleRef: React.Ref<MenuToggleElement>) => (\n <MenuToggle\n variant=\"typeahead\"\n aria-label=\"Multi typeahead creatable menu toggle\"\n onClick={onToggleClick}\n innerRef={toggleRef}\n isExpanded={isOpen}\n isFullWidth\n >\n <TextInputGroup isPlain>\n <TextInputGroupMain\n value={inputValue}\n onClick={onInputClick}\n onChange={onTextInputChange}\n onKeyDown={onInputKeyDown}\n id=\"multi-create-typeahead-select-input\"\n autoComplete=\"off\"\n innerRef={textInputRef}\n placeholder=\"Select a state\"\n {...(activeItemId && { 'aria-activedescendant': activeItemId })}\n role=\"combobox\"\n isExpanded={isOpen}\n aria-controls=\"select-multi-create-typeahead-listbox\"\n >\n <LabelGroup aria-label=\"Current selections\">\n {selected.map((selection, index) => (\n <Label\n key={index}\n variant=\"outline\"\n onClose={(ev) => {\n ev.stopPropagation();\n onSelect(selection);\n }}\n >\n {getChildren(selection)}\n </Label>\n ))}\n </LabelGroup>\n </TextInputGroupMain>\n <TextInputGroupUtilities {...(selected.length === 0 ? { style: { display: 'none' } } : {})}>\n <Button\n variant=\"plain\"\n onClick={onClearButtonClick}\n aria-label=\"Clear input value\"\n icon={<RhMicronsCloseIcon />}\n />\n </TextInputGroupUtilities>\n </TextInputGroup>\n </MenuToggle>\n );\n\n return (\n <Select\n id=\"multi-create-typeahead-select\"\n isOpen={isOpen}\n selected={selected}\n onSelect={(_event, selection) => onSelect(selection as string)}\n onOpenChange={(isOpen) => {\n !isOpen && closeMenu();\n }}\n toggle={toggle}\n variant=\"typeahead\"\n >\n <SelectList isAriaMultiselectable id=\"select-multi-create-typeahead-listbox\">\n {selectOptions.map((option, index) => (\n <SelectOption\n key={option.value || option.children}\n isFocused={focusedItemIndex === index}\n className={option.className}\n id={createItemId(option.value)}\n {...option}\n ref={null}\n />\n ))}\n </SelectList>\n </Select>\n );\n};\n","title":"Multiple typeahead with create option","lang":"ts","className":""}}>
917
+
918
+ <p {...{"className":"pf-v6-c-content--p pf-m-editorial ws-p "}}>
919
+ {`If the text that is entered into a typeahead doesn't match a menu item, users can choose to create a new option that matches the text input. You can also combine this create functionality with a label group to display created items as labels.`}
920
+ </p>
921
+ </Example>,
922
+ 'Multiple typeahead with checkboxes': props =>
923
+ <Example {...pageData} {...props} {...{"code":"import { useEffect, useRef, useState } from 'react';\nimport {\n Select,\n SelectOption,\n SelectList,\n SelectOptionProps,\n MenuToggle,\n MenuToggleElement,\n TextInputGroup,\n TextInputGroupMain,\n TextInputGroupUtilities,\n Button\n} from '@patternfly/react-core';\nimport RhMicronsCloseIcon from '@patternfly/react-icons/dist/esm/icons/rh-microns-close-icon';\n\nconst initialSelectOptions: SelectOptionProps[] = [\n { value: 'Alabama', children: 'Alabama' },\n { value: 'Florida', children: 'Florida' },\n { value: 'New Jersey', children: 'New Jersey' },\n { value: 'New Mexico', children: 'New Mexico' },\n { value: 'New York', children: 'New York' },\n { value: 'North Carolina', children: 'North Carolina' }\n];\n\nexport const SelectMultiTypeaheadCheckbox: React.FunctionComponent = () => {\n const [isOpen, setIsOpen] = useState(false);\n const [inputValue, setInputValue] = useState<string>('');\n const [selected, setSelected] = useState<string[]>([]);\n const [selectOptions, setSelectOptions] = useState<SelectOptionProps[]>(initialSelectOptions);\n const [focusedItemIndex, setFocusedItemIndex] = useState<number | null>(null);\n const [activeItemId, setActiveItemId] = useState<string | null>(null);\n const [placeholder, setPlaceholder] = useState('0 items selected');\n const textInputRef = useRef<HTMLInputElement>(undefined);\n\n const NO_RESULTS = 'no results';\n\n useEffect(() => {\n let newSelectOptions: SelectOptionProps[] = initialSelectOptions;\n\n // Filter menu items based on the text input value when one exists\n if (inputValue) {\n newSelectOptions = initialSelectOptions.filter((menuItem) =>\n String(menuItem.children).toLowerCase().includes(inputValue.toLowerCase())\n );\n\n // When no options are found after filtering, display 'No results found'\n if (!newSelectOptions.length) {\n newSelectOptions = [\n {\n isAriaDisabled: true,\n children: `No results found for \"${inputValue}\"`,\n value: NO_RESULTS,\n hasCheckbox: false\n }\n ];\n }\n\n // Open the menu when the input value changes and the new value is not empty\n if (!isOpen) {\n setIsOpen(true);\n }\n }\n\n setSelectOptions(newSelectOptions);\n }, [inputValue]);\n\n useEffect(() => {\n setPlaceholder(`${selected.length} item${selected.length !== 1 ? 's' : ''} selected`);\n }, [selected]);\n\n const createItemId = (value: any) => `select-multi-typeahead-${value.replace(' ', '-')}`;\n\n const setActiveAndFocusedItem = (itemIndex: number) => {\n setFocusedItemIndex(itemIndex);\n const focusedItem = selectOptions[itemIndex];\n setActiveItemId(createItemId(focusedItem.value));\n };\n\n const resetActiveAndFocusedItem = () => {\n setFocusedItemIndex(null);\n setActiveItemId(null);\n };\n\n const closeMenu = () => {\n setIsOpen(false);\n resetActiveAndFocusedItem();\n };\n\n const onInputClick = () => {\n if (!isOpen) {\n setIsOpen(true);\n } else if (!inputValue) {\n closeMenu();\n }\n };\n\n const handleMenuArrowKeys = (key: string) => {\n let indexToFocus = 0;\n\n if (!isOpen) {\n setIsOpen(true);\n }\n\n if (selectOptions.every((option) => option.isDisabled)) {\n return;\n }\n\n if (key === 'ArrowUp') {\n // When no index is set or at the first index, focus to the last, otherwise decrement focus index\n if (focusedItemIndex === null || focusedItemIndex === 0) {\n indexToFocus = selectOptions.length - 1;\n } else {\n indexToFocus = focusedItemIndex - 1;\n }\n\n // Skip disabled options\n while (selectOptions[indexToFocus].isDisabled) {\n indexToFocus--;\n if (indexToFocus === -1) {\n indexToFocus = selectOptions.length - 1;\n }\n }\n }\n\n if (key === 'ArrowDown') {\n // When no index is set or at the last index, focus to the first, otherwise increment focus index\n if (focusedItemIndex === null || focusedItemIndex === selectOptions.length - 1) {\n indexToFocus = 0;\n } else {\n indexToFocus = focusedItemIndex + 1;\n }\n\n // Skip disabled options\n while (selectOptions[indexToFocus].isDisabled) {\n indexToFocus++;\n if (indexToFocus === selectOptions.length) {\n indexToFocus = 0;\n }\n }\n }\n\n setActiveAndFocusedItem(indexToFocus);\n };\n\n const onInputKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {\n const focusedItem = focusedItemIndex !== null ? selectOptions[focusedItemIndex] : null;\n\n switch (event.key) {\n case 'Enter':\n if (isOpen && focusedItem && focusedItem.value !== NO_RESULTS && !focusedItem.isAriaDisabled) {\n onSelect(focusedItem.value);\n }\n\n if (!isOpen) {\n setIsOpen(true);\n }\n\n break;\n case 'ArrowUp':\n case 'ArrowDown':\n event.preventDefault();\n handleMenuArrowKeys(event.key);\n break;\n }\n };\n\n const onToggleClick = () => {\n setIsOpen(!isOpen);\n textInputRef?.current?.focus();\n };\n\n const onTextInputChange = (_event: React.FormEvent<HTMLInputElement>, value: string) => {\n setInputValue(value);\n resetActiveAndFocusedItem();\n };\n\n const onSelect = (value: string) => {\n if (value && value !== NO_RESULTS) {\n // eslint-disable-next-line no-console\n console.log('selected', value);\n\n setSelected(\n selected.includes(value) ? selected.filter((selection) => selection !== value) : [...selected, value]\n );\n }\n\n textInputRef.current?.focus();\n };\n\n const onClearButtonClick = () => {\n setSelected([]);\n setInputValue('');\n resetActiveAndFocusedItem();\n textInputRef?.current?.focus();\n };\n\n const toggle = (toggleRef: React.Ref<MenuToggleElement>) => (\n <MenuToggle\n variant=\"typeahead\"\n aria-label=\"Multi typeahead checkbox menu toggle\"\n onClick={onToggleClick}\n innerRef={toggleRef}\n isExpanded={isOpen}\n isFullWidth\n >\n <TextInputGroup isPlain>\n <TextInputGroupMain\n value={inputValue}\n onClick={onInputClick}\n onChange={onTextInputChange}\n onKeyDown={onInputKeyDown}\n id=\"multi-typeahead-select-checkbox-input\"\n autoComplete=\"off\"\n innerRef={textInputRef}\n placeholder={placeholder}\n {...(activeItemId && { 'aria-activedescendant': activeItemId })}\n role=\"combobox\"\n isExpanded={isOpen}\n aria-controls=\"select-multi-typeahead-checkbox-listbox\"\n />\n <TextInputGroupUtilities {...(selected.length === 0 ? { style: { display: 'none' } } : {})}>\n <Button\n variant=\"plain\"\n onClick={onClearButtonClick}\n aria-label=\"Clear input value\"\n icon={<RhMicronsCloseIcon />}\n />\n </TextInputGroupUtilities>\n </TextInputGroup>\n </MenuToggle>\n );\n\n return (\n <Select\n role=\"menu\"\n id=\"multi-typeahead-checkbox-select\"\n isOpen={isOpen}\n selected={selected}\n onSelect={(_event, selection) => onSelect(selection as string)}\n onOpenChange={(isOpen) => {\n !isOpen && closeMenu();\n }}\n toggle={toggle}\n variant=\"typeahead\"\n >\n <SelectList isAriaMultiselectable id=\"select-multi-typeahead-checkbox-listbox\">\n {selectOptions.map((option, index) => (\n <SelectOption\n {...(!option.isDisabled && !option.isAriaDisabled && { hasCheckbox: true })}\n isSelected={selected.includes(option.value)}\n key={option.value || option.children}\n isFocused={focusedItemIndex === index}\n className={option.className}\n id={createItemId(option.value)}\n {...option}\n ref={null}\n />\n ))}\n </SelectList>\n </Select>\n );\n};\n","title":"Multiple typeahead with checkboxes","lang":"ts","className":""}}>
924
+
925
+ <p {...{"className":"pf-v6-c-content--p pf-m-editorial ws-p "}}>
926
+ {`By default, a multiple typeahead select allows you to select multiple menu items, placing a checkmark beside selected items. Like basic checkbox select menus, you can add checkboxes to your menu items. This approach may be more accurate and comprehensive for more complex menu scenarios like filtering.`}
927
+ </p>
928
+ </Example>,
929
+ 'With view more': props =>
930
+ <Example {...pageData} {...props} {...{"code":"import { useEffect, useRef, useState } from 'react';\nimport { Select, SelectOption, SelectList, MenuToggle, Spinner } from '@patternfly/react-core';\n\nexport const SelectViewMore: React.FunctionComponent = () => {\n const [isOpen, setIsOpen] = useState(false);\n const [selected, setSelected] = useState<string>('Select a value');\n const [activeItem, setActiveItem] = useState<number | string>(0);\n const [isLoading, setIsLoading] = useState(false);\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const [selectOptions, setSelectOptions] = useState([\n <SelectOption key={0} value=\"Option 1\">\n Option 1\n </SelectOption>,\n <SelectOption key={1} value=\"Option 2\">\n Option 2\n </SelectOption>,\n <SelectOption key={2} value=\"Option 3\">\n Option 3\n </SelectOption>,\n <SelectOption key={3} value=\"Option 4\">\n Option 4\n </SelectOption>,\n <SelectOption key={4} value=\"Option 5\">\n Option 5\n </SelectOption>,\n <SelectOption key={5} value=\"Option 6\">\n Option 6\n </SelectOption>,\n <SelectOption key={6} value=\"Option 7\">\n Option 7\n </SelectOption>,\n <SelectOption key={7} value=\"Option 8\">\n Option 8\n </SelectOption>,\n <SelectOption key={8} value=\"Option 9\">\n Option 9\n </SelectOption>,\n <SelectOption key={9} value=\"Final Option 10\">\n Final Option 10\n </SelectOption>\n ]);\n const [numOptions, setNumOptions] = useState(3);\n const [visibleOptions, setVisibleOptions] = useState(selectOptions.slice(0, numOptions));\n const activeItemRef = useRef<HTMLElement>(null);\n const viewMoreRef = useRef<HTMLLIElement>(null);\n const toggleRef = useRef<HTMLButtonElement>(null);\n\n useEffect(() => {\n activeItemRef.current?.focus();\n }, [visibleOptions]);\n\n const simulateNetworkCall = (networkCallback: () => void) => {\n setTimeout(networkCallback, 2000);\n };\n\n const getNextValidItem = (startingIndex: number, maxLength: number) => {\n let validItem;\n for (let i = startingIndex; i < maxLength; i++) {\n if (selectOptions[i].props.isDisabled) {\n continue;\n } else {\n validItem = selectOptions[i];\n break;\n }\n }\n return validItem;\n };\n\n const loadMoreOptions = () => {\n const newLength = numOptions + 3 <= selectOptions.length ? numOptions + 3 : selectOptions.length;\n const prevPosition = numOptions;\n const nextValidItem = getNextValidItem(prevPosition, newLength);\n\n setNumOptions(newLength);\n setIsLoading(false);\n setActiveItem(nextValidItem.props.value);\n setVisibleOptions(selectOptions.slice(0, newLength));\n };\n\n const onViewMoreClick = () => {\n setIsLoading(true);\n simulateNetworkCall(() => {\n loadMoreOptions();\n });\n };\n\n const onToggleClick = () => {\n setIsOpen(!isOpen);\n };\n\n const onSelect = (_event: React.MouseEvent<Element, MouseEvent> | undefined, value: string | number | undefined) => {\n // eslint-disable-next-line no-console\n console.log('selected', value);\n\n if (value !== 'loader') {\n setSelected(value as string);\n setIsOpen(false);\n toggleRef?.current?.focus(); // Only focus the toggle when a non-loader option is selected\n }\n };\n\n const toggle = (\n <MenuToggle\n ref={toggleRef}\n onClick={onToggleClick}\n isExpanded={isOpen}\n style={\n {\n width: '200px'\n } as React.CSSProperties\n }\n >\n {selected}\n </MenuToggle>\n );\n\n return (\n <Select\n id=\"single-view-more-select\"\n isOpen={isOpen}\n selected={selected}\n onSelect={onSelect}\n onOpenChange={(isOpen) => setIsOpen(isOpen)}\n toggle={{ toggleNode: toggle, toggleRef }}\n >\n <SelectList>\n {visibleOptions.map((option) => {\n const props = option.props;\n\n return <SelectOption key={option.key} ref={props.value === activeItem ? activeItemRef : null} {...props} />;\n })}\n {numOptions !== selectOptions.length && (\n <SelectOption\n {...(!isLoading && { isLoadButton: true })}\n {...(isLoading && { isLoading: true })}\n onClick={onViewMoreClick}\n value=\"loader\"\n ref={viewMoreRef}\n >\n {isLoading ? <Spinner size=\"lg\" /> : 'View more'}\n </SelectOption>\n )}\n </SelectList>\n </Select>\n );\n};\n","title":"With view more","lang":"ts","className":""}}>
931
+
932
+ <p {...{"className":"pf-v6-c-content--p pf-m-editorial ws-p "}}>
933
+ {`To reduce the processing load for long select lists, you can add a "View more" action to load additional items.`}
934
+ </p>
935
+
936
+ <p {...{"className":"pf-v6-c-content--p pf-m-editorial ws-p "}}>
937
+ {`The following example shows 3 items before the "View more" link, but you can adjust the number of visible items for your use case.`}
938
+ </p>
939
+ </Example>,
940
+ 'With a footer': props =>
941
+ <Example {...pageData} {...props} {...{"code":"import { useState } from 'react';\nimport { MenuToggle, MenuFooter, Select, SelectList, SelectOption, Button } from '@patternfly/react-core';\n\nexport const SelectFooter: React.FunctionComponent = () => {\n const [isOpen, setIsOpen] = useState<boolean>(false);\n const [selected, setSelected] = useState<string>('Select a value');\n\n const onToggleClick = () => {\n setIsOpen(!isOpen);\n };\n\n const toggle = (toggleRef) => (\n <MenuToggle\n ref={toggleRef}\n onClick={onToggleClick}\n isExpanded={isOpen}\n style={\n {\n width: '200px'\n } as React.CSSProperties\n }\n >\n {selected}\n </MenuToggle>\n );\n\n function onSelect(event: React.MouseEvent | undefined, value: string | number | undefined) {\n if (typeof value === 'undefined') {\n return;\n }\n\n setSelected(value.toString());\n }\n\n return (\n <Select\n isOpen={isOpen}\n onOpenChange={(isOpen) => setIsOpen(isOpen)}\n onOpenChangeKeys={['Escape']}\n toggle={toggle}\n id=\"menu-with-footer\"\n onSelect={onSelect}\n selected={selected}\n >\n <SelectList>\n <SelectOption value=\"Option 1\">Option 1</SelectOption>\n <SelectOption value=\"Option 2\">Option 2</SelectOption>\n <SelectOption value=\"Option 3\">Option 3</SelectOption>\n </SelectList>\n <MenuFooter>\n <Button variant=\"link\" isInline>\n Footer action\n </Button>\n </MenuFooter>\n </Select>\n );\n};\n","title":"With a footer","lang":"ts","className":""}}>
942
+
943
+ <p {...{"className":"pf-v6-c-content--p pf-m-editorial ws-p "}}>
944
+ {`You can add a `}
945
+
946
+ <code {...{"className":"ws-code "}}>
947
+ {`<MenuFooter>`}
948
+ </code>
949
+ {` component to a select menu to hold additional actions that users can take on menu items, through elements such as link buttons. A footer will be placed beneath a divider at the end of the select menu.`}
950
+ </p>
951
+ </Example>
952
+ };
953
+
954
+ const Component = () => (
955
+ <React.Fragment>
956
+ <AutoLinkHeader {...{"id":"examples","headingLevel":"h2","className":"ws-title ws-h2"}}>
957
+ {`Examples`}
958
+ </AutoLinkHeader>
959
+ <p {...{"className":"pf-v6-c-content--p pf-m-editorial ws-p "}}>
960
+ {`Select builds off of the menu component suite to adapt commonly used properties and functions to create a select menu. See the `}
961
+ <PatternflyThemeLink {...{"to":"/components/menus/menu","className":""}}>
962
+ {`menu documentation`}
963
+ </PatternflyThemeLink>
964
+ {` for a full list of properties that may be used to further customize a select menu. View the `}
965
+ <PatternflyThemeLink {...{"to":"/components/menus/custom-menus","className":""}}>
966
+ {`custom menu examples`}
967
+ </PatternflyThemeLink>
968
+ {` to see examples of fully functional select menus.`}
969
+ </p>
970
+ <p {...{"className":"pf-v6-c-content--p pf-m-editorial ws-p "}}>
971
+ {`For use cases that do not require a lot of customization, there are various template components available to use in the `}
972
+ <code {...{"className":"ws-code "}}>
973
+ {`@react-templates`}
974
+ </code>
975
+ {` package. These templates have a streamlined API and logic, making them easier to set up and use, but are limited in scope and flexibility. See the `}
976
+ <PatternflyThemeLink {...{"to":"/components/menus/select/react-templates","className":""}}>
977
+ {`templates page`}
978
+ </PatternflyThemeLink>
979
+ {` for details.`}
980
+ </p>
981
+ {React.createElement(pageData.examples["Single select"])}
982
+ {React.createElement(pageData.examples["Select option variants"])}
983
+ {React.createElement(pageData.examples["With grouped items"])}
984
+ {React.createElement(pageData.examples["With validation"])}
985
+ {React.createElement(pageData.examples["Checkbox select"])}
986
+ {React.createElement(pageData.examples["Typeahead"])}
987
+ {React.createElement(pageData.examples["Typeahead with create option"])}
988
+ {React.createElement(pageData.examples["Multiple typeahead with labels"])}
989
+ {React.createElement(pageData.examples["Multiple typeahead with create option"])}
990
+ {React.createElement(pageData.examples["Multiple typeahead with checkboxes"])}
991
+ {React.createElement(pageData.examples["With view more"])}
992
+ {React.createElement(pageData.examples["With a footer"])}
993
+ </React.Fragment>
994
+ );
995
+ Component.displayName = 'ComponentsMenusSelectReactDocs';
996
+ Component.pageData = pageData;
997
+
998
+ export default Component;