diff --git a/src/app/demo/components-demo-page.js b/src/app/demo/components-demo-page.js index 1c3e49ab..ee3c80d4 100644 --- a/src/app/demo/components-demo-page.js +++ b/src/app/demo/components-demo-page.js @@ -8,6 +8,9 @@ import Button from 'core-components/button'; import Input from 'core-components/input'; import Checkbox from 'core-components/checkbox'; import Widget from 'core-components/widget'; +import DropDown from 'core-components/drop-down'; + +var dropDownItems = ['English', 'Spanish', 'German', 'Portuguese', 'Japanese']; var DemoPage = React.createClass({ @@ -43,12 +46,18 @@ var DemoPage = React.createClass({ { title: 'Widget', render: ( - +

Register here!

) + }, + { + title: 'DropDown', + render: ( + + ) } ], diff --git a/src/core-components/drop-down.js b/src/core-components/drop-down.js new file mode 100644 index 00000000..86247fa3 --- /dev/null +++ b/src/core-components/drop-down.js @@ -0,0 +1,110 @@ +import React from 'react'; +import classNames from 'classnames'; +import _ from 'lodash'; +import {Motion, spring} from 'react-motion'; + + +import callback from 'lib/callback'; + +var DropDown = React.createClass({ + + propTypes: { + defaultSelectedIndex: React.PropTypes.number, + selectedIndex: React.PropTypes.number, + + items: React.PropTypes.array.isRequired + }, + + getDefaultProps() { + return { + defaultSelectedIndex: 0 + }; + }, + + getInitialState() { + return { + selectedIndex: 0, + opened: false + }; + }, + + getAnimationStyles() { + var closedStyle = { + opacity: spring(0, [200, 20]), + translateY: spring(20, [200, 20]) + }; + var openedStyle = { + opacity: spring(1, [200, 20]), + translateY: spring(0, [200, 20]) + }; + + return { + defaultStyle: closedStyle, + style: (this.state.opened) ? openedStyle : closedStyle + } + }, + + render() { + var animation = this.getAnimationStyles(); + + return ( +
+
+ {this.props.items[this.getSelectedIndex()]} +
+ + {this.renderList} + +
+ ); + }, + + renderList({opacity, translateY}) { + var style = { opacity: opacity, transform: `translateY(${translateY}px)`}; + + return ( +
+
    + {this.props.items.map(this.renderItem)} +
+
+ ); + }, + + renderItem(item, index) { + var render = null; + + if (index !== this.state.selectedIndex) { + render = ( +
  • + {item} +
  • + ); + } + + return render; + }, + + getClickCallback(index) { + return callback(this.handleClick.bind(this, index), this.props.onChange, {index: index}) + }, + + handleClick(index) { + if (this.getSelectedIndex() === index) { + this.setState({ + opened: !this.state.opened + }); + } + else { + this.setState({ + selectedIndex: index + }); + } + }, + + getSelectedIndex() { + return (this.props.selectedIndex !== undefined) ? this.props.selectedIndex : this.state.selectedIndex; + } +}); + +export default DropDown; \ No newline at end of file diff --git a/src/core-components/drop-down.scss b/src/core-components/drop-down.scss new file mode 100644 index 00000000..34862ddb --- /dev/null +++ b/src/core-components/drop-down.scss @@ -0,0 +1,35 @@ +@import "../scss/vars"; + +.drop-down { + border-radius: 4px; + width: 150px; + font-size: 13px; + user-select: none; + cursor: pointer; + + &--current { + color: $primary-black; + background-color: $light-grey; + padding: 8px; + } + + &--list-container { + background-color: white; + } + + &--list { + color: $dark-grey; + margin: 0; + padding: 0; + list-style-type: none; + + &-item { + padding: 8px; + + &:hover { + background-color: $primary-red; + color: white; + } + } + } +} \ No newline at end of file