UNPKG

5.91 kBJavaScriptView Raw
1import React from 'react'
2import PropTypes from 'prop-types'
3import styled from 'styled-components'
4
5import cloudinary from 'SRC/services/cloudinary'
6
7const SearchDiv = styled.div`
8 position: relative;
9 display: flex;
10 align-items: center;
11`
12
13const SearchBarDiv = styled.div`
14 z-index: 4;
15 position: fixed;
16 top: 0;
17 left: 0;
18 height: 326px;
19 width: 100%;
20 background-color: #FFFFFF;
21 overflow: hidden;
22
23 ${props => props.theme.breakpointsVerbose.aboveTabletMax`
24 height: 336px;
25 `}
26`
27
28const SearchModalDiv = styled.div`
29 z-index: 3;
30 position: fixed;
31 width: 100%;
32 height: 100%;
33 top: 0;
34 left: 0;
35 background-color: rgba(216, 216, 216, 0.7);
36`
37
38const SearchOverlayImage = styled.img`
39 margin: 17px auto 0 auto;
40 display: block;
41
42 ${props => props.theme.breakpointsVerbose.aboveTabletMax`
43 margin: 30px auto 0 auto;
44 `}
45`
46
47const SearchExitWrapperDiv = styled.div`
48 display: inline-block;
49 cursor: pointer;
50 width: 37px;
51 height: 37px;
52 position: absolute;
53 top: 0;
54 right: 0;
55
56 ${props => props.theme.breakpointsVerbose.aboveTabletMax`
57 top: 53px;
58 right: calc(50% - 300px - 10%);
59 `}
60
61 > svg {
62 position: absolute;
63 bottom: 0;
64 left: 0;
65
66 ${props => props.theme.breakpointsVerbose.aboveTabletMax`
67 top: 10px;
68 left: 10px;
69 `}
70 }
71`
72
73const SearchSuggestionsDiv = styled.div`
74 height: 42px;
75 width: 265px;
76 margin: auto;
77 margin-top: 5px;
78 font-family: ff-din-web,Helvetica,Arial,sans-serif;
79 font-size: 16px;
80 text-align: center;
81 color: #00003C;
82
83 ${props => props.theme.breakpointsVerbose.aboveTabletMax`
84 height: 21px;
85 width: 565px;
86 margin-top: 15px;
87 `}
88`
89
90const SearchForm = styled.form`
91 margin: auto;
92 margin-top: 75px;
93 width: 280px;
94 height: 37px;
95 border-bottom: 1px solid #0073D1;
96
97 ${props => props.theme.breakpointsVerbose.aboveTabletMax`
98 margin-top: 90px;
99 width: 600px;
100 height: 37px;
101 `}
102`
103
104const SearchClearWrapperDiv = styled.div`
105 display: inline-block;
106 cursor: pointer;
107 height: 26px;
108 width: 26px;
109
110 > svg {
111 margin-left: 10px;
112
113 ${props => props.theme.breakpointsVerbose.aboveTabletMax`
114 margin-bottom: 10px;
115 `}
116 }
117`
118
119const SearchInput = styled.input`
120 width: 250px;
121 height: 36px;
122 border: 0;
123 outline: none;
124 font-family: ${props => props.theme.fonts.secondaryFont};
125 font-size: 26px;
126 font-weight: 500;
127 color: #00003C;
128 display: inline-block;
129 padding: 0;
130 margin: 0;
131
132 ${props => props.theme.breakpointsVerbose.aboveTabletMax`
133 width: 570px;
134 height: 34px;
135 `}
136`
137
138class BaseSearchModal extends React.Component {
139 constructor (props) {
140 super(props)
141
142 this.state = { searchTerm: props.initialSearchTerm || '' }
143
144 this.updateSearchTerm = this.updateSearchTerm.bind(this)
145 this.clearSearchInput = this.clearSearchInput.bind(this)
146 this.keyDownSearchInput = this.keyDownSearchInput.bind(this)
147 this.submitSearch = this.submitSearch.bind(this)
148 }
149
150 updateSearchTerm = (event) => {
151 const { saveInitialSearchTerm } = this.props
152
153 const currentSearchTerm = event.target.value
154
155 this.setState({ searchTerm: currentSearchTerm })
156 saveInitialSearchTerm(currentSearchTerm)
157 }
158
159 clearSearchInput = () => {
160 this.setState({ searchTerm: '' })
161
162 const searchInput = document.getElementById('input-search');
163 searchInput.focus()
164 }
165
166 // Escape key exits search
167 keyDownSearchInput = (event) => {
168 const { exitSearch } = this.props
169
170 if (event.keyCode === 27) { exitSearch() }
171 }
172
173 submitSearch = (event) => {
174 event.preventDefault()
175
176 const { exitSearch, submitSearch } = this.props
177 const { searchTerm } = this.state
178
179 if (searchTerm.length > 0) {
180 submitSearch(searchTerm)
181 exitSearch()
182 }
183 }
184
185 render () {
186 const { exitSearch } = this.props
187 const { searchTerm } = this.state
188
189 const searchOverlayImageSrc = cloudinary.url('web/search/SearchOverlayDesktop')
190
191 return (
192 <SearchDiv>
193 <SearchBarDiv>
194 <SearchForm role='search' onSubmit={this.submitSearch}>
195 <SearchInput
196 id='input-search'
197 value={searchTerm}
198 onChange={this.updateSearchTerm}
199 onKeyDown={this.keyDownSearchInput}
200 autoFocus />
201 <SearchClearWrapperDiv onClick={this.clearSearchInput}>
202 <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 14 14">
203 <g fill="none" fillRule="evenodd">
204 <circle cx="7" cy="7" r="7" fill="#DCD6CE" />
205 <path stroke="#FFF" strokeLinecap="square" strokeWidth="2" d="M9.898 4.142l-5.796 6.216M4.102 4.142l5.796 6.216" />
206 </g>
207 </svg>
208 </SearchClearWrapperDiv>
209 </SearchForm>
210
211 <SearchSuggestionsDiv>Find it fast! Try: rainbow, sequin, neon, camo, ombre…</SearchSuggestionsDiv>
212 <SearchExitWrapperDiv onClick={() => exitSearch()}>
213 <svg xmlns="http://www.w3.org/2000/svg" width="17" height="17" viewBox="0 0 17 17">
214 <g fill="none" fillRule="evenodd" stroke="#0073D1">
215 <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" />
216 <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" />
217 </g>
218 </svg>
219 </SearchExitWrapperDiv>
220
221 <SearchOverlayImage src={searchOverlayImageSrc} />
222 </SearchBarDiv>
223 <SearchModalDiv onClick={() => exitSearch()} />
224 </SearchDiv>
225 )
226 }
227}
228
229BaseSearchModal.propTypes = {
230 initialSearchTerm: PropTypes.string,
231 saveInitialSearchTerm: PropTypes.func,
232 exitSearch: PropTypes.func,
233 submitSearch: PropTypes.func
234}
235
236const SearchModal = styled(BaseSearchModal)``
237
238export default SearchModal