diff --git a/app/components/ColorPicker.js b/app/components/ColorPicker.js index 65d33e8d..9610e5d3 100644 --- a/app/components/ColorPicker.js +++ b/app/components/ColorPicker.js @@ -1,11 +1,11 @@ // @flow import * as React from 'react'; -import { observable, computed, action } from 'mobx'; +import { observable } from 'mobx'; import { observer } from 'mobx-react'; +import { TwitterPicker } from 'react-color'; import styled from 'styled-components'; -import Flex from 'shared/components/Flex'; -import { LabelText, Outline } from 'components/Input'; -import { validateColorHex } from 'shared/utils/color'; +import Fade from 'components/Fade'; +import { LabelText } from 'components/Input'; const colors = [ '#4E5C6E', @@ -15,175 +15,92 @@ const colors = [ '#FC2D2D', '#FFE100', '#14CF9F', + '#00D084', '#EE84F0', '#2F362F', ]; type Props = { - onSelect: (color: string) => void, + onChange: (color: string) => void, value?: string, }; @observer class ColorPicker extends React.Component { - @observable selectedColor: string = colors[0]; - @observable customColorValue: string = ''; - @observable customColorSelected: boolean; - - componentWillMount() { - const { value } = this.props; - if (value && colors.includes(value)) { - this.selectedColor = value; - } else if (value) { - this.customColorSelected = true; - this.customColorValue = value.replace('#', ''); - } - } + @observable isOpen: boolean = false; + node: ?HTMLElement; componentDidMount() { - this.fireCallback(); + window.addEventListener('click', this.handleClickOutside); } - fireCallback = () => { - this.props.onSelect( - this.customColorSelected ? this.customColor : this.selectedColor - ); - }; - - @computed - get customColor(): string { - return this.customColorValue && - validateColorHex(`#${this.customColorValue}`) - ? `#${this.customColorValue}` - : colors[0]; + componentWillUnmount() { + window.removeEventListener('click', this.handleClickOutside); } - @action - setColor = (color: string) => { - this.selectedColor = color; - this.customColorSelected = false; - this.fireCallback(); + handleClose = () => { + this.isOpen = false; }; - @action - focusOnCustomColor = (event: SyntheticEvent<>) => { - this.selectedColor = ''; - this.customColorSelected = true; - this.fireCallback(); + handleOpen = () => { + this.isOpen = true; }; - @action - setCustomColor = (event: SyntheticEvent) => { - let target = event.target; - if (target instanceof HTMLInputElement) { - const color = target.value; - this.customColorValue = color.replace('#', ''); - this.fireCallback(); + handleClickOutside = (ev: SyntheticMouseEvent<>) => { + // $FlowFixMe + if (ev.target && this.node && this.node.contains(ev.target)) { + return; } + + this.handleClose(); }; render() { return ( - - Color - - - {colors.map(color => ( - this.setColor(color)} + (this.node = ref)}> + + + + {this.isOpen && ( + + this.props.onChange(color.hex)} + triangle="top-right" /> - ))} - - - Custom color: - # - - - - - + + )} + + ); } } -type SwatchProps = { - onClick?: () => void, - color?: string, - active?: boolean, -}; - -const Swatch = ({ onClick, ...props }: SwatchProps) => ( - - - -); - -const SwatchOutset = styled(Flex)` - width: 24px; - height: 24px; - margin-right: 5px; - border: 2px solid ${({ active, color }) => (active ? color : 'transparent')}; - border-radius: 2px; - background: ${({ color }) => color}; - ${({ onClick }) => onClick && `cursor: pointer;`} &:last-child { - margin-right: 0; - } +const Wrapper = styled('div')` + display: inline-block; + position: relative; +`; +const Floating = styled('div')` + position: absolute; + top: 60px; + right: 0; + z-index: 1; `; -const SwatchInset = styled(Flex)` - width: 20px; - height: 20px; +const Swatch = styled('div')` + display: inline-block; + width: 40px; + height: 36px; border: 1px solid ${({ active, color }) => (active ? 'white' : 'transparent')}; - border-radius: 2px; + border-radius: 4px; background: ${({ color }) => color}; `; -const StyledOutline = styled(Outline)` - padding: 5px; - flex-wrap: wrap; - - strong { - font-weight: 500; - } -`; - -const HexHash = styled.div` - margin-left: 12px; - padding-bottom: 0; - font-weight: 500; - user-select: none; -`; - -const CustomColorInput = styled.input` - border: 0; - flex: 1; - width: 65px; - margin-right: 12px; - padding-bottom: 0; - outline: none; - background: none; - font-family: ${props => props.theme.monospaceFontFamily}; - font-weight: 500; - - &::placeholder { - color: ${props => props.theme.slate}; - font-family: ${props => props.theme.monospaceFontFamily}; - font-weight: 500; - } -`; - export default ColorPicker; diff --git a/app/scenes/CollectionEdit.js b/app/scenes/CollectionEdit.js index ba894121..8d43f67a 100644 --- a/app/scenes/CollectionEdit.js +++ b/app/scenes/CollectionEdit.js @@ -1,6 +1,6 @@ // @flow import * as React from 'react'; -import { withRouter, type RouterHistory } from 'react-router-dom'; +import { withRouter } from 'react-router-dom'; import { observable } from 'mobx'; import { inject, observer } from 'mobx-react'; import Input from 'components/Input'; @@ -13,7 +13,7 @@ import Collection from 'models/Collection'; import UiStore from 'stores/UiStore'; type Props = { - history: RouterHistory, + history: Object, collection: Collection, ui: UiStore, onSubmit: () => void, @@ -23,15 +23,16 @@ type Props = { class CollectionEdit extends React.Component { @observable name: string; @observable description: string = ''; - @observable color: string = ''; + @observable color: string = '#4E5C6E'; @observable isSaving: boolean; componentWillMount() { this.name = this.props.collection.name; this.description = this.props.collection.description; + this.color = this.props.collection.color; } - handleSubmit = async (ev: SyntheticEvent<>) => { + handleSubmit = async (ev: SyntheticEvent<*>) => { ev.preventDefault(); this.isSaving = true; @@ -66,17 +67,21 @@ class CollectionEdit extends React.Component {
- You can edit a collection’s name and other details at any time, - however doing so often might confuse your team mates. + You can edit the name and other details at any time, however doing + so often might confuse your team mates. - + + +   + { minHeight={68} maxHeight={200} /> -