UNPKG

@pubsweet/ui

Version:

React component library for use in pubsweet apps

202 lines (177 loc) 5.32 kB
import React, { useState } from 'react' import PropTypes from 'prop-types' import styled from 'styled-components' import { override, th } from '@pubsweet/ui-toolkit' import { Button as UIButton, Icon as UIIcon } from '../atoms' const Icon = styled(UIIcon)` font-family: ${th('fontInterface')}; font-size: ${th('fontSizeBase')}; height: ${th('fontSizeBase')}; vertical-align: top; /* stylelint-disable-next-line order/properties-alphabetical-order */ ${override('ui.Button.Icon')} ` const ChevronIcon = styled(Icon)` float: right; ` const StyledDropdown = styled.div` display: inline-block; position: relative; margin: 0; /* stylelint-disable-next-line order/properties-alphabetical-order */ ${override('ui.Dropdown.Wrapper')} ` const DropdownTitle = styled(UIButton)` cursor: pointer; display: inline-block; white-space: nowrap; text-decoration: none; padding: ${props => (props.size === 'small' ? '2px' : '8px')}; color: ${props => props.color}; &:hover { color: ${props => props.color}; } text-transform: capitalize; /* stylelint-disable-next-line order/properties-alphabetical-order */ ${override('ui.Dropdown.Title')} ` const DropdownMenu = styled.ul` background-color: ${th('colorBackground')}; border-color: ${th('colorBorder')}; border-style: ${th('borderStyle')}; border-width: ${th('borderWidth')}; color: ${th('colorText')}; display: ${props => (props.menuIsOpen ? 'block' : 'none')}; font-family: ${th('fontInterface')}; font-size: ${th('fontSizeBase')}; list-style-type: none; margin: calc(${th('gridUnit')} / 4) 0 0 0; padding: 0; position: absolute; top: ${props => (props.direction === 'down' ? '100%' : '-')}; bottom: ${props => (props.direction === 'down' ? '-' : '100%')}; width: 100%; z-index: 9; /* stylelint-disable-next-line order/properties-alphabetical-order */ ${override('ui.Dropdown.Menu')} ` const Item = styled.li` cursor: pointer; font-family: ${th('fontInterface')}; font-size: ${th('fontSizeBase')}; padding: ${th('gridUnit')}; white-space: normal; word-break: break-word; &:hover { background-color: ${th('colorBackgroundHue')}; } /* stylelint-disable-next-line order/properties-alphabetical-order */ ${override('ui.Dropdown.MenuItem')} ` const Dropdown = ({ children, direction, icon, iconPosition, itemsList, primary, size, dataTestId, color, }) => { const [menuIsOpen, setMenuIsOpen] = useState(false) let colorIcon if (color) { colorIcon = color } else { primary ? (colorIcon = '#fff') : (colorIcon = '#0B65CB') } const getIconDirection = () => { if (direction === 'up') { return menuIsOpen ? 'chevron-down' : 'chevron-up' } return !menuIsOpen ? 'chevron-down' : 'chevron-up' } return ( <StyledDropdown size={size}> <DropdownTitle color={color} data-test-id={dataTestId} onBlur={() => setMenuIsOpen(false)} onClick={() => setMenuIsOpen(!menuIsOpen)} primary={primary} size={size} > <span data-testid="iconButton"> {icon && iconPosition === 'start' && ( <Icon color={colorIcon} data-testid="leftIconButton" primary={primary} > {icon}{' '} </Icon> )} <span>{children}</span> {icon && iconPosition === 'end' && ( <Icon color={colorIcon} data-testid="rightIconButton"> {icon}{' '} </Icon> )} </span> <ChevronIcon color={colorIcon}>{getIconDirection()}</ChevronIcon> </DropdownTitle> <DropdownMenu direction={direction} menuIsOpen={menuIsOpen}> {itemsList.map(item => ( <Item key={item.id} onClick={() => { item.onClick() setMenuIsOpen(false) }} {...item.props} data-test-id={item.dataTestId} onMouseDown={e => e.preventDefault()} > {item.title} </Item> ))} </DropdownMenu> </StyledDropdown> ) } Dropdown.propTypes = { /** Content of the button of the dropdown */ children: PropTypes.node.isRequired, dataTestId: PropTypes.string, /** Dropdow direction */ direction: PropTypes.oneOf(['up', 'down']), /** Icon name (An icon name, from the Feather icon set.) */ icon: PropTypes.string, /** Icon Position (Defines the position of the icon (if is is at the start of the button , or at the end)) */ iconPosition: PropTypes.oneOf(['start', 'end']), /** List of the items for the drop down items */ itemsList: PropTypes.arrayOf( PropTypes.shape({ /** The key for the item */ id: PropTypes.string.isRequired, /** The click function for the item */ onClick: PropTypes.func, /** The title for the item */ title: PropTypes.node.isRequired, }), ), size: PropTypes.string, /** Primary property for the dropdown, if it is false(or not set) then the dropdown will be secondary */ primary: PropTypes.bool, } Dropdown.defaultProps = { direction: 'down', icon: null, iconPosition: 'start', itemsList: [], primary: false, size: '', dataTestId: '', } export default Dropdown