Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

EuiColorStops: Feature Stepped ColorStops #4613

Merged
merged 20 commits into from
Mar 31, 2021
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 26 additions & 1 deletion src-docs/src/views/color_picker/color_stops.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import React, { useState } from 'react';

import { EuiColorStops, EuiFormRow } from '../../../../src/components';
import {
EuiColorStops,
EuiFormRow,
EuiRange,
} from '../../../../src/components';

import { useColorStopsState } from '../../../../src/services';

Expand All @@ -12,6 +16,8 @@ export default () => {
addRandomColor,
] = useColorStopsState(true);
const [fixedColorStops, setFixedColorStops] = useColorStopsState(true);
const [steppedColorStops, setSteppedColorStops] = useColorStopsState(true);
const [value, setValue] = useState(10);

const [extendedColorStops, setExtendedColorStops] = useState([
{
Expand Down Expand Up @@ -87,6 +93,25 @@ export default () => {
stopType="fixed"
/>
</EuiFormRow>
<EuiFormRow label="Stepped color segments">
<EuiColorStops
label="Stepped color segments"
onChange={setSteppedColorStops}
colorStops={steppedColorStops}
stepNumber={value}
min={0}
max={100}
stopType="stepped"
/>
</EuiFormRow>
<EuiRange
value={value}
onChange={(e) => setValue(e.target.value)}
showInput
aria-label="An example of EuiRange"
min={2}
max={20}
/>
</React.Fragment>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -812,3 +812,114 @@ exports[`renders readOnly EuiColorStops 1`] = `
</div>
</div>
`;

exports[`renders stepped stop EuiColorStops 1`] = `
<div
class="euiRangeWrapper euiColorStops testClass1 testClass2"
data-test-subj="euiColorStops"
tabindex="0"
>
<p
aria-live="polite"
class="euiScreenReaderOnly"
>
Test: Color stop picker. Each stop consists of a number and corresponding color value. Use the Down and Up arrow keys to select individual stops. Press the Enter key to create a new stop.
</p>
<div
class="euiRangeTrack"
>
<div
class="euiRangeHighlight euiColorStops__highlight"
>
<div
class="euiRangeHighlight__progress"
style="background:linear-gradient(to right,#ff0000 0% 10%, #8e7100 10% 20%, #1ce300 20% 30%, #002bd5 30% 40%, #0000ff 40% 50%, #0000ff 50% 60%, #0000ff 60% 70%, #0000ff 70% 80%, #0000ff 80% 90%, #0000ff 90% 100%);margin-left:0%;width:100%"
/>
</div>
<div
class="euiColorStops__addContainer"
data-test-subj="euiColorStopsAdd"
>
<div
class="euiColorStops__addTarget"
style="left:0%"
/>
</div>
<div
class="euiPopover euiPopover--anchorDownCenter euiColorStopPopover"
style="left:0%"
>
<div
class="euiPopover__anchor euiColorStopPopover__anchor"
>
<button
aria-disabled="false"
aria-label="Press the Enter key to modify this stop. Press Escape to focus the group"
aria-valuemax="24"
aria-valuemin="0"
aria-valuenow="0"
aria-valuetext="Stop: 0, Color: #FF0000 (1 of 3)"
class="euiRangeThumb euiColorStopThumb"
data-index="euiColorStop_0"
data-test-subj="euiColorStopThumb"
role="slider"
style="background:rgb(255,0,0)"
tabindex="-1"
title="Click to edit, drag to reposition"
type="button"
/>
</div>
</div>
<div
class="euiPopover euiPopover--anchorDownCenter euiColorStopPopover"
style="left:21%"
>
<div
class="euiPopover__anchor euiColorStopPopover__anchor"
>
<button
aria-disabled="false"
aria-label="Press the Enter key to modify this stop. Press Escape to focus the group"
aria-valuemax="34"
aria-valuemin="1"
aria-valuenow="25"
aria-valuetext="Stop: 25, Color: #00FF00 (2 of 3)"
class="euiRangeThumb euiColorStopThumb"
data-index="euiColorStop_1"
data-test-subj="euiColorStopThumb"
role="slider"
style="background:rgb(0,255,0)"
tabindex="-1"
title="Click to edit, drag to reposition"
type="button"
/>
</div>
</div>
<div
class="euiPopover euiPopover--anchorDownCenter euiColorStopPopover"
style="left:29.4%"
>
<div
class="euiPopover__anchor euiColorStopPopover__anchor"
>
<button
aria-disabled="false"
aria-label="Press the Enter key to modify this stop. Press Escape to focus the group"
aria-valuemax="100"
aria-valuemin="26"
aria-valuenow="35"
aria-valuetext="Stop: 35, Color: #0000FF (3 of 3)"
class="euiRangeThumb euiColorStopThumb"
data-index="euiColorStop_2"
data-test-subj="euiColorStopThumb"
role="slider"
style="background:rgb(0,0,255)"
tabindex="-1"
title="Click to edit, drag to reposition"
type="button"
/>
</div>
</div>
</div>
</div>
`;
16 changes: 16 additions & 0 deletions src/components/color_picker/color_stops/color_stops.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,22 @@ test('renders fixed stop EuiColorStops', () => {
expect(colorStops).toMatchSnapshot();
});

test('renders stepped stop EuiColorStops', () => {
const colorStops = render(
<EuiColorStops
label="Test"
onChange={onChange}
colorStops={colorStopsArray}
min={0}
max={100}
stopType="stepped"
stepNumber={10}
{...requiredProps}
/>
);
expect(colorStops).toMatchSnapshot();
});

test('renders empty EuiColorStops', () => {
const colorStops = render(
<EuiColorStops
Expand Down
39 changes: 31 additions & 8 deletions src/components/color_picker/color_stops/color_stops.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,14 @@ import {
} from './utils';

import { EuiColorPickerProps } from '../';
import { getChromaColor } from '../utils';
import { getChromaColor, getSteppedGradient } from '../utils';
import { EuiI18n } from '../../i18n';
import { EuiScreenReaderOnly } from '../../accessibility';
import { EuiRangeHighlight } from '../../form/range/range_highlight';
import { EuiRangeTrack } from '../../form/range/range_track';
import { EuiRangeWrapper } from '../../form/range/range_wrapper';
// import { colorPalette } from '../../../services/color/color_palette';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unused imports, please remove

// import { EuiColorPaletteDisplayFixed } from '../color_palette_display/color_palette_display_fixed';

export interface EuiColorStopsProps extends CommonProps {
addColor?: ColorStop['color'];
Expand All @@ -62,7 +64,8 @@ export interface EuiColorStopsProps extends CommonProps {
max?: number;
min?: number;
label: string;
stopType?: 'fixed' | 'gradient';
stopType?: 'fixed' | 'gradient' | 'stepped';
stepNumber?: number;
mode?: EuiColorPickerProps['mode'];
swatches?: EuiColorPickerProps['swatches'];
showAlpha?: EuiColorPickerProps['showAlpha'];
Expand Down Expand Up @@ -139,6 +142,7 @@ export const EuiColorStops: FunctionComponent<EuiColorStopsProps> = ({
className,
label,
stopType = 'gradient',
stepNumber = 10,
swatches,
showAlpha = false,
}) => {
Expand Down Expand Up @@ -291,7 +295,6 @@ export const EuiColorStops: FunctionComponent<EuiColorStopsProps> = ({
if (isNotInteractive || isTargetAThumb(e.target) || !wrapperRef) return;
const newStop = getStopFromMouseLocationFn({ x: e.pageX, y: e.pageY });
const newColorStops = addDefinedStop(colorStops, newStop, addColor);

setFocusStopOnUpdate(newStop);
handleOnChange(newColorStops);
};
Expand Down Expand Up @@ -440,10 +443,30 @@ export const EuiColorStops: FunctionComponent<EuiColorStopsProps> = ({
)}`;
}
};
const linearGradient = sortedStops.map(
stopType === 'gradient' ? gradientStop : fixedStop
);
const background = `linear-gradient(to right,${linearGradient})`;

let gradient: string = '';

if (stopType === 'stepped') {
const steppedColors = getSteppedGradient(colorStops, stepNumber);
console.log(steppedColors);
let steppedGradient = '';
const percentage = 100 / steppedColors.length;
let percentageSteps = 100 / steppedColors.length;

steppedColors.forEach((color) => {
steppedGradient = steppedGradient.concat(
`${color} ${percentageSteps - percentage}% ${percentageSteps}%, `
);
percentageSteps = percentageSteps + percentage;
});
steppedGradient = steppedGradient.substring(0, steppedGradient.length - 2);
gradient = `linear-gradient(to right,${steppedGradient})`;
} else {
const linearGradient = sortedStops.map(
stopType === 'gradient' ? gradientStop : fixedStop
);
gradient = `linear-gradient(to right,${linearGradient})`;
}

return (
<EuiRangeWrapper
Expand Down Expand Up @@ -483,7 +506,7 @@ export const EuiColorStops: FunctionComponent<EuiColorStopsProps> = ({
max={max || rangeMax}
lowerValue={min || rangeMin}
upperValue={max || rangeMax}
background={background}
background={gradient}
compressed={compressed}
/>
<div
Expand Down
5 changes: 4 additions & 1 deletion src/components/color_picker/color_stops/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,10 @@ export const addDefinedStop = (
stop,
color,
};
return [...colorStops, newStop];
colorStops = [...colorStops, newStop];
// eslint-disable-next-line no-nested-ternary
colorStops.sort((a, b) => (a.stop > b.stop ? 1 : b.stop > a.stop ? -1 : 0));
return colorStops;
};

export const addStop = (
Expand Down
13 changes: 13 additions & 0 deletions src/components/color_picker/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -258,3 +258,16 @@ export const getFixedLinearGradient = (palette: string[] | ColorStop[]) => {
return fixedLinearGradientWidthAuto;
}
};

export const getSteppedGradient = function (
colors: ColorStop[],
steps: number
) {
const finalStops = [0, ...colors.map((item) => item.stop / 100), 1];
const color = [
colors[0].color,
...colors.map((item) => item.color),
colors[colors.length - 1].color,
];
return chroma.scale(color).domain(finalStops).colors(steps);
};
1 change: 1 addition & 0 deletions src/components/form/range/range_highlight.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ export const EuiRangeHighlight: FunctionComponent<EuiRangeHighlightProps> = ({
// const rangeWidth = (value - min) / (max - min);
const leftPosition = (lowerValue - min) / (max - min);
const rangeWidth = (upperValue - lowerValue) / (max - min);

const rangeWidthStyle = {
background,
marginLeft: `${leftPosition * 100}%`,
Expand Down