From 0faf5d93e45d652a4e8ed86772bb698547bf1968 Mon Sep 17 00:00:00 2001 From: Dave Snider Date: Fri, 18 May 2018 14:46:34 -0700 Subject: [PATCH 1/7] Replace EuiColorPicker with an accessible, non-library component --- package.json | 1 - .../src/views/color_picker/color_picker.js | 24 ++- .../color_picker/color_picker_example.js | 20 -- .../outside_click_detector_example.js | 2 +- .../__snapshots__/color_picker.test.js.snap | 83 +++------ .../color_picker/_color_picker.scss | 51 ++---- src/components/color_picker/color_picker.js | 136 +++++++++----- .../color_picker/color_picker.test.js | 173 +++++++++--------- .../color_picker/color_picker_empty_swatch.js | 10 - .../color_picker/color_picker_swatch.js | 37 ---- src/services/color/index.js | 1 + src/services/color/is_valid_hex.js | 5 + src/services/index.js | 1 + yarn.lock | 71 +------ 14 files changed, 243 insertions(+), 372 deletions(-) delete mode 100644 src/components/color_picker/color_picker_empty_swatch.js delete mode 100644 src/components/color_picker/color_picker_swatch.js create mode 100644 src/services/color/is_valid_hex.js diff --git a/package.json b/package.json index 9688c6b3d00..8289f297d24 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,6 @@ "numeral": "^2.0.6", "prop-types": "^15.6.0", "react-ace": "^5.5.0", - "react-color": "^2.13.8", "react-datepicker": "v1.4.1", "react-input-autosize": "^2.2.1", "react-virtualized": "^9.18.5", diff --git a/src-docs/src/views/color_picker/color_picker.js b/src-docs/src/views/color_picker/color_picker.js index cc2410ce8fb..1b28f3814dd 100644 --- a/src-docs/src/views/color_picker/color_picker.js +++ b/src-docs/src/views/color_picker/color_picker.js @@ -2,13 +2,14 @@ import React, { Component, } from 'react'; -import { EuiColorPicker } from '../../../../src/components'; +import { EuiColorPicker, EuiFormRow } from '../../../../src/components'; +import { isValidHex } from '../../../../src/services'; export class ColorPicker extends Component { constructor(props) { super(props); this.state = { - color: '#ffffff' + color: '#666' }; } @@ -17,6 +18,23 @@ export class ColorPicker extends Component { }; render() { - return ; + let errors; + if (!isValidHex(this.state.color)) { + errors = ['Provide a valid hex value']; + } + + return ( + + + + ); } } diff --git a/src-docs/src/views/color_picker/color_picker_example.js b/src-docs/src/views/color_picker/color_picker_example.js index 9a3c4c9e483..59caea5cd19 100644 --- a/src-docs/src/views/color_picker/color_picker_example.js +++ b/src-docs/src/views/color_picker/color_picker_example.js @@ -29,25 +29,5 @@ export const ColorPickerExample = { code: colorPickerHtml, }], demo: , - }, { - title: 'With label and reset link', - source: [{ - type: GuideSectionTypes.JS, - code: colorPickerClearSource, - }, { - type: GuideSectionTypes.HTML, - code: colorPickerClearHtml, - }], - demo: , - }, { - title: 'Without a color label', - source: [{ - type: GuideSectionTypes.JS, - code: colorPickerNoColorLabelSource, - }, { - type: GuideSectionTypes.HTML, - code: colorPickerNoColorLabelHtml, - }], - demo: , }], }; diff --git a/src-docs/src/views/outside_click_detector/outside_click_detector_example.js b/src-docs/src/views/outside_click_detector/outside_click_detector_example.js index 3584e91af18..82fca516e4f 100644 --- a/src-docs/src/views/outside_click_detector/outside_click_detector_example.js +++ b/src-docs/src/views/outside_click_detector/outside_click_detector_example.js @@ -28,7 +28,7 @@ export const OutsideClickDetectorExample = { text: (

Use EuiOutsideClickDetector to trigger a handler when the user clicks outside of the - child element. + child element. Note that it will not work if the immediate child is a React Fragment.

), props: { EuiOutsideClickDetector }, diff --git a/src/components/color_picker/__snapshots__/color_picker.test.js.snap b/src/components/color_picker/__snapshots__/color_picker.test.js.snap index a6cfc2c7bc4..f6a5b812acc 100644 --- a/src/components/color_picker/__snapshots__/color_picker.test.js.snap +++ b/src/components/color_picker/__snapshots__/color_picker.test.js.snap @@ -3,74 +3,37 @@ exports[`renders EuiColorPicker 1`] = `
-
- #ffeedd -
-
-
-`; - -exports[`renders EuiColorPicker with an empty swatch when color is null 1`] = ` -
-
-
- - +
-
- (transparent) -
-
-
-`; - -exports[`renders EuiColorPicker without a color label when showColorLabel is false 1`] = ` -
-
-
`; diff --git a/src/components/color_picker/_color_picker.scss b/src/components/color_picker/_color_picker.scss index bf342a78be7..22be2e52431 100644 --- a/src/components/color_picker/_color_picker.scss +++ b/src/components/color_picker/_color_picker.scss @@ -1,43 +1,26 @@ .euiColorPicker { - cursor: pointer; -} + position: relative; + max-width: 400px; - .euiColorPicker__preview { - display: flex; - align-items: center; - } + .euiColorPicker__panel { + max-width: 400px; + border-radius: 0 0 $euiBorderRadius $euiBorderRadius; + position: absolute; + top: 100%; + // 5 columns + margins + border + width: ($euiSizeL * 5) + ($euiSizeS * 6) + 2px; - .euiColorPicker__swatch { - width: $colorPickerSize; - height: $colorPickerSize; - border-radius: $euiBorderRadius; - box-shadow: inset 0 0 0 1px rgba(#000, 0.2); - display: inline-block; } - .euiColorPicker__emptySwatch { - svg { - position: absolute; - width: $colorPickerSize; - height: $colorPickerSize; - } + .euiColorPicker__swatchSelect { + display: inline-block; + height: $euiSizeL; + width: $euiSizeL; + border-radius: $euiBorderRadius / 2; + cursor: pointer; - svg line { - stroke: rgb(255, 0, 0); - stroke-width: 2; + &:focus { + @include euiFocusRing; } } - - .euiColorPicker__label { - font-size: $euiFontSize; - line-height: $euiLineHeight; - margin-left: 10px; - display: inline-block; - vertical-align: middle; - } - -.euiColorPickerPopUp { - position: absolute; - z-index: 10; } - diff --git a/src/components/color_picker/color_picker.js b/src/components/color_picker/color_picker.js index 0a93aacd53d..60295bbe3d1 100644 --- a/src/components/color_picker/color_picker.js +++ b/src/components/color_picker/color_picker.js @@ -3,11 +3,12 @@ import React, { } from 'react'; import PropTypes from 'prop-types'; import classNames from 'classnames'; -import { ChromePicker } from 'react-color'; -import { EuiOutsideClickDetector } from '../outside_click_detector'; - -import { EuiColorPickerSwatch } from './color_picker_swatch'; +import { EuiFieldText } from '../form' +import { EuiPanel } from '../panel' +import { EuiOutsideClickDetector } from '../outside_click_detector' +import { EuiFlexGroup, EuiFlexItem } from '../flex' +import { VISUALIZATION_COLORS, keyCodes } from '../../services'; export class EuiColorPicker extends Component { constructor(props) { @@ -15,62 +16,109 @@ export class EuiColorPicker extends Component { this.state = { showColorSelector: false, }; + } closeColorSelector = () => { + // To do proper label coloring if used as a child of EuiFormRow + if (this.props.onBlur) { + this.props.onBlur(); + } + this.setState({ showColorSelector: false }); }; - toggleColorSelector = () => { - this.setState({ showColorSelector: !this.state.showColorSelector }); + showColorSelector = () => { + // To do proper label coloring if used as a child of EuiFormRow + if (this.props.onFocus) { + this.props.onFocus(); + } + + this.setState({ showColorSelector: true }); }; - handleColorSelection = (color) => { - this.props.onChange(color.hex); + handleColorSelection = (e) => { + this.props.onChange(e.target.value); }; getColorLabel() { const { color } = this.props; const colorValue = color === null ? '(transparent)' : color; - return ( -
- { colorValue } -
- ); + return (colorValue); + } + + handleSwatchSelection(color) { + this.props.onChange(color); + this.input.focus(); } + onKeyDown = event => { + if (event.keyCode === keyCodes.ESCAPE) { + event.preventDefault(); + event.stopPropagation(); + this.closeColorSelector(); + } + }; + render() { - const { color, className, showColorLabel } = this.props; + const { + className, + color, + compressed, + disabled, + id, + isInvalid, + swatches, + } = this.props; const classes = classNames('euiColorPicker', className); - return ( - -
( + +