@rocketsofawesome/mirage
Version:
[Live Demo of the Pattern Library](https://rocketsofawesome.github.io/mirage/)
237 lines (195 loc) • 5.88 kB
JavaScript
import React from 'react'
import PropTypes from 'prop-types'
import styled from 'styled-components'
import cloudinary from 'SRC/services/cloudinary'
const SearchDiv = styled.div`
position: relative;
display: flex;
align-items: center;
`
const SearchBarDiv = styled.div`
z-index: 51;
position: fixed;
top: 0;
left: 0;
height: 326px;
width: 100%;
background-color: #FFFFFF;
overflow: hidden;
${props => props.theme.breakpointsVerbose.aboveTabletMax`
height: 336px;
`}
`
const SearchModalDiv = styled.div`
z-index: 50;
position: fixed;
width: 100%;
height: 100%;
top: 0;
left: 0;
background-color: rgba(216, 216, 216, 0.7);
`
const SearchOverlayImage = styled.img`
margin: 17px auto 0 auto;
display: block;
${props => props.theme.breakpointsVerbose.aboveTabletMax`
margin: 30px auto 0 auto;
`}
`
const SearchExitWrapperDiv = styled.div`
display: inline-block;
cursor: pointer;
width: 37px;
height: 37px;
position: absolute;
top: 0;
right: 0;
${props => props.theme.breakpointsVerbose.aboveTabletMax`
top: 53px;
right: calc(50% - 300px - 10%);
`}
> svg {
position: absolute;
bottom: 0;
left: 0;
${props => props.theme.breakpointsVerbose.aboveTabletMax`
top: 10px;
left: 10px;
`}
}
`
const SearchSuggestionsDiv = styled.div`
height: 42px;
width: 265px;
margin: auto;
margin-top: 5px;
font-family: ff-din-web,Helvetica,Arial,sans-serif;
font-size: 16px;
text-align: center;
color: #00003C;
${props => props.theme.breakpointsVerbose.aboveTabletMax`
height: 21px;
width: 565px;
margin-top: 15px;
`}
`
const SearchForm = styled.form`
margin: auto;
margin-top: 75px;
width: 280px;
border-bottom: 1px solid #0073D1;
${props => props.theme.breakpointsVerbose.aboveTabletMax`
margin-top: 90px;
width: 600px;
`}
`
const SearchClearWrapperDiv = styled.div`
display: inline-block;
cursor: pointer;
height: 26px;
width: 26px;
> svg {
margin-left: 10px;
${props => props.theme.breakpointsVerbose.aboveTabletMax`
margin-bottom: 10px;
`}
}
`
const SearchInput = styled.input`
width: 250px;
height: 36px;
border: 0;
outline: none;
font-family: ${props => props.theme.fonts.secondaryFont};
font-size: 26px;
font-weight: 500;
color: #00003C;
display: inline-block;
padding: 0;
margin: 0;
${props => props.theme.breakpointsVerbose.aboveTabletMax`
width: 570px;
height: 34px;
`}
`
class BaseSearchModal extends React.Component {
constructor (props) {
super(props)
this.state = { searchTerm: props.initialSearchTerm || '' }
this.updateSearchTerm = this.updateSearchTerm.bind(this)
this.clearSearchInput = this.clearSearchInput.bind(this)
this.keyDownSearchInput = this.keyDownSearchInput.bind(this)
this.submitSearch = this.submitSearch.bind(this)
}
updateSearchTerm = (event) => {
const { saveInitialSearchTerm } = this.props
const currentSearchTerm = event.target.value
this.setState({ searchTerm: currentSearchTerm })
saveInitialSearchTerm(currentSearchTerm)
}
clearSearchInput = () => {
this.setState({ searchTerm: '' })
const searchInput = document.getElementById('input-search');
searchInput.focus()
}
// Escape key exits search
keyDownSearchInput = (event) => {
const { exitSearch } = this.props
if (event.keyCode === 27) { exitSearch() }
}
submitSearch = (event) => {
event.preventDefault()
const { exitSearch, submitSearch } = this.props
const { searchTerm } = this.state
if (searchTerm.length > 0) {
submitSearch(searchTerm)
exitSearch()
}
}
render () {
const { exitSearch } = this.props
const { searchTerm } = this.state
const searchOverlayImageSrc = cloudinary.url('web/search/SearchOverlay')
return (
<SearchDiv>
<SearchBarDiv>
<SearchForm role='search' onSubmit={this.submitSearch}>
<SearchInput
id='input-search'
value={searchTerm}
onChange={this.updateSearchTerm}
onKeyDown={this.keyDownSearchInput}
autoFocus />
<SearchClearWrapperDiv onClick={this.clearSearchInput}>
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 14 14">
<g fill="none" fillRule="evenodd">
<circle cx="7" cy="7" r="7" fill="#DCD6CE" />
<path stroke="#FFF" strokeLinecap="square" strokeWidth="2" d="M9.898 4.142l-5.796 6.216M4.102 4.142l5.796 6.216" />
</g>
</svg>
</SearchClearWrapperDiv>
</SearchForm>
<SearchSuggestionsDiv>Find it fast! Try: CrazySoft, joggers, leggings, jackets...</SearchSuggestionsDiv>
<SearchExitWrapperDiv onClick={() => exitSearch()}>
<svg xmlns="http://www.w3.org/2000/svg" width="17" height="17" viewBox="0 0 17 17">
<g fill="none" fillRule="evenodd" stroke="#0073D1">
<path d="M1.37 1.841a.442.442 0 0 0-.002.628l12.69 12.69a.439.439 0 0 0 .628 0 .442.442 0 0 0 .001-.628L1.997 1.84a.439.439 0 0 0-.628 0z" />
<path d="M1.37 15.159a.442.442 0 0 0 .627 0l12.69-12.69a.439.439 0 0 0 0-.628.442.442 0 0 0-.628 0L1.369 14.53a.439.439 0 0 0 0 .628z" />
</g>
</svg>
</SearchExitWrapperDiv>
<SearchOverlayImage src={searchOverlayImageSrc} />
</SearchBarDiv>
<SearchModalDiv onClick={() => exitSearch()} />
</SearchDiv>
)
}
}
BaseSearchModal.propTypes = {
initialSearchTerm: PropTypes.string,
saveInitialSearchTerm: PropTypes.func,
exitSearch: PropTypes.func,
submitSearch: PropTypes.func
}
const SearchModal = styled(BaseSearchModal)``
export default SearchModal