diff --git a/src/components/Dropdown/Dropdown.jsx b/src/components/Dropdown/Dropdown.jsx new file mode 100644 index 000000000..6ee7f635f --- /dev/null +++ b/src/components/Dropdown/Dropdown.jsx @@ -0,0 +1,110 @@ +require('./Dropdown.scss') + +import React, { Component, PropTypes } from 'react' +import classNames from 'classnames' + +class Dropdown extends Component { + constructor(props) { + super(props) + + this.state = { isHidden: true } + + this.onClickOutside = this.onClickOutside.bind(this) + this.onClick = this.onClick.bind(this) + this.onClickOtherDropdown = this.onClickOtherDropdown.bind(this) + } + + onClickOutside(evt) { + let currNode = evt.target + let isDropdown = false + + do { + if(currNode.className + && currNode.className.indexOf + && currNode.className.indexOf('dropdown-wrap') > -1) { + isDropdown = true + break + } + + currNode = currNode.parentNode + + if(!currNode) + break + } while(currNode.tagName) + + if(!isDropdown) { + this.setState({ isHidden: true }) + } + } + + onClick(evt) { + const dropdownClicked = document.createEvent('Event') + dropdownClicked.initEvent('dropdownClicked', true, false) + + document.dispatchEvent(dropdownClicked) + + this.setState({ isHidden: !this.state.isHidden }) + evt.stopPropagation() + } + + onClickOtherDropdown() { + this.setState({ isHidden: true }) + } + + componentDidMount() { + document.removeEventListener('click', this.onClickOutside) + document.removeEventListener('dropdownClicked', this.onClickOtherDropdown) + + document.addEventListener('click', this.onClickOutside) + document.addEventListener('dropdownClicked', this.onClickOtherDropdown) + } + + componentWillUnmount() { + document.removeEventListener('click', this.onClickOutside) + document.removeEventListener('dropdownClicked', this.onClickOtherDropdown) + } + + render() { + const { className, pointerShadow, noPointer, pointerLeft, noAutoclose } = this.props + const ddClasses = classNames('dropdown-wrap', { + [`${className}`] : true, + [`${ this.props.theme }`] : true, + hide : this.state.isHidden + }) + const ndClasses = classNames('Dropdown', { + 'pointer-shadow' : pointerShadow, + 'pointer-hide' : noPointer, + 'pointer-left' : pointerLeft, + 'no-autoclose' : noAutoclose + }) + + return ( +
{} : this.onClick } ref="Dropdown"> + { + this.props.children.map((child, index) => { + if (child.props.className.indexOf('dropdown-menu-header') > -1) + return noAutoclose ? React.cloneElement(child, { + onClick: this.onClick, + key: child.props.key || index + }) : child + }) + } + +
+ { + this.props.children.map((child) => { + if (child.props.className.indexOf('dropdown-menu-list') > -1) + return child + }) + } +
+
+ ) + } +} + +Dropdown.propTypes = { + children: PropTypes.array.isRequired +} + +export default Dropdown diff --git a/src/components/Dropdown/Dropdown.scss b/src/components/Dropdown/Dropdown.scss new file mode 100644 index 000000000..9f12ed615 --- /dev/null +++ b/src/components/Dropdown/Dropdown.scss @@ -0,0 +1,162 @@ +@import 'tc-includes'; + + +.dropdown-wrap { + cursor: pointer; + position: relative; +} + +.Dropdown { + background-color: #fff; + box-shadow: 0 2px 7px rgba(0, 0, 0, 0.17); + border-radius: 5px; + display: inline-block; + position: absolute; + left: 0; + top: 5px; + width: 100%; + z-index: 2; + + ul { + height: 100%; + width: 100%; + position: relative; + z-index: 10; + background-color: #fff; + padding: 11px 20px; + border-radius: 5px; + + li { + list-style: none; + } + + li a { + color: #394146; + font-family: "Roboto", Arial, Helvetica, sans-serif; + font-size: 12px; + display: block; + line-height: 26px; + } + } +} + +.Dropdown.no-autoclose { + cursor: default; +} + +.dropdown-wrap.default { + border: 1px solid $tc-gray-20; + display: flex; + align-items: center; + padding: calc(2 * #{$base_unit}); + position: relative; + + .Dropdown { + ul.dropdown-menu-list { + padding: 10px 0px; + li { + padding: 0 20px; + @include ellipsis; + } + + li:hover { + background-color: $tc-gray-neutral-dark; + } + } + } +} + +.dropdown-wrap.default::after { + content: " "; + width: 10px; + height: 10px; + display: block; + right: 10px; + top: 50%; + position: absolute; + transform: translateY(-50%) rotate(45deg); + border-bottom: 2px solid $tc-gray-20; + border-right: 2px solid $tc-gray-20; +} + +.dropdown-wrap.hide .Dropdown { + display: none; +} + +.Dropdown.pointer-left:before { + right: initial; + left: 15px; +} + +.UserDropdownMenu .Dropdown.pointer-shadow { + margin-top: 35px; + + &:before { + content: ''; + display: block; + position: absolute; + top: -6px; + right: 24px; + width: 12px; + height: 12px; + background: #FFFFFF; + border-right: 1px solid $tc-gray-20;; + border-bottom: 1px solid $tc-gray-20;; + transform: rotate(-135deg); + z-index:999; + } +} + +.Dropdown.pointer-hide:before { + display: none; +} + +.new-theme { + text-align: left; + height: 30px; + color: $tc-black; + background: $tc-gray-neutral-light; + border: 1px solid $tc-gray-20; + @include roboto; + font-size: 13px; + line-height: 20px; + width: 100%; + border-radius: 2px; + position: relative; + + .dropdown-menu-header { + width: 100%; + border: 0; + height: 28px; + line-height: 28px; + margin: 0; + padding: 0 0 0 10px; + color: $tc-gray-50; + font-size: 13px; + } + &:after{ + display: block; + content: ''; + position: absolute; + width: 10px; + height: 14px; + right: 11px; + top: 50%; + margin-top: -7px; + background: url("./icon-select.png") left top no-repeat; + background-size: 10px 14px; + z-index:2; + } + .Dropdown { + ul.dropdown-menu-list { + padding: 10px 0px; + li { + padding: 0 20px; + @include ellipsis; + } + li:hover { + background-color: $tc-gray-neutral-dark; + } + } + } +} diff --git a/src/components/Dropdown/arrow-dropdown.png b/src/components/Dropdown/arrow-dropdown.png new file mode 100644 index 000000000..2aa5059e9 Binary files /dev/null and b/src/components/Dropdown/arrow-dropdown.png differ diff --git a/src/components/Dropdown/icon-select.png b/src/components/Dropdown/icon-select.png new file mode 100644 index 000000000..8b58102b3 Binary files /dev/null and b/src/components/Dropdown/icon-select.png differ diff --git a/src/components/NotificationsDropdown/NotificationsDropdown.jsx b/src/components/NotificationsDropdown/NotificationsDropdown.jsx index bb1fd0e27..0a1df2284 100644 --- a/src/components/NotificationsDropdown/NotificationsDropdown.jsx +++ b/src/components/NotificationsDropdown/NotificationsDropdown.jsx @@ -5,7 +5,7 @@ */ import React, { PropTypes } from 'react' import SVGIconImage from '../SVGIconImage' -import { Dropdown } from 'appirio-tech-react-components' +import Dropdown from '../Dropdown/Dropdown' import cn from 'classnames' const NotificationsDropdown = (props) => {