WIP: Search form in header bar
This commit is contained in:
1
assets/icons/close.svg
Normal file
1
assets/icons/close.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 22 22" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:1.41421;"><path d="M18.703,1.405l-7.675,7.732l-7.674,-7.732c-0.54,-0.54 -1.405,-0.54 -1.892,0c-0.54,0.541 -0.54,1.406 0,1.892l7.675,7.731l-7.732,7.675c-0.54,0.54 -0.54,1.405 0,1.892c0.541,0.54 1.406,0.54 1.892,0l7.731,-7.675l7.675,7.675c0.54,0.54 1.405,0.54 1.892,0c0.487,-0.541 0.54,-1.405 0,-1.892l-7.675,-7.675l7.675,-7.674c0.54,-0.54 0.54,-1.405 0,-1.892c-0.484,-0.54 -1.352,-0.54 -1.892,-0.057Z" style="fill:#7e8991;"/></svg>
|
||||
|
After Width: | Height: | Size: 830 B |
@@ -1,11 +1,39 @@
|
||||
import React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import Branding from './Branding';
|
||||
import Link from './Link';
|
||||
import LogoLink from './LogoLink';
|
||||
import Search from './Search';
|
||||
import { getItemPageNames } from '../../common/config';
|
||||
|
||||
export default function Header({ pageName }) {
|
||||
class Header extends React.Component {
|
||||
constructor(...args) {
|
||||
super(...args);
|
||||
this.state = {
|
||||
searchOpen: false,
|
||||
};
|
||||
}
|
||||
|
||||
openSearch = () => {
|
||||
this.setState({
|
||||
searchOpen: true,
|
||||
});
|
||||
}
|
||||
|
||||
closeSearch = () => {
|
||||
this.setState({
|
||||
searchOpen: false,
|
||||
});
|
||||
}
|
||||
|
||||
handleOpenClick = (e) => {
|
||||
e.preventDefault();
|
||||
this.openSearch();
|
||||
}
|
||||
|
||||
render() {
|
||||
const { pageName } = this.props;
|
||||
const { searchOpen } = this.state;
|
||||
const smallLogo = pageName !== 'index';
|
||||
|
||||
return (
|
||||
@@ -24,11 +52,17 @@ export default function Header({ pageName }) {
|
||||
</Link>
|
||||
</div>
|
||||
<div className="nav__item">
|
||||
<a className="icon-link" href="#todo">
|
||||
<a className="icon-link" href="#" onClick={this.handleOpenClick}>
|
||||
<span className="icon icon--search icon-link__icon"></span>Search
|
||||
</a>
|
||||
<div className={classNames('nav__search', { 'is-open': searchOpen })}>
|
||||
<Search onClose={this.closeSearch} open={searchOpen} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Branding>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default Header;
|
||||
|
||||
@@ -30,7 +30,6 @@ class PageOverview extends React.Component {
|
||||
e.preventDefault();
|
||||
|
||||
this.setState({
|
||||
...this.state,
|
||||
ring,
|
||||
});
|
||||
}
|
||||
@@ -66,7 +65,6 @@ class PageOverview extends React.Component {
|
||||
|
||||
handleSearchTermChange = (value) => {
|
||||
this.setState({
|
||||
...this.state,
|
||||
search: value,
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1,14 +1,21 @@
|
||||
import React from 'react';
|
||||
import classNames from 'classnames';
|
||||
|
||||
export default function Search({ value, onChange, onSubmit = () => {} }) {
|
||||
export default function Search({ value, onChange, onClose, open = false, onSubmit = () => {} }) {
|
||||
const closable = typeof onClose === 'function';
|
||||
|
||||
const handleSubmit = (e) => {
|
||||
e.preventDefault();
|
||||
onSubmit();
|
||||
};
|
||||
|
||||
const handleClose = (e) => {
|
||||
e.preventDefault();
|
||||
onClose();
|
||||
}
|
||||
|
||||
return (
|
||||
<form className="search" onSubmit={handleSubmit}>
|
||||
<form className={classNames('search', { 'search--closable': closable })} onSubmit={handleSubmit}>
|
||||
<input
|
||||
value={value}
|
||||
type="text"
|
||||
@@ -16,12 +23,19 @@ export default function Search({ value, onChange, onSubmit = () => {} }) {
|
||||
className="search__field"
|
||||
placeholder="What are you looking for?"
|
||||
/>
|
||||
<span className="search__button">
|
||||
<span className={classNames('search__button', { 'is-open': open })}>
|
||||
<button type="submit" className="button">
|
||||
<span className="icon icon--search button__icon" />
|
||||
Search
|
||||
</button>
|
||||
</span>
|
||||
{
|
||||
closable && (
|
||||
<a href="#" className={classNames('search__close', { 'is-open': open })} onClick={handleClose}>
|
||||
<span className="icon icon--close" />
|
||||
</a>
|
||||
)
|
||||
}
|
||||
</form>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -26,4 +26,8 @@
|
||||
&--back {
|
||||
background-image: url('/assets/icons/back.svg');
|
||||
}
|
||||
|
||||
&--close {
|
||||
background-image: url('/assets/icons/close.svg');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,33 @@
|
||||
.nav {
|
||||
white-space: nowrap;
|
||||
|
||||
&__item {
|
||||
display: inline-flex;
|
||||
position: relative;
|
||||
& + .nav__item {
|
||||
margin-left: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
&__search {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 50%;
|
||||
visibility: hidden;
|
||||
overflow: hidden;
|
||||
width: 0;
|
||||
margin-top: -25px;
|
||||
opacity: 0.8;
|
||||
transition:
|
||||
width 400ms cubic-bezier(0.24, 1.12, 0.71, 0.98) 100ms,
|
||||
visibility 0s linear 500ms,
|
||||
opacity 200ms linear;
|
||||
|
||||
&.is-open {
|
||||
opacity: 1;
|
||||
width: 600px;
|
||||
visibility: visible;
|
||||
transition-delay: 0s;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,4 +35,38 @@
|
||||
margin-top: -18px;
|
||||
right: 7px;
|
||||
}
|
||||
|
||||
&--closable {
|
||||
.search {
|
||||
&__field {
|
||||
padding-right: 160px;
|
||||
}
|
||||
|
||||
&__button {
|
||||
right: 50px;
|
||||
transform: translateX(20px);
|
||||
transition: transform 450ms cubic-bezier(0.24, 1.12, 0.71, 0.98) 100ms;
|
||||
|
||||
&.is-open {
|
||||
transform: translateX(0);
|
||||
transition-delay: 250ms;
|
||||
}
|
||||
}
|
||||
|
||||
&__close {
|
||||
position: absolute;
|
||||
padding: 10px;
|
||||
top: 50%;
|
||||
margin-top: -21px;
|
||||
right: 4px;
|
||||
transform: scale(0.2);
|
||||
transition: transform 400ms cubic-bezier(0.24, 1.12, 0.71, 0.98);
|
||||
|
||||
&.is-open {
|
||||
transform: rotate(180deg) scale(1);
|
||||
transition-delay: 300ms;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user