123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148 |
- import fuse from 'fuse.js'
- import theme from '../styles/theme'
- const dummyResults = [
- {
- title: 'good :-)',
- text: 'a good text.',
- link: 'good'
- },
- {
- title: 'bad :-(',
- text: 'a bad text.',
- link: 'bad'
- }
- ]
- class Search extends React.Component {
- state = {
- active: false,
- query: '',
- results: []
- }
- focus = ev => {
- this.setState({ active: true })
- }
- blur = ev => {
- this.setState({ active: false })
- }
- change = ev => {
- const { value } = ev.target
- this.setState({ query: ev.target.value })
- const fuseOptions = {
- shouldSort: true,
- includeMatches: true,
- threshold: 0.3,
- location: true,
- keys: ['title', 'text', 'link']
- }
- const fuseInst = new fuse(dummyResults, fuseOptions)
- const searchResults = fuseInst.search(value)
- console.log(dummyResults, searchResults)
- if (value) {
- this.setState({
- results: searchResults
- })
- } else {
- this.setState({ results: [] })
- }
- }
- clear = ev => {
- this.setState({ query: '' })
- }
- render () {
- return (
- <>
- <div id='searchbar'>
- <input
- type='text'
- placeholder='Search..'
- onFocus={this.focus}
- onBlur={this.blur}
- onChange={this.change}
- value={this.state.query}
- />
- <button
- style={{ display: this.state.query ? 'block' : 'none' }}
- onClick={this.clear}
- >
- x
- </button>
- <button type='submit' disabled={!this.state.query}>
- <span>Search</span>
- </button>
- {this.state.active &&
- this.state.query &&
- (this.state.results ? (
- <ul id='searchresults'>
- {this.state.results.map(result => (
- <Result key={result.title} {...result} />
- ))}
- </ul>
- ) : (
- <p>Nothing found.</p>
- ))}
- </div>
- <style jsx>
- {`
- #searchbar {
- display: grid;
- grid-template-columns: 1fr 1em 2em;
- border: 1px solid ${theme.colors.lightgrey};
- padding: 0.3em 2em;
- }
- input[type='text'] {
- border: none;
- width: 60%;
- }
- button {
- font-weight: 900;
- background: transparent;
- color: ${theme.colors.darkgrey};
- border: none;
- cursor: pointer;
- box-shadow: none;
- }
- button[type='submit'] {
- content: '';
- }
- button > span {
- display: none;
- }
- #searchresults {
- position: absolute;
- background: ${theme.colors.lightgrey};
- top: 2em;
- }
- `}
- </style>
- </>
- )
- }
- }
- const Result = props => {
- const { item, matches } = props
- return (
- <li>
- <a href={item.link}>
- <h3>{item.title}</h3>
- <p>{item.text}</p>
- </a>
- </li>
- )
- }
- export default Search
|