diff --git a/x-pack/plugins/lens/public/datatable_visualization/components/dimension_editor.scss b/x-pack/plugins/lens/public/datatable_visualization/components/dimension_editor.scss new file mode 100644 index 0000000000000..d7664b9d2da16 --- /dev/null +++ b/x-pack/plugins/lens/public/datatable_visualization/components/dimension_editor.scss @@ -0,0 +1,3 @@ +.lnsDynamicColoringRow { + align-items: center; +} \ No newline at end of file diff --git a/x-pack/plugins/lens/public/datatable_visualization/components/dimension_editor.tsx b/x-pack/plugins/lens/public/datatable_visualization/components/dimension_editor.tsx index 937084b15d77a..b76ab196cf76f 100644 --- a/x-pack/plugins/lens/public/datatable_visualization/components/dimension_editor.tsx +++ b/x-pack/plugins/lens/public/datatable_visualization/components/dimension_editor.tsx @@ -29,6 +29,7 @@ import { } from '../../shared_components/'; import { PalettePanelContainer } from './palette_panel_container'; import { findMinMaxByColumnId } from './shared_utils'; +import './dimension_editor.scss'; const idPrefix = htmlIdGenerator()(); @@ -245,10 +246,11 @@ export function TableDimensionEditor( {hasDynamicColoring && ( diff --git a/x-pack/plugins/lens/public/datatable_visualization/components/palette_panel_container.tsx b/x-pack/plugins/lens/public/datatable_visualization/components/palette_panel_container.tsx index c3c094999e656..1371fbe73ef84 100644 --- a/x-pack/plugins/lens/public/datatable_visualization/components/palette_panel_container.tsx +++ b/x-pack/plugins/lens/public/datatable_visualization/components/palette_panel_container.tsx @@ -86,7 +86,7 @@ export function PalettePanelContainer({ > {i18n.translate('xpack.lens.table.palettePanelTitle', { - defaultMessage: 'Color palette settings', + defaultMessage: 'Edit color', })} diff --git a/x-pack/plugins/lens/public/shared_components/coloring/color_stops.tsx b/x-pack/plugins/lens/public/shared_components/coloring/color_stops.tsx index 33efb6ad9c66d..382b060020e2f 100644 --- a/x-pack/plugins/lens/public/shared_components/coloring/color_stops.tsx +++ b/x-pack/plugins/lens/public/shared_components/coloring/color_stops.tsx @@ -8,13 +8,13 @@ import React, { useState, useEffect } from 'react'; import type { FocusEvent } from 'react'; import { i18n } from '@kbn/i18n'; import { - EuiFormRow, EuiFieldNumber, EuiColorPicker, EuiButtonIcon, EuiFlexItem, EuiFlexGroup, EuiButtonEmpty, + EuiSpacer, EuiScreenReaderOnly, } from '@elastic/eui'; import { DEFAULT_COLOR } from './constants'; @@ -70,178 +70,184 @@ export const CustomStops = ({ return ( <> - + {sortedReason ? ( -
-

- {sortedReason - ? i18n.translate('xpack.lens.dynamicColoring.customPalette.sortReason', { - defaultMessage: 'Color stops have been sorted due to new stop value {value}', - values: { - value: sortedReason, - }, - }) - : null} -

-
+

+ {i18n.translate('xpack.lens.dynamicColoring.customPalette.sortReason', { + defaultMessage: 'Color stops have been sorted due to new stop value {value}', + values: { + value: sortedReason, + }, + })} +

- - {localColorStops.map(({ color, stop }, index) => { - const prevStopValue = Number(localColorStops[index - 1]?.stop ?? -Infinity); - const nextStopValue = Number(localColorStops[index + 1]?.stop ?? Infinity); - const errorMessages = []; - // do not show color error messages if number field is already in error - if (!isValidColor(color) && errorMessages.length === 0) { - errorMessages.push( - i18n.translate('xpack.lens.dynamicColoring.customPalette.hexWarningLabel', { - defaultMessage: 'Color must provide a valid hex value', - }) - ); - } - return ( - ) => { - // sort the stops when the focus leaves the row container - const shouldSort = Number(stop) > nextStopValue || prevStopValue > Number(stop); - const isFocusStillInContent = - (e.currentTarget as Node)?.contains(e.relatedTarget as Node) || popoverInFocus; - if (shouldSort && !isFocusStillInContent) { - setLocalColorStops( - [...localColorStops].sort( - ({ stop: stopA }, { stop: stopB }) => Number(stopA) - Number(stopB) - ) - ); - setSortReason(stop); - } - }} - > - - - { - const newStopString = target.value.trim(); - const newColorStops = [...localColorStops]; - newColorStops[index] = { - color, - stop: newStopString, - }; - setLocalColorStops(newColorStops); - }} - append={rangeType === 'percent' ? '%' : undefined} + ) : null} + + + {localColorStops.map(({ color, stop }, index) => { + const prevStopValue = Number(localColorStops[index - 1]?.stop ?? -Infinity); + const nextStopValue = Number(localColorStops[index + 1]?.stop ?? Infinity); + + // TODO: Commented out the below error message code because 1) the individual color stops no longer use an `EuiFormRow` component and 2) I don't think such error message are needed, as the `EuiColorPicker` dropdown already has the hex field displaying such an error in the case of an invalid hex value. Instead of having a redundant error message, can we instead change it so that if an invalid hex value remains on blur of the `EuiColorPicker`, we simply revert to last known good hex value? + // const errorMessages = []; + // // do not show color error messages if number field is already in error + // if (!isValidColor(color) && errorMessages.length === 0) { + // errorMessages.push( + // i18n.translate('xpack.lens.dynamicColoring.customPalette.hexWarningLabel', { + // defaultMessage: 'Color must provide a valid hex value', + // }) + // ); + // } + + return ( + ) => { + // sort the stops when the focus leaves the row container + const shouldSort = Number(stop) > nextStopValue || prevStopValue > Number(stop); + const isFocusStillInContent = + (e.currentTarget as Node)?.contains(e.relatedTarget as Node) || popoverInFocus; + if (shouldSort && !isFocusStillInContent) { + setLocalColorStops( + [...localColorStops].sort( + ({ stop: stopA }, { stop: stopB }) => Number(stopA) - Number(stopB) + ) + ); + setSortReason(stop); + } + }} + > + + + { + const newStopString = target.value.trim(); + const newColorStops = [...localColorStops]; + newColorStops[index] = { + color, + stop: newStopString, + }; + setLocalColorStops(newColorStops); + }} + append={rangeType === 'percent' ? '%' : undefined} + aria-label={i18n.translate( + 'xpack.lens.dynamicColoring.customPalette.stopAriaLabel', + { + defaultMessage: 'Stop {index}', + values: { + index: index + 1, + }, + } + )} + /> + + + + { + const newColorStops = [...localColorStops]; + newColorStops[index] = { color: newColor, stop }; + setLocalColorStops(newColorStops); + }} + secondaryInputDisplay="top" + color={color} + isInvalid={!isValidColor(color)} + showAlpha + compressed + onFocus={() => setPopoverInFocus(true)} + onBlur={() => setPopoverInFocus(false)} + /> + + + + + - - - { - const newColorStops = [...localColorStops]; - newColorStops[index] = { color: newColor, stop }; - setLocalColorStops(newColorStops); - }} - secondaryInputDisplay="top" - color={color} - isInvalid={!isValidColor(color)} - showAlpha - compressed - onFocus={() => setPopoverInFocus(true)} - onBlur={() => setPopoverInFocus(false)} - /> - - - - { - const newColorStops = localColorStops.filter((_, i) => i !== index); - setLocalColorStops(newColorStops); - }} - data-test-subj={`${dataTestPrefix}_dynamicColoring_removeStop_${index}`} - isDisabled={!shouldEnableDelete} - /> - - - - - ); - })} - -
- - - { - const newColorStops = [...localColorStops]; - const length = newColorStops.length; - const { max } = getDataMinMax(rangeType, dataBounds); - const step = getStepValue( - colorStops, - newColorStops.map(({ color, stop }) => ({ color, stop: Number(stop) })), - max - ); - const prevColor = localColorStops[length - 1].color || DEFAULT_COLOR; - const newStop = step + Number(localColorStops[length - 1].stop); - newColorStops.push({ - color: prevColor, - stop: String(newStop), - }); - setLocalColorStops(newColorStops); - }} - > - {i18n.translate('xpack.lens.dynamicColoring.customPalette.addColorStop', { - defaultMessage: 'Add color stop', - })} - - + onClick={() => { + const newColorStops = localColorStops.filter((_, i) => i !== index); + setLocalColorStops(newColorStops); + }} + data-test-subj={`${dataTestPrefix}_dynamicColoring_removeStop_${index}`} + isDisabled={!shouldEnableDelete} + /> + + + + + ); + })}
+ + + + { + const newColorStops = [...localColorStops]; + const length = newColorStops.length; + const { max } = getDataMinMax(rangeType, dataBounds); + const step = getStepValue( + colorStops, + newColorStops.map(({ color, stop }) => ({ color, stop: Number(stop) })), + max + ); + const prevColor = localColorStops[length - 1].color || DEFAULT_COLOR; + const newStop = step + Number(localColorStops[length - 1].stop); + newColorStops.push({ + color: prevColor, + stop: String(newStop), + }); + setLocalColorStops(newColorStops); + }} + > + {i18n.translate('xpack.lens.dynamicColoring.customPalette.addColorStop', { + defaultMessage: 'Add color stop', + })} + ); }; diff --git a/x-pack/plugins/lens/public/shared_components/coloring/palette_configuration.scss b/x-pack/plugins/lens/public/shared_components/coloring/palette_configuration.scss index e81e679b17dc3..c6b14c5c5f9a3 100644 --- a/x-pack/plugins/lens/public/shared_components/coloring/palette_configuration.scss +++ b/x-pack/plugins/lens/public/shared_components/coloring/palette_configuration.scss @@ -4,8 +4,4 @@ .lnsPalettePanel__section { padding: $euiSizeS; -} - -.lnsPalettePanel__reverseButton { - margin-top: -4px; } \ No newline at end of file diff --git a/x-pack/plugins/lens/public/shared_components/coloring/palette_configuration.tsx b/x-pack/plugins/lens/public/shared_components/coloring/palette_configuration.tsx index 465c05ac2382e..12491a1797825 100644 --- a/x-pack/plugins/lens/public/shared_components/coloring/palette_configuration.tsx +++ b/x-pack/plugins/lens/public/shared_components/coloring/palette_configuration.tsx @@ -11,10 +11,13 @@ import { EuiFormRow, htmlIdGenerator, EuiButtonGroup, + EuiFlexGroup, + EuiFlexItem, EuiSuperSelect, - EuiToolTip, EuiIcon, - EuiButtonEmpty, + EuiIconTip, + EuiLink, + EuiText, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { PalettePicker } from './palette_picker'; @@ -123,6 +126,7 @@ export function CustomizablePalette({ > - - {i18n.translate('xpack.lens.table.dynamicColoring.rangeType.label', { - defaultMessage: 'Value type', - })}{' '} - - - + <> + {i18n.translate('xpack.lens.table.dynamicColoring.rangeType.label', { + defaultMessage: 'Value type', + })}{' '} + + } display="rowCompressed" > @@ -267,44 +271,52 @@ export function CustomizablePalette({ /> { - const params: CustomPaletteParams = { reverse: !activePalette.params?.reverse }; - if (isCurrentPaletteCustom) { - params.colorStops = reversePalette(colorStopsToShow); - params.stops = getPaletteStops( - palettes, - { - ...(activePalette?.params || {}), - colorStops: params.colorStops, - }, - { dataBounds } - ); - } else { - params.stops = reversePalette( - activePalette?.params?.stops || - getPaletteStops( - palettes, - { ...activePalette.params, ...params }, - { prevPalette: activePalette.name, dataBounds } - ) - ); - } - setPalette(mergePaletteParams(activePalette, params)); - }} - > - {i18n.translate('xpack.lens.table.dynamicColoring.reverse.label', { - defaultMessage: 'Reverse colors', - })} - + + { + const params: CustomPaletteParams = { reverse: !activePalette.params?.reverse }; + if (isCurrentPaletteCustom) { + params.colorStops = reversePalette(colorStopsToShow); + params.stops = getPaletteStops( + palettes, + { + ...(activePalette?.params || {}), + colorStops: params.colorStops, + }, + { dataBounds } + ); + } else { + params.stops = reversePalette( + activePalette?.params?.stops || + getPaletteStops( + palettes, + { ...activePalette.params, ...params }, + { prevPalette: activePalette.name, dataBounds } + ) + ); + } + setPalette(mergePaletteParams(activePalette, params)); + }} + > + + + + + + {i18n.translate('xpack.lens.table.dynamicColoring.reverse.label', { + defaultMessage: 'Reverse colors', + })} + + + + } >