@patternfly/react-core 5.0.0-alpha.62 → 5.0.0-alpha.63

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 (227) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/dist/esm/components/CalendarMonth/CalendarMonth.d.ts.map +1 -1
  3. package/dist/esm/components/CalendarMonth/CalendarMonth.js +9 -11
  4. package/dist/esm/components/CalendarMonth/CalendarMonth.js.map +1 -1
  5. package/dist/esm/components/DualListSelector/DualListSelectorControl.d.ts +1 -1
  6. package/dist/esm/components/Menu/MenuItem.d.ts +1 -1
  7. package/dist/esm/components/MenuToggle/MenuToggle.d.ts.map +1 -1
  8. package/dist/esm/components/MenuToggle/MenuToggle.js +3 -1
  9. package/dist/esm/components/MenuToggle/MenuToggle.js.map +1 -1
  10. package/dist/esm/components/Select/Select.d.ts +26 -192
  11. package/dist/esm/components/Select/Select.d.ts.map +1 -1
  12. package/dist/esm/components/Select/Select.js +51 -935
  13. package/dist/esm/components/Select/Select.js.map +1 -1
  14. package/dist/esm/components/Select/SelectGroup.d.ts +7 -8
  15. package/dist/esm/components/Select/SelectGroup.d.ts.map +1 -1
  16. package/dist/esm/components/Select/SelectGroup.js +4 -7
  17. package/dist/esm/components/Select/SelectGroup.js.map +1 -1
  18. package/dist/{js/next → esm}/components/Select/SelectList.d.ts +1 -1
  19. package/dist/esm/components/Select/SelectList.d.ts.map +1 -0
  20. package/dist/esm/{next/components → components}/Select/SelectList.js +1 -1
  21. package/dist/esm/components/Select/SelectList.js.map +1 -0
  22. package/dist/esm/components/Select/SelectOption.d.ts +13 -66
  23. package/dist/esm/components/Select/SelectOption.d.ts.map +1 -1
  24. package/dist/esm/components/Select/SelectOption.js +6 -192
  25. package/dist/esm/components/Select/SelectOption.js.map +1 -1
  26. package/dist/esm/components/Select/index.d.ts +1 -1
  27. package/dist/esm/components/Select/index.d.ts.map +1 -1
  28. package/dist/esm/components/Select/index.js +1 -1
  29. package/dist/esm/components/Select/index.js.map +1 -1
  30. package/dist/esm/deprecated/components/Select/Select.d.ts +199 -0
  31. package/dist/esm/deprecated/components/Select/Select.d.ts.map +1 -0
  32. package/dist/esm/deprecated/components/Select/Select.js +940 -0
  33. package/dist/esm/deprecated/components/Select/Select.js.map +1 -0
  34. package/dist/esm/deprecated/components/Select/SelectGroup.d.ts +13 -0
  35. package/dist/esm/deprecated/components/Select/SelectGroup.d.ts.map +1 -0
  36. package/dist/esm/deprecated/components/Select/SelectGroup.js +13 -0
  37. package/dist/esm/deprecated/components/Select/SelectGroup.js.map +1 -0
  38. package/dist/esm/deprecated/components/Select/SelectMenu.d.ts.map +1 -0
  39. package/dist/esm/{components → deprecated/components}/Select/SelectMenu.js +1 -1
  40. package/dist/esm/deprecated/components/Select/SelectMenu.js.map +1 -0
  41. package/dist/esm/deprecated/components/Select/SelectOption.d.ts +73 -0
  42. package/dist/esm/deprecated/components/Select/SelectOption.d.ts.map +1 -0
  43. package/dist/esm/deprecated/components/Select/SelectOption.js +196 -0
  44. package/dist/esm/deprecated/components/Select/SelectOption.js.map +1 -0
  45. package/dist/esm/deprecated/components/Select/SelectToggle.d.ts.map +1 -0
  46. package/dist/esm/{components → deprecated/components}/Select/SelectToggle.js +2 -2
  47. package/dist/esm/deprecated/components/Select/SelectToggle.js.map +1 -0
  48. package/dist/esm/{next → deprecated}/components/Select/index.d.ts +1 -1
  49. package/dist/esm/deprecated/components/Select/index.d.ts.map +1 -0
  50. package/dist/esm/{next → deprecated}/components/Select/index.js +1 -1
  51. package/dist/esm/deprecated/components/Select/index.js.map +1 -0
  52. package/dist/esm/deprecated/components/Select/selectConstants.d.ts.map +1 -0
  53. package/dist/esm/deprecated/components/Select/selectConstants.js.map +1 -0
  54. package/dist/esm/deprecated/components/index.d.ts +1 -0
  55. package/dist/esm/deprecated/components/index.d.ts.map +1 -1
  56. package/dist/esm/deprecated/components/index.js +1 -0
  57. package/dist/esm/deprecated/components/index.js.map +1 -1
  58. package/dist/esm/next/components/index.d.ts +0 -1
  59. package/dist/esm/next/components/index.d.ts.map +1 -1
  60. package/dist/esm/next/components/index.js +0 -1
  61. package/dist/esm/next/components/index.js.map +1 -1
  62. package/dist/js/components/CalendarMonth/CalendarMonth.d.ts.map +1 -1
  63. package/dist/js/components/CalendarMonth/CalendarMonth.js +8 -10
  64. package/dist/js/components/CalendarMonth/CalendarMonth.js.map +1 -1
  65. package/dist/js/components/DualListSelector/DualListSelectorControl.d.ts +1 -1
  66. package/dist/js/components/Menu/MenuItem.d.ts +1 -1
  67. package/dist/js/components/MenuToggle/MenuToggle.d.ts.map +1 -1
  68. package/dist/js/components/MenuToggle/MenuToggle.js +3 -1
  69. package/dist/js/components/MenuToggle/MenuToggle.js.map +1 -1
  70. package/dist/js/components/Select/Select.d.ts +26 -192
  71. package/dist/js/components/Select/Select.d.ts.map +1 -1
  72. package/dist/js/components/Select/Select.js +51 -936
  73. package/dist/js/components/Select/Select.js.map +1 -1
  74. package/dist/js/components/Select/SelectGroup.d.ts +7 -8
  75. package/dist/js/components/Select/SelectGroup.d.ts.map +1 -1
  76. package/dist/js/components/Select/SelectGroup.js +4 -7
  77. package/dist/js/components/Select/SelectGroup.js.map +1 -1
  78. package/dist/{esm/next → js}/components/Select/SelectList.d.ts +1 -1
  79. package/dist/js/components/Select/SelectList.d.ts.map +1 -0
  80. package/dist/js/{next/components → components}/Select/SelectList.js +1 -1
  81. package/dist/js/components/Select/SelectList.js.map +1 -0
  82. package/dist/js/components/Select/SelectOption.d.ts +13 -66
  83. package/dist/js/components/Select/SelectOption.d.ts.map +1 -1
  84. package/dist/js/components/Select/SelectOption.js +7 -193
  85. package/dist/js/components/Select/SelectOption.js.map +1 -1
  86. package/dist/js/components/Select/index.d.ts +1 -1
  87. package/dist/js/components/Select/index.d.ts.map +1 -1
  88. package/dist/js/components/Select/index.js +1 -1
  89. package/dist/js/components/Select/index.js.map +1 -1
  90. package/dist/js/deprecated/components/Select/Select.d.ts +199 -0
  91. package/dist/js/deprecated/components/Select/Select.d.ts.map +1 -0
  92. package/dist/js/deprecated/components/Select/Select.js +944 -0
  93. package/dist/js/deprecated/components/Select/Select.js.map +1 -0
  94. package/dist/js/deprecated/components/Select/SelectGroup.d.ts +13 -0
  95. package/dist/js/deprecated/components/Select/SelectGroup.d.ts.map +1 -0
  96. package/dist/js/deprecated/components/Select/SelectGroup.js +17 -0
  97. package/dist/js/deprecated/components/Select/SelectGroup.js.map +1 -0
  98. package/dist/js/deprecated/components/Select/SelectMenu.d.ts.map +1 -0
  99. package/dist/js/{components → deprecated/components}/Select/SelectMenu.js +1 -1
  100. package/dist/js/deprecated/components/Select/SelectMenu.js.map +1 -0
  101. package/dist/js/deprecated/components/Select/SelectOption.d.ts +73 -0
  102. package/dist/js/deprecated/components/Select/SelectOption.d.ts.map +1 -0
  103. package/dist/js/deprecated/components/Select/SelectOption.js +200 -0
  104. package/dist/js/deprecated/components/Select/SelectOption.js.map +1 -0
  105. package/dist/js/deprecated/components/Select/SelectToggle.d.ts.map +1 -0
  106. package/dist/js/{components → deprecated/components}/Select/SelectToggle.js +2 -2
  107. package/dist/js/deprecated/components/Select/SelectToggle.js.map +1 -0
  108. package/dist/js/{next → deprecated}/components/Select/index.d.ts +1 -1
  109. package/dist/js/deprecated/components/Select/index.d.ts.map +1 -0
  110. package/dist/js/{next → deprecated}/components/Select/index.js +1 -1
  111. package/dist/js/deprecated/components/Select/index.js.map +1 -0
  112. package/dist/js/deprecated/components/Select/selectConstants.d.ts.map +1 -0
  113. package/dist/js/deprecated/components/Select/selectConstants.js.map +1 -0
  114. package/dist/js/deprecated/components/index.d.ts +1 -0
  115. package/dist/js/deprecated/components/index.d.ts.map +1 -1
  116. package/dist/js/deprecated/components/index.js +1 -0
  117. package/dist/js/deprecated/components/index.js.map +1 -1
  118. package/dist/js/next/components/index.d.ts +0 -1
  119. package/dist/js/next/components/index.d.ts.map +1 -1
  120. package/dist/js/next/components/index.js +0 -1
  121. package/dist/js/next/components/index.js.map +1 -1
  122. package/dist/umd/react-core.min.js +3 -3
  123. package/package.json +2 -2
  124. package/src/components/CalendarMonth/CalendarMonth.tsx +25 -15
  125. package/src/components/DatePicker/__tests__/__snapshots__/DatePicker.test.tsx.snap +22 -31
  126. package/src/components/LoginPage/examples/LoginPageLanguageSelect.tsx +28 -19
  127. package/src/components/MenuToggle/MenuToggle.tsx +2 -1
  128. package/src/components/MenuToggle/__tests__/__snapshots__/MenuToggle.test.tsx.snap +18 -10
  129. package/src/components/Select/Select.tsx +113 -1475
  130. package/src/components/Select/SelectGroup.tsx +13 -25
  131. package/src/{next/components → components}/Select/SelectList.tsx +1 -1
  132. package/src/components/Select/SelectOption.tsx +22 -452
  133. package/src/components/Select/examples/Select.md +11 -2897
  134. package/src/{next/components → components}/Select/examples/SelectBasic.tsx +1 -2
  135. package/src/{next/components → components}/Select/examples/SelectCheckbox.tsx +1 -2
  136. package/src/{next/components → components}/Select/examples/SelectGrouped.tsx +1 -2
  137. package/src/{next/components → components}/Select/examples/SelectMultiTypeahead.tsx +4 -1
  138. package/src/{next/components → components}/Select/examples/SelectTypeahead.tsx +4 -1
  139. package/src/components/Select/index.ts +1 -1
  140. package/src/components/Toolbar/__tests__/Toolbar.test.tsx +3 -21
  141. package/src/components/Toolbar/__tests__/__snapshots__/Toolbar.test.tsx.snap +12 -124
  142. package/src/components/Toolbar/examples/Toolbar.md +0 -1
  143. package/src/components/Toolbar/examples/ToolbarComponentManagedToggleGroups.tsx +59 -63
  144. package/src/components/Toolbar/examples/ToolbarConsumerManagedToggleGroups.tsx +58 -62
  145. package/src/components/Toolbar/examples/ToolbarCustomChipGroupContent.tsx +107 -23
  146. package/src/components/Toolbar/examples/ToolbarGroups.tsx +96 -59
  147. package/src/components/Toolbar/examples/ToolbarStacked.tsx +56 -39
  148. package/src/components/Toolbar/examples/ToolbarWithFilters.tsx +115 -28
  149. package/src/components/Tooltip/examples/TooltipOptions.tsx +53 -23
  150. package/src/demos/Card/Card.md +39 -23
  151. package/src/demos/CardDemos.md +99 -46
  152. package/src/demos/Toolbar.md +51 -21
  153. package/src/demos/examples/Tabs/TabsAndTable.tsx +5 -22
  154. package/src/deprecated/components/Select/Select.tsx +1495 -0
  155. package/src/deprecated/components/Select/SelectGroup.tsx +36 -0
  156. package/src/{components → deprecated/components}/Select/SelectMenu.tsx +2 -2
  157. package/src/deprecated/components/Select/SelectOption.tsx +461 -0
  158. package/src/{components → deprecated/components}/Select/SelectToggle.tsx +3 -3
  159. package/src/{components → deprecated/components}/Select/__tests__/Select.test.tsx +1 -1
  160. package/src/deprecated/components/Select/examples/Select.md +2937 -0
  161. package/src/{next → deprecated}/components/Select/index.ts +1 -1
  162. package/src/deprecated/components/index.ts +1 -0
  163. package/src/next/components/index.ts +0 -1
  164. package/dist/esm/components/Select/SelectMenu.d.ts.map +0 -1
  165. package/dist/esm/components/Select/SelectMenu.js.map +0 -1
  166. package/dist/esm/components/Select/SelectToggle.d.ts.map +0 -1
  167. package/dist/esm/components/Select/SelectToggle.js.map +0 -1
  168. package/dist/esm/components/Select/selectConstants.d.ts.map +0 -1
  169. package/dist/esm/components/Select/selectConstants.js.map +0 -1
  170. package/dist/esm/next/components/Select/Select.d.ts +0 -33
  171. package/dist/esm/next/components/Select/Select.d.ts.map +0 -1
  172. package/dist/esm/next/components/Select/Select.js +0 -56
  173. package/dist/esm/next/components/Select/Select.js.map +0 -1
  174. package/dist/esm/next/components/Select/SelectGroup.d.ts +0 -12
  175. package/dist/esm/next/components/Select/SelectGroup.d.ts.map +0 -1
  176. package/dist/esm/next/components/Select/SelectGroup.js +0 -10
  177. package/dist/esm/next/components/Select/SelectGroup.js.map +0 -1
  178. package/dist/esm/next/components/Select/SelectList.d.ts.map +0 -1
  179. package/dist/esm/next/components/Select/SelectList.js.map +0 -1
  180. package/dist/esm/next/components/Select/SelectOption.d.ts +0 -20
  181. package/dist/esm/next/components/Select/SelectOption.d.ts.map +0 -1
  182. package/dist/esm/next/components/Select/SelectOption.js +0 -10
  183. package/dist/esm/next/components/Select/SelectOption.js.map +0 -1
  184. package/dist/esm/next/components/Select/index.d.ts.map +0 -1
  185. package/dist/esm/next/components/Select/index.js.map +0 -1
  186. package/dist/js/components/Select/SelectMenu.d.ts.map +0 -1
  187. package/dist/js/components/Select/SelectMenu.js.map +0 -1
  188. package/dist/js/components/Select/SelectToggle.d.ts.map +0 -1
  189. package/dist/js/components/Select/SelectToggle.js.map +0 -1
  190. package/dist/js/components/Select/selectConstants.d.ts.map +0 -1
  191. package/dist/js/components/Select/selectConstants.js.map +0 -1
  192. package/dist/js/next/components/Select/Select.d.ts +0 -33
  193. package/dist/js/next/components/Select/Select.d.ts.map +0 -1
  194. package/dist/js/next/components/Select/Select.js +0 -59
  195. package/dist/js/next/components/Select/Select.js.map +0 -1
  196. package/dist/js/next/components/Select/SelectGroup.d.ts +0 -12
  197. package/dist/js/next/components/Select/SelectGroup.d.ts.map +0 -1
  198. package/dist/js/next/components/Select/SelectGroup.js +0 -14
  199. package/dist/js/next/components/Select/SelectGroup.js.map +0 -1
  200. package/dist/js/next/components/Select/SelectList.d.ts.map +0 -1
  201. package/dist/js/next/components/Select/SelectList.js.map +0 -1
  202. package/dist/js/next/components/Select/SelectOption.d.ts +0 -20
  203. package/dist/js/next/components/Select/SelectOption.d.ts.map +0 -1
  204. package/dist/js/next/components/Select/SelectOption.js +0 -14
  205. package/dist/js/next/components/Select/SelectOption.js.map +0 -1
  206. package/dist/js/next/components/Select/index.d.ts.map +0 -1
  207. package/dist/js/next/components/Select/index.js.map +0 -1
  208. package/src/next/components/Select/Select.tsx +0 -133
  209. package/src/next/components/Select/SelectGroup.tsx +0 -24
  210. package/src/next/components/Select/SelectOption.tsx +0 -31
  211. package/src/next/components/Select/examples/Select.md +0 -38
  212. /package/dist/esm/{components → deprecated/components}/Select/SelectMenu.d.ts +0 -0
  213. /package/dist/esm/{components → deprecated/components}/Select/SelectToggle.d.ts +0 -0
  214. /package/dist/esm/{components → deprecated/components}/Select/selectConstants.d.ts +0 -0
  215. /package/dist/esm/{components → deprecated/components}/Select/selectConstants.js +0 -0
  216. /package/dist/js/{components → deprecated/components}/Select/SelectMenu.d.ts +0 -0
  217. /package/dist/js/{components → deprecated/components}/Select/SelectToggle.d.ts +0 -0
  218. /package/dist/js/{components → deprecated/components}/Select/selectConstants.d.ts +0 -0
  219. /package/dist/js/{components → deprecated/components}/Select/selectConstants.js +0 -0
  220. /package/src/{components → deprecated/components}/Select/__tests__/SelectGroup.test.tsx +0 -0
  221. /package/src/{components → deprecated/components}/Select/__tests__/SelectOption.test.tsx +0 -0
  222. /package/src/{components → deprecated/components}/Select/__tests__/SelectToggle.test.tsx +0 -0
  223. /package/src/{components → deprecated/components}/Select/__tests__/__snapshots__/Select.test.tsx.snap +0 -0
  224. /package/src/{components → deprecated/components}/Select/__tests__/__snapshots__/SelectGroup.test.tsx.snap +0 -0
  225. /package/src/{components → deprecated/components}/Select/__tests__/__snapshots__/SelectOption.test.tsx.snap +0 -0
  226. /package/src/{components → deprecated/components}/Select/__tests__/__snapshots__/SelectToggle.test.tsx.snap +0 -0
  227. /package/src/{components → deprecated/components}/Select/selectConstants.tsx +0 -0
@@ -0,0 +1,2937 @@
1
+ ---
2
+ id: Select
3
+ section: components
4
+ subsection: menus
5
+ cssPrefix: pf-c-select
6
+ propComponents: ['Select', 'SelectOption', 'SelectGroup', 'SelectOptionObject', 'SelectViewMoreObject']
7
+ ouia: true
8
+ ---
9
+
10
+ import CubeIcon from '@patternfly/react-icons/dist/esm/icons/cube-icon';
11
+
12
+ ## Examples
13
+
14
+ ### Single select
15
+
16
+ To let users select a single item from a list, use a single select list.
17
+
18
+ A select list may use other properties for additional customization. Select each checkbox in the example below to visualize the following behavior:
19
+
20
+ - To prevent a toggle click from opening a select list, use the `isDisabled` property.
21
+ - To adjust the direction a select menu opens, use the `direction` property. The menu in the following example expands upwards. By default, select lists open upwards.
22
+ - To add an icon to a select toggle, use the `toggleIcon` property.
23
+
24
+ ```js
25
+ import React from 'react';
26
+ import CubeIcon from '@patternfly/react-icons/dist/esm/icons/cube-icon';
27
+ import { Checkbox, Divider } from '@patternfly/react-core';
28
+ import { Select, SelectOption, SelectVariant, SelectDirection } from '@patternfly/react-core/deprecated';
29
+
30
+ class SingleSelectInput extends React.Component {
31
+ constructor(props) {
32
+ super(props);
33
+ this.options = [
34
+ <SelectOption key={0} value="Select a title" isPlaceholder />,
35
+ <SelectOption key={1} value="Mr" />,
36
+ <SelectOption key={2} value="Miss" />,
37
+ <SelectOption key={3} value="Mrs" />,
38
+ <SelectOption key={4} value="Ms" />,
39
+ <Divider component="li" key={5} />,
40
+ <SelectOption key={6} value="Dr" />,
41
+ <SelectOption key={7} value="Other" />
42
+ ];
43
+
44
+ this.toggleRef = React.createRef();
45
+
46
+ this.state = {
47
+ isToggleIcon: false,
48
+ isOpen: false,
49
+ selected: null,
50
+ isDisabled: false,
51
+ direction: SelectDirection.down
52
+ };
53
+
54
+ this.onToggle = (_event, isOpen) => {
55
+ this.setState({
56
+ isOpen
57
+ });
58
+ };
59
+
60
+ this.onSelect = (event, selection, isPlaceholder) => {
61
+ if (isPlaceholder) this.clearSelection();
62
+ else {
63
+ this.setState({
64
+ selected: selection,
65
+ isOpen: false
66
+ });
67
+ console.log('selected:', selection);
68
+ this.toggleRef.current.focus();
69
+ }
70
+ };
71
+
72
+ this.clearSelection = () => {
73
+ this.setState({
74
+ selected: null,
75
+ isOpen: false
76
+ });
77
+ };
78
+
79
+ this.toggleDisabled = checked => {
80
+ this.setState({
81
+ isDisabled: checked
82
+ });
83
+ };
84
+
85
+ this.setIcon = checked => {
86
+ this.setState({
87
+ isToggleIcon: checked
88
+ });
89
+ };
90
+
91
+ this.toggleDirection = () => {
92
+ if (this.state.direction === SelectDirection.up) {
93
+ this.setState({
94
+ direction: SelectDirection.down
95
+ });
96
+ } else {
97
+ this.setState({
98
+ direction: SelectDirection.up
99
+ });
100
+ }
101
+ };
102
+ }
103
+
104
+ render() {
105
+ const { isOpen, selected, isDisabled, direction, isToggleIcon } = this.state;
106
+ const titleId = 'title-id-1';
107
+ return (
108
+ <div>
109
+ <span id={titleId} hidden>
110
+ Title
111
+ </span>
112
+ <Select
113
+ toggleRef={this.toggleRef}
114
+ toggleIcon={isToggleIcon && <CubeIcon />}
115
+ variant={SelectVariant.single}
116
+ aria-label="Select Input"
117
+ onToggle={this.onToggle}
118
+ onSelect={this.onSelect}
119
+ selections={selected}
120
+ isOpen={isOpen}
121
+ aria-labelledby={titleId}
122
+ isDisabled={isDisabled}
123
+ direction={direction}
124
+ ouiaId="SingleSelect"
125
+ >
126
+ {this.options}
127
+ </Select>
128
+ <Checkbox
129
+ label="isDisabled"
130
+ isChecked={this.state.isDisabled}
131
+ onChange={(_event, checked) => this.toggleDisabled(checked)}
132
+ aria-label="disabled checkbox"
133
+ id="toggle-disabled"
134
+ name="toggle-disabled"
135
+ />
136
+ <Checkbox
137
+ label="Expands up"
138
+ isChecked={direction === SelectDirection.up}
139
+ onChange={this.toggleDirection}
140
+ aria-label="direction checkbox"
141
+ id="toggle-direction"
142
+ name="toggle-direction"
143
+ />
144
+ <Checkbox
145
+ label="Show icon"
146
+ isChecked={isToggleIcon}
147
+ onChange={(_event, checked) => this.setIcon(checked)}
148
+ aria-label="show icon checkbox"
149
+ id="toggle-icon"
150
+ name="toggle-icon"
151
+ />
152
+ </div>
153
+ );
154
+ }
155
+ }
156
+ ```
157
+
158
+ ### With item descriptions
159
+
160
+ To give more context to a `<SelectOption>` in a list, use the `description` property.
161
+
162
+ ```js
163
+ import React from 'react';
164
+ import { Select, SelectOption, SelectVariant } from '@patternfly/react-core/deprecated';
165
+
166
+ class SingleSelectDescription extends React.Component {
167
+ constructor(props) {
168
+ super(props);
169
+ this.options = [
170
+ { value: 'Mr', disabled: false },
171
+ { value: 'Miss', disabled: false },
172
+ { value: 'Mrs', disabled: false },
173
+ { value: 'Ms', disabled: false },
174
+ { value: 'Dr', disabled: false },
175
+ { value: 'Other', disabled: false }
176
+ ];
177
+
178
+ this.toggleRef = React.createRef();
179
+
180
+ this.state = {
181
+ isOpen: false,
182
+ selected: null,
183
+ isDisabled: false
184
+ };
185
+
186
+ this.onToggle = (_event, isOpen) => {
187
+ this.setState({
188
+ isOpen
189
+ });
190
+ };
191
+
192
+ this.onSelect = (event, selection, isPlaceholder) => {
193
+ if (isPlaceholder) this.clearSelection();
194
+ else {
195
+ this.setState({
196
+ selected: selection,
197
+ isOpen: false
198
+ });
199
+ console.log('selected:', selection);
200
+ this.toggleRef.current.focus();
201
+ }
202
+ };
203
+
204
+ this.clearSelection = () => {
205
+ this.setState({
206
+ selected: null,
207
+ isOpen: false
208
+ });
209
+ };
210
+ }
211
+
212
+ render() {
213
+ const { isOpen, selected, isDisabled, direction, isToggleIcon } = this.state;
214
+ const titleId = 'select-descriptions-title';
215
+ return (
216
+ <div>
217
+ <span id={titleId} hidden>
218
+ Title
219
+ </span>
220
+ <Select
221
+ variant={SelectVariant.single}
222
+ placeholderText="Select an option"
223
+ aria-label="Select Input with descriptions"
224
+ onToggle={this.onToggle}
225
+ toggleRef={this.toggleRef}
226
+ onSelect={this.onSelect}
227
+ selections={selected}
228
+ isOpen={isOpen}
229
+ aria-labelledby={titleId}
230
+ isDisabled={isDisabled}
231
+ >
232
+ {this.options.map((option, index) => (
233
+ <SelectOption
234
+ isDisabled={option.disabled}
235
+ key={index}
236
+ value={option.value}
237
+ isPlaceholder={option.isPlaceholder}
238
+ description="This is a description"
239
+ />
240
+ ))}
241
+ </Select>
242
+ </div>
243
+ );
244
+ }
245
+ }
246
+ ```
247
+
248
+ ### With grouped items
249
+
250
+ To group related select options together, use 1 or more `<SelectGroup>` components and title each group using the `label` property.
251
+
252
+ ```js
253
+ import React from 'react';
254
+ import { Divider } from '@patternfly/react-core';
255
+ import { Select, SelectOption, SelectVariant, SelectGroup } from '@patternfly/react-core/deprecated';
256
+
257
+ class GroupedSingleSelectInput extends React.Component {
258
+ constructor(props) {
259
+ super(props);
260
+ this.state = {
261
+ isOpen: false,
262
+ selected: null
263
+ };
264
+
265
+ this.toggleRef = React.createRef();
266
+
267
+ this.onToggle = (_event, isOpen) => {
268
+ this.setState({
269
+ isOpen
270
+ });
271
+ };
272
+
273
+ this.onSelect = (event, selection) => {
274
+ this.setState({
275
+ selected: selection,
276
+ isOpen: false
277
+ });
278
+ this.toggleRef.current.focus();
279
+ };
280
+
281
+ this.clearSelection = () => {
282
+ this.setState({
283
+ selected: null
284
+ });
285
+ };
286
+
287
+ this.options = [
288
+ <SelectGroup label="Status" key="group1">
289
+ <SelectOption key={0} value="Running" />
290
+ <SelectOption key={1} value="Stopped" />
291
+ <SelectOption key={2} value="Down" />
292
+ <SelectOption key={3} value="Degraded" />
293
+ <SelectOption key={4} value="Needs maintenance" />
294
+ </SelectGroup>,
295
+ <Divider key="divider" />,
296
+ <SelectGroup label="Vendor names" key="group2">
297
+ <SelectOption key={5} value="Dell" />
298
+ <SelectOption key={6} value="Samsung" isDisabled />
299
+ <SelectOption key={7} value="Hewlett-Packard" />
300
+ </SelectGroup>
301
+ ];
302
+ }
303
+
304
+ render() {
305
+ const { isOpen, selected } = this.state;
306
+ const titleId = 'grouped-single-select-id';
307
+ return (
308
+ <div>
309
+ <span id={titleId} hidden>
310
+ Grouped Checkbox Title
311
+ </span>
312
+ <Select
313
+ variant={SelectVariant.single}
314
+ toggleRef={this.toggleRef}
315
+ onToggle={this.onToggle}
316
+ onSelect={this.onSelect}
317
+ selections={selected}
318
+ isOpen={isOpen}
319
+ placeholderText="Filter by status/vendor"
320
+ aria-labelledby={titleId}
321
+ isGrouped
322
+ >
323
+ {this.options}
324
+ </Select>
325
+ </div>
326
+ );
327
+ }
328
+ }
329
+ ```
330
+
331
+ ### Favoriting items
332
+
333
+ To allow users to favorite items in a select list, use the `onFavorite` callback. When users click the favorite button, the item is duplicated and placed in a separated group at the top of the menu. To change the name of the group use the `favoritesLabel` property.
334
+
335
+ ```js
336
+ import React from 'react';
337
+ import { Select, SelectOption, SelectVariant, SelectGroup } from '@patternfly/react-core/deprecated';
338
+
339
+ class FavoritesSelect extends React.Component {
340
+ constructor(props) {
341
+ super(props);
342
+ this.state = {
343
+ isOpen: false,
344
+ selected: null,
345
+ favorites: []
346
+ };
347
+
348
+ this.onToggle = (_event, isOpen) => {
349
+ this.setState({
350
+ isOpen
351
+ });
352
+ };
353
+
354
+ this.onSelect = (event, selection, isPlaceholder) => {
355
+ if (isPlaceholder) this.clearSelection();
356
+ else {
357
+ this.setState({
358
+ selected: selection,
359
+ isOpen: false
360
+ });
361
+ console.log('selected:', selection);
362
+ }
363
+ };
364
+
365
+ this.clearSelection = () => {
366
+ this.setState({
367
+ selected: null,
368
+ isOpen: false
369
+ });
370
+ };
371
+
372
+ this.onFavorite = (itemId, isFavorite) => {
373
+ if (isFavorite) {
374
+ this.setState({
375
+ favorites: this.state.favorites.filter(id => id !== itemId)
376
+ });
377
+ } else
378
+ this.setState({
379
+ favorites: [...this.state.favorites, itemId]
380
+ });
381
+ };
382
+
383
+ this.options = [
384
+ <SelectGroup label="Status" key="group1">
385
+ <SelectOption id={'option-1'} key={0} value="Running" description="This is a description." />
386
+ <SelectOption id={'option-2'} key={1} value="Stopped" />
387
+ <SelectOption id={'option-3'} key={2} value="Down (disabled)" isDisabled />
388
+ <SelectOption id={'option-4'} key={3} value="Degraded" />
389
+ <SelectOption id={'option-5'} key={4} value="Needs maintenance" />
390
+ </SelectGroup>,
391
+ <SelectGroup label="Vendor names" key="group2">
392
+ <SelectOption id={'option-6'} key={5} value="Dell" />
393
+ <SelectOption id={'option-7'} key={6} value="Samsung" description="This is a description." />
394
+ <SelectOption id={'option-8'} key={7} value="Hewlett-Packard" />
395
+ </SelectGroup>
396
+ ];
397
+ }
398
+
399
+ render() {
400
+ const { isOpen, selected, favorites } = this.state;
401
+ const titleId = 'grouped-single-select-id';
402
+ return (
403
+ <Select
404
+ variant={SelectVariant.typeahead}
405
+ typeAheadAriaLabel="Select value"
406
+ onToggle={this.onToggle}
407
+ onSelect={this.onSelect}
408
+ selections={selected}
409
+ isOpen={isOpen}
410
+ placeholderText="Favorites"
411
+ aria-labelledby={titleId}
412
+ isGrouped
413
+ onFavorite={this.onFavorite}
414
+ favorites={favorites}
415
+ onClear={this.clearSelection}
416
+ >
417
+ {this.options}
418
+ </Select>
419
+ );
420
+ }
421
+ }
422
+ ```
423
+
424
+ ### Validated selections
425
+
426
+ To validate selections that users make, pass a validation state to the `validated` property. Validating selections can let users know if the selections they make would cause issues or errors.
427
+
428
+ The example below passes an "error" state when you choose “select a title”, a "warning" state when you choose "other", and a "success" state for any other item selected from the menu.
429
+
430
+ ```js
431
+ import React from 'react';
432
+ import { Select, SelectOption, SelectVariant } from '@patternfly/react-core/deprecated';
433
+
434
+ class ValidatedSelect extends React.Component {
435
+ constructor(props) {
436
+ super(props);
437
+ this.options = [
438
+ <SelectOption key={0} value="Select a title" isPlaceholder />,
439
+ <SelectOption key={1} value="Mr" />,
440
+ <SelectOption key={2} value="Miss" />,
441
+ <SelectOption key={3} value="Mrs" />,
442
+ <SelectOption key={4} value="Ms" />,
443
+ <SelectOption key={5} value="Dr" />,
444
+ <SelectOption key={6} value="Other" />
445
+ ];
446
+
447
+ this.toggleRef = React.createRef();
448
+
449
+ this.state = {
450
+ isOpen: false,
451
+ selected: null,
452
+ isDisabled: false,
453
+ validated: 'default'
454
+ };
455
+
456
+ this.onToggle = (_event, isOpen) => {
457
+ this.setState({
458
+ isOpen
459
+ });
460
+ };
461
+
462
+ this.onSelect = (event, selection, isPlaceholder) => {
463
+ let validatedState = 'success';
464
+ if (isPlaceholder) {
465
+ this.clearSelection();
466
+ validatedState = 'error';
467
+ } else {
468
+ if (selection === 'Other') {
469
+ validatedState = 'warning';
470
+ } else {
471
+ validatedState = 'success';
472
+ }
473
+ this.setState({
474
+ selected: selection,
475
+ isOpen: false
476
+ });
477
+ console.log('selected:', selection);
478
+ }
479
+ this.setState({
480
+ validated: validatedState
481
+ });
482
+ this.toggleRef.current.focus();
483
+ };
484
+
485
+ this.clearSelection = () => {
486
+ this.setState({
487
+ selected: null,
488
+ isOpen: false
489
+ });
490
+ };
491
+ }
492
+
493
+ render() {
494
+ const { isOpen, selected, isDisabled, direction, isToggleIcon, validated } = this.state;
495
+ const titleId = 'select-validated-title';
496
+ return (
497
+ <div>
498
+ <span id={titleId} hidden>
499
+ Title
500
+ </span>
501
+ <Select
502
+ variant={SelectVariant.single}
503
+ toggleRef={this.toggleRef}
504
+ placeholderText="Select an option"
505
+ aria-label="Select Input with validation"
506
+ onToggle={this.onToggle}
507
+ onSelect={this.onSelect}
508
+ selections={selected}
509
+ isOpen={isOpen}
510
+ aria-labelledby={titleId}
511
+ isDisabled={isDisabled}
512
+ validated={validated}
513
+ aria-describedby="validated-helper"
514
+ aria-invalid={validated === 'error' ? true : false}
515
+ >
516
+ {this.options}
517
+ </Select>
518
+ <div aria-live="polite" id="validated-helper" hidden>
519
+ {validated}
520
+ </div>
521
+ </div>
522
+ );
523
+ }
524
+ }
525
+ ```
526
+
527
+ ### Styled placeholder text
528
+
529
+ To add a toggle label to a select, use the `placeholderText` property. The following example displays "Filter by status" in the toggle before a selection is made.
530
+
531
+ To fade the color of `placeholderText` to gray, use the `hasPlaceholderStyle` property.
532
+
533
+ ```js
534
+ import React from 'react';
535
+ import { Select, SelectOption, SelectVariant } from '@patternfly/react-core/deprecated';
536
+
537
+ function SelectWithPlaceholderStyle() {
538
+ const [isOpen, setIsOpen] = React.useState(false);
539
+ const [selected, setSelected] = React.useState([]);
540
+
541
+ const options = [
542
+ <SelectOption key={0} value="Active" />,
543
+ <SelectOption key={1} value="Cancelled" />,
544
+ <SelectOption key={2} value="Paused" />
545
+ ];
546
+
547
+ const onToggle = (_event, isOpen) => setIsOpen(isOpen);
548
+
549
+ const onSelect = (event, selection, isPlaceholder) => {
550
+ setSelected(selection);
551
+ setIsOpen(false);
552
+ };
553
+
554
+ const clearSelection = () => {
555
+ setSelected(null);
556
+ setIsOpen(false);
557
+ };
558
+
559
+ const titleId = 'placeholder-style-select-id';
560
+
561
+ return (
562
+ <div>
563
+ <span id={titleId} hidden>
564
+ Placeholder styles
565
+ </span>
566
+ <Select
567
+ variant={SelectVariant.single}
568
+ hasPlaceholderStyle
569
+ aria-label="Select input"
570
+ onToggle={onToggle}
571
+ onSelect={onSelect}
572
+ onClear={clearSelection}
573
+ selections={selected}
574
+ isOpen={isOpen}
575
+ placeholderText="Filter by status"
576
+ aria-labelledby={titleId}
577
+ >
578
+ {options}
579
+ </Select>
580
+ </div>
581
+ );
582
+ }
583
+ ```
584
+
585
+ ### Placeholder select options
586
+
587
+ To set a `<SelectOption>` as a placeholder, use the `isPlaceholder` property. The following example sets the "Filter by status" as a placeholder so that it is pre-selected.
588
+
589
+ ```js
590
+
591
+ import React from 'react';
592
+ import { Select, SelectOption, SelectVariant } from '@patternfly/react-core/deprecated';
593
+
594
+ function SelectWithPlaceholderStyle() {
595
+ const [isOpen, setIsOpen] = React.useState(false);
596
+ const [selected, setSelected] = React.useState([]);
597
+
598
+ const options = [
599
+ <SelectOption key={0} value="Filter by status" isPlaceholder />,
600
+ <SelectOption key={1} value="Active" />,
601
+ <SelectOption key={2} value="Cancelled" />,
602
+ <SelectOption key={3} value="Paused" />
603
+ ];
604
+
605
+ const onToggle = (_event, isOpen) => setIsOpen(isOpen);
606
+
607
+ const onSelect = (event, selection, isPlaceholder) => {
608
+ setSelected(selection);
609
+ setIsOpen(false);
610
+ };
611
+
612
+ const clearSelection = () => {
613
+ setSelected(null);
614
+ setIsOpen(false);
615
+ };
616
+
617
+ const titleId = 'placeholder-style-select-option-id';
618
+
619
+ return (
620
+ <div>
621
+ <span id={titleId} hidden>
622
+ Placeholder styles - select option
623
+ </span>
624
+ <Select
625
+ variant={SelectVariant.single}
626
+ hasPlaceholderStyle
627
+ aria-label="Select input"
628
+ onToggle={onToggle}
629
+ onSelect={onSelect}
630
+ onClear={clearSelection}
631
+ selections={selected}
632
+ isOpen={isOpen}
633
+ aria-labelledby={titleId}
634
+ >
635
+ {options}
636
+ </Select>
637
+ </div>
638
+ );
639
+ }
640
+ ```
641
+
642
+ ### With a footer
643
+
644
+ You can add a `footer` to a `<Select>` list to hold actions that users can take on menu items.
645
+
646
+ ```js
647
+ import React from 'react';
648
+ import CubeIcon from '@patternfly/react-icons/dist/esm/icons/cube-icon';
649
+ import { Divider, Button } from '@patternfly/react-core';
650
+ import { Select, SelectOption, SelectVariant, SelectDirection } from '@patternfly/react-core/deprecated';
651
+
652
+ class SelectWithFooter extends React.Component {
653
+ constructor(props) {
654
+ super(props);
655
+ this.options = [
656
+ <SelectOption key={0} value="Select a title" isPlaceholder />,
657
+ <SelectOption key={1} value="Mr" />,
658
+ <SelectOption key={2} value="Miss" />,
659
+ <SelectOption key={3} value="Mrs" />,
660
+ <SelectOption key={4} value="Ms" />,
661
+ <Divider component="li" key={5} />,
662
+ <SelectOption key={6} value="Dr" />,
663
+ <SelectOption key={7} value="Other" />
664
+ ];
665
+
666
+ this.toggleRef = React.createRef();
667
+
668
+ this.state = {
669
+ isToggleIcon: false,
670
+ isOpen: false,
671
+ selected: null,
672
+ isDisabled: false,
673
+ direction: SelectDirection.down
674
+ };
675
+
676
+ this.onToggle = (_event, isOpen) => {
677
+ this.setState({
678
+ isOpen
679
+ });
680
+ };
681
+
682
+ this.onSelect = (event, selection, isPlaceholder) => {
683
+ if (isPlaceholder) this.clearSelection();
684
+ else {
685
+ this.setState({
686
+ selected: selection,
687
+ isOpen: false
688
+ });
689
+ console.log('selected:', selection);
690
+ this.toggleRef.current.focus();
691
+ }
692
+ };
693
+
694
+ this.clearSelection = () => {
695
+ this.setState({
696
+ selected: null,
697
+ isOpen: false
698
+ });
699
+ };
700
+ }
701
+
702
+ render() {
703
+ const { isOpen, selected, isDisabled, direction, isToggleIcon } = this.state;
704
+ const titleId = 'title-id-footer';
705
+ return (
706
+ <div>
707
+ <span id={titleId} hidden>
708
+ Title
709
+ </span>
710
+ <Select
711
+ toggleIcon={isToggleIcon && <CubeIcon />}
712
+ toggleRef={this.toggleRef}
713
+ variant={SelectVariant.single}
714
+ aria-label="Select Input"
715
+ onToggle={this.onToggle}
716
+ onSelect={this.onSelect}
717
+ selections={selected}
718
+ isOpen={isOpen}
719
+ aria-labelledby={titleId}
720
+ isDisabled={isDisabled}
721
+ direction={direction}
722
+ footer={
723
+ <>
724
+ <Button variant="link" isInline>
725
+ Action
726
+ </Button>
727
+ </>
728
+ }
729
+ >
730
+ {this.options}
731
+ </Select>
732
+ </div>
733
+ );
734
+ }
735
+ }
736
+ ```
737
+
738
+ ### With view more
739
+
740
+ To reduce the processing load for long select lists, replace overflow items with a "View more" link at the bottom of the select menu.
741
+
742
+ Adjust the number of items shown above the "View more" link with the `numOptions` property. The following example passes 3 items into this property.
743
+
744
+ ```js
745
+ import React from 'react';
746
+ import { Select, SelectOption, SelectVariant } from '@patternfly/react-core/deprecated';
747
+
748
+ class SelectViewMore extends React.Component {
749
+ constructor(props) {
750
+ super(props);
751
+ this.options = [
752
+ <SelectOption key={0} value="Select a title" isPlaceholder />,
753
+ <SelectOption key={1} value="Mr" />,
754
+ <SelectOption key={2} value="Miss" />,
755
+ <SelectOption key={3} value="Mrs" />,
756
+ <SelectOption key={4} value="Ms" />,
757
+ <SelectOption key={5} value="Dr" />,
758
+ <SelectOption key={6} value="Other" />
759
+ ];
760
+
761
+ this.toggleRef = React.createRef();
762
+
763
+ this.state = {
764
+ isOpen: false,
765
+ selected: null,
766
+ numOptions: 3,
767
+ isLoading: false
768
+ };
769
+
770
+ this.onToggle = (_event, isOpen) => {
771
+ this.setState({
772
+ isOpen
773
+ });
774
+ };
775
+
776
+ this.onSelect = (event, selection, isPlaceholder) => {
777
+ if (isPlaceholder) this.clearSelection();
778
+ else {
779
+ this.setState({
780
+ selected: selection,
781
+ isOpen: false
782
+ });
783
+ console.log('selected:', selection);
784
+ this.toggleRef.current.focus();
785
+ }
786
+ };
787
+
788
+ this.clearSelection = () => {
789
+ this.setState({
790
+ selected: null,
791
+ isOpen: false
792
+ });
793
+ };
794
+
795
+ this.simulateNetworkCall = callback => {
796
+ setTimeout(callback, 2000);
797
+ };
798
+
799
+ this.onViewMoreClick = () => {
800
+ // Set select loadingVariant to spinner then simulate network call before loading more options
801
+ this.setState({ isLoading: true });
802
+ this.simulateNetworkCall(() => {
803
+ const newLength =
804
+ this.state.numOptions + 3 <= this.options.length ? this.state.numOptions + 3 : this.options.length;
805
+ this.setState({ numOptions: newLength, isLoading: false });
806
+ });
807
+ };
808
+ }
809
+
810
+ render() {
811
+ const { isOpen, selected, isToggleIcon, numOptions, loadingVariant, isLoading } = this.state;
812
+ const titleId = 'title-id-view-more';
813
+ return (
814
+ <div>
815
+ <span id={titleId} hidden>
816
+ Title
817
+ </span>
818
+ <Select
819
+ variant={SelectVariant.single}
820
+ toggleRef={this.toggleRef}
821
+ aria-label="Select Input"
822
+ onToggle={this.onToggle}
823
+ onSelect={this.onSelect}
824
+ selections={selected}
825
+ isOpen={isOpen}
826
+ aria-labelledby={titleId}
827
+ {...(!isLoading &&
828
+ numOptions < this.options.length && {
829
+ loadingVariant: { text: 'View more', onClick: this.onViewMoreClick }
830
+ })}
831
+ {...(isLoading && { loadingVariant: 'spinner' })}
832
+ >
833
+ {this.options.slice(0, numOptions)}
834
+ </Select>
835
+ </div>
836
+ );
837
+ }
838
+ }
839
+ ```
840
+
841
+ ### Checkbox select
842
+
843
+ To let users select multiple list options via checkbox input, use a checkbox select. To create a checkbox select, pass `variant={SelectVariant.checkbox}` into the `<Select>` component.
844
+
845
+ By default, a badge is displayed in the menu toggle that indicates the number of items a user has selected.
846
+
847
+ ```js
848
+ import React from 'react';
849
+ import { Divider } from '@patternfly/react-core';
850
+ import { Select, SelectOption, SelectVariant } from '@patternfly/react-core/deprecated';
851
+
852
+ class CheckboxSelectInput extends React.Component {
853
+ constructor(props) {
854
+ super(props);
855
+
856
+ this.state = {
857
+ isOpen: false,
858
+ selected: []
859
+ };
860
+
861
+ this.onToggle = (_event, isOpen) => {
862
+ this.setState({
863
+ isOpen
864
+ });
865
+ };
866
+
867
+ this.onSelect = (event, selection) => {
868
+ const { selected } = this.state;
869
+ if (selected.includes(selection)) {
870
+ this.setState(
871
+ prevState => ({ selected: prevState.selected.filter(item => item !== selection) }),
872
+ () => console.log('selections: ', this.state.selected)
873
+ );
874
+ } else {
875
+ this.setState(
876
+ prevState => ({ selected: [...prevState.selected, selection] }),
877
+ () => console.log('selections: ', this.state.selected)
878
+ );
879
+ }
880
+ };
881
+
882
+ this.clearSelection = () => {
883
+ this.setState({
884
+ selected: []
885
+ });
886
+ };
887
+
888
+ this.options = [
889
+ <SelectOption key={0} value="Active" description="This is a description" />,
890
+ <SelectOption key={1} value="Cancelled" />,
891
+ <SelectOption key={2} value="Paused" />,
892
+ <Divider key={3} />,
893
+ <SelectOption key={4} value="Warning" />,
894
+ <SelectOption key={5} value="Restarted" />
895
+ ];
896
+ }
897
+
898
+ render() {
899
+ const { isOpen, selected } = this.state;
900
+ const titleId = 'checkbox-select-id';
901
+ return (
902
+ <div>
903
+ <span id={titleId} hidden>
904
+ Checkbox Title
905
+ </span>
906
+ <Select
907
+ variant={SelectVariant.checkbox}
908
+ aria-label="Select Input"
909
+ onToggle={this.onToggle}
910
+ onSelect={this.onSelect}
911
+ selections={selected}
912
+ isOpen={isOpen}
913
+ placeholderText="Filter by status"
914
+ aria-labelledby={titleId}
915
+ >
916
+ {this.options}
917
+ </Select>
918
+ </div>
919
+ );
920
+ }
921
+ }
922
+ ```
923
+
924
+ ### Checkbox select with grouped items
925
+
926
+ You can use groups alongside checkbox input. The item count badge will display the number of items selected across all groups.
927
+
928
+ ```js
929
+ import React from 'react';
930
+ import { Select, SelectOption, SelectVariant, SelectGroup } from '@patternfly/react-core/deprecated';
931
+
932
+ class GroupedCheckboxSelectInput extends React.Component {
933
+ constructor(props) {
934
+ super(props);
935
+ this.state = {
936
+ isOpen: false,
937
+ selected: []
938
+ };
939
+
940
+ this.onToggle = (_event, isOpen) => {
941
+ this.setState({
942
+ isOpen
943
+ });
944
+ };
945
+
946
+ this.onSelect = (event, selection) => {
947
+ const { selected } = this.state;
948
+ if (selected.includes(selection)) {
949
+ this.setState(
950
+ prevState => ({ selected: prevState.selected.filter(item => item !== selection) }),
951
+ () => console.log('selections: ', this.state.selected)
952
+ );
953
+ } else {
954
+ this.setState(
955
+ prevState => ({ selected: [...prevState.selected, selection] }),
956
+ () => console.log('selections: ', this.state.selected)
957
+ );
958
+ }
959
+ };
960
+
961
+ this.clearSelection = () => {
962
+ this.setState({
963
+ selected: []
964
+ });
965
+ };
966
+
967
+ this.options = [
968
+ <SelectGroup label="Status" key="group1">
969
+ <SelectOption key={0} value="Running" />
970
+ <SelectOption key={1} value="Stopped" />
971
+ <SelectOption key={2} value="Down" />
972
+ <SelectOption key={3} value="Degraded" />
973
+ <SelectOption key={4} value="Needs maintenance" />
974
+ </SelectGroup>,
975
+ <SelectGroup label="Vendor names" key="group2">
976
+ <SelectOption key={5} value="Dell" />
977
+ <SelectOption key={6} value="Samsung" isDisabled />
978
+ <SelectOption key={7} value="Hewlett-Packard" />
979
+ </SelectGroup>
980
+ ];
981
+ }
982
+
983
+ render() {
984
+ const { isOpen, selected } = this.state;
985
+ const titleId = 'grouped-checkbox-select-id-1';
986
+ return (
987
+ <div>
988
+ <span id={titleId} hidden>
989
+ Grouped Checkbox Title
990
+ </span>
991
+ <Select
992
+ variant={SelectVariant.checkbox}
993
+ onToggle={this.onToggle}
994
+ onSelect={this.onSelect}
995
+ selections={selected}
996
+ isOpen={isOpen}
997
+ placeholderText="Filter by status"
998
+ aria-labelledby={titleId}
999
+ isGrouped
1000
+ >
1001
+ {this.options}
1002
+ </Select>
1003
+ </div>
1004
+ );
1005
+ }
1006
+ }
1007
+ ```
1008
+
1009
+ ### Checkbox select with custom badge
1010
+
1011
+ To change the default badge text for a checkbox select, use the `customBadgeText` property. The following example uses `customBadgeText` to display "all" in the badge once all menu items are selected.
1012
+
1013
+ ```js
1014
+ import React from 'react';
1015
+ import { Select, SelectOption, SelectGroup, SelectVariant } from '@patternfly/react-core/deprecated';
1016
+
1017
+ class FilteringCheckboxSelectInputWithBadging extends React.Component {
1018
+ constructor(props) {
1019
+ super(props);
1020
+
1021
+ this.state = {
1022
+ isOpen: false,
1023
+ selected: [],
1024
+ customBadgeText: 0
1025
+ };
1026
+
1027
+ this.options = [
1028
+ <SelectGroup label="Status" key="group1">
1029
+ <SelectOption key={0} value="Running" />
1030
+ <SelectOption key={1} value="Stopped" />
1031
+ <SelectOption key={2} value="Down" />
1032
+ <SelectOption key={3} value="Degraded" />
1033
+ <SelectOption key={4} value="Needs maintenance" />
1034
+ </SelectGroup>,
1035
+ <SelectGroup label="Vendor names" key="group2">
1036
+ <SelectOption key={5} value="Dell" />
1037
+ <SelectOption key={6} value="Samsung" isDisabled />
1038
+ <SelectOption key={7} value="Hewlett-Packard" />
1039
+ </SelectGroup>
1040
+ ];
1041
+
1042
+ this.onToggle = (_event, isOpen) => {
1043
+ this.setState({
1044
+ isOpen
1045
+ });
1046
+ };
1047
+
1048
+ this.onSelect = (event, selection) => {
1049
+ const { selected } = this.state;
1050
+ if (selected.includes(selection)) {
1051
+ this.setState(
1052
+ prevState => ({
1053
+ selected: prevState.selected.filter(item => item !== selection),
1054
+ customBadgeText: this.setBadgeText(prevState.selected.length - 1)
1055
+ }),
1056
+ () => console.log('selections: ', this.state.selected)
1057
+ );
1058
+ } else {
1059
+ this.setState(
1060
+ prevState => ({
1061
+ selected: [...prevState.selected, selection],
1062
+ customBadgeText: this.setBadgeText(prevState.selected.length + 1)
1063
+ }),
1064
+ () => console.log('selections: ', this.state.selected)
1065
+ );
1066
+ }
1067
+ };
1068
+
1069
+ this.onFilter = (_, textInput) => {
1070
+ if (textInput === '') {
1071
+ return this.options;
1072
+ } else {
1073
+ let filteredGroups = this.options
1074
+ .map(group => {
1075
+ let filteredGroup = React.cloneElement(group, {
1076
+ children: group.props.children.filter(item => {
1077
+ return item.props.value.toLowerCase().includes(textInput.toLowerCase());
1078
+ })
1079
+ });
1080
+ if (filteredGroup.props.children.length > 0) return filteredGroup;
1081
+ })
1082
+ .filter(newGroup => newGroup);
1083
+ return filteredGroups;
1084
+ }
1085
+ };
1086
+
1087
+ this.clearSelection = () => {
1088
+ this.setState({
1089
+ selected: [],
1090
+ customBadgeText: this.setBadgeText(0)
1091
+ });
1092
+ };
1093
+
1094
+ this.setBadgeText = selected => {
1095
+ if (selected === 7) {
1096
+ return 'All';
1097
+ }
1098
+ if (selected === 0) {
1099
+ return 0;
1100
+ }
1101
+ return null;
1102
+ };
1103
+ }
1104
+
1105
+ render() {
1106
+ const { isOpen, selected, filteredOptions, customBadgeText } = this.state;
1107
+ const titleId = 'checkbox-filtering-custom-badging-select-id';
1108
+ return (
1109
+ <div>
1110
+ <span id={titleId} hidden>
1111
+ Checkbox Title
1112
+ </span>
1113
+ <Select
1114
+ variant={SelectVariant.checkbox}
1115
+ onToggle={this.onToggle}
1116
+ onSelect={this.onSelect}
1117
+ selections={selected}
1118
+ isOpen={isOpen}
1119
+ placeholderText="Filter by status"
1120
+ aria-labelledby={titleId}
1121
+ onFilter={this.onFilter}
1122
+ onClear={this.clearSelection}
1123
+ isGrouped
1124
+ hasInlineFilter
1125
+ customBadgeText={customBadgeText}
1126
+ >
1127
+ {this.options}
1128
+ </Select>
1129
+ </div>
1130
+ );
1131
+ }
1132
+ }
1133
+ ```
1134
+
1135
+ ### Checkbox select without selected count
1136
+
1137
+ To remove the default item count badge, use the `isCheckboxSelectionBadgeHidden` property.
1138
+
1139
+ ```js
1140
+ import React from 'react';
1141
+ import { Select, SelectOption, SelectVariant } from '@patternfly/react-core/deprecated';
1142
+
1143
+ class CheckboxSelectInputNoBadge extends React.Component {
1144
+ constructor(props) {
1145
+ super(props);
1146
+
1147
+ this.state = {
1148
+ isOpen: false,
1149
+ selected: []
1150
+ };
1151
+
1152
+ this.onToggle = (_event, isOpen) => {
1153
+ this.setState({
1154
+ isOpen
1155
+ });
1156
+ };
1157
+
1158
+ this.onSelect = (event, selection) => {
1159
+ const { selected } = this.state;
1160
+ if (selected.includes(selection)) {
1161
+ this.setState(
1162
+ prevState => ({ selected: prevState.selected.filter(item => item !== selection) }),
1163
+ () => console.log('selections: ', this.state.selected)
1164
+ );
1165
+ } else {
1166
+ this.setState(
1167
+ prevState => ({ selected: [...prevState.selected, selection] }),
1168
+ () => console.log('selections: ', this.state.selected)
1169
+ );
1170
+ }
1171
+ };
1172
+
1173
+ this.clearSelection = () => {
1174
+ this.setState({
1175
+ selected: []
1176
+ });
1177
+ };
1178
+
1179
+ this.options = [
1180
+ <SelectOption key={0} value="Debug" />,
1181
+ <SelectOption key={1} value="Info" />,
1182
+ <SelectOption key={2} value="Warn" />,
1183
+ <SelectOption key={3} value="Error" />
1184
+ ];
1185
+ }
1186
+
1187
+ render() {
1188
+ const { isOpen, selected } = this.state;
1189
+ const titleId = 'checkbox-no-badge-select-id';
1190
+ return (
1191
+ <div>
1192
+ <span id={titleId} hidden>
1193
+ Checkbox Title
1194
+ </span>
1195
+ <Select
1196
+ variant={SelectVariant.checkbox}
1197
+ aria-label="Select Input"
1198
+ onToggle={this.onToggle}
1199
+ onSelect={this.onSelect}
1200
+ selections={selected}
1201
+ isCheckboxSelectionBadgeHidden
1202
+ isOpen={isOpen}
1203
+ placeholderText="Filter by status"
1204
+ aria-labelledby={titleId}
1205
+ >
1206
+ {this.options}
1207
+ </Select>
1208
+ </div>
1209
+ );
1210
+ }
1211
+ }
1212
+ ```
1213
+
1214
+ ### Checkbox select with item counts
1215
+
1216
+ To show users the number of items that a `<SelectOption>` would match, use the `itemCount` property. The numerical value you pass into `itemCount` is displayed to the right of each menu item.
1217
+
1218
+ ```js
1219
+ import React from 'react';
1220
+ import { Divider } from '@patternfly/react-core';
1221
+ import { Select, SelectOption, SelectVariant } from '@patternfly/react-core/deprecated';
1222
+
1223
+ class CheckboxSelectWithCounts extends React.Component {
1224
+ constructor(props) {
1225
+ super(props);
1226
+
1227
+ this.state = {
1228
+ isOpen: false,
1229
+ selected: []
1230
+ };
1231
+
1232
+ this.onToggle = (_event, isOpen) => {
1233
+ this.setState({
1234
+ isOpen
1235
+ });
1236
+ };
1237
+
1238
+ this.onSelect = (event, selection) => {
1239
+ const { selected } = this.state;
1240
+ if (selected.includes(selection)) {
1241
+ this.setState(
1242
+ prevState => ({ selected: prevState.selected.filter(item => item !== selection) }),
1243
+ () => console.log('selections: ', this.state.selected)
1244
+ );
1245
+ } else {
1246
+ this.setState(
1247
+ prevState => ({ selected: [...prevState.selected, selection] }),
1248
+ () => console.log('selections: ', this.state.selected)
1249
+ );
1250
+ }
1251
+ };
1252
+
1253
+ this.clearSelection = () => {
1254
+ this.setState({
1255
+ selected: []
1256
+ });
1257
+ };
1258
+
1259
+ this.options = [
1260
+ <SelectOption key={0} value="Active" description="This is a description" itemCount={3} />,
1261
+ <SelectOption key={1} value="Cancelled" itemCount={1} />,
1262
+ <SelectOption key={2} value="Paused" itemCount={15} />,
1263
+ <SelectOption key={3} value="Warning" itemCount={2} />,
1264
+ <SelectOption key={4} value="Restarted" itemCount={8} />
1265
+ ];
1266
+ }
1267
+
1268
+ render() {
1269
+ const { isOpen, selected } = this.state;
1270
+ const titleId = 'checkbox-select-with-counts-id';
1271
+ return (
1272
+ <div>
1273
+ <span id={titleId} hidden>
1274
+ Checkbox With Counts Title
1275
+ </span>
1276
+ <Select
1277
+ variant={SelectVariant.checkbox}
1278
+ aria-label="Select Input"
1279
+ onToggle={this.onToggle}
1280
+ onSelect={this.onSelect}
1281
+ selections={selected}
1282
+ isOpen={isOpen}
1283
+ placeholderText="Filter by status"
1284
+ aria-labelledby={titleId}
1285
+ >
1286
+ {this.options}
1287
+ </Select>
1288
+ </div>
1289
+ );
1290
+ }
1291
+ }
1292
+ ```
1293
+
1294
+ ### Checkbox select with a footer
1295
+
1296
+ You can combine a footer with checkbox input to allow users to apply an action to multiple items.
1297
+
1298
+ ```js
1299
+ import React from 'react';
1300
+ import { Button } from '@patternfly/react-core';
1301
+ import { Select, SelectOption, SelectVariant } from '@patternfly/react-core/deprecated';
1302
+
1303
+ class SelectWithFooterCheckbox extends React.Component {
1304
+ constructor(props) {
1305
+ super(props);
1306
+ this.state = {
1307
+ isOpen: false,
1308
+ selected: [],
1309
+ numOptions: 3,
1310
+ isLoading: false
1311
+ };
1312
+
1313
+ this.toggleRef = React.createRef();
1314
+
1315
+ this.options = [
1316
+ <SelectOption key={0} value="Active" description="This is a description" />,
1317
+ <SelectOption key={1} value="Cancelled" />,
1318
+ <SelectOption key={2} value="Paused" />,
1319
+ <SelectOption key={4} value="Warning" />,
1320
+ <SelectOption key={5} value="Restarted" />
1321
+ ];
1322
+
1323
+ this.onToggle = (_event, isOpen) => {
1324
+ this.setState({ isOpen });
1325
+ };
1326
+
1327
+ this.onSelect = (event, selection) => {
1328
+ this.setState({ selected: selection, isOpen: false }), console.log('selected: ', selection);
1329
+ this.toggleRef.current.focus();
1330
+ };
1331
+
1332
+ this.onFilter = (_, textInput) => {
1333
+ if (textInput === '') {
1334
+ return this.options;
1335
+ } else {
1336
+ this.setState(
1337
+ prevState => ({ selected: [...prevState.selected, selection] }),
1338
+ () => console.log('selections: ', this.state.selected)
1339
+ );
1340
+ }
1341
+ };
1342
+
1343
+ this.clearSelection = () => {
1344
+ this.setState({
1345
+ selected: []
1346
+ });
1347
+ };
1348
+ }
1349
+
1350
+ render() {
1351
+ const { isOpen, selected, isDisabled, direction, isToggleIcon } = this.state;
1352
+ const titleId = 'title-id-footer-checkbox';
1353
+ return (
1354
+ <div>
1355
+ <span id={titleId} hidden>
1356
+ Title
1357
+ </span>
1358
+ <Select
1359
+ variant={SelectVariant.single}
1360
+ toggleRef={this.toggleRef}
1361
+ onToggle={this.onToggle}
1362
+ onSelect={this.onSelect}
1363
+ selections={selected}
1364
+ isOpen={isOpen}
1365
+ placeholderText="Filter by status"
1366
+ aria-labelledby={titleId}
1367
+ footer={
1368
+ <Button variant="link" isInline>
1369
+ Action
1370
+ </Button>
1371
+ }
1372
+ >
1373
+ {this.options}
1374
+ </Select>
1375
+ </div>
1376
+ );
1377
+ }
1378
+ }
1379
+ ```
1380
+
1381
+ ### Checkbox select with view more
1382
+
1383
+ When a "view more" link is used alongside checkbox input, selections that users make prior to clicking "view more" are persisted after the click.
1384
+
1385
+ ```js
1386
+ import React from 'react';
1387
+ import { Select, SelectOption, SelectVariant } from '@patternfly/react-core/deprecated';
1388
+
1389
+ class SelectViewMoreCheckbox extends React.Component {
1390
+ constructor(props) {
1391
+ super(props);
1392
+
1393
+ this.state = {
1394
+ isOpen: false,
1395
+ selected: [],
1396
+ numOptions: 3,
1397
+ isLoading: false
1398
+ };
1399
+
1400
+ this.options = [
1401
+ <SelectOption key={0} value="Active" description="This is a description" />,
1402
+ <SelectOption key={1} value="Cancelled" />,
1403
+ <SelectOption key={2} value="Paused" />,
1404
+ <SelectOption key={4} value="Warning" />,
1405
+ <SelectOption key={5} value="Restarted" />,
1406
+ <SelectOption key={6} value="Down" />,
1407
+ <SelectOption key={7} value="Disabled" />,
1408
+ <SelectOption key={8} value="Needs maintenance " />,
1409
+ <SelectOption key={9} value="Degraded " />
1410
+ ];
1411
+
1412
+ this.onToggle = (_event, isOpen) => {
1413
+ this.setState({
1414
+ isOpen
1415
+ });
1416
+ };
1417
+
1418
+ this.onSelect = (event, selection) => {
1419
+ const { selected } = this.state;
1420
+ if (selected.includes(selection)) {
1421
+ this.setState(
1422
+ prevState => ({ selected: prevState.selected.filter(item => item !== selection) }),
1423
+ () => console.log('selections: ', this.state.selected)
1424
+ );
1425
+ } else {
1426
+ this.setState(
1427
+ prevState => ({ selected: [...prevState.selected, selection] }),
1428
+ () => console.log('selections: ', this.state.selected)
1429
+ );
1430
+ }
1431
+ };
1432
+
1433
+ this.clearSelection = () => {
1434
+ this.setState({
1435
+ selected: []
1436
+ });
1437
+ };
1438
+
1439
+ this.simulateNetworkCall = callback => {
1440
+ setTimeout(callback, 2000);
1441
+ };
1442
+
1443
+ this.onViewMoreClick = () => {
1444
+ // Set select loadingVariant to spinner then simulate network call before loading more options
1445
+ this.setState({ isLoading: true });
1446
+ this.simulateNetworkCall(() => {
1447
+ const newLength =
1448
+ this.state.numOptions + 3 <= this.options.length ? this.state.numOptions + 3 : this.options.length;
1449
+ this.setState({ numOptions: newLength, isLoading: false });
1450
+ });
1451
+ };
1452
+ }
1453
+
1454
+ render() {
1455
+ const { isOpen, selected, numOptions, isLoading } = this.state;
1456
+ const titleId = 'view-more-checkbox-select-id';
1457
+ return (
1458
+ <div>
1459
+ <span id={titleId} hidden>
1460
+ Checkbox View more check
1461
+ </span>
1462
+ <Select
1463
+ variant={SelectVariant.checkbox}
1464
+ aria-label="Select input"
1465
+ onToggle={this.onToggle}
1466
+ onSelect={this.onSelect}
1467
+ selections={selected}
1468
+ isOpen={isOpen}
1469
+ placeholderText="Filter by status"
1470
+ aria-labelledby={titleId}
1471
+ {...(!isLoading &&
1472
+ numOptions < this.options.length && {
1473
+ loadingVariant: { text: 'View more', onClick: this.onViewMoreClick }
1474
+ })}
1475
+ {...(isLoading && { loadingVariant: 'spinner' })}
1476
+ >
1477
+ {this.options.slice(0, numOptions)}
1478
+ </Select>
1479
+ </div>
1480
+ );
1481
+ }
1482
+ }
1483
+ ```
1484
+
1485
+ ### Filtering with placeholder text
1486
+
1487
+ To preload a filter search bar with placeholder text, use the `inlineFilterPlaceholderText` property. The following example preloads the search bar with "Filter by status".
1488
+
1489
+ ```js
1490
+ import React from 'react';
1491
+ import { Select, SelectOption, SelectGroup, SelectVariant } from '@patternfly/react-core/deprecated';
1492
+
1493
+ class FilteringCheckboxSelectInputWithPlaceholder extends React.Component {
1494
+ constructor(props) {
1495
+ super(props);
1496
+
1497
+ this.state = {
1498
+ isOpen: false,
1499
+ selected: []
1500
+ };
1501
+
1502
+ this.options = [
1503
+ <SelectGroup label="Status" key="group1">
1504
+ <SelectOption key={0} value="Running" />
1505
+ <SelectOption key={1} value="Stopped" />
1506
+ <SelectOption key={2} value="Down" />
1507
+ <SelectOption key={3} value="Degraded" />
1508
+ <SelectOption key={4} value="Needs maintenance" />
1509
+ </SelectGroup>,
1510
+ <SelectGroup label="Vendor names" key="group2">
1511
+ <SelectOption key={5} value="Dell" />
1512
+ <SelectOption key={6} value="Samsung" isDisabled />
1513
+ <SelectOption key={7} value="Hewlett-Packard" />
1514
+ </SelectGroup>
1515
+ ];
1516
+
1517
+ this.onToggle = (_event, isOpen) => {
1518
+ this.setState({
1519
+ isOpen
1520
+ });
1521
+ };
1522
+
1523
+ this.onSelect = (event, selection) => {
1524
+ const { selected } = this.state;
1525
+ if (selected.includes(selection)) {
1526
+ this.setState(
1527
+ prevState => ({ selected: prevState.selected.filter(item => item !== selection) }),
1528
+ () => console.log('selections: ', this.state.selected)
1529
+ );
1530
+ } else {
1531
+ this.setState(
1532
+ prevState => ({ selected: [...prevState.selected, selection] }),
1533
+ () => console.log('selections: ', this.state.selected)
1534
+ );
1535
+ }
1536
+ };
1537
+
1538
+ this.onFilter = (_, textInput) => {
1539
+ if (textInput === '') {
1540
+ return this.options;
1541
+ } else {
1542
+ let filteredGroups = this.options
1543
+ .map(group => {
1544
+ let filteredGroup = React.cloneElement(group, {
1545
+ children: group.props.children.filter(item => {
1546
+ return item.props.value.toLowerCase().includes(textInput.toLowerCase());
1547
+ })
1548
+ });
1549
+ if (filteredGroup.props.children.length > 0) return filteredGroup;
1550
+ })
1551
+ .filter(newGroup => newGroup);
1552
+ return filteredGroups;
1553
+ }
1554
+ };
1555
+
1556
+ this.clearSelection = () => {
1557
+ this.setState({
1558
+ selected: []
1559
+ });
1560
+ };
1561
+ }
1562
+
1563
+ render() {
1564
+ const { isOpen, selected, filteredOptions } = this.state;
1565
+ const titleId = 'checkbox-filtering-with-placeholder-select-id';
1566
+ return (
1567
+ <div>
1568
+ <span id={titleId} hidden>
1569
+ Checkbox Title
1570
+ </span>
1571
+ <Select
1572
+ variant={SelectVariant.checkbox}
1573
+ onToggle={this.onToggle}
1574
+ onSelect={this.onSelect}
1575
+ selections={selected}
1576
+ isOpen={isOpen}
1577
+ placeholderText="Filter by status"
1578
+ aria-labelledby={titleId}
1579
+ onFilter={this.onFilter}
1580
+ onClear={this.clearSelection}
1581
+ isGrouped
1582
+ hasInlineFilter
1583
+ inlineFilterPlaceholderText="Filter by status"
1584
+ >
1585
+ {this.options}
1586
+ </Select>
1587
+ </div>
1588
+ );
1589
+ }
1590
+ }
1591
+ ```
1592
+
1593
+ ### Inline filtering
1594
+
1595
+ To allow users to filter select lists using text input, use the `hasInlineFilter` property. Filtering behavior can be further customized with other properties, as shown in the example below. Select each checkbox to visualize the following behavior:
1596
+
1597
+ - To persist filter results on blur, use the `isInputValuePersisted` property.
1598
+ - To persist a filter that a user has searched, use the `isInputFilterPersisted` property.
1599
+ - To allow users to add new items to a select list, use the `isCreatable` property. When this property is applied and a user searches for an option that doesn't exist, they will be prompted to "create" the item.
1600
+
1601
+ ```js
1602
+ import React from 'react';
1603
+ import { Checkbox } from '@patternfly/react-core';
1604
+ import { Select, SelectOption, SelectGroup, SelectVariant } from '@patternfly/react-core/deprecated';
1605
+
1606
+ class FilteringSingleSelectInput extends React.Component {
1607
+ constructor(props) {
1608
+ super(props);
1609
+
1610
+ this.state = {
1611
+ isOpen: false,
1612
+ selected: '',
1613
+ isCreatable: false,
1614
+ isInputValuePersisted: false,
1615
+ isInputFilterPersisted: false
1616
+ };
1617
+
1618
+ this.options = [
1619
+ <SelectGroup label="Status" key="group1">
1620
+ <SelectOption key={0} value="Running" />
1621
+ <SelectOption key={1} value="Stopped" />
1622
+ <SelectOption key={2} value="Down" />
1623
+ <SelectOption key={3} value="Degraded" />
1624
+ <SelectOption key={4} value="Needs maintenance" />
1625
+ </SelectGroup>,
1626
+ <SelectGroup label="Vendor names" key="group2">
1627
+ <SelectOption key={5} value="Dell" />
1628
+ <SelectOption key={6} value="Samsung" isDisabled />
1629
+ <SelectOption key={7} value="Hewlett-Packard" />
1630
+ </SelectGroup>
1631
+ ];
1632
+
1633
+ this.onToggle = (_event, isOpen) => {
1634
+ this.setState({
1635
+ isOpen
1636
+ });
1637
+ };
1638
+
1639
+ this.onSelect = (event, selection) => {
1640
+ this.setState({ selected: selection, isOpen: false }), console.log('selected: ', selection);
1641
+ };
1642
+
1643
+ this.onFilter = (_, textInput) => {
1644
+ if (textInput === '') {
1645
+ return this.options;
1646
+ } else {
1647
+ let filteredGroups = this.options
1648
+ .map(group => {
1649
+ let filteredGroup = React.cloneElement(group, {
1650
+ children: group.props.children.filter(item => {
1651
+ return item.props.value.toLowerCase().includes(textInput.toLowerCase());
1652
+ })
1653
+ });
1654
+ if (filteredGroup.props.children.length > 0) return filteredGroup;
1655
+ })
1656
+ .filter(Boolean);
1657
+ return filteredGroups;
1658
+ }
1659
+ };
1660
+
1661
+ this.toggleCreatable = (_, checked) => {
1662
+ this.setState({
1663
+ isCreatable: checked
1664
+ });
1665
+ };
1666
+
1667
+ this.toggleInputValuePersisted = (_, checked) => {
1668
+ this.setState({
1669
+ isInputValuePersisted: checked
1670
+ });
1671
+ };
1672
+
1673
+ this.toggleInputFilterPersisted = (_, checked) => {
1674
+ this.setState({
1675
+ isInputFilterPersisted: checked
1676
+ });
1677
+ };
1678
+ }
1679
+
1680
+ render() {
1681
+ const {
1682
+ isOpen,
1683
+ selected,
1684
+ filteredOptions,
1685
+ isInputValuePersisted,
1686
+ isInputFilterPersisted,
1687
+ isCreatable
1688
+ } = this.state;
1689
+ const titleId = 'single-filtering-select-id';
1690
+ return (
1691
+ <div>
1692
+ <span id={titleId} hidden>
1693
+ Single select with filter
1694
+ </span>
1695
+ <Select
1696
+ variant={SelectVariant.single}
1697
+ onToggle={this.onToggle}
1698
+ onSelect={this.onSelect}
1699
+ selections={selected}
1700
+ isOpen={isOpen}
1701
+ placeholderText="Filter by status"
1702
+ aria-labelledby={titleId}
1703
+ onFilter={this.onFilter}
1704
+ isGrouped
1705
+ hasInlineFilter
1706
+ isCreatable={isCreatable}
1707
+ isInputValuePersisted={isInputValuePersisted}
1708
+ isInputFilterPersisted={isInputFilterPersisted}
1709
+ >
1710
+ {this.options}
1711
+ </Select>
1712
+ <Checkbox
1713
+ label="isInputValuePersisted"
1714
+ isChecked={isInputValuePersisted}
1715
+ onChange={this.toggleInputValuePersisted}
1716
+ aria-label="toggle input value persisted"
1717
+ id="toggle-inline-filter-input-value-persisted"
1718
+ name="toggle-inline-filter-input-value-persisted"
1719
+ />
1720
+ <Checkbox
1721
+ label="isInputFilterPersisted"
1722
+ isChecked={isInputFilterPersisted}
1723
+ onChange={this.toggleInputFilterPersisted}
1724
+ aria-label="toggle input filter persisted"
1725
+ id="toggle-inline-filter-input-filter-persisted"
1726
+ name="toggle-inline-filter-input-filter-persisted"
1727
+ />
1728
+ <Checkbox
1729
+ label="isCreatable"
1730
+ isChecked={this.state.isCreatable}
1731
+ onChange={this.toggleCreatable}
1732
+ aria-label="toggle creatable checkbox"
1733
+ id="toggle-inline-filter-creatable-typeahead"
1734
+ name="toggle-inline-filter-creatable-typeahead"
1735
+ />
1736
+ </div>
1737
+ );
1738
+ }
1739
+ }
1740
+ ```
1741
+
1742
+ ### Typeahead
1743
+
1744
+ 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 types in the text input, the select menu will provide suggestions by filtering the select options.
1745
+
1746
+ To make a typeahead, pass `variant=typeahead` into the `<Select>` component. To specify a label for the input field, use the `typeAheadAriaLabel` property.
1747
+
1748
+ A few additional customization options are shown in the example below. Select each checkbox to visualize the following behavior:
1749
+
1750
+ - To place a created item at the top of a typeahead list use the `isCreateOptionOnTop` property.
1751
+ - To trigger a callback for newly created items, use the `onCreateOption` property.
1752
+ - To reset the typeahead value after a user makes a selection, use the `shouldResetOnSelect` property.
1753
+
1754
+ ```js
1755
+ import React from 'react';
1756
+ import { Checkbox } from '@patternfly/react-core';
1757
+ import { Select, SelectOption, SelectVariant } from '@patternfly/react-core/deprecated';
1758
+
1759
+ class TypeaheadSelectInput extends React.Component {
1760
+ constructor(props) {
1761
+ super(props);
1762
+ this.defaultOptions = [
1763
+ { value: 'Alabama' },
1764
+ { value: 'Florida', description: 'This is a description' },
1765
+ { value: 'New Jersey' },
1766
+ { value: 'New Mexico' },
1767
+ { value: 'New York' },
1768
+ { value: 'North Carolina' }
1769
+ ];
1770
+
1771
+ this.state = {
1772
+ options: this.defaultOptions,
1773
+ isOpen: false,
1774
+ selected: null,
1775
+ isDisabled: false,
1776
+ isCreatable: false,
1777
+ isCreateOptionOnTop: false,
1778
+ isInputValuePersisted: false,
1779
+ isInputFilterPersisted: false,
1780
+ hasOnCreateOption: false,
1781
+ resetOnSelect: true
1782
+ };
1783
+
1784
+ this.onToggle = (_event, isOpen) => {
1785
+ this.setState({
1786
+ isOpen
1787
+ });
1788
+ };
1789
+
1790
+ this.onSelect = (event, selection, isPlaceholder) => {
1791
+ if (isPlaceholder) this.clearSelection();
1792
+ else {
1793
+ this.setState({
1794
+ selected: selection,
1795
+ isOpen: this.state.resetOnSelect ? false : this.state.isOpen
1796
+ });
1797
+ console.log('selected:', selection);
1798
+ }
1799
+ };
1800
+
1801
+ this.onCreateOption = newValue => {
1802
+ this.setState({
1803
+ options: [...this.state.options, { value: newValue }]
1804
+ });
1805
+ };
1806
+
1807
+ this.clearSelection = () => {
1808
+ this.setState({
1809
+ selected: null,
1810
+ isOpen: false,
1811
+ options: this.defaultOptions
1812
+ });
1813
+ };
1814
+
1815
+ this.toggleDisabled = checked => {
1816
+ this.setState({
1817
+ isDisabled: checked
1818
+ });
1819
+ };
1820
+
1821
+ this.toggleCreatable = checked => {
1822
+ this.setState({
1823
+ isCreatable: checked
1824
+ });
1825
+ };
1826
+
1827
+ this.toggleCreateOptionOnTop = checked => {
1828
+ this.setState({
1829
+ isCreateOptionOnTop: checked
1830
+ });
1831
+ };
1832
+
1833
+ this.toggleCreateNew = checked => {
1834
+ this.setState({
1835
+ hasOnCreateOption: checked
1836
+ });
1837
+ };
1838
+
1839
+ this.toggleInputValuePersisted = checked => {
1840
+ this.setState({
1841
+ isInputValuePersisted: checked
1842
+ });
1843
+ };
1844
+
1845
+ this.toggleInputFilterPersisted = checked => {
1846
+ this.setState({
1847
+ isInputFilterPersisted: checked
1848
+ });
1849
+ };
1850
+
1851
+ this.toggleResetOnSelect = checked => {
1852
+ this.setState({
1853
+ resetOnSelect: checked
1854
+ });
1855
+ };
1856
+ }
1857
+
1858
+ render() {
1859
+ const {
1860
+ isOpen,
1861
+ selected,
1862
+ isDisabled,
1863
+ isCreatable,
1864
+ isCreateOptionOnTop,
1865
+ hasOnCreateOption,
1866
+ isInputValuePersisted,
1867
+ isInputFilterPersisted,
1868
+ resetOnSelect,
1869
+ options
1870
+ } = this.state;
1871
+ const titleId = 'typeahead-select-id-1';
1872
+ return (
1873
+ <div>
1874
+ <span id={titleId} hidden>
1875
+ Select a state
1876
+ </span>
1877
+ <Select
1878
+ variant={SelectVariant.typeahead}
1879
+ typeAheadAriaLabel="Select a state"
1880
+ onToggle={this.onToggle}
1881
+ onSelect={this.onSelect}
1882
+ onClear={this.clearSelection}
1883
+ selections={selected}
1884
+ isOpen={isOpen}
1885
+ aria-labelledby={titleId}
1886
+ isInputValuePersisted={isInputValuePersisted}
1887
+ isInputFilterPersisted={isInputFilterPersisted}
1888
+ placeholderText="Select a state"
1889
+ isDisabled={isDisabled}
1890
+ isCreatable={isCreatable}
1891
+ isCreateOptionOnTop={isCreateOptionOnTop}
1892
+ onCreateOption={(hasOnCreateOption && this.onCreateOption) || undefined}
1893
+ shouldResetOnSelect={resetOnSelect}
1894
+ >
1895
+ {options.map((option, index) => (
1896
+ <SelectOption
1897
+ isDisabled={option.disabled}
1898
+ key={index}
1899
+ value={option.value}
1900
+ {...(option.description && { description: option.description })}
1901
+ />
1902
+ ))}
1903
+ </Select>
1904
+ <Checkbox
1905
+ label="isDisabled"
1906
+ isChecked={this.state.isDisabled}
1907
+ onChange={(_event, checked) => this.toggleDisabled(checked)}
1908
+ aria-label="toggle disabled checkbox"
1909
+ id="toggle-disabled-typeahead"
1910
+ name="toggle-disabled-typeahead"
1911
+ />
1912
+ <Checkbox
1913
+ label="isCreatable"
1914
+ isChecked={this.state.isCreatable}
1915
+ onChange={(_event, checked) => this.toggleCreatable(checked)}
1916
+ aria-label="toggle creatable checkbox"
1917
+ id="toggle-creatable-typeahead"
1918
+ name="toggle-creatable-typeahead"
1919
+ />
1920
+ <Checkbox
1921
+ label="isCreateOptionOnTop"
1922
+ isChecked={this.state.isCreateOptionOnTop}
1923
+ onChange={(_event, checked) => this.toggleCreateOptionOnTop(checked)}
1924
+ aria-label="toggle createOptionOnTop checkbox"
1925
+ id="toggle-create-option-on-top-typeahead"
1926
+ name="toggle-create-option-on-top-typeahead"
1927
+ />
1928
+ <Checkbox
1929
+ label="onCreateOption"
1930
+ isChecked={this.state.hasOnCreateOption}
1931
+ onChange={(_event, checked) => this.toggleCreateNew(checked)}
1932
+ aria-label="toggle new checkbox"
1933
+ id="toggle-new-typeahead"
1934
+ name="toggle-new-typeahead"
1935
+ />
1936
+ <Checkbox
1937
+ label="isInputValuePersisted"
1938
+ isChecked={isInputValuePersisted}
1939
+ onChange={(_event, checked) => this.toggleInputValuePersisted(checked)}
1940
+ aria-label="toggle input value persisted"
1941
+ id="toggle-input-value-persisted"
1942
+ name="toggle-input-value-persisted"
1943
+ />
1944
+ <Checkbox
1945
+ label="isInputFilterPersisted"
1946
+ isChecked={isInputFilterPersisted}
1947
+ onChange={(_event, checked) => this.toggleInputFilterPersisted(checked)}
1948
+ aria-label="toggle input filter persisted"
1949
+ id="toggle-input-filter-persisted"
1950
+ name="toggle-input-filter-persisted"
1951
+ />
1952
+ <Checkbox
1953
+ label="shouldResetOnSelect"
1954
+ isChecked={this.state.resetOnSelect}
1955
+ onChange={(_event, checked) => this.toggleResetOnSelect(checked)}
1956
+ aria-label="toggle reset checkbox"
1957
+ id="toggle-reset-typeahead"
1958
+ name="toggle-reset-typeahead"
1959
+ />
1960
+ </div>
1961
+ );
1962
+ }
1963
+ }
1964
+ ```
1965
+
1966
+ ### Grouped typeahead
1967
+
1968
+ Typeahead matches items with user input across groups.
1969
+
1970
+ ```js
1971
+ import React from 'react';
1972
+ import { Checkbox, Divider } from '@patternfly/react-core';
1973
+ import { Select, SelectGroup, SelectOption, SelectVariant } from '@patternfly/react-core/deprecated';
1974
+
1975
+ class GroupedTypeaheadSelectInput extends React.Component {
1976
+ constructor(props) {
1977
+ super(props);
1978
+
1979
+ this.state = {
1980
+ options: [
1981
+ <SelectGroup label="Status" key="group1">
1982
+ <SelectOption key={0} value="Running" />
1983
+ <SelectOption key={1} value="Stopped" />
1984
+ <SelectOption key={2} value="Down" />
1985
+ <SelectOption key={3} value="Degraded" />
1986
+ <SelectOption key={4} value="Needs maintenance" />
1987
+ </SelectGroup>,
1988
+ <Divider key="divider" />,
1989
+ <SelectGroup label="Vendor names" key="group2">
1990
+ <SelectOption key={5} value="Dell" />
1991
+ <SelectOption key={6} value="Samsung" isDisabled />
1992
+ <SelectOption key={7} value="Hewlett-Packard" />
1993
+ </SelectGroup>
1994
+ ],
1995
+ newOptions: [],
1996
+ isOpen: false,
1997
+ selected: null,
1998
+ isCreatable: false,
1999
+ hasOnCreateOption: false
2000
+ };
2001
+
2002
+ this.onToggle = (_event, isOpen) => {
2003
+ this.setState({
2004
+ isOpen
2005
+ });
2006
+ };
2007
+
2008
+ this.onSelect = (event, selection, isPlaceholder) => {
2009
+ if (isPlaceholder) this.clearSelection();
2010
+ else {
2011
+ this.setState({
2012
+ selected: selection,
2013
+ isOpen: false
2014
+ });
2015
+ console.log('selected:', selection);
2016
+ }
2017
+ };
2018
+
2019
+ this.onCreateOption = newValue => {
2020
+ this.setState({
2021
+ newOptions: [...this.state.newOptions, <SelectOption key={newValue} value={newValue} />]
2022
+ });
2023
+ };
2024
+
2025
+ this.clearSelection = () => {
2026
+ this.setState({
2027
+ selected: null,
2028
+ isOpen: false
2029
+ });
2030
+ };
2031
+
2032
+ this.toggleCreatable = checked => {
2033
+ this.setState({
2034
+ isCreatable: checked
2035
+ });
2036
+ };
2037
+
2038
+ this.toggleCreateNew = checked => {
2039
+ this.setState({
2040
+ hasOnCreateOption: checked
2041
+ });
2042
+ };
2043
+ }
2044
+
2045
+ render() {
2046
+ const { isOpen, selected, isDisabled, isCreatable, hasOnCreateOption, options, newOptions } = this.state;
2047
+ const titleId = 'grouped-typeahead-select-id';
2048
+ const allOptions =
2049
+ newOptions.length > 0
2050
+ ? options.concat(
2051
+ <SelectGroup label="Created" key="create-group">
2052
+ {newOptions}
2053
+ </SelectGroup>
2054
+ )
2055
+ : options;
2056
+ return (
2057
+ <div>
2058
+ <span id={titleId} hidden>
2059
+ Select a state
2060
+ </span>
2061
+ <Select
2062
+ variant={SelectVariant.typeahead}
2063
+ typeAheadAriaLabel="Select a state"
2064
+ onToggle={this.onToggle}
2065
+ onSelect={this.onSelect}
2066
+ onClear={this.clearSelection}
2067
+ selections={selected}
2068
+ isOpen={isOpen}
2069
+ aria-labelledby={titleId}
2070
+ placeholderText="Select a state"
2071
+ isGrouped
2072
+ isCreatable={isCreatable}
2073
+ onCreateOption={(hasOnCreateOption && this.onCreateOption) || undefined}
2074
+ >
2075
+ {allOptions}
2076
+ </Select>
2077
+ <Checkbox
2078
+ label="isCreatable"
2079
+ isChecked={this.state.isCreatable}
2080
+ onChange={(_event, checked) => this.toggleCreatable(checked)}
2081
+ aria-label="toggle creatable checkbox"
2082
+ id="toggle-creatable-grouped-typeahead"
2083
+ name="toggle-creatable-grouped-typeahead"
2084
+ />
2085
+ <Checkbox
2086
+ label="onCreateOption"
2087
+ isChecked={this.state.hasOnCreateOption}
2088
+ onChange={(_event, checked) => this.toggleCreateNew(checked)}
2089
+ aria-label="toggle new checkbox"
2090
+ id="toggle-new-grouped-typeahead"
2091
+ name="toggle-new-grouped-typeahead"
2092
+ />
2093
+ </div>
2094
+ );
2095
+ }
2096
+ }
2097
+ ```
2098
+
2099
+ ### Typeahead with custom filtering
2100
+
2101
+ You can add custom filtering to a select list to better fit needs that aren't covered by inline filtering. If you use custom filtering, use the `onFilter` property to trigger a callback with your custom filter implementation.
2102
+
2103
+ ```js
2104
+ import React from 'react';
2105
+ import { Select, SelectOption, SelectVariant } from '@patternfly/react-core/deprecated';
2106
+
2107
+ class TypeaheadSelectInput extends React.Component {
2108
+ constructor(props) {
2109
+ super(props);
2110
+ this.options = [
2111
+ <SelectOption key={0} value="Alabama" />,
2112
+ <SelectOption key={1} value="Florida" />,
2113
+ <SelectOption key={2} value="New Jersey" />,
2114
+ <SelectOption key={3} value="New Mexico" />,
2115
+ <SelectOption key={4} value="New York" />,
2116
+ <SelectOption key={5} value="North Carolina" />
2117
+ ];
2118
+ this.state = {
2119
+ isOpen: false,
2120
+ selected: null
2121
+ };
2122
+
2123
+ this.onToggle = (_event, isOpen) => {
2124
+ this.setState({
2125
+ isOpen
2126
+ });
2127
+ };
2128
+
2129
+ this.onSelect = (event, selection, isPlaceholder) => {
2130
+ if (isPlaceholder) this.clearSelection();
2131
+ else {
2132
+ this.setState({
2133
+ selected: selection,
2134
+ isOpen: false
2135
+ });
2136
+ console.log('selected:', selection);
2137
+ }
2138
+ };
2139
+
2140
+ this.clearSelection = () => {
2141
+ this.setState({
2142
+ selected: null,
2143
+ isOpen: false
2144
+ });
2145
+ };
2146
+
2147
+ this.customFilter = (_, value) => {
2148
+ if (!value) {
2149
+ return this.options;
2150
+ }
2151
+
2152
+ const input = new RegExp(value, 'i');
2153
+ return this.options.filter(child => input.test(child.props.value));
2154
+ };
2155
+ }
2156
+
2157
+ render() {
2158
+ const { isOpen, selected } = this.state;
2159
+ const titleId = 'typeahead-select-id-2';
2160
+ return (
2161
+ <div>
2162
+ <span id={titleId} hidden>
2163
+ Select a state
2164
+ </span>
2165
+ <Select
2166
+ variant={SelectVariant.typeahead}
2167
+ typeAheadAriaLabel="Select a state"
2168
+ onToggle={this.onToggle}
2169
+ onSelect={this.onSelect}
2170
+ onClear={this.clearSelection}
2171
+ onFilter={this.customFilter}
2172
+ selections={selected}
2173
+ isOpen={isOpen}
2174
+ aria-labelledby={titleId}
2175
+ placeholderText="Select a state"
2176
+ >
2177
+ {this.options}
2178
+ </Select>
2179
+ </div>
2180
+ );
2181
+ }
2182
+ }
2183
+ ```
2184
+
2185
+ ### Multiple typeahead
2186
+
2187
+ To create a multiple typeahead select variant, pass `variant={SelectVariant.typeaheadMulti}` into the `<Select>` component. Multiple typeaheads let users select multiple items from a select list. Selected items appear as chips in the select toggle.
2188
+
2189
+ When many items are selected, you can hide overflowing items under a "more" button. The following example hides items after more than 3 are selected. To show hidden items, select the “more” button. Click "show less" to hide extra items again.
2190
+
2191
+ ```js
2192
+ import React from 'react';
2193
+ import { Checkbox } from '@patternfly/react-core';
2194
+ import { Select, SelectOption, SelectVariant } from '@patternfly/react-core/deprecated';
2195
+
2196
+ class MultiTypeaheadSelectInput extends React.Component {
2197
+ constructor(props) {
2198
+ super(props);
2199
+
2200
+ this.state = {
2201
+ options: [
2202
+ { value: 'Alabama', disabled: false },
2203
+ { value: 'Florida', disabled: false },
2204
+ { value: 'New Jersey', disabled: false },
2205
+ { value: 'New Mexico', disabled: false, description: 'This is a description' },
2206
+ { value: 'New York', disabled: false },
2207
+ { value: 'North Carolina', disabled: false }
2208
+ ],
2209
+ isOpen: false,
2210
+ selected: [],
2211
+ isCreatable: false,
2212
+ hasOnCreateOption: false,
2213
+ hasDisabledOption: false,
2214
+ resetOnSelect: true
2215
+ };
2216
+
2217
+ this.onCreateOption = newValue => {
2218
+ this.setState({
2219
+ options: [...this.state.options, { value: newValue }]
2220
+ });
2221
+ };
2222
+
2223
+ this.onToggle = (_event, isOpen) => {
2224
+ this.setState({
2225
+ isOpen
2226
+ });
2227
+ };
2228
+
2229
+ this.onSelect = (event, selection) => {
2230
+ const { selected } = this.state;
2231
+ if (selected.includes(selection)) {
2232
+ this.setState(
2233
+ prevState => ({ selected: prevState.selected.filter(item => item !== selection) }),
2234
+ () => console.log('selections: ', this.state.selected)
2235
+ );
2236
+ } else {
2237
+ this.setState(
2238
+ prevState => ({ selected: [...prevState.selected, selection] }),
2239
+ () => console.log('selections: ', this.state.selected)
2240
+ );
2241
+ }
2242
+ };
2243
+
2244
+ this.clearSelection = () => {
2245
+ this.setState({
2246
+ selected: [],
2247
+ isOpen: false
2248
+ });
2249
+ };
2250
+
2251
+ this.toggleCreatable = checked => {
2252
+ this.setState({
2253
+ isCreatable: checked
2254
+ });
2255
+ };
2256
+
2257
+ this.toggleCreateNew = checked => {
2258
+ this.setState({
2259
+ hasOnCreateOption: checked
2260
+ });
2261
+ };
2262
+
2263
+ this.toggleOptionDisabled = toggleIndex => () => {
2264
+ this.setState(prevState => ({
2265
+ hasDisabledOption: !prevState.hasDisabledOption,
2266
+ options: prevState.options.map((option, index) =>
2267
+ index === toggleIndex ? { ...option, disabled: !option.disabled } : option
2268
+ )
2269
+ }));
2270
+ };
2271
+
2272
+ this.toggleResetOnSelect = checked => {
2273
+ this.setState({
2274
+ resetOnSelect: checked
2275
+ });
2276
+ };
2277
+ }
2278
+
2279
+ render() {
2280
+ const { isOpen, selected, isCreatable, hasOnCreateOption, resetOnSelect, options } = this.state;
2281
+ const titleId = 'multi-typeahead-select-id-1';
2282
+
2283
+ return (
2284
+ <div>
2285
+ <span id={titleId} hidden>
2286
+ Select a state
2287
+ </span>
2288
+ <Select
2289
+ variant={SelectVariant.typeaheadMulti}
2290
+ typeAheadAriaLabel="Select a state"
2291
+ onToggle={this.onToggle}
2292
+ onSelect={this.onSelect}
2293
+ onClear={this.clearSelection}
2294
+ selections={selected}
2295
+ isOpen={isOpen}
2296
+ aria-labelledby={titleId}
2297
+ placeholderText="Select a state"
2298
+ isCreatable={isCreatable}
2299
+ onCreateOption={(hasOnCreateOption && this.onCreateOption) || undefined}
2300
+ shouldResetOnSelect={resetOnSelect}
2301
+ >
2302
+ {options.map((option, index) => (
2303
+ <SelectOption
2304
+ isDisabled={option.disabled}
2305
+ key={index}
2306
+ value={option.value}
2307
+ {...(option.description && { description: option.description })}
2308
+ />
2309
+ ))}
2310
+ </Select>
2311
+ <Checkbox
2312
+ label="isCreatable"
2313
+ isChecked={this.state.isCreatable}
2314
+ onChange={(_event, checked) => this.toggleCreatable(checked)}
2315
+ aria-label="toggle creatable checkbox"
2316
+ id="toggle-creatable-typeahead-multi"
2317
+ name="toggle-creatable-typeahead-multi"
2318
+ />
2319
+ <Checkbox
2320
+ label="onCreateOption"
2321
+ isChecked={this.state.hasOnCreateOption}
2322
+ onChange={(_event, checked) => this.toggleCreateNew(checked)}
2323
+ aria-label="toggle new checkbox"
2324
+ id="toggle-new-typeahead-multi"
2325
+ name="toggle-new-typeahead-multi"
2326
+ />
2327
+ <Checkbox
2328
+ label="isDisabled (1st option only)"
2329
+ isChecked={this.state.hasDisabledOption}
2330
+ onChange={this.toggleOptionDisabled(0)}
2331
+ aria-label="toggle disable first option"
2332
+ id="toggle-disable-first-option"
2333
+ name="toggle-disable-first-option"
2334
+ />
2335
+ <Checkbox
2336
+ label="shouldResetOnSelect"
2337
+ isChecked={this.state.resetOnSelect}
2338
+ onChange={(_event, checked) => this.toggleResetOnSelect(checked)}
2339
+ aria-label="toggle multi reset checkbox"
2340
+ id="toggle-reset-multi-typeahead"
2341
+ name="toggle-reset-multi-typeahead"
2342
+ />
2343
+ </div>
2344
+ );
2345
+ }
2346
+ }
2347
+ ```
2348
+
2349
+ ### Multiple typeahead with custom chips
2350
+
2351
+ To customize the appearance of chips, use the `chipGroupProps` property. The `numChips` property allows you to control the number of items shown, while the `expandedText` and `collapsedText` properties allow you to control the labels of the expansion and collapse chips.
2352
+
2353
+ ```js
2354
+ import React from 'react';
2355
+ import { Select, SelectOption, SelectVariant } from '@patternfly/react-core/deprecated';
2356
+
2357
+ class MultiTypeaheadSelectInputWithChipGroupProps extends React.Component {
2358
+ constructor(props) {
2359
+ super(props);
2360
+
2361
+ this.state = {
2362
+ options: [
2363
+ { value: 'Alabama', disabled: false },
2364
+ { value: 'Florida', disabled: false },
2365
+ { value: 'New Jersey', disabled: false },
2366
+ { value: 'New Mexico', disabled: false, description: 'This is a description' },
2367
+ { value: 'New York', disabled: false },
2368
+ { value: 'North Carolina', disabled: false }
2369
+ ],
2370
+ isOpen: false,
2371
+ selected: []
2372
+ };
2373
+
2374
+ this.onToggle = (_event, isOpen) => {
2375
+ this.setState({
2376
+ isOpen
2377
+ });
2378
+ };
2379
+
2380
+ this.onSelect = (event, selection) => {
2381
+ const { selected } = this.state;
2382
+ if (selected.includes(selection)) {
2383
+ this.setState(
2384
+ prevState => ({ selected: prevState.selected.filter(item => item !== selection) }),
2385
+ () => console.log('selections: ', this.state.selected)
2386
+ );
2387
+ } else {
2388
+ this.setState(
2389
+ prevState => ({ selected: [...prevState.selected, selection] }),
2390
+ () => console.log('selections: ', this.state.selected)
2391
+ );
2392
+ }
2393
+ };
2394
+
2395
+ this.clearSelection = () => {
2396
+ this.setState({
2397
+ selected: [],
2398
+ isOpen: false
2399
+ });
2400
+ };
2401
+ }
2402
+
2403
+ render() {
2404
+ const { isOpen, selected, isCreatable, hasOnCreateOption } = this.state;
2405
+ const titleId = 'multi-typeahead-custom-chip-group-props-id-1';
2406
+
2407
+ return (
2408
+ <div>
2409
+ <span id={titleId} hidden>
2410
+ Select a state
2411
+ </span>
2412
+ <Select
2413
+ chipGroupProps={{ numChips: 1, expandedText: 'Hide', collapsedText: 'Show ${remaining}' }}
2414
+ variant={SelectVariant.typeaheadMulti}
2415
+ typeAheadAriaLabel="Select a state"
2416
+ onToggle={this.onToggle}
2417
+ onSelect={this.onSelect}
2418
+ onClear={this.clearSelection}
2419
+ selections={selected}
2420
+ isOpen={isOpen}
2421
+ aria-labelledby={titleId}
2422
+ placeholderText="Select a state"
2423
+ >
2424
+ {this.state.options.map((option, index) => (
2425
+ <SelectOption
2426
+ isDisabled={option.disabled}
2427
+ key={index}
2428
+ value={option.value}
2429
+ {...(option.description && { description: option.description })}
2430
+ />
2431
+ ))}
2432
+ </Select>
2433
+ </div>
2434
+ );
2435
+ }
2436
+ }
2437
+ ```
2438
+
2439
+ ### Multiple typeahead with chip group
2440
+
2441
+ To customize chips even more, render a [`<ChipGroup>`](/components/chip-group) component and pass it into the `chipGroupComponent` property of the `<Select>` component.
2442
+
2443
+ ```js
2444
+ import React from 'react';
2445
+ import { ChipGroup, Chip } from '@patternfly/react-core';
2446
+ import { Select, SelectOption, SelectVariant } from '@patternfly/react-core/deprecated';
2447
+
2448
+ class MultiTypeaheadSelectInputWithChipGroupProps extends React.Component {
2449
+ constructor(props) {
2450
+ super(props);
2451
+
2452
+ this.state = {
2453
+ options: [
2454
+ { value: 'Alabama', disabled: false },
2455
+ { value: 'Florida', disabled: false },
2456
+ { value: 'New Jersey', disabled: false },
2457
+ { value: 'New Mexico', disabled: false, description: 'This is a description' },
2458
+ { value: 'New York', disabled: false },
2459
+ { value: 'North Carolina', disabled: false }
2460
+ ],
2461
+ isOpen: false,
2462
+ selected: []
2463
+ };
2464
+
2465
+ this.onToggle = (_event, isOpen) => {
2466
+ this.setState({
2467
+ isOpen
2468
+ });
2469
+ };
2470
+
2471
+ this.onSelect = (event, selection) => {
2472
+ const { selected } = this.state;
2473
+ if (selected.includes(selection)) {
2474
+ this.setState(
2475
+ prevState => ({ selected: prevState.selected.filter(item => item !== selection) }),
2476
+ () => console.log('selections: ', this.state.selected)
2477
+ );
2478
+ } else {
2479
+ this.setState(
2480
+ prevState => ({ selected: [...prevState.selected, selection] }),
2481
+ () => console.log('selections: ', this.state.selected)
2482
+ );
2483
+ }
2484
+ };
2485
+
2486
+ this.clearSelection = () => {
2487
+ this.setState({
2488
+ selected: [],
2489
+ isOpen: false
2490
+ });
2491
+ };
2492
+ this.chipGroupComponent = () => {
2493
+ const { selected } = this.state;
2494
+ return (
2495
+ <ChipGroup>
2496
+ {(selected || []).map((currentChip, index) => (
2497
+ <Chip
2498
+ isReadOnly={index === 0 ? true : false}
2499
+ key={currentChip}
2500
+ onClick={event => this.onSelect(event, currentChip)}
2501
+ >
2502
+ {currentChip}
2503
+ </Chip>
2504
+ ))}
2505
+ </ChipGroup>
2506
+ );
2507
+ };
2508
+ }
2509
+
2510
+ render() {
2511
+ const { isOpen, selected, isCreatable, hasOnCreateOption } = this.state;
2512
+ const titleId = 'multi-typeahead-render-chip-group-props-id-1';
2513
+
2514
+ return (
2515
+ <div>
2516
+ <span id={titleId} hidden>
2517
+ Select a state
2518
+ </span>
2519
+ <Select
2520
+ chipGroupProps={{ numChips: 1, expandedText: 'Hide', collapsedText: 'Show ${remaining}' }}
2521
+ variant={SelectVariant.typeaheadMulti}
2522
+ typeAheadAriaLabel="Select a state"
2523
+ onToggle={this.onToggle}
2524
+ onSelect={this.onSelect}
2525
+ onClear={this.clearSelection}
2526
+ selections={selected}
2527
+ isOpen={isOpen}
2528
+ aria-labelledby={titleId}
2529
+ placeholderText="Select a state"
2530
+ chipGroupComponent={this.chipGroupComponent()}
2531
+ >
2532
+ {this.state.options.map((option, index) => (
2533
+ <SelectOption
2534
+ isDisabled={option.disabled}
2535
+ key={index}
2536
+ value={option.value}
2537
+ {...(option.description && { description: option.description })}
2538
+ />
2539
+ ))}
2540
+ </Select>
2541
+ </div>
2542
+ );
2543
+ }
2544
+ }
2545
+ ```
2546
+
2547
+ ### Multiple typeahead with custom objects
2548
+
2549
+ A `<SelectOption>` can have an object passed into the `value` property in order to store additional data beyond just a string value. The object passed in must have a `toString` function that returns a string to display in the `SelectMenu`.
2550
+
2551
+ ```js
2552
+ import React from 'react';
2553
+ import { Divider } from '@patternfly/react-core';
2554
+ import { Select, SelectOption, SelectVariant } from '@patternfly/react-core/deprecated';
2555
+
2556
+ class MultiTypeaheadSelectInputCustomObjects extends React.Component {
2557
+ constructor(props) {
2558
+ super(props);
2559
+ this.createState = (name, abbreviation, capital, founded) => {
2560
+ return {
2561
+ name: name,
2562
+ abbreviation: abbreviation,
2563
+ capital: capital,
2564
+ founded: founded,
2565
+ toString: function() {
2566
+ return `${this.name} (${this.abbreviation}) - Founded: ${this.founded}`;
2567
+ },
2568
+ compareTo: function(value) {
2569
+ return this.toString()
2570
+ .toLowerCase()
2571
+ .includes(value.toString().toLowerCase());
2572
+ }
2573
+ };
2574
+ };
2575
+ this.options = [
2576
+ <SelectOption key={0} value={this.createState('Alabama', 'AL', 'Montgomery', 1846)} />,
2577
+ <Divider component="li" key={111} />,
2578
+ <SelectOption key={1} value={this.createState('Florida', 'FL', 'Tailahassee', 1845)} />,
2579
+ <SelectOption key={2} value={this.createState('New Jersey', 'NJ', 'Trenton', 1787)} />,
2580
+ <SelectOption key={3} value={this.createState('New Mexico', 'NM', 'Santa Fe', 1912)} />,
2581
+ <SelectOption key={4} value={this.createState('New York', 'NY', 'Albany', 1788)} />,
2582
+ <SelectOption key={5} value={this.createState('North Carolina', 'NC', 'Raleigh', 1789)} />
2583
+ ];
2584
+
2585
+ this.state = {
2586
+ isOpen: false,
2587
+ selected: []
2588
+ };
2589
+
2590
+ this.onToggle = (_event, isOpen) => {
2591
+ this.setState({
2592
+ isOpen
2593
+ });
2594
+ };
2595
+
2596
+ this.onSelect = (event, selection) => {
2597
+ const { selected } = this.state;
2598
+ if (selected.includes(selection)) {
2599
+ this.setState(
2600
+ prevState => ({ selected: prevState.selected.filter(item => item !== selection) }),
2601
+ () => console.log('selections: ', this.state.selected)
2602
+ );
2603
+ } else {
2604
+ this.setState(
2605
+ prevState => ({ selected: [...prevState.selected, selection] }),
2606
+ () => console.log('selections: ', this.state.selected)
2607
+ );
2608
+ }
2609
+ };
2610
+
2611
+ this.clearSelection = () => {
2612
+ this.setState({
2613
+ selected: [],
2614
+ isOpen: false
2615
+ });
2616
+ };
2617
+ }
2618
+
2619
+ render() {
2620
+ const { isOpen, selected } = this.state;
2621
+ const titleId = 'multi-typeahead-select-id-2';
2622
+
2623
+ return (
2624
+ <div>
2625
+ <span id={titleId} hidden>
2626
+ Select a state
2627
+ </span>
2628
+ <Select
2629
+ variant={SelectVariant.typeaheadMulti}
2630
+ typeAheadAriaLabel="Select a state"
2631
+ onToggle={this.onToggle}
2632
+ onSelect={this.onSelect}
2633
+ onClear={this.clearSelection}
2634
+ onFilter={this.customFilter}
2635
+ selections={selected}
2636
+ isOpen={isOpen}
2637
+ aria-labelledby={titleId}
2638
+ placeholderText="Select a state"
2639
+ >
2640
+ {this.options}
2641
+ </Select>
2642
+ </div>
2643
+ );
2644
+ }
2645
+ }
2646
+ ```
2647
+
2648
+ ### Plain multiple typeahead
2649
+
2650
+ To plainly style a typeahead, use the `isPlain` property.
2651
+
2652
+ ```js
2653
+ import React from 'react';
2654
+ import { Select, SelectOption, SelectVariant } from '@patternfly/react-core/deprecated';
2655
+
2656
+ class PlainSelectInput extends React.Component {
2657
+ constructor(props) {
2658
+ super(props);
2659
+ this.options = [
2660
+ { value: 'Alabama', disabled: false },
2661
+ { value: 'Florida', disabled: false },
2662
+ { value: 'New Jersey', disabled: false },
2663
+ { value: 'New Mexico', disabled: false },
2664
+ { value: 'New York', disabled: false },
2665
+ { value: 'North Carolina', disabled: false }
2666
+ ];
2667
+
2668
+ this.state = {
2669
+ isOpen: false,
2670
+ isPlain: true,
2671
+ selected: []
2672
+ };
2673
+
2674
+ this.onToggle = (_event, isOpen) => {
2675
+ this.setState({
2676
+ isOpen
2677
+ });
2678
+ };
2679
+
2680
+ this.onSelect = (event, selection) => {
2681
+ const { selected } = this.state;
2682
+ if (selected.includes(selection)) {
2683
+ this.setState(
2684
+ prevState => ({ selected: prevState.selected.filter(item => item !== selection) }),
2685
+ () => console.log('selections: ', this.state.selected)
2686
+ );
2687
+ } else {
2688
+ this.setState(
2689
+ prevState => ({ selected: [...prevState.selected, selection] }),
2690
+ () => console.log('selections: ', this.state.selected)
2691
+ );
2692
+ }
2693
+ };
2694
+
2695
+ this.clearSelection = () => {
2696
+ this.setState({
2697
+ selected: [],
2698
+ isOpen: false
2699
+ });
2700
+ };
2701
+ }
2702
+
2703
+ render() {
2704
+ const { isOpen, isPlain, selected } = this.state;
2705
+ const titleId = 'plain-typeahead-select-id';
2706
+
2707
+ return (
2708
+ <div>
2709
+ <span id={titleId} hidden>
2710
+ Select a state
2711
+ </span>
2712
+ <Select
2713
+ variant={SelectVariant.typeaheadMulti}
2714
+ typeAheadAriaLabel="Select a state"
2715
+ onToggle={this.onToggle}
2716
+ onSelect={this.onSelect}
2717
+ onClear={this.clearSelection}
2718
+ selections={selected}
2719
+ isOpen={isOpen}
2720
+ isPlain={isPlain}
2721
+ aria-labelledby={titleId}
2722
+ placeholderText="Select a state"
2723
+ >
2724
+ {this.options.map((option, index) => (
2725
+ <SelectOption isDisabled={option.disabled} key={index} value={option.value} />
2726
+ ))}
2727
+ </Select>
2728
+ </div>
2729
+ );
2730
+ }
2731
+ }
2732
+ ```
2733
+
2734
+ ### Custom menu content
2735
+
2736
+ To add custom menu content, use the `customContent` property.
2737
+
2738
+ ```js
2739
+ import React from 'react';
2740
+ import CubeIcon from '@patternfly/react-icons/dist/esm/icons/cube-icon';
2741
+ import { Checkbox } from '@patternfly/react-core';
2742
+ import { Select, SelectOption, SelectDirection } from '@patternfly/react-core/deprecated';
2743
+
2744
+ class SingleSelectInput extends React.Component {
2745
+ constructor(props) {
2746
+ super(props);
2747
+ this.state = {
2748
+ isOpen: false,
2749
+ isDisabled: false,
2750
+ direction: SelectDirection.down
2751
+ };
2752
+
2753
+ this.onToggle = (_event, isOpen) => {
2754
+ this.setState({
2755
+ isOpen
2756
+ });
2757
+ };
2758
+
2759
+ this.toggleDisabled = checked => {
2760
+ this.setState({
2761
+ isDisabled: checked
2762
+ });
2763
+ };
2764
+
2765
+ this.toggleDirection = () => {
2766
+ if (this.state.direction === SelectDirection.up) {
2767
+ this.setState({
2768
+ direction: SelectDirection.down
2769
+ });
2770
+ } else {
2771
+ this.setState({
2772
+ direction: SelectDirection.up
2773
+ });
2774
+ }
2775
+ };
2776
+ }
2777
+
2778
+ render() {
2779
+ const { isOpen, selected, isDisabled, direction } = this.state;
2780
+ const titleId = 'title-id-2';
2781
+ return (
2782
+ <div>
2783
+ <span id={titleId} hidden>
2784
+ Title
2785
+ </span>
2786
+ <Select
2787
+ aria-label="Select Input"
2788
+ onToggle={this.onToggle}
2789
+ isOpen={isOpen}
2790
+ aria-labelledby={titleId}
2791
+ isDisabled={isDisabled}
2792
+ direction={direction}
2793
+ customContent="[Panel contents here]"
2794
+ placeholderText="Filter by birth month"
2795
+ />
2796
+ <Checkbox
2797
+ label="isDisabled"
2798
+ isChecked={this.state.isDisabled}
2799
+ onChange={(_event, checked) => this.toggleDisabled(checked)}
2800
+ aria-label="disabled checkbox panel"
2801
+ id="toggle-disabled-panel"
2802
+ name="toggle-disabled-panel"
2803
+ />
2804
+ <Checkbox
2805
+ label="Expands up"
2806
+ isChecked={direction === SelectDirection.up}
2807
+ onChange={this.toggleDirection}
2808
+ aria-label="direction checkbox panel"
2809
+ id="toggle-direction-panel"
2810
+ name="toggle-direction-panel"
2811
+ />
2812
+ </div>
2813
+ );
2814
+ }
2815
+ }
2816
+ ```
2817
+
2818
+ ### Appending document body vs parent
2819
+
2820
+ Avoid passing in `document.body` to the `menuAppendTo` property. Doing so can cause accessibility issues because this prevents users from being able to enter the contents of the select options via assistive technologies (like keyboards or screen readers). Instead, pass in `parent` to achieve the same result without sacrificing accessibility.
2821
+
2822
+ The following example demonstrates both methods. When the dropdown is opened, both select variants manage focus the same way, but behave differently when the tab key is pressed after an option is selected.
2823
+
2824
+ - For the `document.body` variant, the focus will be placed at the end of the page, since that is where the dropdown content is appended to in the DOM (rather than focus being placed on the second Select variant as one might expect).
2825
+ - For the `parent` variant, however, the focus will be placed on the next tab-able element (the "Toggle JS code" button for the code editor in this case).
2826
+
2827
+ ```js
2828
+ import React from 'react';
2829
+ import { Flex, FlexItem } from '@patternfly/react-core';
2830
+ import { Select, SelectOption } from '@patternfly/react-core/deprecated';
2831
+
2832
+ class SelectDocumentBodyVsParent extends React.Component {
2833
+ constructor(props) {
2834
+ super(props);
2835
+ this.bodyOptions = [
2836
+ <SelectOption key={0} value="Select a title - document body" isPlaceholder />,
2837
+ <SelectOption key={1} value="Mr" />,
2838
+ <SelectOption key={2} value="Miss" />,
2839
+ <SelectOption key={3} value="Mrs" />,
2840
+ <SelectOption key={4} value="Ms" />,
2841
+ <SelectOption key={6} value="Dr" />,
2842
+ <SelectOption key={7} value="Other" />
2843
+ ];
2844
+
2845
+ this.parentOptions = [
2846
+ <SelectOption key={0} value="Select a title - parent" isPlaceholder />,
2847
+ <SelectOption key={1} value="Mr" />,
2848
+ <SelectOption key={2} value="Miss" />,
2849
+ <SelectOption key={3} value="Mrs" />,
2850
+ <SelectOption key={4} value="Ms" />,
2851
+ <SelectOption key={6} value="Dr" />,
2852
+ <SelectOption key={7} value="Other" />
2853
+ ];
2854
+
2855
+ this.state = {
2856
+ isBodyOpen: false,
2857
+ isParentOpen: false,
2858
+ bodySelected: null,
2859
+ parentSelected: null
2860
+ };
2861
+
2862
+ this.onBodyToggle = (_event, isBodyOpen) => {
2863
+ this.setState({
2864
+ isBodyOpen
2865
+ });
2866
+ };
2867
+
2868
+ this.onParentToggle = (_event, isParentOpen) => {
2869
+ this.setState({
2870
+ isParentOpen
2871
+ });
2872
+ };
2873
+
2874
+ this.onBodySelect = (event, selection, isPlaceholder) => {
2875
+ if (isPlaceholder) this.clearSelection();
2876
+ else {
2877
+ this.setState({
2878
+ bodySelected: selection,
2879
+ isBodyOpen: false
2880
+ });
2881
+ console.log('selected on document body:', selection);
2882
+ }
2883
+ };
2884
+
2885
+ this.onParentSelect = (event, selection, isPlaceholder) => {
2886
+ if (isPlaceholder) this.clearSelection();
2887
+ else {
2888
+ this.setState({
2889
+ parentSelected: selection,
2890
+ isParentOpen: false
2891
+ });
2892
+ console.log('selected on parent:', selection);
2893
+ }
2894
+ };
2895
+
2896
+ this.clearSelection = () => {
2897
+ this.setState({
2898
+ selected: null,
2899
+ isOpen: false
2900
+ });
2901
+ };
2902
+ }
2903
+
2904
+ render() {
2905
+ const { isBodyOpen, isParentOpen, bodySelected, parentSelected } = this.state;
2906
+
2907
+ return (
2908
+ <Flex space={{ default: 'spacerMd' }} direction={{ default: 'column' }}>
2909
+ <FlexItem>
2910
+ <Select
2911
+ aria-label="Select Input for Document Body"
2912
+ onToggle={this.onBodyToggle}
2913
+ onSelect={this.onBodySelect}
2914
+ selections={bodySelected}
2915
+ isOpen={isBodyOpen}
2916
+ menuAppendTo={() => document.body}
2917
+ >
2918
+ {this.bodyOptions}
2919
+ </Select>
2920
+ </FlexItem>
2921
+ <FlexItem>
2922
+ <Select
2923
+ aria-label="Select Input for Parent"
2924
+ onToggle={this.onParentToggle}
2925
+ onSelect={this.onParentSelect}
2926
+ selections={parentSelected}
2927
+ isOpen={isParentOpen}
2928
+ menuAppendTo="parent"
2929
+ >
2930
+ {this.parentOptions}
2931
+ </Select>
2932
+ </FlexItem>
2933
+ </Flex>
2934
+ );
2935
+ }
2936
+ }
2937
+ ```