From 234a45d0ce8c7a6c5009e73ce9fb5666f67bbf94 Mon Sep 17 00:00:00 2001 From: Max Lielje Date: Thu, 6 May 2021 13:05:23 +0200 Subject: [PATCH] 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. --- src/autocomplete/autocomplete.js | 18 ++++++++-- src/autocomplete/autocomplete.module.css | 11 +++++- src/icons.js | 46 ++++++++++++++++++++++++ 3 files changed, 72 insertions(+), 3 deletions(-) diff --git a/src/autocomplete/autocomplete.js b/src/autocomplete/autocomplete.js index 0543e85..b4577b7 100644 --- a/src/autocomplete/autocomplete.js +++ b/src/autocomplete/autocomplete.js @@ -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: '', @@ -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(() => { @@ -38,6 +39,7 @@ export default ({ return } + setIsLoading(false) setResults({ text, features }) }) .catch(onError) @@ -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) } } @@ -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 @@ -96,6 +109,7 @@ export default ({
+ { isLoading && }
    diff --git a/src/autocomplete/autocomplete.module.css b/src/autocomplete/autocomplete.module.css index a699943..64f20b4 100644 --- a/src/autocomplete/autocomplete.module.css +++ b/src/autocomplete/autocomplete.module.css @@ -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; @@ -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; diff --git a/src/icons.js b/src/icons.js index ad77a7e..59e7bd8 100644 --- a/src/icons.js +++ b/src/icons.js @@ -12,3 +12,49 @@ export const LocationMarker = ({className}) => + +/** + * SVG Loaders (github.com/SamHerbert/SVG-Loaders) + * Copyright (c) 2014 Sam Herbert + * + * @license MIT + */ + +// this is the `puff` loader +export const Loading = ({className}) => + + + + + + + + + + + +