Skip to content
Snippets Groups Projects
Menu.js 2.21 KiB
Newer Older
import React from 'react'
import classnames from 'classnames'
Alf Eaton's avatar
Alf Eaton committed
import classes from './Menu.local.scss'
// TODO: match the width of the container to the width of the widest option?
Alf Eaton's avatar
Alf Eaton committed
// TODO: use a <select> element instead of divs?
class Menu extends React.Component {
Yannis Barlas's avatar
Yannis Barlas committed
  constructor(props) {
    super(props)

    this.state = {
      open: false,
Yannis Barlas's avatar
Yannis Barlas committed
      selected: props.value,
    }
  }

  toggleMenu = () => {
    this.setState({
Yannis Barlas's avatar
Yannis Barlas committed
      open: !this.state.open,
    })
  }

  handleSelect = selected => {
    this.setState({
      selected,
Yannis Barlas's avatar
Yannis Barlas committed
      open: false,
    this.props.onChange(selected)
  }

  optionLabel = value => {
    const { options } = this.props

    return options.find(option => option.value === value).label
  }

Yannis Barlas's avatar
Yannis Barlas committed
  render() {
Alf Eaton's avatar
Alf Eaton committed
    const { label, options, placeholder = 'Choose in the list' } = this.props
    const { open, selected } = this.state

    return (
Yannis Barlas's avatar
Yannis Barlas committed
      <div
        className={classnames(classes.root, {
          [classes.open]: open,
        })}
      >
        {label && <span className={classes.label}>{label}</span>}
Alf Eaton's avatar
Alf Eaton committed

        <div className={classes.main}>
          <div className={classes.openerContainer}>
            <button
              type="button"
              className={classes.opener}
Yannis Barlas's avatar
Yannis Barlas committed
              onClick={this.toggleMenu}
            >
              {selected ? (
                <span>{this.optionLabel(selected)}</span>
              ) : (
                <span className={classes.placeholder}>{placeholder}</span>
              )}
              <span className={classes.arrow}></span>
            </button>
          </div>
          <div className={classes.optionsContainer}>
            {open && (
              <div className={classes.options}>
                {options.map(option => (
                  <div
                    key={option.value}
                    className={classnames(classes.option, {
Yannis Barlas's avatar
Yannis Barlas committed
                      [classes.active]: option.value === selected,
                    })}
                    onClick={() => this.handleSelect(option.value)}
Yannis Barlas's avatar
Yannis Barlas committed
                  >
                    {option.label || option.value}
                  </div>
        </div>
      </div>
    )
  }
}

export default Menu