Skip to content

Commit

Permalink
add loading spinner
Browse files Browse the repository at this point in the history
the spinner is shown as the user types (and requests are being made) and
is hidden when a request comes back with results, as well as when an
error occurs.

to hide it on error required wrapping the user-supplied error callback
in our own function.
  • Loading branch information
mxlje committed May 11, 2021
1 parent 9fcb781 commit 234a45d
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 3 deletions.
18 changes: 16 additions & 2 deletions src/autocomplete/autocomplete.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { createAutocomplete } from '@geocodeearth/core-js'
import debounce from 'lodash.debounce'
import styles, { css } from './autocomplete.module.css'
import strings from '../strings'
import { LocationMarker } from '../icons'
import { LocationMarker, Loading } from '../icons'

const emptyResults = {
text: '',
Expand All @@ -18,11 +18,12 @@ export default ({
placeholder = strings.inputPlaceholder,
debounce: debounceWait = 300,
onSelect: userOnSelectItem,
onError = () => {},
onError: userOnError,
environment = window
}) => {
const [results, setResults] = useState(emptyResults)
const [searchTerm, setSearchTerm] = useState('')
const [isLoading, setIsLoading] = useState(false)

// Geocode Earth Autocomplete Client
const autocomplete = useMemo(() => {
Expand All @@ -38,6 +39,7 @@ export default ({
return
}

setIsLoading(false)
setResults({ text, features })
})
.catch(onError)
Expand All @@ -52,10 +54,13 @@ export default ({
const term = inputValue.trim()
setSearchTerm(term)

if (term === '') setIsLoading(false)

// only search if the input value actually changed and not if an item was selected,
// which also fires this callback. this prevents an additional request after the user has already
// selected an item.
if (type === useCombobox.stateChangeTypes.InputChange && term.length > 0) {
setIsLoading(true)
debouncedSearch(term)
}
}
Expand All @@ -67,6 +72,14 @@ export default ({
}
}

// call user-supplied error callback
const onError = (error) => {
setIsLoading(false) // hide loading indicator as this normally happens after a successful request
if (typeof userOnError === 'function') {
userOnError(error)
}
}

// turns an autocomplete result (feature) into a string
const itemToString = ({ properties: { label } }) => label

Expand Down Expand Up @@ -96,6 +109,7 @@ export default ({

<div {...getComboboxProps()} >
<input {...getInputProps()} spellCheck={false} placeholder={placeholder} className={styles.input} />
{ isLoading && <Loading className={styles.loading} /> }
</div>

<ol {...getMenuProps()} className={showResults ? styles.results : styles.resultsEmpty}>
Expand Down
11 changes: 10 additions & 1 deletion src/autocomplete/autocomplete.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
width: 100%;
height: 45px;
border: solid 1px rgba(255,255,255,.5);
padding: 8px 12px;
padding: 8px 55px 8px 12px; /* 12 + 31 + 12 = 55, loading spinner is 31 wide */
border-radius: 5px;
appearance: none;
-webkit-appearance: none;
Expand All @@ -34,6 +34,15 @@
box-shadow: rgba(0, 0, 0, 0.2) 0px 1px 10px 0px, rgba(0, 0, 0, 0.1) 0px 2px 4px 0px;
}

.loading {
position: absolute;
right: 12px;
top: 7px;
width: 31px;
height: 31px;
stroke: #707f8e;
}

.results {
font-size: 16px;
position: absolute;
Expand Down
46 changes: 46 additions & 0 deletions src/icons.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,49 @@ export const LocationMarker = ({className}) =>
<path fillRule="evenodd" d="M5.05 4.05a7 7 0 119.9 9.9L10 18.9l-4.95-4.95a7 7 0 010-9.9zM10 11a2 2 0 100-4 2 2 0 000 4z" clipRule="evenodd" />
</svg>


/**
* SVG Loaders (github.com/SamHerbert/SVG-Loaders)
* Copyright (c) 2014 Sam Herbert
*
* @license MIT
*/

// this is the `puff` loader
export const Loading = ({className}) =>
<svg width="44" height="44" viewBox="0 0 44 44" xmlns="http://www.w3.org/2000/svg" stroke="currentColor" className={className}>
<g fill="none" fillRule="evenodd" strokeWidth="2">
<circle cx="22" cy="22" r="1">
<animate attributeName="r"
begin="0s" dur="1.4s"
values="1; 20"
calcMode="spline"
keyTimes="0; 1"
keySplines="0.165, 0.84, 0.44, 1"
repeatCount="indefinite" />
<animate attributeName="stroke-opacity"
begin="0s" dur="1.4s"
values="1; 0"
calcMode="spline"
keyTimes="0; 1"
keySplines="0.3, 0.61, 0.355, 1"
repeatCount="indefinite" />
</circle>
<circle cx="22" cy="22" r="1">
<animate attributeName="r"
begin="-0.7s" dur="1.4s"
values="1; 20"
calcMode="spline"
keyTimes="0; 1"
keySplines="0.165, 0.84, 0.44, 1"
repeatCount="indefinite" />
<animate attributeName="stroke-opacity"
begin="-0.7s" dur="1.4s"
values="1; 0"
calcMode="spline"
keyTimes="0; 1"
keySplines="0.3, 0.61, 0.355, 1"
repeatCount="indefinite" />
</circle>
</g>
</svg>

0 comments on commit 234a45d

Please sign in to comment.