backpack-ui
Version:
Lonely Planet's Components
279 lines (241 loc) • 6.69 kB
JSX
import React from "react";
import radium, { Style } from "radium";
import { Link } from "react-router";
import { color, media, timing, zIndex } from "../../../settings.json";
import Heading from "../heading";
import Flyout from "../flyout";
import PaginatorButton from "../paginatorButton";
const styles = {
container: {
base: {
display: "inline-block",
cursor: "pointer",
position: "relative",
zIndex: zIndex.globalHeader,
},
},
heading: {
base: {
display: "inline-block",
marginRight: "10px",
[` (min-width: ${media.min["600"]})`]: {
marginRight: "20px",
},
},
},
menu: {
base: {
backfaceVisibility: "hidden",
position: "absolute",
top: "70px",
transition: `opacity ${timing.default},
transform ${timing.default},
visibility ${timing.default}`,
width: "290px",
},
hidden: {
opacity: 0,
transform: "translateY(-1rem)",
visibility: "hidden",
},
visible: {
opacity: 1,
pointerEvents: "all",
transform: "translateY(0)",
visibility: "visible",
},
},
};
class TypeSelector extends React.Component {
constructor(props) {
super(props);
this.state = {
menu: false,
};
this.toggleMenu = this.toggleMenu.bind(this);
this.handleClickOutside = this.handleClickOutside.bind(this);
this.handleKeydown = this.handleKeydown.bind(this);
}
componentDidMount() {
document.addEventListener("click", this.handleClickOutside);
document.addEventListener("keydown", this.handleKeydown);
}
componentWillUnmount() {
document.removeEventListener("click", this.handleClickOutside);
document.removeEventListener("keydown", this.handleKeydown);
}
toggleMenu() {
this.setState({
menu: !this.state.menu,
});
}
handleClickOutside(event) {
const container = this._container;
const menu = this._menu;
if (container.contains(event.target)) {
return;
} else if (!menu.contains(event.target) && this.state.menu) {
this.toggleMenu();
}
}
handleKeydown(event) {
if (event.keyCode === 27 && this.state.menu) {
this.toggleMenu();
}
}
render() {
const {
title,
menuItems,
onClick,
mobile,
} = this.props;
return (
<div
className="TypeSelector"
style={[
styles.container.base,
mobile && { display: "block" },
]}
onClick={this.toggleMenu}
ref={(node) => { this._container = node; }}
>
{mobile &&
<Style
scopeSelector=".TypeSelector"
rules={{
".Flyout-arrow span": {
left: "auto !important",
marginLeft: "44px !important",
},
}}
/>
}
<Heading
level={1}
size="large"
weight="thin"
override={styles.heading.base}
>
{title}
</Heading>
<PaginatorButton
arrow="triangle"
color="blue"
direction="down"
size="small"
shadow="tight"
align="vertical"
iconLabel="Open menu"
owns="type-selector-menu"
/>
<div
className="TypeSelector-menu"
id="type-selector-menu"
style={[
styles.menu.base,
!mobile && { right: "-125px" },
mobile && { maxWidth: "290px", width: "100%" },
this.state.menu ? styles.menu.visible : styles.menu.hidden,
]}
aria-hidden={!this.state.menu}
ref={(node) => { this._menu = node; }}
>
<Flyout
arrow="up"
size="medium"
displayType="dropdown"
fill
>
<Style
scopeSelector=".SubNavigation"
rules={{
listStyle: "none",
".TypeSelector-listItem": {
color: "#646c74",
display: "block",
fontSize: "20px",
fontWeight: 300,
marginLeft: `${-40 / 20}em`,
marginRight: `${-40 / 20}em`,
padding: `${17.5 / 20}em ${40 / 20}em`,
position: "relative",
},
".TypeSelector-listItem:hover": {
backgroundColor: "#f4f8fc",
},
".TypeSelector-listItem:active": {
backgroundColor: "#f4f8fc",
},
".TypeSelector-listItem:focus": {
backgroundColor: "#f4f8fc",
},
".TypeSelector-listItem--active .ActiveMarker": {
backgroundColor: color.red,
borderRadius: "100%",
bottom: 0,
display: "block",
height: ".4rem",
left: "2rem",
marginBottom: "auto",
marginTop: "auto",
position: "absolute",
top: 0,
width: ".4rem",
zIndex: 1,
},
}}
/>
<ul className="SubNavigation">
{menuItems.map((menuItem, index) => (
<li key={index}>
<Link
to={`${menuItem.slug}`}
key={`link ${index}`}
onClick={() => {
this.toggleMenu();
if (onClick) {
onClick();
}
}}
className="TypeSelector-listItem"
activeClassName="TypeSelector-listItem--active"
>
<span className="ActiveMarker" />
{menuItem.item}
</Link>
</li>
))}
</ul>
</Flyout>
</div>
</div>
);
}
}
TypeSelector.propTypes = {
/**
* Title for Type Selector
*/
title: React.PropTypes.string.isRequired,
/**
* Menu Items for Type Selector
*/
menuItems: React.PropTypes.arrayOf(React.PropTypes.string).isRequired,
/**
* Method to run when the Link component is clicked
*/
onClick: React.PropTypes.func,
/**
* Whether or not to use the mobile layout
*/
mobile: React.PropTypes.bool,
};
TypeSelector.defaultProps = {
title: "",
menuItems: [],
onClick: null,
mobile: false,
};
TypeSelector.styles = styles;
export default radium(TypeSelector);