From 15ba9157638df83bbdcfe330e36d93942bfb0b0c Mon Sep 17 00:00:00 2001 From: Timothy Biles Date: Fri, 16 Aug 2019 09:30:44 -0500 Subject: [PATCH 1/2] Add 3 autocomplete examples --- src/data/docs.yml | 1 + src/examples/AutoCompleteInput.md | 315 ++++++++++++++++++++++++++++++ 2 files changed, 316 insertions(+) create mode 100644 src/examples/AutoCompleteInput.md diff --git a/src/data/docs.yml b/src/data/docs.yml index fcf283e..ee81907 100644 --- a/src/data/docs.yml +++ b/src/data/docs.yml @@ -4,6 +4,7 @@ - section: Inputs paths: - /docs/checkbox + - /docs/autocomplete - section: Forms paths: - /docs/dynamic-fields diff --git a/src/examples/AutoCompleteInput.md b/src/examples/AutoCompleteInput.md new file mode 100644 index 0000000..5770fdc --- /dev/null +++ b/src/examples/AutoCompleteInput.md @@ -0,0 +1,315 @@ +--- +path: /docs/autocomplete +--- + +# Autocomplete Input + +Accessible autocomplete examples. + +(Compliant with [wai-aria-practices](https://www.w3.org/TR/wai-aria-practices-1.1/#Listbox)) + +## Usage + +### Standard dropdown search. + +```jsx +import React, { useState, useEffect } from 'react'; + +const dropdownStyle = { + background: '#efefef', + padding: '5px', +}; + +const optionStyle = { + cursor: 'pointer', +}; + +function Example() { + const [color, setColor] = useState(''); + const [options] = useState([ + 'red', + 'green', + 'blue', + 'purple', + 'orange', + 'yellow', + ]); + const [filteredOptions, setFilteredOptions] = useState([]); + const [selected, setSelected] = useState(false); + + // As the color changes with every keystroke, the options array will be filtered out to match the color variable + useEffect(() => { + const filteredSearch = options.filter(option => + option.toLowerCase().includes(color.toLowerCase()) + ); + setFilteredOptions(filteredSearch); + }, [color, options, setFilteredOptions]); + + const handleColorChange = event => { + setColor(event.target.value); + setSelected(false); + }; + + const selectOption = option => { + setColor(option); + setSelected(true); + }; + + return ( +
+

Tell us your favorite color!

+ + {/* The dropdown options will display if the input field has value, and no option has been selected. */} + {color && !selected && ( +
+ {filteredOptions.length > 0 ? ( + filteredOptions.map((option, optionIndex) => { + return ( +

selectOption(option)} + > + {option} +

+ ); + }) + ) : ( + // If the color is not found in the options array, this error message will display. +

Option not found!

+ )} +
+ )} +
+ ); +} +``` + + +### Autocomplete with keyboard accessible. + +```jsx +import React, { useState, useEffect } from 'react'; + +const dropdownStyle = { + background: '#efefef', + padding: '5px', +}; + +const optionStyle = { + cursor: 'pointer', +}; + +const activeOptionStyle = { + color: 'teal', + background: '#e9e9e9', + cursor: 'pointer', +}; + +function Example() { + const [color, setColor] = useState(''); + const [options] = useState([ + 'red', + 'green', + 'blue', + 'purple', + 'orange', + 'yellow', + ]); + const [filteredOptions, setFilteredOptions] = useState([]); + const [selected, setSelected] = useState(false); + const [activeSuggestion, setActiveSuggestion] = useState(0) + + // As the color changes with every keystroke, the options array will be filtered out to match the color variable + useEffect(() => { + const filteredSearch = options.filter(option => + option.toLowerCase().includes(color.toLowerCase()) + ); + setActiveSuggestion(0) + setFilteredOptions(filteredSearch); + }, [color, options, setFilteredOptions]); + + const handleColorChange = event => { + setColor(event.target.value); + setSelected(false); + }; + + const selectOption = option => { + setColor(option); + setSelected(true); + }; + +// Keydown event handles the ability to navigate with the up and down arrows. + const handleKeyDown = event => { + if ( + event.key === 'ArrowDown' && + activeSuggestion < filteredOptions.length - 1 + ) { + setActiveSuggestion(activeSuggestion + 1); + } + if (event.key === 'ArrowUp' && activeSuggestion > 0) { + setActiveSuggestion(activeSuggestion - 1); + } + + if (event.key === 'Enter') { + setColor(filteredOptions[activeSuggestion]); + setSelected(true) + } + }; + + return ( +
+

Tell us your favorite color!

+ + {/* The dropdown options will display if the input field has value, and no option has been selected. */} + {color && !selected && ( +
+ {filteredOptions.length > 0 ? ( + filteredOptions.map((option, optionIndex) => { + return ( +

selectOption(option)} + > + {option} +

+ ); + }) + ) : ( + // If the color is not found in the options array, this error message will display. +

Option not found!

+ )} +
+ )} +
+ ); +} +``` + +### Autocomplete with asynchronous information + +```jsx +import React, { useState, useEffect } from 'react'; + +const dropdownStyle = { + background: '#efefef', + padding: '5px', +}; + +const optionStyle = { + cursor: 'pointer', +}; + +const activeOptionStyle = { + color: 'teal', + background: '#e9e9e9', + cursor: 'pointer', +}; + +function Example() { + const [color, setColor] = useState(''); + const [options, setOptions] = useState([]); + const [filteredOptions, setFilteredOptions] = useState([]); + const [selected, setSelected] = useState(false); + const [activeSuggestion, setActiveSuggestion] = useState(0); + + // API to retrieve the information from the pokemon API + // https://pokeapi.co/ + useEffect(() => { + fetch('https://pokeapi.co/api/v2/pokemon/?limit=20') + .then(function(response) { + return response.json(); + }) + .then(function(data) { + const pokemonData = data.results.map(pokemon => pokemon.name); + // Set the options once data is received. + setOptions(pokemonData); + }); + }, []); + + // As the color changes with every keystroke, the options array will be filtered out to match the color variable + useEffect(() => { + const filteredSearch = options.filter(option => + option.toLowerCase().includes(color.toLowerCase()) + ); + setActiveSuggestion(0); + setFilteredOptions(filteredSearch); + }, [color, options, setFilteredOptions]); + + const handleColorChange = event => { + setColor(event.target.value); + setSelected(false); + }; + + const selectOption = option => { + setColor(option); + setSelected(true); + }; + +// Keydown event handles the ability to navigate with the up and down arrows. + const handleKeyDown = event => { + if ( + event.key === 'ArrowDown' && + activeSuggestion < filteredOptions.length - 1 + ) { + setActiveSuggestion(activeSuggestion + 1); + } + if (event.key === 'ArrowUp' && activeSuggestion > 0) { + setActiveSuggestion(activeSuggestion - 1); + } + + if (event.key === 'Enter') { + setColor(filteredOptions[activeSuggestion]); + setSelected(true); + } + }; + + return ( +
+

Tell us your favorite pokemon!

+ + {/* The dropdown options will display if the input field has value, and no option has been selected. */} + {color && !selected && ( +
+ {!options.length ? ( +

loading ...

+ ) : filteredOptions.length > 0 ? ( + filteredOptions.map((option, optionIndex) => { + return ( +

selectOption(option)} + > + {option} +

+ ); + }) + ) : ( + // If the color is not found in the options array, this error message will display. +

Option not found!

+ )} +
+ )} +
+ ); +} + + +``` + + +## Props + +N/A + From 5091156533e1eac3fe85718af36a9a7ab024fbd8 Mon Sep 17 00:00:00 2001 From: Timothy Biles Date: Fri, 16 Aug 2019 11:05:49 -0500 Subject: [PATCH 2/2] Edit md header, spelling error on checkbox.md --- src/examples/AutoCompleteInput.md | 8 ++++---- src/examples/Checkbox.md | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/examples/AutoCompleteInput.md b/src/examples/AutoCompleteInput.md index 5770fdc..7d851ca 100644 --- a/src/examples/AutoCompleteInput.md +++ b/src/examples/AutoCompleteInput.md @@ -10,7 +10,7 @@ Accessible autocomplete examples. ## Usage -### Standard dropdown search. +### Standard dropdown search ```jsx import React, { useState, useEffect } from 'react'; @@ -86,7 +86,7 @@ function Example() { ``` -### Autocomplete with keyboard accessible. +### Dropdown with keyboard accessibility ```jsx import React, { useState, useEffect } from 'react'; @@ -187,7 +187,7 @@ function Example() { } ``` -### Autocomplete with asynchronous information +### Dropdown with asynchronous information ```jsx import React, { useState, useEffect } from 'react'; @@ -217,7 +217,7 @@ function Example() { // API to retrieve the information from the pokemon API // https://pokeapi.co/ useEffect(() => { - fetch('https://pokeapi.co/api/v2/pokemon/?limit=20') + fetch('https://pokeapi.co/api/v2/pokemon/?limit=150') .then(function(response) { return response.json(); }) diff --git a/src/examples/Checkbox.md b/src/examples/Checkbox.md index d0ef1a2..9fe2295 100644 --- a/src/examples/Checkbox.md +++ b/src/examples/Checkbox.md @@ -51,7 +51,7 @@ label { ``` -### With Custom Chechbox +### With Custom Checkbox ```jsx import React, { useState } from "react";