Skip to content
This repository has been archived by the owner on Oct 1, 2019. It is now read-only.

Commit

Permalink
[#830] Don't allow closed Dropdown to listen to click events
Browse files Browse the repository at this point in the history
Support using different icons for opened and closed dropdown.
  • Loading branch information
artkravchenko committed Mar 19, 2017
1 parent f89fa3f commit 70817cd
Showing 1 changed file with 75 additions and 26 deletions.
101 changes: 75 additions & 26 deletions src/components/dropdown.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,69 @@
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import React, { Component } from 'react';
import React, { PropTypes } from 'react';
import classNames from 'classnames';
import omit from 'lodash/omit';

import ClickOutsideComponentDecorator from '../decorators/ClickOutsideComponentDecorator';
import Icon from './icon';

class Dropdown extends Component {
class OpenedDropdownContent extends React.Component {
static propTypes = {
children: PropTypes.node,
icon: PropTypes.string,
onClose: PropTypes.func
};

shouldComponentUpdate(nextProps) {
return nextProps !== this.props;
}

onClickOutside = () => {
this.props.onClose();
};

render() {
return (
<div>
<div className="dropdown__trigger action" onClick={this.props.onClose}>
<Icon className="micon micon-small" icon={this.props.icon} />
</div>
{this.props.children &&
<div className="dropdown__body">
{this.props.children}
</div>
}
</div>
);
}
}

const defaultIcon = 'arrow_drop_down';
const Body = ClickOutsideComponentDecorator(OpenedDropdownContent);

export default class Dropdown extends React.Component {
static displayName = 'Dropdown';

static propTypes = {
children: PropTypes.node,
className: PropTypes.string,
icon: PropTypes.string,
iconClosed: PropTypes.string,
iconOpen: PropTypes.string,
isVisible: PropTypes.bool,
theme: PropTypes.string
};

static defaultProps = {
isVisible: false,
theme: 'old'
};

constructor(props) {
super(props);

constructor(props, ...args) {
super(props, ...args);
this.state = {
isVisible: props.isVisible || false
isVisible: props.isVisible
};
}

Expand All @@ -41,10 +86,6 @@ class Dropdown extends Component {
|| nextState.isVisible !== this.state.isVisible;
}

onClickOutside = () => {
this.hide();
};

toggleVisibility = () => {
this.setState({ isVisible: !this.state.isVisible });
};
Expand All @@ -54,13 +95,7 @@ class Dropdown extends Component {
};

render() {
const { className, icon, iconOpen, iconClosed, theme, ...props } = this.props;

const dropdownClassName =
classNames('dropdown', `dropdown--theme_${theme}`, className, {
'dropdown-open': this.state.isVisible,
'dropdown-closed': !this.state.isVisible
});
const { className, icon, iconOpen, iconClosed, ...props } = this.props;

let i;
if (icon) {
Expand All @@ -70,21 +105,35 @@ class Dropdown extends Component {
} else if (this.state.isVisible && iconOpen) {
i = iconOpen;
} else {
i = 'arrow_drop_down';
i = defaultIcon;
}

return (
<div className={dropdownClassName} {...props}>
let body;
let dropdownClassName = classNames(
'dropdown',
`dropdown--theme_${this.props.theme}`,
className
);
if (this.state.isVisible) {
dropdownClassName += ' dropdown-open';
body = (
<Body icon={i} onClose={this.toggleVisibility}>
{this.props.children}
</Body>
);
} else {
dropdownClassName += ' dropdown-closed';
body = (
<div className="dropdown__trigger action" onClick={this.toggleVisibility}>
<Icon className="micon micon-small" icon={i} />
</div>
<div className="dropdown__body">
{props.children}
</div>
);
}

return (
<div className={dropdownClassName} {...omit(props, ['children'])}>
{body}
</div>
);
}
}

const DecoratedDropdown = ClickOutsideComponentDecorator(Dropdown);
export default DecoratedDropdown;

0 comments on commit 70817cd

Please sign in to comment.