WAI-ARIA compliant React autosuggest component with extensive customization options
npx @tessl/cli install tessl/npm-react-autosuggest@10.1.00
# React Autosuggest
1
2
React Autosuggest is a WAI-ARIA compliant React component that provides accessible autosuggest/autocomplete functionality. It offers extensive customization options, supports both single-section and multi-section suggestion layouts, handles asynchronous suggestion loading, and provides full keyboard navigation with mobile-friendly interactions.
3
4
## Package Information
5
6
- **Package Name**: react-autosuggest
7
- **Package Type**: npm
8
- **Language**: JavaScript (React)
9
- **Installation**: `npm install react-autosuggest`
10
11
## Core Imports
12
13
```javascript
14
import Autosuggest from 'react-autosuggest';
15
```
16
17
For CommonJS:
18
19
```javascript
20
const Autosuggest = require('react-autosuggest');
21
```
22
23
## Basic Usage
24
25
```javascript
26
import React, { useState } from 'react';
27
import Autosuggest from 'react-autosuggest';
28
29
const languages = [
30
{ name: 'C', year: 1972 },
31
{ name: 'JavaScript', year: 1995 },
32
{ name: 'Python', year: 1991 }
33
];
34
35
// Function that tells Autosuggest how to calculate suggestions for any given input value
36
const getSuggestions = value => {
37
const inputValue = value.trim().toLowerCase();
38
const inputLength = inputValue.length;
39
40
return inputLength === 0 ? [] : languages.filter(lang =>
41
lang.name.toLowerCase().slice(0, inputLength) === inputValue
42
);
43
};
44
45
// Function that tells Autosuggest what should be the input value when suggestion is clicked
46
const getSuggestionValue = suggestion => suggestion.name;
47
48
// Function that renders each suggestion
49
const renderSuggestion = suggestion => (
50
<div>
51
{suggestion.name}
52
</div>
53
);
54
55
function MyAutosuggest() {
56
const [value, setValue] = useState('');
57
const [suggestions, setSuggestions] = useState([]);
58
59
const onChange = (event, { newValue }) => {
60
setValue(newValue);
61
};
62
63
const onSuggestionsFetchRequested = ({ value }) => {
64
setSuggestions(getSuggestions(value));
65
};
66
67
const onSuggestionsClearRequested = () => {
68
setSuggestions([]);
69
};
70
71
const inputProps = {
72
placeholder: 'Type a programming language',
73
value,
74
onChange: onChange
75
};
76
77
return (
78
<Autosuggest
79
suggestions={suggestions}
80
onSuggestionsFetchRequested={onSuggestionsFetchRequested}
81
onSuggestionsClearRequested={onSuggestionsClearRequested}
82
getSuggestionValue={getSuggestionValue}
83
renderSuggestion={renderSuggestion}
84
inputProps={inputProps}
85
/>
86
);
87
}
88
```
89
90
## Capabilities
91
92
### Autosuggest Component
93
94
The main React component providing autosuggest functionality with full accessibility support.
95
96
```javascript { .api }
97
class Autosuggest extends React.Component {
98
constructor(props);
99
render();
100
}
101
```
102
103
#### Required Props
104
105
```javascript { .api }
106
interface AutosuggestProps {
107
/** Array of suggestions to display */
108
suggestions: Array<any>;
109
110
/** Called when suggestions need to be recalculated */
111
onSuggestionsFetchRequested: (request: SuggestionsFetchRequest) => void;
112
113
/** Returns input value for a selected suggestion */
114
getSuggestionValue: (suggestion: any) => string;
115
116
/** Renders individual suggestions */
117
renderSuggestion: (
118
suggestion: any,
119
params: RenderSuggestionParams
120
) => React.ReactNode;
121
122
/** Input props including required value and onChange */
123
inputProps: InputProps;
124
}
125
126
interface SuggestionsFetchRequest {
127
value: string;
128
reason: 'input-changed' | 'input-focused' | 'escape-pressed' | 'suggestions-revealed' | 'suggestions-updated' | 'suggestion-selected' | 'input-blurred';
129
}
130
131
interface RenderSuggestionParams {
132
query: string;
133
isHighlighted: boolean;
134
}
135
136
interface InputProps {
137
value: string;
138
onChange: (event: Event, params: InputChangeParams) => void;
139
onBlur?: (event: Event, params: InputBlurParams) => void;
140
[key: string]: any; // Additional HTML input attributes
141
}
142
143
interface InputBlurParams {
144
highlightedSuggestion: any | null;
145
}
146
147
interface InputChangeParams {
148
newValue: string;
149
method: 'down' | 'up' | 'escape' | 'enter' | 'click' | 'type';
150
}
151
```
152
153
#### Optional Props
154
155
```javascript { .api }
156
interface OptionalAutosuggestProps {
157
/** Called to clear suggestions (required unless alwaysRenderSuggestions=true) */
158
onSuggestionsClearRequested?: () => void;
159
160
/** Props passed to outer container div */
161
containerProps?: object;
162
163
/** Called when suggestion is selected */
164
onSuggestionSelected?: (event: Event, params: SuggestionSelectedParams) => void;
165
166
/** Called when highlighted suggestion changes */
167
onSuggestionHighlighted?: (params: SuggestionHighlightedParams) => void;
168
169
/** Controls when suggestions are rendered */
170
shouldRenderSuggestions?: (value: string, reason: string) => boolean;
171
172
/** Render suggestions even when input not focused */
173
alwaysRenderSuggestions?: boolean;
174
175
/** Automatically highlight first suggestion */
176
highlightFirstSuggestion?: boolean;
177
178
/** Keep input focused on suggestion click */
179
focusInputOnSuggestionClick?: boolean;
180
181
/** Enable multi-section suggestions layout */
182
multiSection?: boolean;
183
184
/** Renders section titles (required when multiSection=true) */
185
renderSectionTitle?: (section: any) => React.ReactNode;
186
187
/** Gets suggestions for a section (required when multiSection=true) */
188
getSectionSuggestions?: (section: any) => Array<any>;
189
190
/** Custom input component renderer */
191
renderInputComponent?: (inputProps: object) => React.ReactElement;
192
193
/** Custom suggestions container renderer */
194
renderSuggestionsContainer?: (params: RenderSuggestionsContainerParams) => React.ReactElement;
195
196
/** CSS class names for styling */
197
theme?: Theme;
198
199
/** Unique identifier for multiple Autosuggest instances */
200
id?: string;
201
202
/** Control suggestions visibility after selection */
203
shouldKeepSuggestionsOnSelect?: (suggestion: any) => boolean;
204
}
205
206
interface SuggestionSelectedParams {
207
suggestion: any;
208
suggestionValue: string;
209
suggestionIndex: number;
210
sectionIndex: number | null;
211
method: 'click' | 'enter';
212
}
213
214
interface SuggestionHighlightedParams {
215
suggestion: any | null;
216
}
217
218
interface RenderSuggestionsContainerParams {
219
containerProps: object;
220
children: React.ReactNode;
221
query: string;
222
}
223
224
interface Theme {
225
container?: string;
226
containerOpen?: string;
227
input?: string;
228
inputOpen?: string;
229
inputFocused?: string;
230
suggestionsContainer?: string;
231
suggestionsContainerOpen?: string;
232
suggestionsList?: string;
233
suggestion?: string;
234
suggestionFirst?: string;
235
suggestionHighlighted?: string;
236
sectionContainer?: string;
237
sectionContainerFirst?: string;
238
sectionTitle?: string;
239
}
240
```
241
242
### Multi-Section Usage
243
244
For organizing suggestions into multiple sections:
245
246
```javascript
247
const languages = [
248
{
249
title: 'C',
250
languages: [
251
{ name: 'C', year: 1972 },
252
{ name: 'C#', year: 2000 },
253
{ name: 'C++', year: 1983 }
254
]
255
},
256
{
257
title: 'JavaScript',
258
languages: [
259
{ name: 'JavaScript', year: 1995 },
260
{ name: 'TypeScript', year: 2012 }
261
]
262
}
263
];
264
265
const getSectionSuggestions = section => section.languages;
266
267
const renderSectionTitle = section => (
268
<strong>{section.title}</strong>
269
);
270
271
// In component:
272
<Autosuggest
273
multiSection={true}
274
suggestions={languages}
275
onSuggestionsFetchRequested={onSuggestionsFetchRequested}
276
onSuggestionsClearRequested={onSuggestionsClearRequested}
277
getSuggestionValue={getSuggestionValue}
278
renderSuggestion={renderSuggestion}
279
renderSectionTitle={renderSectionTitle}
280
getSectionSuggestions={getSectionSuggestions}
281
inputProps={inputProps}
282
/>
283
```
284
285
### Custom Styling with Theme
286
287
```javascript
288
const theme = {
289
container: 'my-autosuggest-container',
290
containerOpen: 'my-autosuggest-container--open',
291
input: 'my-autosuggest-input',
292
inputOpen: 'my-autosuggest-input--open',
293
inputFocused: 'my-autosuggest-input--focused',
294
suggestionsContainer: 'my-autosuggest-suggestions-container',
295
suggestionsContainerOpen: 'my-autosuggest-suggestions-container--open',
296
suggestionsList: 'my-autosuggest-suggestions-list',
297
suggestion: 'my-autosuggest-suggestion',
298
suggestionFirst: 'my-autosuggest-suggestion--first',
299
suggestionHighlighted: 'my-autosuggest-suggestion--highlighted',
300
sectionContainer: 'my-autosuggest-section-container',
301
sectionContainerFirst: 'my-autosuggest-section-container--first',
302
sectionTitle: 'my-autosuggest-section-title'
303
};
304
305
<Autosuggest
306
theme={theme}
307
// ... other props
308
/>
309
```
310
311
### Custom Input Component
312
313
```javascript
314
const renderInputComponent = inputProps => (
315
<div>
316
<input {...inputProps} />
317
<div>custom stuff</div>
318
</div>
319
);
320
321
<Autosuggest
322
renderInputComponent={renderInputComponent}
323
// ... other props
324
/>
325
```
326
327
### Custom Suggestions Container
328
329
```javascript
330
const renderSuggestionsContainer = ({ containerProps, children }) => (
331
<div {...containerProps}>
332
<div>custom header</div>
333
{children}
334
<div>custom footer</div>
335
</div>
336
);
337
338
<Autosuggest
339
renderSuggestionsContainer={renderSuggestionsContainer}
340
// ... other props
341
/>
342
```
343
344
### Asynchronous Suggestions
345
346
```javascript
347
const onSuggestionsFetchRequested = ({ value }) => {
348
// Clear previous suggestions
349
setSuggestions([]);
350
351
// Fetch suggestions asynchronously
352
fetch(`/api/suggestions?q=${encodeURIComponent(value)}`)
353
.then(response => response.json())
354
.then(data => {
355
setSuggestions(data.suggestions);
356
})
357
.catch(error => {
358
console.error('Error fetching suggestions:', error);
359
setSuggestions([]);
360
});
361
};
362
```
363
364
## Default Values
365
366
```javascript { .api }
367
// Default prop values
368
const defaultProps = {
369
renderSuggestionsContainer: ({ containerProps, children }) => (
370
<div {...containerProps}>{children}</div>
371
),
372
shouldRenderSuggestions: (value) => value.trim().length > 0,
373
alwaysRenderSuggestions: false,
374
multiSection: false,
375
shouldKeepSuggestionsOnSelect: () => false,
376
focusInputOnSuggestionClick: true,
377
highlightFirstSuggestion: false,
378
theme: {
379
container: 'react-autosuggest__container',
380
containerOpen: 'react-autosuggest__container--open',
381
input: 'react-autosuggest__input',
382
inputOpen: 'react-autosuggest__input--open',
383
inputFocused: 'react-autosuggest__input--focused',
384
suggestionsContainer: 'react-autosuggest__suggestions-container',
385
suggestionsContainerOpen: 'react-autosuggest__suggestions-container--open',
386
suggestionsList: 'react-autosuggest__suggestions-list',
387
suggestion: 'react-autosuggest__suggestion',
388
suggestionFirst: 'react-autosuggest__suggestion--first',
389
suggestionHighlighted: 'react-autosuggest__suggestion--highlighted',
390
sectionContainer: 'react-autosuggest__section-container',
391
sectionContainerFirst: 'react-autosuggest__section-container--first',
392
sectionTitle: 'react-autosuggest__section-title'
393
},
394
id: '1',
395
containerProps: {}
396
};
397
```
398
399
## Accessibility Features
400
401
React Autosuggest is fully WAI-ARIA compliant and provides:
402
403
- **Keyboard Navigation**: Arrow keys to navigate suggestions, Enter to select, Escape to close
404
- **Screen Reader Support**: Proper ARIA attributes for announcing suggestions and changes
405
- **Focus Management**: Maintains proper focus throughout interactions
406
- **Live Regions**: Announces suggestion counts and selection changes to screen readers
407
- **Role Attributes**: Proper semantic roles for autosuggest functionality
408
409
The component automatically handles all accessibility concerns without requiring additional configuration.