Skip to content

Commit cbeed30

Browse files
committed
add loading spinner
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. the color can be changed using the --loading-color variable.
1 parent 2061865 commit cbeed30

File tree

4 files changed

+74
-4
lines changed

4 files changed

+74
-4
lines changed

example/index.html

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,11 @@
1111
<div class="logo"></div>
1212

1313
<ge-autocomplete
14-
apiKey='ge-2550bcc43e8dd92e'
14+
apiKey='ge-9ccf84885004f273'
1515
size='4'
1616
lang='en'
1717
boundary.country='de'
18+
__host='api.dev.geocode.earth'
1819
></ge-autocomplete>
1920
<pre id="result"></pre>
2021
</div>

src/autocomplete/autocomplete.css

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929
rgba(0, 0, 0, 0) 0px 0px 0px 0px,
3030
rgba(0, 0, 0, 0.05) 0px 1px 2px 0px;
3131

32+
--loading-color: var(--gray-500);
33+
3234
--results-bg: #fff;
3335
--results-z-index: 10;
3436
--results-shadow:
@@ -75,7 +77,7 @@
7577
display: block;
7678
width: 100%;
7779
border: 1px solid var(--input-border-color);
78-
padding: 13px 12px;
80+
padding: 13px 55px 13px 12px; /* 12 + 31 + 12 = 55, loading spinner is 31 wide */;
7981
border-radius: var(--border-radius);
8082
appearance: none;
8183
-webkit-appearance: none;
@@ -84,6 +86,15 @@
8486
box-shadow: var(--input-shadow);
8587
}
8688

89+
.loading {
90+
position: absolute;
91+
right: 12px;
92+
top: 7px;
93+
width: 31px;
94+
height: 31px;
95+
stroke: var(--loading-color);
96+
}
97+
8798
.results {
8899
font-size: 16px;
89100
position: absolute;

src/autocomplete/autocomplete.js

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { createAutocomplete } from '@geocodeearth/core-js'
44
import debounce from 'lodash.debounce'
55
import css from './autocomplete.css'
66
import strings from '../strings'
7-
import { LocationMarker } from '../icons'
7+
import { LocationMarker, Loading } from '../icons'
88

99
const emptyResults = {
1010
text: '',
@@ -20,10 +20,11 @@ export default ({
2020
debounce: debounceWait = 300,
2121
onSelect: userOnSelectItem,
2222
onChange: userOnChange,
23-
onError = () => {},
23+
onError: userOnError,
2424
environment = window
2525
}) => {
2626
const [results, setResults] = useState(emptyResults)
27+
const [isLoading, setIsLoading] = useState(false)
2728
const inputRef = useRef()
2829

2930
// Geocode Earth Autocomplete Client
@@ -40,6 +41,7 @@ export default ({
4041
return
4142
}
4243

44+
setIsLoading(false)
4345
setResults({ text, features })
4446
})
4547
.catch(onError)
@@ -53,6 +55,7 @@ export default ({
5355
const onInputValueChange = ({ type, inputValue }) => {
5456
const term = inputValue.trim()
5557
if (term === '') {
58+
setIsLoading(false)
5659
setResults(emptyResults)
5760
}
5861

@@ -65,6 +68,7 @@ export default ({
6568
// which also fires this callback. this prevents an additional request after the user has already
6669
// selected an item.
6770
if (type === useCombobox.stateChangeTypes.InputChange && term.length > 0) {
71+
setIsLoading(true)
6872
debouncedSearch(term)
6973
}
7074
}
@@ -76,6 +80,14 @@ export default ({
7680
}
7781
}
7882

83+
// call user-supplied error callback
84+
const onError = (error) => {
85+
setIsLoading(false) // hide loading indicator as this normally happens after a successful request
86+
if (typeof userOnError === 'function') {
87+
userOnError(error)
88+
}
89+
}
90+
7991
// turns an autocomplete result (feature) into a string
8092
const itemToString = ({ properties: { label } }) => label
8193

@@ -112,6 +124,7 @@ export default ({
112124

113125
<div {...getComboboxProps()} >
114126
<input {...getInputProps({ref: inputRef})} spellCheck={false} placeholder={placeholder} className='input' />
127+
{isLoading && <Loading className={'loading'} />}
115128
</div>
116129

117130
<ol {...getMenuProps()} className={showResults ? 'results' : 'results-empty'}>

src/icons.js

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,48 @@ export const LocationMarker = ({className}) =>
1212
<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" />
1313
</svg>
1414

15+
/**
16+
* SVG Loaders (github.com/SamHerbert/SVG-Loaders)
17+
* Copyright (c) 2014 Sam Herbert
18+
*
19+
* @license MIT
20+
*/
21+
22+
// this is the `puff` loader
23+
export const Loading = ({ className }) =>
24+
<svg width="44" height="44" viewBox="0 0 44 44" xmlns="http://www.w3.org/2000/svg" stroke="currentColor" className={className}>
25+
<g fill="none" fillRule="evenodd" strokeWidth="2">
26+
<circle cx="22" cy="22" r="1">
27+
<animate attributeName="r"
28+
begin="0s" dur="1.4s"
29+
values="1; 20"
30+
calcMode="spline"
31+
keyTimes="0; 1"
32+
keySplines="0.165, 0.84, 0.44, 1"
33+
repeatCount="indefinite" />
34+
<animate attributeName="stroke-opacity"
35+
begin="0s" dur="1.4s"
36+
values="1; 0"
37+
calcMode="spline"
38+
keyTimes="0; 1"
39+
keySplines="0.3, 0.61, 0.355, 1"
40+
repeatCount="indefinite" />
41+
</circle>
42+
<circle cx="22" cy="22" r="1">
43+
<animate attributeName="r"
44+
begin="-0.7s" dur="1.4s"
45+
values="1; 20"
46+
calcMode="spline"
47+
keyTimes="0; 1"
48+
keySplines="0.165, 0.84, 0.44, 1"
49+
repeatCount="indefinite" />
50+
<animate attributeName="stroke-opacity"
51+
begin="-0.7s" dur="1.4s"
52+
values="1; 0"
53+
calcMode="spline"
54+
keyTimes="0; 1"
55+
keySplines="0.3, 0.61, 0.355, 1"
56+
repeatCount="indefinite" />
57+
</circle>
58+
</g>
59+
</svg>

0 commit comments

Comments
 (0)