From 270f4f2a506e4750d6fba8f80d25a291e0276df3 Mon Sep 17 00:00:00 2001 From: Greg Thompson Date: Thu, 16 Apr 2020 12:03:09 -0500 Subject: [PATCH 01/10] inputDisplay prop for popover panel input --- src/components/color_picker/color_picker.tsx | 70 ++++++++++++++++--- .../color_stops/color_stop_thumb.tsx | 38 +--------- 2 files changed, 64 insertions(+), 44 deletions(-) diff --git a/src/components/color_picker/color_picker.tsx b/src/components/color_picker/color_picker.tsx index 32982a47cdc..bbaebd823fc 100644 --- a/src/components/color_picker/color_picker.tsx +++ b/src/components/color_picker/color_picker.tsx @@ -40,6 +40,7 @@ import { EuiFieldText, EuiFormControlLayout, EuiFormControlLayoutProps, + EuiFormRow, EuiRange, } from '../form'; import { EuiI18n } from '../i18n'; @@ -140,6 +141,10 @@ export interface EuiColorPickerProps * Default is to display the last format entered by the user */ format?: 'hex' | 'rgba'; + /** + * Placement option for a popover panel color value input. + */ + inputDisplay?: 'top' | 'bottom' | 'none'; } function isKeyboardEvent( @@ -201,6 +206,7 @@ export const EuiColorPicker: FunctionComponent = ({ append, showAlpha = false, format, + inputDisplay = 'none', }) => { const preferredFormat = useMemo(() => { if (format) return format; @@ -248,7 +254,8 @@ export const EuiColorPicker: FunctionComponent = ({ const classes = classNames('euiColorPicker', className); const popoverClass = 'euiColorPicker__popoverAnchor'; const panelClasses = classNames('euiColorPicker__popoverPanel', { - 'euiColorPicker__popoverPanel--pickerOnly': mode === 'picker', + 'euiColorPicker__popoverPanel--pickerOnly': + mode === 'picker' && inputDisplay !== 'bottom', 'euiColorPicker__popoverPanel--customButton': button, }); const swatchClass = 'euiColorPicker__swatchSelect'; @@ -414,8 +421,44 @@ export const EuiColorPicker: FunctionComponent = ({ } }; + const inlineInput = inputDisplay !== 'none' && ( + + {([colorLabel, colorErrorMessage, transparent]: string[]) => ( + + + + )} + + ); + const composite = ( - + <> + {inputDisplay === 'top' && ( + <> + {inlineInput} + + + )} {mode !== 'swatch' && (
= ({ ))} )} + {inputDisplay === 'bottom' && ( + <> + {mode !== 'picker' && } + {inlineInput} + + )} {showAlpha && ( - + <> = ({ /> )} - + )} - + ); let buttonOrInput; @@ -514,18 +563,23 @@ export const EuiColorPicker: FunctionComponent = ({ color: colorStyle, }}> - {([openLabel, closeLabel]: string[]) => ( + {([openLabel, closeLabel, transparent]: string[]) => ( = ({ return chromaColor ? chromaColor.css() : undefined; }, [color, colorPickerShowAlpha]); const [hasFocus, setHasFocus] = useState(isPopoverOpen); - const [colorIsInvalid, setColorIsInvalid] = useState( - isColorInvalid(color, colorPickerShowAlpha) - ); const [stopIsInvalid, setStopIsInvalid] = useState(isStopInvalid(stop)); const [numberInputRef, setNumberInputRef] = useState(); const popoverRef = useRef(null); @@ -151,13 +147,9 @@ export const EuiColorStopThumb: FunctionComponent = ({ const setHasFocusFalse = () => setHasFocus(false); const handleColorChange = (value: ColorStop['color']) => { - setColorIsInvalid(isColorInvalid(value, colorPickerShowAlpha)); onChange({ stop, color: value }); }; - const handleColorInputChange = (e: React.ChangeEvent) => - handleColorChange(e.target.value); - const handleStopChange = (value: ColorStop['stop']) => { const willBeInvalid = value > localMax || value < localMin; @@ -382,36 +374,10 @@ export const EuiColorStopThumb: FunctionComponent = ({ swatches={colorPickerSwatches} display="inline" showAlpha={colorPickerShowAlpha} + inputDisplay={colorPickerMode === 'swatch' ? 'none' : 'bottom'} /> )} - {colorPickerMode !== 'swatch' && ( - - - - {([hexLabel, hexErrorMessage]: React.ReactChild[]) => ( - - - - )} - - - )}
); From a9ef673f6a7076ffa52e74250dce468ae6561b15 Mon Sep 17 00:00:00 2001 From: Greg Thompson Date: Thu, 16 Apr 2020 12:03:38 -0500 Subject: [PATCH 02/10] tests --- .../color_picker/color_picker.test.tsx | 36 ++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/src/components/color_picker/color_picker.test.tsx b/src/components/color_picker/color_picker.test.tsx index df7422887ea..c98adfd95c2 100644 --- a/src/components/color_picker/color_picker.test.tsx +++ b/src/components/color_picker/color_picker.test.tsx @@ -283,7 +283,7 @@ test('Setting a new alpha value calls onChange', () => { }); }); -test('default mode does redners child components', () => { +test('default mode does renders child components', () => { const colorPicker = mount( ); @@ -334,3 +334,37 @@ test('picker mode does not render swatches', () => { const swatches = colorPicker.find('button.euiColorPicker__swatchSelect'); expect(swatches.length).toBe(0); }); + +test('inputDisplay `top` has a popover panel input', () => { + const colorPicker = mount( + + ); + + findTestSubject(colorPicker, 'colorPickerAnchor').simulate('click'); + const inputTop = findTestSubject(colorPicker, 'topColorPickerInput'); + const inputBottom = findTestSubject(colorPicker, 'bottomColorPickerInput'); + expect(inputTop.length).toBe(1); + expect(inputBottom.length).toBe(0); +}); + +test('inputDisplay `bottom` has a popover panel input', () => { + const colorPicker = mount( + + ); + + findTestSubject(colorPicker, 'colorPickerAnchor').simulate('click'); + const inputTop = findTestSubject(colorPicker, 'topColorPickerInput'); + const inputBottom = findTestSubject(colorPicker, 'bottomColorPickerInput'); + expect(inputTop.length).toBe(0); + expect(inputBottom.length).toBe(1); +}); From 0b2c02cdad9d1335ea9df0288daffc0d4116405a Mon Sep 17 00:00:00 2001 From: Greg Thompson Date: Thu, 16 Apr 2020 12:04:44 -0500 Subject: [PATCH 03/10] docs --- .../color_picker/color_picker_example.js | 22 ++++++++++++++----- .../src/views/color_picker/custom_button.js | 2 ++ 2 files changed, 18 insertions(+), 6 deletions(-) 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 1f90a21358c..e3abda3a815 100644 --- a/src-docs/src/views/color_picker/color_picker_example.js +++ b/src-docs/src/views/color_picker/color_picker_example.js @@ -122,6 +122,7 @@ const customButtonHtml = renderToHtml(CustomButton); const customButtonSnippet = ` - Available only in EuiColorPicker. You can optionally - use a custom button as the trigger for selection using the{' '} - button prop. Please remember to add accessibility - to this component, using proper button markup and aria labeling. -

+ <> +

+ Available only in EuiColorPicker. You can + optionally use a custom button as the trigger for selection using + the button prop. Please remember to add + accessibility to this component, using proper button markup and aria + labeling. +

+

+ Additionally, use the inputDisplay prop to show a + color value input inside the popover panel. Options include{' '} + top and bottom placement. +

+ ), snippet: [customButtonSnippet, customBadgeSnippet], demo: , diff --git a/src-docs/src/views/color_picker/custom_button.js b/src-docs/src/views/color_picker/custom_button.js index e8c227cd011..3a4105d0841 100644 --- a/src-docs/src/views/color_picker/custom_button.js +++ b/src-docs/src/views/color_picker/custom_button.js @@ -23,6 +23,7 @@ export const CustomButton = () => { { onChange={handleColorChange} color={color} isInvalid={!!errors} + inputDisplay="bottom" button={ Date: Fri, 17 Apr 2020 16:49:06 -0500 Subject: [PATCH 04/10] reinstate validation --- .../color_picker/color_stops/color_stop_thumb.tsx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/components/color_picker/color_stops/color_stop_thumb.tsx b/src/components/color_picker/color_stops/color_stop_thumb.tsx index 6e840e93ff6..6e9af98a2e4 100644 --- a/src/components/color_picker/color_stops/color_stop_thumb.tsx +++ b/src/components/color_picker/color_stops/color_stop_thumb.tsx @@ -31,6 +31,7 @@ import { CommonProps } from '../../common'; import { getPositionFromStop, getStopFromMouseLocation, + isColorInvalid, isStopInvalid, } from './utils'; import { useMouseMove, getChromaColor } from '../utils'; @@ -110,6 +111,9 @@ export const EuiColorStopThumb: FunctionComponent = ({ }, [color, colorPickerShowAlpha]); const [hasFocus, setHasFocus] = useState(isPopoverOpen); const [stopIsInvalid, setStopIsInvalid] = useState(isStopInvalid(stop)); + const [colorIsInvalid, setColorIsInvalid] = useState( + isColorInvalid(color, colorPickerShowAlpha) + ); const [numberInputRef, setNumberInputRef] = useState(); const popoverRef = useRef(null); @@ -147,6 +151,7 @@ export const EuiColorStopThumb: FunctionComponent = ({ const setHasFocusFalse = () => setHasFocus(false); const handleColorChange = (value: ColorStop['color']) => { + setColorIsInvalid(isColorInvalid(value, colorPickerShowAlpha)); onChange({ stop, color: value }); }; @@ -374,6 +379,7 @@ export const EuiColorStopThumb: FunctionComponent = ({ swatches={colorPickerSwatches} display="inline" showAlpha={colorPickerShowAlpha} + isInvalid={colorIsInvalid} inputDisplay={colorPickerMode === 'swatch' ? 'none' : 'bottom'} />
From f0f85a61b86ea7987b4514e38b1f0392c6812dd3 Mon Sep 17 00:00:00 2001 From: Greg Thompson Date: Fri, 17 Apr 2020 16:52:26 -0500 Subject: [PATCH 05/10] clean up --- src/components/color_picker/color_stops/color_stop_thumb.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/color_picker/color_stops/color_stop_thumb.tsx b/src/components/color_picker/color_stops/color_stop_thumb.tsx index 6e9af98a2e4..4fe780d3b97 100644 --- a/src/components/color_picker/color_stops/color_stop_thumb.tsx +++ b/src/components/color_picker/color_stops/color_stop_thumb.tsx @@ -110,10 +110,10 @@ export const EuiColorStopThumb: FunctionComponent = ({ return chromaColor ? chromaColor.css() : undefined; }, [color, colorPickerShowAlpha]); const [hasFocus, setHasFocus] = useState(isPopoverOpen); - const [stopIsInvalid, setStopIsInvalid] = useState(isStopInvalid(stop)); const [colorIsInvalid, setColorIsInvalid] = useState( isColorInvalid(color, colorPickerShowAlpha) ); + const [stopIsInvalid, setStopIsInvalid] = useState(isStopInvalid(stop)); const [numberInputRef, setNumberInputRef] = useState(); const popoverRef = useRef(null); From 42d890a39d1e4479847f2be73161aaf4d1a1d6ca Mon Sep 17 00:00:00 2001 From: Greg Thompson Date: Mon, 20 Apr 2020 10:13:36 -0500 Subject: [PATCH 06/10] use secondaryInputDispay name --- .../views/color_picker/color_picker_example.js | 6 +++--- src-docs/src/views/color_picker/custom_button.js | 4 ++-- .../color_picker/color_picker.test.tsx | 8 ++++---- src/components/color_picker/color_picker.tsx | 16 ++++++++-------- .../color_stops/color_stop_thumb.tsx | 4 +++- 5 files changed, 20 insertions(+), 18 deletions(-) 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 e3abda3a815..1dec55d48a5 100644 --- a/src-docs/src/views/color_picker/color_picker_example.js +++ b/src-docs/src/views/color_picker/color_picker_example.js @@ -122,7 +122,7 @@ const customButtonHtml = renderToHtml(CustomButton); const customButtonSnippet = `

Additionally, use the inputDisplay prop to show a - color value input inside the popover panel. Options include{' '} + secondary or alternative color value input. Options include{' '} top and bottom placement.

diff --git a/src-docs/src/views/color_picker/custom_button.js b/src-docs/src/views/color_picker/custom_button.js index 3a4105d0841..a18b6235f31 100644 --- a/src-docs/src/views/color_picker/custom_button.js +++ b/src-docs/src/views/color_picker/custom_button.js @@ -23,7 +23,7 @@ export const CustomButton = () => { { onChange={handleColorChange} color={color} isInvalid={!!errors} - inputDisplay="bottom" + secondaryInputDisplay="bottom" button={ { expect(swatches.length).toBe(0); }); -test('inputDisplay `top` has a popover panel input', () => { +test('secondaryInputDisplay `top` has a popover panel input', () => { const colorPicker = mount( @@ -352,11 +352,11 @@ test('inputDisplay `top` has a popover panel input', () => { expect(inputBottom.length).toBe(0); }); -test('inputDisplay `bottom` has a popover panel input', () => { +test('secondaryInputDisplay `bottom` has a popover panel input', () => { const colorPicker = mount( diff --git a/src/components/color_picker/color_picker.tsx b/src/components/color_picker/color_picker.tsx index bbaebd823fc..6e55acb7922 100644 --- a/src/components/color_picker/color_picker.tsx +++ b/src/components/color_picker/color_picker.tsx @@ -142,9 +142,9 @@ export interface EuiColorPickerProps */ format?: 'hex' | 'rgba'; /** - * Placement option for a popover panel color value input. + * Placement option for a secondary color value input. */ - inputDisplay?: 'top' | 'bottom' | 'none'; + secondaryInputDisplay?: 'top' | 'bottom' | 'none'; } function isKeyboardEvent( @@ -206,7 +206,7 @@ export const EuiColorPicker: FunctionComponent = ({ append, showAlpha = false, format, - inputDisplay = 'none', + secondaryInputDisplay = 'none', }) => { const preferredFormat = useMemo(() => { if (format) return format; @@ -255,7 +255,7 @@ export const EuiColorPicker: FunctionComponent = ({ const popoverClass = 'euiColorPicker__popoverAnchor'; const panelClasses = classNames('euiColorPicker__popoverPanel', { 'euiColorPicker__popoverPanel--pickerOnly': - mode === 'picker' && inputDisplay !== 'bottom', + mode === 'picker' && secondaryInputDisplay !== 'bottom', 'euiColorPicker__popoverPanel--customButton': button, }); const swatchClass = 'euiColorPicker__swatchSelect'; @@ -421,7 +421,7 @@ export const EuiColorPicker: FunctionComponent = ({ } }; - const inlineInput = inputDisplay !== 'none' && ( + const inlineInput = secondaryInputDisplay !== 'none' && ( = ({ readOnly={readOnly} aria-label={colorLabel} autoComplete="off" - data-test-subj={`${inputDisplay}ColorPickerInput`} + data-test-subj={`${secondaryInputDisplay}ColorPickerInput`} /> )} @@ -453,7 +453,7 @@ export const EuiColorPicker: FunctionComponent = ({ const composite = ( <> - {inputDisplay === 'top' && ( + {secondaryInputDisplay === 'top' && ( <> {inlineInput} @@ -499,7 +499,7 @@ export const EuiColorPicker: FunctionComponent = ({ ))} )} - {inputDisplay === 'bottom' && ( + {secondaryInputDisplay === 'bottom' && ( <> {mode !== 'picker' && } {inlineInput} diff --git a/src/components/color_picker/color_stops/color_stop_thumb.tsx b/src/components/color_picker/color_stops/color_stop_thumb.tsx index 4fe780d3b97..0be5c0ea249 100644 --- a/src/components/color_picker/color_stops/color_stop_thumb.tsx +++ b/src/components/color_picker/color_stops/color_stop_thumb.tsx @@ -380,7 +380,9 @@ export const EuiColorStopThumb: FunctionComponent = ({ display="inline" showAlpha={colorPickerShowAlpha} isInvalid={colorIsInvalid} - inputDisplay={colorPickerMode === 'swatch' ? 'none' : 'bottom'} + secondaryInputDisplay={ + colorPickerMode === 'swatch' ? 'none' : 'bottom' + } /> )} From 2f41b8a0d8ed8e41b7e80934e336378bb75c4e37 Mon Sep 17 00:00:00 2001 From: Greg Thompson Date: Mon, 20 Apr 2020 14:25:08 -0500 Subject: [PATCH 07/10] Update src-docs/src/views/color_picker/color_picker_example.js Co-Authored-By: Caroline Horn <549577+cchaos@users.noreply.github.com> --- src-docs/src/views/color_picker/color_picker_example.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 1dec55d48a5..6ef54556bc1 100644 --- a/src-docs/src/views/color_picker/color_picker_example.js +++ b/src-docs/src/views/color_picker/color_picker_example.js @@ -478,7 +478,7 @@ export const ColorPickerExample = { labeling.

- Additionally, use the inputDisplay prop to show a + Additionally, use the secondaryInputDisplay prop to show a secondary or alternative color value input. Options include{' '} top and bottom placement.

From 11b833d484d0c3439461acfc2cde1626a36033d4 Mon Sep 17 00:00:00 2001 From: Greg Thompson Date: Mon, 20 Apr 2020 15:05:48 -0500 Subject: [PATCH 08/10] reinstate readonly input --- .../color_picker/color_picker_example.js | 7 +++-- src/components/color_picker/color_picker.tsx | 12 ++++--- .../color_stops/color_stop_thumb.tsx | 31 +++++++++---------- 3 files changed, 26 insertions(+), 24 deletions(-) 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 6ef54556bc1..5aaf9300bd8 100644 --- a/src-docs/src/views/color_picker/color_picker_example.js +++ b/src-docs/src/views/color_picker/color_picker_example.js @@ -478,9 +478,10 @@ export const ColorPickerExample = { labeling.

- Additionally, use the secondaryInputDisplay prop to show a - secondary or alternative color value input. Options include{' '} - top and bottom placement. + Additionally, use the secondaryInputDisplay prop + to show a secondary or alternative color value input. Options + include top and bottom{' '} + placement.

), diff --git a/src/components/color_picker/color_picker.tsx b/src/components/color_picker/color_picker.tsx index 6e55acb7922..3ec4e6190d9 100644 --- a/src/components/color_picker/color_picker.tsx +++ b/src/components/color_picker/color_picker.tsx @@ -60,7 +60,7 @@ import { } from './utils'; type EuiColorPickerDisplay = 'default' | 'inline'; -type EuiColorPickerMode = 'default' | 'swatch' | 'picker'; +type EuiColorPickerMode = 'default' | 'swatch' | 'picker' | 'secondaryInput'; export interface EuiColorPickerOutput { rgba: ColorSpaces['rgba']; @@ -107,7 +107,7 @@ export interface EuiColorPickerProps */ isInvalid?: boolean; /** - * Choose between swatches with gradient picker (default), swatches only, or gradient picker only. + * Choose between swatches with gradient picker (default), swatches only, gradient picker only, or secondary input only. */ mode?: EuiColorPickerMode; /** @@ -451,6 +451,10 @@ export const EuiColorPicker: FunctionComponent = ({
); + const showSecondaryInputOnly = mode === 'secondaryInput'; + const showPicker = mode !== 'swatch' && !showSecondaryInputOnly; + const showSwatches = mode !== 'picker' && !showSecondaryInputOnly; + const composite = ( <> {secondaryInputDisplay === 'top' && ( @@ -459,7 +463,7 @@ export const EuiColorPicker: FunctionComponent = ({ )} - {mode !== 'swatch' && ( + {showPicker && (
= ({ />
)} - {mode !== 'picker' && ( + {showSwatches && ( {swatches.map((swatch, index) => ( diff --git a/src/components/color_picker/color_stops/color_stop_thumb.tsx b/src/components/color_picker/color_stops/color_stop_thumb.tsx index 0be5c0ea249..8979318a9b4 100644 --- a/src/components/color_picker/color_stops/color_stop_thumb.tsx +++ b/src/components/color_picker/color_stops/color_stop_thumb.tsx @@ -369,23 +369,20 @@ export const EuiColorStopThumb: FunctionComponent = ({ - {!readOnly && ( - - - - - )} + {!readOnly && } +
); From dfd30169a28027699ae73f28a99de76c2640ffa8 Mon Sep 17 00:00:00 2001 From: Greg Thompson Date: Tue, 21 Apr 2020 13:50:21 -0500 Subject: [PATCH 09/10] readonly and input spacing cleanup --- .../color_stops/color_stop_thumb.tsx | 40 ++++++++++--------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/src/components/color_picker/color_stops/color_stop_thumb.tsx b/src/components/color_picker/color_stops/color_stop_thumb.tsx index 8979318a9b4..615265d9742 100644 --- a/src/components/color_picker/color_stops/color_stop_thumb.tsx +++ b/src/components/color_picker/color_stops/color_stop_thumb.tsx @@ -350,26 +350,28 @@ export const EuiColorStopThumb: FunctionComponent = ({ )} - - - - {(removeLabel: string) => ( - - )} - - - + {!readOnly && ( + + + + {(removeLabel: string) => ( + + )} + + + + )} - {!readOnly && } + {!readOnly && } Date: Tue, 21 Apr 2020 14:29:49 -0500 Subject: [PATCH 10/10] CL --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c1e179ded4f..9eba0a3671a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ - Added `panelStyle` prop to `EuiPopover` to distinguish style object configuration ([#3329](https://github.com/elastic/eui/pull/3329)) - Extended `EuiDatePicker`'s `startDate` and `endDate` types to accept `null` values for better interoperability ([#3343](https://github.com/elastic/eui/pull/3343)) - Added `EuiCommentList` component ([#3344](https://github.com/elastic/eui/pull/3344)) +- Added secondary color value input element to `EuiColorPicker` ([#3336](https://github.com/elastic/eui/pull/3336)) **Bug Fixes**