From 05d18805568c8fbb95b053880389c070f6540120 Mon Sep 17 00:00:00 2001 From: Tom Moor Date: Tue, 17 Oct 2017 23:21:22 -0700 Subject: [PATCH] Add reusable empty state Add empty state for no starred documents Add empty state for no search results --- frontend/components/Empty/Empty.js | 21 +++++++++ frontend/components/Empty/index.js | 3 ++ frontend/scenes/Search/Search.js | 11 +++-- .../components/SearchField/SearchField.js | 45 ++++++++++--------- frontend/scenes/Starred/Starred.js | 10 +++-- frontend/styles/animations.js | 5 +++ 6 files changed, 68 insertions(+), 27 deletions(-) create mode 100644 frontend/components/Empty/Empty.js create mode 100644 frontend/components/Empty/index.js diff --git a/frontend/components/Empty/Empty.js b/frontend/components/Empty/Empty.js new file mode 100644 index 000000000..822d990aa --- /dev/null +++ b/frontend/components/Empty/Empty.js @@ -0,0 +1,21 @@ +// @flow +import React from 'react'; +import styled from 'styled-components'; +import { color } from 'styles/constants'; + +type Props = { + children: string, +}; + +const Empty = (props: Props) => { + const { children, ...rest } = props; + return {children}; +}; + +const Container = styled.div` + display: flex; + color: ${color.slate}; + text-align: center; +`; + +export default Empty; diff --git a/frontend/components/Empty/index.js b/frontend/components/Empty/index.js new file mode 100644 index 000000000..5c3c3a071 --- /dev/null +++ b/frontend/components/Empty/index.js @@ -0,0 +1,3 @@ +// @flow +import Empty from './Empty'; +export default Empty; diff --git a/frontend/scenes/Search/Search.js b/frontend/scenes/Search/Search.js index 71e0b2c83..9050d0564 100644 --- a/frontend/scenes/Search/Search.js +++ b/frontend/scenes/Search/Search.js @@ -12,6 +12,7 @@ import { searchUrl } from 'utils/routeHelpers'; import styled from 'styled-components'; import ArrowKeyNavigation from 'boundless-arrow-key-navigation'; +import Empty from 'components/Empty'; import Flex from 'components/Flex'; import CenteredContent from 'components/CenteredContent'; import LoadingIndicator from 'components/LoadingIndicator'; @@ -57,7 +58,7 @@ const StyledArrowKeyNavigation = styled(ArrowKeyNavigation)` firstDocument: HTMLElement; props: Props; - @observable resultIds: Array = []; // Document IDs + @observable resultIds: string[] = []; // Document IDs @observable searchTerm: ?string = null; @observable isFetching = false; @@ -131,18 +132,19 @@ const StyledArrowKeyNavigation = styled(ArrowKeyNavigation)` } render() { - const { documents } = this.props; + const { documents, notFound } = this.props; const query = this.props.match.params.query; const hasResults = this.resultIds.length > 0; + const showEmpty = !this.isFetching && this.searchTerm && !hasResults; return ( {this.isFetching && } - {this.props.notFound && + {notFound &&

Not Found

-

We're unable to find the page you're accessing.

+

We’re unable to find the page you’re accessing.

} + {showEmpty && Oop, no matching documents.} { + setRef = (ref: HTMLInputElement) => { this.input = ref; }; render() { return ( - - @@ -58,4 +45,22 @@ class SearchField extends Component { } } +const StyledInput = styled.input` + width: 100%; + padding: 10px; + font-size: 48px; + font-weight: 400; + outline: none; + border: 0; + + ::-webkit-input-placeholder { color: ${color.slateLight}; } + :-moz-placeholder { color: ${color.slateLight}; } + ::-moz-placeholder { color: ${color.slateLight}; } + :-ms-input-placeholder { color: ${color.slateLight}; } +`; + +const StyledIcon = styled(Icon)` + top: 3px; +`; + export default SearchField; diff --git a/frontend/scenes/Starred/Starred.js b/frontend/scenes/Starred/Starred.js index 6704045c1..c2abfbb08 100644 --- a/frontend/scenes/Starred/Starred.js +++ b/frontend/scenes/Starred/Starred.js @@ -3,6 +3,7 @@ import React, { Component } from 'react'; import { observer, inject } from 'mobx-react'; import CenteredContent from 'components/CenteredContent'; import { ListPlaceholder } from 'components/LoadingPlaceholder'; +import Empty from 'components/Empty'; import PageTitle from 'components/PageTitle'; import DocumentList from 'components/DocumentList'; import DocumentsStore from 'stores/DocumentsStore'; @@ -17,14 +18,17 @@ import DocumentsStore from 'stores/DocumentsStore'; } render() { - const { isLoaded, isFetching } = this.props.documents; + const { isLoaded, isFetching, starred } = this.props.documents; + const showLoading = !isLoaded && isFetching; + const showEmpty = isLoaded && !starred.length; return (

Starred

- {!isLoaded && isFetching && } - + {showLoading && } + {showEmpty && No starred documents yet.} +
); } diff --git a/frontend/styles/animations.js b/frontend/styles/animations.js index 257528b57..e6a9d5c25 100644 --- a/frontend/styles/animations.js +++ b/frontend/styles/animations.js @@ -1,6 +1,11 @@ // @flow import { keyframes } from 'styled-components'; +export const fadeIn = keyframes` + from { opacity: 0; } + to { opacity: 1; } +`; + export const fadeAndScaleIn = keyframes` from { opacity: 0;