@openedx/paragon 21.11.2 → 21.11.4

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openedx/paragon",
3
- "version": "21.11.2",
3
+ "version": "21.11.4",
4
4
  "description": "Accessible, responsive UI component library based on Bootstrap.",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.js",
@@ -282,7 +282,7 @@ $element-color-levels: map-merge(
282
282
  "border": 200,
283
283
  "icon": 300,
284
284
  "active-border": 300,
285
- "focus": 300,
285
+ "focus": 500,
286
286
  "graphic": 300,
287
287
  "default": 500,
288
288
  "light-text": 500,
@@ -22,11 +22,11 @@ This component utilizes `Button` from React-Bootstrap and extends it with an abi
22
22
 
23
23
  return (
24
24
  <Stack gap={2} direction={ isExtraSmall ? "vertical" : "horizontal" }>
25
- <Button variant="brand" className="mb-2 mb-sm-0">Brand</Button>
26
- <Button variant="outline-brand" className="mb-2 mb-sm-0">Outline Brand</Button>
27
- <Button variant="primary" className="mb-2 mb-sm-0">Primary</Button>
28
- <Button variant="outline-primary" className="mb-2 mb-sm-0">Outline Primary</Button>
29
- <Button variant="tertiary" className="mb-2 mb-sm-0">Tertiary</Button>
25
+ <Button variant="brand">Brand</Button>
26
+ <Button variant="outline-brand">Outline Brand</Button>
27
+ <Button variant="primary">Primary</Button>
28
+ <Button variant="outline-primary">Outline Primary</Button>
29
+ <Button variant="tertiary">Tertiary</Button>
30
30
  </Stack>
31
31
  )}
32
32
  ```
@@ -43,11 +43,11 @@ This component utilizes `Button` from React-Bootstrap and extends it with an abi
43
43
  gap={2}
44
44
  direction={ isExtraSmall ? "vertical" : "horizontal" }
45
45
  >
46
- <Button variant="inverse-brand" className="mb-2 mb-sm-0">Brand</Button>
47
- <Button variant="inverse-outline-brand" className="mb-2 mb-sm-0">Outline Brand</Button>
48
- <Button variant="inverse-primary" className="mb-2 mb-sm-0">Primary</Button>
49
- <Button variant="inverse-outline-primary" className="mb-2 mb-sm-0">Outline Primary</Button>
50
- <Button variant="inverse-tertiary" className="mb-2 mb-sm-0">Tertiary</Button>
46
+ <Button variant="inverse-brand">Brand</Button>
47
+ <Button variant="inverse-outline-brand">Outline Brand</Button>
48
+ <Button variant="inverse-primary">Primary</Button>
49
+ <Button variant="inverse-outline-primary">Outline Primary</Button>
50
+ <Button variant="inverse-tertiary">Tertiary</Button>
51
51
  </Stack>
52
52
  )}
53
53
  ```
@@ -65,20 +65,20 @@ This component utilizes `Button` from React-Bootstrap and extends it with an abi
65
65
  gap={2}
66
66
  direction={ isExtraSmall ? "vertical" : "horizontal" }
67
67
  >
68
- <Button variant="success" className="mb-2 mb-sm-0">Success</Button>
69
- <Button variant="danger" className="mb-2 mb-sm-0">Danger</Button>
70
- <Button variant="outline-success" className="mb-2 mb-sm-0">Success</Button>
71
- <Button variant="outline-danger" className="mb-2 mb-sm-0">Danger</Button>
68
+ <Button variant="success">Success</Button>
69
+ <Button variant="danger">Danger</Button>
70
+ <Button variant="outline-success">Success</Button>
71
+ <Button variant="outline-danger">Danger</Button>
72
72
  </Stack>
73
73
  <Stack
74
74
  gap={2}
75
75
  direction={ isExtraSmall ? "vertical" : "horizontal" }
76
76
  >
77
- <Button variant="link" className="mb-2 mb-sm-0">Link</Button>
78
- <Button variant="light" className="mb-2 mb-sm-0">Light</Button>
79
- <Button variant="dark" className="mb-2 mb-sm-0">Dark</Button>
80
- <Button variant="outline-light" className="mb-2 mb-sm-0">Light</Button>
81
- <Button variant="outline-dark" className="mb-2 mb-sm-0">Dark</Button>
77
+ <Button variant="link">Link</Button>
78
+ <Button variant="light">Light</Button>
79
+ <Button variant="dark">Dark</Button>
80
+ <Button variant="outline-light">Light</Button>
81
+ <Button variant="outline-dark">Dark</Button>
82
82
  </Stack>
83
83
  </>
84
84
  )}
@@ -92,34 +92,41 @@ This component utilizes `Button` from React-Bootstrap and extends it with an abi
92
92
 
93
93
  return (
94
94
  <>
95
- <Stack
96
- className="mb-2"
97
- gap={2}
98
- direction={ isExtraSmall ? "vertical" : "horizontal" }
99
- >
100
- <Button variant="primary" size="lg" className="mb-2 mb-sm-0">
101
- Large button
102
- </Button>
103
- <Button variant="outline-primary" size="lg" className="mb-2 mb-sm-0">
104
- Large button
105
- </Button>
106
- </Stack>
107
- <Stack
108
- className="mb-2"
109
- gap={2}
110
- direction={ isExtraSmall ? "vertical" : "horizontal" }
111
- >
112
- <Button variant="primary" size="sm" className="mb-2 mb-sm-0">
113
- Small button
114
- </Button>
115
- <Button variant="outline-primary" size="sm" className="mb-2 mb-sm-0">
116
- Small button
117
- </Button>
118
- </Stack>
119
- <Button variant="link" size="inline" className="mb-2 mb-sm-0">Inline button</Button>
120
- <Button variant="link" size="inline" className="mb-2 mb-sm-0">Inline button</Button>
95
+ <Stack
96
+ className="mb-2"
97
+ gap={2}
98
+ direction={ isExtraSmall ? "vertical" : "horizontal" }
99
+ >
100
+ <Button variant="primary" size="lg">
101
+ Large button
102
+ </Button>
103
+ <Button variant="outline-primary" size="lg">
104
+ Large button
105
+ </Button>
106
+ </Stack>
107
+ <Stack
108
+ className="mb-2"
109
+ gap={2}
110
+ direction={ isExtraSmall ? "vertical" : "horizontal" }
111
+ >
112
+ <Button variant="primary" size="sm">
113
+ Small button
114
+ </Button>
115
+ <Button variant="outline-primary" size="sm">
116
+ Small button
117
+ </Button>
118
+ </Stack>
119
+ <Stack
120
+ className="mb-2"
121
+ gap={2}
122
+ direction={ isExtraSmall ? "vertical" : "horizontal" }
123
+ >
124
+ <Button variant="link" size="inline">Inline button</Button>
125
+ <Button variant="link" size="inline">Inline button</Button>
126
+ </Stack>
121
127
  </>
122
- )}
128
+ )
129
+ }
123
130
  ```
124
131
 
125
132
  ### When to use the inline size
@@ -127,13 +134,11 @@ This component utilizes `Button` from React-Bootstrap and extends it with an abi
127
134
  Use inline size buttons for when a button sits with a line of text.
128
135
 
129
136
  ```jsx live
130
- <>
131
- <p>
132
- <span className="mr-1">2 items selected.</span>
133
- <Button variant="link" size="inline" className="mr-1">Select all</Button>
134
- <Button variant="link" size="inline">Clear</Button>
135
- </p>
136
- </>
137
+ <p>
138
+ <span className="mr-1">2 items selected.</span>
139
+ <Button variant="link" size="inline" className="mr-1">Select all</Button>
140
+ <Button variant="link" size="inline">Clear</Button>
141
+ </p>
137
142
  ```
138
143
 
139
144
  ## Block Buttons
@@ -152,21 +157,41 @@ Use inline size buttons for when a button sits with a line of text.
152
157
  ### Disabled
153
158
 
154
159
  ```jsx live
155
- <>
156
- <Button variant="primary" disabled>Primary disabled</Button>
157
- <Button variant="secondary" disabled>Secondary disabled</Button>
158
- <Button as="a" href="https://edx.org" disabled>Link disabled</Button>
159
- </>
160
+ () => {
161
+ const isExtraSmall = useMediaQuery({ maxWidth: breakpoints.extraSmall.maxWidth });
162
+
163
+ return (
164
+ <Stack
165
+ className="mb-2"
166
+ gap={2}
167
+ direction={ isExtraSmall ? "vertical" : "horizontal" }
168
+ >
169
+ <Button variant="primary" disabled>Primary disabled</Button>
170
+ <Button variant="secondary" disabled>Secondary disabled</Button>
171
+ <Button as="a" href="https://edx.org" disabled>Link disabled</Button>
172
+ </Stack>
173
+ )
174
+ }
160
175
  ```
161
176
 
162
177
  ### With empty href
163
178
  For link to be `disabled`, it must have href defined with some value.
164
179
 
165
180
  ```jsx live
166
- <>
167
- <Button as='a' disabled>No href</Button>
168
- <Button as='a' href='' disabled>Empty string href</Button>
169
- </>
181
+ () => {
182
+ const isExtraSmall = useMediaQuery({ maxWidth: breakpoints.extraSmall.maxWidth });
183
+
184
+ return (
185
+ <Stack
186
+ className="mb-2"
187
+ gap={2}
188
+ direction={ isExtraSmall ? "vertical" : "horizontal" }
189
+ >
190
+ <Button as="a" disabled>No href</Button>
191
+ <Button as="a" href="" disabled>Empty string href</Button>
192
+ </Stack>
193
+ )
194
+ }
170
195
  ```
171
196
 
172
197
  ### With Icons before or after
@@ -181,23 +206,24 @@ For link to be `disabled`, it must have href defined with some value.
181
206
  gap={2}
182
207
  direction={ isExtraSmall ? "vertical" : "horizontal" }
183
208
  >
184
- <Button variant="brand" iconBefore={ArrowBack} className="mb-2 mb-sm-0">
209
+ <Button variant="brand" iconBefore={ArrowBack}>
185
210
  Brand
186
211
  </Button>
187
- <Button variant="outline-brand" iconAfter={ArrowDropDown} className="mb-2 mb-sm-0">
212
+ <Button variant="outline-brand" iconAfter={ArrowDropDown}>
188
213
  Outline Brand
189
214
  </Button>
190
- <Button variant="primary" iconBefore={Remove} iconAfter={Add} className="mb-2 mb-sm-0">
215
+ <Button variant="primary" iconBefore={Remove} iconAfter={Add}>
191
216
  Primary
192
217
  </Button>
193
- <Button variant="outline-primary" iconBefore={Highlight} className="mb-2 mb-sm-0">
218
+ <Button variant="outline-primary" iconBefore={Highlight}>
194
219
  Outline Primary
195
220
  </Button>
196
- <Button variant="tertiary" iconAfter={Add} className="mb-2 mb-sm-0">
221
+ <Button variant="tertiary" iconAfter={Add}>
197
222
  Tertiary
198
223
  </Button>
199
224
  </Stack>
200
- )}
225
+ )
226
+ }
201
227
  ```
202
228
 
203
229
  ## Stateful buttons
@@ -219,33 +245,63 @@ user-friendly experience.
219
245
  ### (Deprecated) color variants
220
246
 
221
247
  ```jsx live
222
- <div>
223
- <Button.Deprecated className="btn-primary">Primary</Button.Deprecated>
224
- <Button.Deprecated className="btn-success">Success</Button.Deprecated>
225
- <Button.Deprecated className="btn-danger">Danger</Button.Deprecated>
226
- <Button.Deprecated className="btn-light">Light</Button.Deprecated>
227
- <Button.Deprecated className="btn-dark">Dark</Button.Deprecated>
228
- </div>
248
+ () => {
249
+ const isExtraSmall = useMediaQuery({ maxWidth: breakpoints.large.maxWidth });
250
+
251
+ return (
252
+ <Stack
253
+ className="mb-2"
254
+ gap={2}
255
+ direction={ isExtraSmall ? "vertical" : "horizontal" }
256
+ >
257
+ <Button.Deprecated className="btn-primary">Primary</Button.Deprecated>
258
+ <Button.Deprecated className="btn-success">Success</Button.Deprecated>
259
+ <Button.Deprecated className="btn-danger">Danger</Button.Deprecated>
260
+ <Button.Deprecated className="btn-light">Light</Button.Deprecated>
261
+ <Button.Deprecated className="btn-dark">Dark</Button.Deprecated>
262
+ </Stack>
263
+ )
264
+ }
229
265
  ```
230
266
 
231
267
  ### (Deprecated) outline variants
232
268
 
233
269
  ```jsx live
234
- <div>
235
- <Button.Deprecated className="btn-outline-primary">Primary</Button.Deprecated>
236
- <Button.Deprecated className="btn-outline-success">Success</Button.Deprecated>
237
- <Button.Deprecated className="btn-outline-danger">Danger</Button.Deprecated>
238
- </div>
270
+ () => {
271
+ const isExtraSmall = useMediaQuery({ maxWidth: breakpoints.extraSmall.maxWidth });
272
+
273
+ return (
274
+ <Stack
275
+ className="mb-2"
276
+ gap={2}
277
+ direction={ isExtraSmall ? "vertical" : "horizontal" }
278
+ >
279
+ <Button.Deprecated className="btn-outline-primary">Primary</Button.Deprecated>
280
+ <Button.Deprecated className="btn-outline-success">Success</Button.Deprecated>
281
+ <Button.Deprecated className="btn-outline-danger">Danger</Button.Deprecated>
282
+ </Stack>
283
+ )
284
+ }
239
285
  ```
240
286
 
241
287
  ### (Deprecated) inverse variants
242
288
 
243
289
  ```jsx live
244
- <div className="bg-gray-700 p-3">
245
- <Button.Deprecated className="btn-inverse-primary">Primary</Button.Deprecated>
246
- <Button.Deprecated className="btn-inverse-success">Success</Button.Deprecated>
247
- <Button.Deprecated className="btn-inverse-danger">Danger</Button.Deprecated>
248
- </div>
290
+ () => {
291
+ const isExtraSmall = useMediaQuery({ maxWidth: breakpoints.extraSmall.maxWidth });
292
+
293
+ return (
294
+ <Stack
295
+ className="mb-2 p-3 bg-gray-700"
296
+ gap={2}
297
+ direction={ isExtraSmall ? "vertical" : "horizontal" }
298
+ >
299
+ <Button.Deprecated className="btn-inverse-primary">Primary</Button.Deprecated>
300
+ <Button.Deprecated className="btn-inverse-success">Success</Button.Deprecated>
301
+ <Button.Deprecated className="btn-inverse-danger">Danger</Button.Deprecated>
302
+ </Stack>
303
+ )
304
+ }
249
305
  ```
250
306
 
251
307
  ### (Deprecated) link variant
@@ -19,7 +19,7 @@ $btn-border-width: $input-btn-border-width !default;
19
19
  $btn-font-weight: $font-weight-normal !default;
20
20
  $btn-box-shadow: inset 0 1px 0 rgba($white, .15), 0 1px 1px rgba($black, .075) !default;
21
21
  $btn-focus-width: 2px !default;
22
- $btn-focus-gap: 1px !default;
22
+ $btn-focus-gap: $btn-focus-width !default;
23
23
  $btn-focus-box-shadow: $input-btn-focus-box-shadow !default;
24
24
  $btn-disabled-opacity: .65 !default;
25
25
  $btn-active-box-shadow: none;
@@ -48,3 +48,5 @@ $btn-focus-border-gap: $btn-focus-width + $btn-focus-gap !default;
48
48
  $btn-focus-distance-to-border: $btn-focus-border-gap + $btn-border-width !default;
49
49
 
50
50
  $btn-focus-border-radius: calc(#{$btn-border-radius} + #{$btn-focus-border-gap}) !default;
51
+ $btn-focus-border-radius-lg: $btn-focus-border-radius !default;
52
+ $btn-focus-border-radius-sm: $btn-border-radius !default;
@@ -150,11 +150,11 @@
150
150
  }
151
151
 
152
152
  &.btn-lg::before {
153
- border-radius: $btn-focus-border-radius;
153
+ border-radius: $btn-focus-border-radius-lg;
154
154
  }
155
155
 
156
156
  &.btn-sm::before {
157
- border-radius: $btn-focus-border-radius;
157
+ border-radius: $btn-focus-border-radius-sm;
158
158
  }
159
159
 
160
160
  &:active,
@@ -28,11 +28,11 @@ designStatus: 'Done'
28
28
  devStatus: 'In progress'
29
29
  ---
30
30
 
31
- The DataTable component is a wrapper that uses the <a href="https://react-table.tanstack.com/docs/overview">react-table</a> library to
31
+ The DataTable component is a wrapper that uses the <a href="https://github.com/TanStack/table/tree/v7/docs/src/pages/docs" target="_blank" rel="noopener noreferrer">react-table</a> library to
32
32
  create tables. It can be used as is, or its subcomponents can be used on their own, allowing the developer full control.
33
33
 
34
34
  Paragon also exports all React hooks from ``react-table`` allowing the developers to use them and make customizations more freely without adding ``react-table`` as a separate dependency to their project.
35
- For full list of available hooks view <a href="https://react-table.tanstack.com/docs/api/overview">react-table API reference</a>.
35
+ For full list of available hooks view <a href="https://github.com/TanStack/table/tree/v7/docs/src/pages/docs/api" target="_blank" rel="noopener noreferrer">react-table API reference</a>.
36
36
 
37
37
  ## How children get information
38
38
 
@@ -49,7 +49,7 @@ const instance = useContext(DataTableContext)
49
49
  For small tables (less than ~10,000 rows), filtering, sorting and pagination can be done quickly and easily on the frontend.
50
50
 
51
51
  In this example, a default TextFilter component is used for all columns. A default filter can be passed in,
52
- or a filter component can be defined on the column. See <a href="https://react-table.tanstack.com/docs/api/useFilters">react-table filters documentation</a>
52
+ or a filter component can be defined on the column. See <a href="https://github.com/TanStack/table/blob/v7/docs/src/pages/docs/api/useFilters.md" target="_blank" rel="noopener noreferrer">react-table filters documentation</a>
53
53
  for more information.
54
54
 
55
55
  ```jsx live
@@ -329,7 +329,7 @@ DataTable.propTypes = {
329
329
  /** Function that will fetch table data. Called when page size, page index or filters change.
330
330
  * Meant to be used with manual filters and pagination */
331
331
  fetchData: PropTypes.func,
332
- /** Initial state passed to react-table's documentation https://react-table.tanstack.com/docs/api/useTable */
332
+ /** Initial state passed to react-table's documentation https://github.com/TanStack/table/blob/v7/docs/src/pages/docs/api/useTable.md */
333
333
  initialState: PropTypes.shape({
334
334
  pageSize: requiredWhen(PropTypes.number, 'isPaginated'),
335
335
  pageIndex: requiredWhen(PropTypes.number, 'isPaginated'),
@@ -14,18 +14,18 @@ devStatus: 'In progress'
14
14
  ---
15
15
 
16
16
 
17
- The ``DataTable`` component is a wrapper that uses the <a href="https://react-table.tanstack.com/docs">react-table</a> library to
17
+ The ``DataTable`` component is a wrapper that uses the <a href="https://github.com/TanStack/table/tree/v7/docs/src/pages/docs" target="_blank" rel="noopener noreferrer">react-table</a> library to
18
18
  create tables. It can be used as is, or its subcomponents can be used on their own, allowing the developer full control.
19
19
 
20
20
  ## Filtering and sorting
21
21
  Paragon currently provides a variety of filter types, and you can also define your own filter types.
22
22
 
23
23
  In the example below, a default ``TextFilter`` component is used as the default filter for all columns. A default filter can be passed in,
24
- or a filter component can be defined on the column using the ``Filter`` attribute. See <a href="https://react-table.tanstack.com/docs/api/useFilters">react-table filters documentation</a>
24
+ or a filter component can be defined on the column using the ``Filter`` attribute. See <a href="https://github.com/TanStack/table/blob/v7/docs/src/pages/docs/api/useFilters.md" target="_blank" rel="noopener noreferrer">react-table filters documentation</a>
25
25
  for more information.
26
26
 
27
27
  ## Available filter functions
28
- A filtering function can be defined on the column as well as the filter component. Custom filtering functions can also be defined, see <a href="https://react-table.tanstack.com/docs/api/useFilters#column-options">react-table filters documentation</a>
28
+ A filtering function can be defined on the column as well as the filter component. Custom filtering functions can also be defined, see <a href="https://github.com/TanStack/table/blob/v7/docs/src/pages/docs/api/useFilters.md#column-options" target="_blank" rel="noopener noreferrer">react-table filters documentation</a>
29
29
  for more information.
30
30
  Filter functions are defined on the column as the ``filter`` attribute.
31
31
  <dl>
@@ -6,7 +6,7 @@ import { v4 as uuidv4 } from 'uuid';
6
6
  import { useIntl } from 'react-intl';
7
7
  import { KeyboardArrowUp, KeyboardArrowDown } from '../../icons';
8
8
  import Icon from '../Icon';
9
- import FormGroup from './FormGroup';
9
+ import { FormGroupContextProvider, useFormGroupContext } from './FormGroupContext';
10
10
  import FormControl from './FormControl';
11
11
  import FormControlFeedback from './FormControlFeedback';
12
12
  import IconButton from '../IconButton';
@@ -239,12 +239,18 @@ function FormAutosuggest({
239
239
  setDisplayValue(e.target.value);
240
240
  };
241
241
 
242
+ const { getControlProps } = useFormGroupContext();
243
+ const controlProps = getControlProps(props);
244
+
242
245
  return (
243
246
  <div className="pgn__form-autosuggest__wrapper" ref={parentRef}>
244
247
  <div aria-live="assertive" className="sr-only" data-testid="autosuggest-screen-reader-options-count">
245
248
  {`${state.dropDownItems.length} options found`}
246
249
  </div>
247
- <FormGroup isInvalid={!!state.errorMessage}>
250
+ <FormGroupContextProvider
251
+ controlId={controlProps.id}
252
+ isInvalid={!!state.errorMessage}
253
+ >
248
254
  <FormControl
249
255
  ref={formControlRef}
250
256
  aria-expanded={(state.dropDownItems.length > 0).toString()}
@@ -259,7 +265,7 @@ function FormAutosuggest({
259
265
  onClick={handleClick}
260
266
  trailingElement={iconToggle}
261
267
  data-testid="autosuggest-textbox-input"
262
- {...props}
268
+ {...controlProps}
263
269
  />
264
270
 
265
271
  {helpMessage && !state.errorMessage && (
@@ -269,11 +275,11 @@ function FormAutosuggest({
269
275
  )}
270
276
 
271
277
  {state.errorMessage && (
272
- <FormControlFeedback type="invalid" feedback-for={props.name}>
278
+ <FormControlFeedback type="invalid" feedback-for={controlProps.name}>
273
279
  {errorMessageText}
274
280
  </FormControlFeedback>
275
281
  )}
276
- </FormGroup>
282
+ </FormGroupContextProvider>
277
283
 
278
284
  <ul
279
285
  id="pgn__form-autosuggest__dropdown-box"
@@ -19,93 +19,101 @@ Form auto-suggest enables users to manually select or type to find matching opti
19
19
 
20
20
  ```jsx live
21
21
  () => {
22
- const [selected, setSelected] = useState('');
22
+ const [selected, setSelected] = useState('');
23
23
 
24
- return (
25
- <Form.Autosuggest
26
- floatingLabel="Programming language"
27
- aria-label="form autosuggest"
28
- helpMessage="Select language"
29
- errorMessageText="Error, no selected value"
30
- value={selected}
31
- onSelected={(value) => setSelected(value)}
32
- >
33
- <Form.AutosuggestOption>JavaScript</Form.AutosuggestOption>
34
- <Form.AutosuggestOption>Python</Form.AutosuggestOption>
35
- <Form.AutosuggestOption>Rube</Form.AutosuggestOption>
36
- <Form.AutosuggestOption onClick={(e) => alert(e.currentTarget.getAttribute('data-value'))}>
37
- Option with custom onClick
38
- </Form.AutosuggestOption>
39
- </Form.Autosuggest>
40
- );
41
- }
24
+ return (
25
+ <Form.Group>
26
+ <Form.Label>
27
+ <h4>Programming language</h4>
28
+ </Form.Label>
29
+ <Form.Autosuggest
30
+ aria-label="form autosuggest"
31
+ helpMessage="Select language"
32
+ errorMessageText="Error, no selected value"
33
+ value={selected}
34
+ onSelected={(value) => setSelected(value)}
35
+ >
36
+ <Form.AutosuggestOption>JavaScript</Form.AutosuggestOption>
37
+ <Form.AutosuggestOption>Python</Form.AutosuggestOption>
38
+ <Form.AutosuggestOption>Rube</Form.AutosuggestOption>
39
+ <Form.AutosuggestOption onClick={(e) => alert(e.currentTarget.getAttribute('data-value'))}>
40
+ Option with custom onClick
41
+ </Form.AutosuggestOption>
42
+ </Form.Autosuggest>
43
+ </Form.Group>
44
+ );
45
+ };
42
46
  ```
43
47
 
44
48
  ## Search Usage
45
49
 
46
50
  ```jsx live
47
51
  () => {
48
- const [selected, setSelected] = useState('');
52
+ const [selected, setSelected] = useState('');
49
53
 
50
- return (
51
- <Form.Autosuggest
52
- placeholder="Type 'T'"
53
- aria-label="form autosuggest"
54
- errorMessageText="Error, no selected value"
55
- helpMessage="Select language"
56
- value={selected}
57
- onSelected={(value) => setSelected(value)}
58
- >
59
- <Form.AutosuggestOption>PHP</Form.AutosuggestOption>
60
- <Form.AutosuggestOption>Java</Form.AutosuggestOption>
61
- <Form.AutosuggestOption>Turbo Pascal</Form.AutosuggestOption>
62
- <Form.AutosuggestOption>Flask</Form.AutosuggestOption>
63
- </Form.Autosuggest>
64
- );
65
- }
54
+ return (
55
+ <Form.Autosuggest
56
+ placeholder="Type 'T'"
57
+ aria-label="form autosuggest"
58
+ errorMessageText="Error, no selected value"
59
+ helpMessage="Select language"
60
+ value={selected}
61
+ onSelected={(value) => setSelected(value)}
62
+ >
63
+ <Form.AutosuggestOption>PHP</Form.AutosuggestOption>
64
+ <Form.AutosuggestOption>Java</Form.AutosuggestOption>
65
+ <Form.AutosuggestOption>Turbo Pascal</Form.AutosuggestOption>
66
+ <Form.AutosuggestOption>Flask</Form.AutosuggestOption>
67
+ </Form.Autosuggest>
68
+ );
69
+ };
66
70
  ```
67
71
 
68
72
  ## Loading state
69
73
 
70
74
  ```jsx live
71
75
  () => {
72
- const [data, setData] = useState([]);
73
- const [showLoading, setShowLoading] = useState(false);
76
+ const [data, setData] = useState([]);
77
+ const [showLoading, setShowLoading] = useState(false);
74
78
 
75
- useEffect(() => {
76
- setShowLoading(true);
77
- fetch('https://api.sampleapis.com/coffee/hot')
78
- .then(data => data.json())
79
- .then(items => {
80
- setTimeout(() => {
81
- setData(items);
82
- setShowLoading(false);
83
- }, 1500);
84
- });
85
- }, [])
79
+ useEffect(() => {
80
+ setShowLoading(true);
81
+ fetch('https://api.sampleapis.com/coffee/hot')
82
+ .then(data => data.json())
83
+ .then(items => {
84
+ setTimeout(() => {
85
+ setData(items);
86
+ setShowLoading(false);
87
+ }, 1500);
88
+ });
89
+ }, []);
86
90
 
87
- const searchCoffee = (title) => {
88
- setShowLoading(true);
89
- fetch('https://api.sampleapis.com/coffee/hot')
90
- .then(data => data.json())
91
- .then(items => setTimeout(() => {
92
- const filteredCoffee = items.filter(res => res.title.toLowerCase().includes(title.toLowerCase()));
93
- setShowLoading(false);
94
- if (filteredCoffee) { return filteredCoffee }
95
- return { ...title, filteredCoffee }
96
- }, 1500));
97
- };
91
+ const searchCoffee = (title) => {
92
+ setShowLoading(true);
93
+ fetch('https://api.sampleapis.com/coffee/hot')
94
+ .then(data => data.json())
95
+ .then(items => setTimeout(() => {
96
+ const filteredCoffee = items.filter(res => res.title.toLowerCase().includes(title.toLowerCase()));
97
+ setShowLoading(false);
98
+ if (filteredCoffee) { return filteredCoffee; }
99
+ return { ...title, filteredCoffee };
100
+ }, 1500));
101
+ };
98
102
 
99
- return (
100
- <Form.Autosuggest
101
- isLoading={showLoading}
102
- placeholder="This is placeholder"
103
- floatingLabel="This is floating label"
104
- screenReaderText="Loading..."
105
- onChange={searchCoffee}
106
- >
107
- {data.map((item, index) => <Form.AutosuggestOption key={index}>{item.title}</Form.AutosuggestOption>)}
108
- </Form.Autosuggest>
109
- );
110
- }
103
+ return (
104
+ <Form.Group>
105
+ <Form.Label>
106
+ <h4>Café API</h4>
107
+ </Form.Label>
108
+ <Form.Autosuggest
109
+ isLoading={showLoading}
110
+ placeholder="This is placeholder"
111
+ screenReaderText="Loading..."
112
+ onChange={searchCoffee}
113
+ >
114
+ {data.map((item, index) => <Form.AutosuggestOption key={index}>{item.title}</Form.AutosuggestOption>)}
115
+ </Form.Autosuggest>
116
+ </Form.Group>
117
+ );
118
+ };
111
119
  ```