diff --git a/app/components/FilterOptions.js b/app/components/FilterOptions.js index 9221dda6..de41077d 100644 --- a/app/components/FilterOptions.js +++ b/app/components/FilterOptions.js @@ -76,11 +76,6 @@ const FilterOptions = ({ ); }; -const LabelWithNote = styled.div` - font-weight: 500; - text-align: left; -`; - const Note = styled(HelpText)` margin-top: 2px; margin-bottom: 0; @@ -90,6 +85,15 @@ const Note = styled(HelpText)` color: ${(props) => props.theme.textTertiary}; `; +const LabelWithNote = styled.div` + font-weight: 500; + text-align: left; + + &:hover ${Note} { + color: ${(props) => props.theme.white50}; + } +`; + const StyledButton = styled(Button)` box-shadow: none; text-transform: none; diff --git a/app/components/InputSearchPage.js b/app/components/InputSearchPage.js index 2dec1bff..872d8113 100644 --- a/app/components/InputSearchPage.js +++ b/app/components/InputSearchPage.js @@ -40,14 +40,20 @@ class InputSearchPage extends React.Component { } } - handleSearchInput = (ev: SyntheticInputEvent<>) => { - ev.preventDefault(); - this.props.history.push( - searchUrl(ev.target.value, { - collectionId: this.props.collectionId, - ref: this.props.source, - }) - ); + handleKeyDown = (ev: SyntheticKeyboardEvent) => { + if (ev.key === "Enter") { + ev.preventDefault(); + this.props.history.push( + searchUrl(ev.currentTarget.value, { + collectionId: this.props.collectionId, + ref: this.props.source, + }) + ); + } + + if (this.props.onKeyDown) { + this.props.onKeyDown(ev); + } }; handleFocus = () => { @@ -59,7 +65,7 @@ class InputSearchPage extends React.Component { }; render() { - const { t, value, onChange, onKeyDown } = this.props; + const { t, value, onChange } = this.props; const { theme, placeholder = `${t("Search")}…` } = this.props; return ( @@ -67,10 +73,9 @@ class InputSearchPage extends React.Component { ref={(ref) => (this.input = ref)} type="search" placeholder={placeholder} - onInput={this.handleSearchInput} value={value} onChange={onChange} - onKeyDown={onKeyDown} + onKeyDown={this.handleKeyDown} icon={ { this.props.history.goBack(); } - handleKeyDown = (ev: SyntheticKeyboardEvent<>) => { + handleKeyDown = (ev: SyntheticKeyboardEvent) => { if (ev.key === "Enter") { + this.updateLocation(ev.currentTarget.value); this.fetchResults(); return; } @@ -117,7 +118,7 @@ class Search extends React.Component { // To prevent "no results" showing before debounce kicks in this.isLoading = true; - this.fetchResultsDebounced(); + this.fetchResults(); }; handleTermChange = () => { @@ -127,9 +128,9 @@ class Search extends React.Component { this.allowLoadMore = true; // To prevent "no results" showing before debounce kicks in - this.isLoading = !!this.query; + this.isLoading = true; - this.fetchResultsDebounced(); + this.fetchResults(); }; handleFilterChange = (search: { @@ -241,15 +242,11 @@ class Search extends React.Component { } } else { this.pinToTop = false; + this.isLoading = false; this.lastQuery = this.query; } }; - fetchResultsDebounced = debounce(this.fetchResults, 500, { - leading: false, - trailing: true, - }); - updateLocation = (query: string) => { this.props.history.replace({ pathname: searchUrl(query), @@ -283,10 +280,9 @@ class Search extends React.Component { )} - {showShortcutTip && ( diff --git a/app/scenes/Search/components/SearchField.js b/app/scenes/Search/components/SearchField.js deleted file mode 100644 index c4425f35..00000000 --- a/app/scenes/Search/components/SearchField.js +++ /dev/null @@ -1,97 +0,0 @@ -// @flow -import { SearchIcon } from "outline-icons"; -import * as React from "react"; -import styled, { withTheme } from "styled-components"; -import Flex from "components/Flex"; -import { type Theme } from "types"; - -type Props = { - onChange: (string) => void, - defaultValue?: string, - placeholder?: string, - theme: Theme, -}; - -class SearchField extends React.Component { - input: ?HTMLInputElement; - - componentDidMount() { - if (this.props && this.input) { - // ensure that focus is placed at end of input - const len = (this.props.defaultValue || "").length; - this.input.setSelectionRange(len, len); - } - } - - handleChange = (ev: SyntheticEvent) => { - this.props.onChange(ev.currentTarget.value ? ev.currentTarget.value : ""); - }; - - focusInput = (ev: SyntheticEvent<>) => { - if (this.input) this.input.focus(); - }; - - render() { - return ( - - - (this.input = ref)} - onChange={this.handleChange} - spellCheck="false" - placeholder={this.props.placeholder} - type="search" - autoFocus - /> - - ); - } -} - -const Field = styled(Flex)` - position: relative; - margin-bottom: 8px; -`; - -const StyledInput = styled.input` - width: 100%; - padding: 10px 10px 10px 60px; - font-size: 36px; - font-weight: 400; - outline: none; - border: 0; - background: ${(props) => props.theme.sidebarBackground}; - transition: ${(props) => props.theme.backgroundTransition}; - border-radius: 4px; - - color: ${(props) => props.theme.text}; - - ::-webkit-search-cancel-button { - -webkit-appearance: none; - } - ::-webkit-input-placeholder { - color: ${(props) => props.theme.placeholder}; - } - :-moz-placeholder { - color: ${(props) => props.theme.placeholder}; - } - ::-moz-placeholder { - color: ${(props) => props.theme.placeholder}; - } - :-ms-input-placeholder { - color: ${(props) => props.theme.placeholder}; - } -`; - -const StyledIcon = styled(SearchIcon)` - position: absolute; - left: 8px; -`; - -export default withTheme(SearchField); diff --git a/app/scenes/Search/components/SearchInput.js b/app/scenes/Search/components/SearchInput.js new file mode 100644 index 00000000..bdd8534b --- /dev/null +++ b/app/scenes/Search/components/SearchInput.js @@ -0,0 +1,86 @@ +// @flow +import { SearchIcon } from "outline-icons"; +import * as React from "react"; +import styled, { useTheme } from "styled-components"; +import Flex from "components/Flex"; + +type Props = { + defaultValue?: string, + placeholder?: string, +}; + +function SearchInput({ defaultValue, ...rest }: Props) { + const theme = useTheme(); + const inputRef = React.useRef(); + + React.useEffect(() => { + // ensure that focus is placed at end of input + const len = (defaultValue || "").length; + inputRef.current?.setSelectionRange(len, len); + }, [defaultValue]); + + const focusInput = React.useCallback((ev: SyntheticEvent<>) => { + inputRef.current?.focus(); + }, []); + + return ( + + + + + ); +} + +const Wrapper = styled(Flex)` + position: relative; + margin-bottom: 8px; +`; + +const StyledInput = styled.input` + width: 100%; + padding: 10px 10px 10px 60px; + font-size: 36px; + font-weight: 400; + outline: none; + border: 0; + background: ${(props) => props.theme.sidebarBackground}; + transition: ${(props) => props.theme.backgroundTransition}; + border-radius: 4px; + + color: ${(props) => props.theme.text}; + + ::-webkit-search-cancel-button { + -webkit-appearance: none; + } + ::-webkit-input-placeholder { + color: ${(props) => props.theme.placeholder}; + } + :-moz-placeholder { + color: ${(props) => props.theme.placeholder}; + } + ::-moz-placeholder { + color: ${(props) => props.theme.placeholder}; + } + :-ms-input-placeholder { + color: ${(props) => props.theme.placeholder}; + } +`; + +const StyledIcon = styled(SearchIcon)` + position: absolute; + left: 8px; +`; + +export default SearchInput;