fleet/frontend/components/buttons/DropdownButton/DropdownButton.jsx
noahtalerman 49e71e4ed6
Add new icons for Hosts page. Fix hosts list width on wide screens. (#128)
- Add new PNG files for the new icons in the left side navigation and the right side labels on the Hosts page.
- Rename the old `<Icon />` component to `<KolideIcon />` and create a new `<Icon />` component. The ultimate goal is to get rid of the `<KolideIcon />` and `<PlatformIcon />` components and use the encompassing `<Icon />` component for all icons. The full transition will be made when we have icon assets to replace all the kolide icons and platform icons. Currently, we don't.
- Rename the `icon_name_for_label.js` utility to `icon_name.js` because the utility now includes `iconNameForLabel()` and `iconNameForPlatform()` functions.
- Fixes issue #127.
2020-12-14 18:24:16 -08:00

119 lines
2.8 KiB
JavaScript

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { noop } from 'lodash';
import classnames from 'classnames';
import ClickOutside from 'components/ClickOutside';
import KolideIcon from 'components/icons/KolideIcon';
import Button from 'components/buttons/Button';
const baseClass = 'dropdown-button';
export class DropdownButton extends Component {
static propTypes = {
children: PropTypes.node,
className: PropTypes.string,
disabled: PropTypes.bool,
options: PropTypes.arrayOf(
PropTypes.shape({
disabled: PropTypes.bool,
label: PropTypes.string,
onClick: PropTypes.func,
}),
).isRequired,
size: PropTypes.string,
tabIndex: PropTypes.number,
type: PropTypes.string,
variant: PropTypes.string,
};
static defaultProps = {
onChange: noop,
};
constructor (props) {
super(props);
this.state = { isOpen: false };
}
setDOMNode = (DOMNode) => {
this.DOMNode = DOMNode;
}
toggleDropdown = () => {
const { isOpen } = this.state;
this.setState({ isOpen: !isOpen });
};
optionClick = (evt, onClick) => {
this.setState({ isOpen: false });
onClick(evt);
};
renderOptions = (opt, idx) => {
const { optionClick } = this;
const { disabled, label, onClick } = opt;
return (
<li className={`${baseClass}__option`} key={`dropdown-button-option-${idx}`}>
<Button variant="unstyled" onClick={evt => optionClick(evt, onClick)} disabled={disabled}>{label}</Button>
</li>
);
};
render () {
const {
children,
className,
disabled,
options,
size,
tabIndex,
type,
variant,
} = this.props;
const { isOpen } = this.state;
const { toggleDropdown, renderOptions, setDOMNode } = this;
const buttonClass = classnames(baseClass, className);
const optionsClass = classnames(`${baseClass}__options`, {
[`${baseClass}__options--opened`]: isOpen,
});
return (
<div className={`${baseClass}__wrapper`} ref={setDOMNode}>
<Button
className={buttonClass}
disabled={disabled}
onClick={toggleDropdown}
size={size}
tabIndex={tabIndex}
type={type}
variant={variant}
>
{children} <KolideIcon name="downcarat" className={`${baseClass}__carat`} />
</Button>
<ul className={optionsClass}>
{options.map((option, i) => {
return renderOptions(option, i);
})}
</ul>
</div>
);
}
}
export default ClickOutside(DropdownButton, {
getDOMNode: (component) => {
return component.DOMNode;
},
onOutsideClick: (component) => {
return () => {
component.setState({ isOpen: false });
return false;
};
},
});