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

feat: add 4.5 contrast for text in partition slices #608

Merged
merged 78 commits into from
Jun 8, 2020
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
78 commits
Select commit Hold shift + click to select a range
02f2f53
feat: move luminance value code from kibana in charts
rshen91 Mar 26, 2020
325b5bd
feat: textColor takes into account contrast with background slice
rshen91 Mar 31, 2020
6acca30
feat: account for initial non black or white textColor
rshen91 Mar 31, 2020
8f4ddf5
feat: add background color knob for xy charts
rshen91 Apr 10, 2020
23eb310
test: fix backgrounds to white for vrt
rshen91 Apr 13, 2020
d4b43ca
fix: add color background functionality to partition chart simple
rshen91 Apr 14, 2020
361200e
docs: add story for partition in styling
rshen91 Apr 14, 2020
963572b
feat: add combine color helper function
rshen91 Apr 15, 2020
01d1e2e
Merge remote-tracking branch 'upstream/master' into luminance-pie
rshen91 Apr 15, 2020
c7eec32
Merge remote-tracking branch 'upstream/master' into luminance-pie
rshen91 Apr 16, 2020
c36c79a
feat: add background to geometries
rshen91 Apr 20, 2020
fe5be74
fix: improve contrast
rshen91 Apr 20, 2020
cd31813
Merge remote-tracking branch 'upstream/master' into luminance-pie
rshen91 Apr 21, 2020
38e1250
fix: add updated story file
rshen91 Apr 21, 2020
69168b6
Merge remote-tracking branch 'upstream/master' into luminance-pie
rshen91 Apr 21, 2020
c1bc892
feat: update colorIsDark to adjust text for contrast
rshen91 Apr 21, 2020
7c3c7b0
Merge remote-tracking branch 'upstream/master' into luminance-pie
rshen91 Apr 22, 2020
69a2cc0
fix: readd textInvertible functionality in fill_text_layout
rshen91 Apr 22, 2020
7059318
Merge remote-tracking branch 'upstream/master' into luminance-pie
rshen91 Apr 22, 2020
f9a824d
WIP
rshen91 Apr 23, 2020
9bc19ba
Merge remote-tracking branch 'upstream/master' into luminance-pie
rshen91 Apr 23, 2020
65d8bc8
feat: improve makeHighContrastColor()
rshen91 Apr 23, 2020
71b512e
Merge remote-tracking branch 'upstream/master' into luminance-pie
rshen91 Apr 24, 2020
ba1b1cf
Merge remote-tracking branch 'upstream/master' into luminance-pie
rshen91 Apr 27, 2020
016cc7d
fix: merge conflicts
rshen91 Apr 27, 2020
9d0d6e7
WIP
rshen91 Apr 27, 2020
c0a56e0
feat: add link label contrast functionality
rshen91 Apr 27, 2020
878635c
chore: merge remote-tracking branch 'upstream/master' into luminance-pie
rshen91 Apr 28, 2020
94d69ec
test: update contrast logic and vrts
rshen91 Apr 28, 2020
1152d96
Merge remote-tracking branch 'upstream/master' into luminance-pie
rshen91 Apr 29, 2020
0688de9
Merge remote-tracking branch 'upstream/master' into luminance-pie
rshen91 Apr 29, 2020
e083865
fix: remove broken playground
rshen91 Apr 29, 2020
7ede9a3
fix: add playground from current master
rshen91 Apr 29, 2020
fc86b2a
test: add unit tests for calc file
rshen91 Apr 29, 2020
1fa7fb8
chore: merge remote-tracking branch 'upstream/master' into luminance-pie
rshen91 Apr 30, 2020
08f1dd7
WIP
rshen91 Apr 30, 2020
a957653
WIP
rshen91 Apr 30, 2020
876062a
merging with master but broken build
rshen91 Apr 30, 2020
9492c23
WIP
rshen91 May 2, 2020
fcc7cfe
Merge remote-tracking branch 'upstream/master' into luminance-pie
rshen91 May 2, 2020
8035d6c
Merge remote-tracking branch 'upstream/master' into luminance-pie
rshen91 May 4, 2020
5b3b11f
feat: playground add foreground color functionality
rshen91 May 4, 2020
572cbdd
feat: error handling in conbineColors
rshen91 May 4, 2020
336ae5e
Merge remote-tracking branch 'upstream/master' into luminance-pie
rshen91 May 4, 2020
c09dfca
Merge remote-tracking branch 'upstream/master' into luminance-pie
rshen91 May 5, 2020
08768fa
feat: add contrastText prop and opacity in playground
rshen91 May 5, 2020
1800133
Merge remote-tracking branch 'upstream/master' into luminance-pie
rshen91 May 5, 2020
ee33cfd
fix: fix brightness lightness calc
rshen91 May 5, 2020
4f4801b
chore: merge commit
rshen91 May 8, 2020
7412a60
Merge remote-tracking branch 'upstream/master' into luminance-pie
rshen91 May 8, 2020
0a24a5e
feat: add textContrast number functionality
rshen91 May 11, 2020
1c04a77
feat: fix contrast with luminance over lightness for colorIsDark
rshen91 May 12, 2020
511b5b4
test: add unit tests and add class to playground
rshen91 May 13, 2020
48ec0fa
Merge remote-tracking branch 'upstream/master' into luminance-pie
rshen91 May 19, 2020
f8619e2
feat: low hanging fruit
rshen91 May 20, 2020
b411301
feat: add code review changes
rshen91 May 21, 2020
88e42d3
fix: add internal tag to LinkLabelsViewModelSpec
rshen91 May 21, 2020
41314f9
Merge remote-tracking branch 'upstream/master' into luminance-pie
rshen91 May 26, 2020
8a4c825
fix: cp tmp/charts.api.md to api/chart.api.md
rshen91 May 26, 2020
0946501
Merge remote-tracking branch 'upstream/master' into luminance-pie
rshen91 May 27, 2020
545e78e
feat: add chart background to own component
rshen91 May 27, 2020
ef78e4b
fix: fix order for <ChartBackground />
rshen91 May 27, 2020
299f90e
fix: add styling fix for legend
rshen91 May 28, 2020
aa48c17
chore: merge remote-tracking branch 'upstream/master' into luminance-pie
rshen91 May 28, 2020
69cd5d8
test: add unit test for combine colors and correct contrast
rshen91 May 28, 2020
462debe
Merge remote-tracking branch 'upstream/master' into luminance-pie
rshen91 May 28, 2020
01b7052
docs: add docs to storybook docs about textContrast
rshen91 May 29, 2020
9bb1e8e
Merge remote-tracking branch 'upstream/master' into luminance-pie
rshen91 Jun 1, 2020
36baf2e
feat: update baseThemes
rshen91 Jun 2, 2020
1864be2
Merge branch 'master' into luminance-pie
nickofthyme Jun 7, 2020
f14f2fa
fix: update pr with remaining checks
nickofthyme Jun 8, 2020
33aeb59
refactor: return types and rgb format
markov00 Jun 8, 2020
979ffe0
fix: get correct theme via selector and minor refactoring
markov00 Jun 8, 2020
af65d11
fix: refactor chart size
markov00 Jun 8, 2020
9012b54
fix: cleanup theme colors and add color check
markov00 Jun 8, 2020
20a11c0
fix: api docs
markov00 Jun 8, 2020
44e5101
Merge branch 'master' into luminance-pie
markov00 Jun 8, 2020
9c91e74
fix: broken tests, update prop naming
nickofthyme Jun 8, 2020
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
1 change: 0 additions & 1 deletion .playground/playground.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,6 @@ export class Playground extends React.Component<{}, PlaygroundState> {
.split(',');
return `${r.trim()}, ${g.trim()}, ${b.trim()}, ${opacity})`;
};

render() {
const { backgroundColor, foregroundColor, textColor, value, opacityColor } = this.state;
const combinedColors = combineColors(foregroundColor, backgroundColor);
Expand Down
5 changes: 1 addition & 4 deletions api/charts.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ export interface AxisStyle {

// Warning: (ae-missing-release-tag) "BackgroundStyles" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
// @public
export interface BackgroundStyles {
// (undocumented)
color: string;
Expand Down Expand Up @@ -1277,8 +1277,6 @@ export const Settings: React.FunctionComponent<SettingsSpecProps>;
export interface SettingsSpec extends Spec {
// (undocumented)
animateData: boolean;
// (undocumented)
backgroundColor?: string;
baseTheme?: Theme;
brushAxis?: BrushAxis;
// (undocumented)
Expand Down Expand Up @@ -1413,7 +1411,6 @@ export interface Theme {
areaSeriesStyle: AreaSeriesStyle;
// (undocumented)
axes: AxisConfig;
// (undocumented)
background: BackgroundStyles;
barSeriesStyle: BarSeriesStyle;
bubbleSeriesStyle: BubbleSeriesStyle;
Expand Down
166 changes: 166 additions & 0 deletions docs/0-Intro/1-Overview.mdx
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
import { Chart, Datum, Partition, PartitionLayout, Settings } from '../../src';
import { mocks } from '../../src/mocks/hierarchical/index';
import { config } from '../../src/chart_types/partition_chart/layout/config/config';
import { ShapeTreeNode } from '../../src/chart_types/partition_chart/layout/types/viewmodel_types';
import {
categoricalFillColor,
colorBrewerCategoricalStark9,
countryLookup,
indexInterpolatedFillColor,
interpolatorCET2s,
interpolatorTurbo,
productLookup,
regionLookup,
} from '../../stories/utils/utils';
import { Meta, Story } from "@storybook/addon-docs/blocks";

<Meta title="Introduction/Elastic Charts Overview" />
Expand Down Expand Up @@ -255,3 +269,155 @@ type PointStyleAccessor = (
```

> Note: When overriding bar or point styles be mindful of performance and these accessor functions will be call on every bar/point is every series. Precomputing any expensive task before rendering.

### Background Colors and Text Contrast
You can provide the `backgroundColor` of the container that the chart will be placed onto. You can set the `textContrast` to a boolean value or a number. The default `textContrast` is set to 4.5 but you can always disable this or set your own numerical amount.

> Note: This functionality is currently available for Partition charts. Please see the partition background and partition label stories.

```js
config: {
fillLabel: {
textInvertible: true,
textContrast: true, // can also be set to a number
}
}
```
`textInvertible` will have to be set to true for `textContrast` to be set as well. To see an example of where this applies, please see the Partitions Background story within Stylings. Charts are included below but are static.
If you have `textInvertible` set to true, but do not have `textContrast` set to true, then the red slices, Europe, North America, and Asia, will have white text:

<Chart className="story-chart">
<Settings theme={{background : {color: `rgba(155, 155, 155, 1)`}}} />
<Partition
id="spec_1"
data={mocks.miniSunburst}
valueAccessor={(d) => d.exportVal}
valueFormatter={(d) => `$${config.fillLabel.valueFormatter(Math.round(d / 1000000000))}\xa0Bn`}
layers={[
{
groupByRollup: (d) => d.sitc1,
nodeLabel: (d) => productLookup[d].name,
shape: {
fillColor: (d) => {
return categoricalFillColor(colorBrewerCategoricalStark9, 0.7)(d.sortIndex);
},
},
},
{
groupByRollup: (d) => countryLookup[d.dest].continentCountry.substr(0, 2),
nodeLabel: (d) => regionLookup[d].regionName,
shape: {
fillColor: (d) => {
return categoricalFillColor(colorBrewerCategoricalStark9, 0.5)(d.parent.sortIndex);
},
},
},
{
groupByRollup: (d) => d.dest,
nodeLabel: (d) => countryLookup[d].name,
shape: {
fillColor: (d) => {
return categoricalFillColor(colorBrewerCategoricalStark9, 0.3)(d.parent.parent.sortIndex);
},
},
},
]}
config={{
partitionLayout: PartitionLayout.sunburst,
linkLabel: {
maxCount: 0,
fontSize: 14,
},
fontFamily: 'Arial',
fillLabel: {
valueFormatter: (d) => `$${config.fillLabel.valueFormatter(Math.round(d / 1000000000))}\xa0Bn`,
fontStyle: 'italic',
textInvertible: true,
textContrast: false,
fontWeight: 900,
valueFont: {
fontFamily: 'Menlo',
fontStyle: 'normal',
fontWeight: 100,
},
},
margin: { top: 0, bottom: 0, left: 0, right: 0 },
minFontSize: 1,
idealFontSizeJump: 1.1,
outerSizeRatio: 1,
emptySizeRatio: 0,
circlePadding: 4,
backgroundColor: 'rgba(229,229,229,1)',
}}
/>
</Chart>



Now if you set the `textContrast` to true as well, these slices also become black in text color:

<Chart className="story-chart">
<Settings theme={{background : {color: `rgba(155, 155, 155, 1)`}}} />
<Partition
id="spec_1"
data={mocks.miniSunburst}
valueAccessor={(d) => d.exportVal}
valueFormatter={(d) => `$${config.fillLabel.valueFormatter(Math.round(d / 1000000000))}\xa0Bn`}
layers={[
{
groupByRollup: (d) => d.sitc1,
nodeLabel: (d) => productLookup[d].name,
shape: {
fillColor: (d) => {
return categoricalFillColor(colorBrewerCategoricalStark9, 0.7)(d.sortIndex);
},
},
},
{
groupByRollup: (d) => countryLookup[d.dest].continentCountry.substr(0, 2),
nodeLabel: (d) => regionLookup[d].regionName,
shape: {
fillColor: (d) => {
return categoricalFillColor(colorBrewerCategoricalStark9, 0.5)(d.parent.sortIndex);
},
},
},
{
groupByRollup: (d) => d.dest,
nodeLabel: (d) => countryLookup[d].name,
shape: {
fillColor: (d) => {
return categoricalFillColor(colorBrewerCategoricalStark9, 0.3)(d.parent.parent.sortIndex);
},
},
},
]}
config={{
partitionLayout: PartitionLayout.sunburst,
linkLabel: {
maxCount: 0,
fontSize: 14,
},
fontFamily: 'Arial',
fillLabel: {
valueFormatter: (d) => `$${config.fillLabel.valueFormatter(Math.round(d / 1000000000))}\xa0Bn`,
fontStyle: 'italic',
textInvertible: true,
textContrast: true,
fontWeight: 900,
valueFont: {
fontFamily: 'Menlo',
fontStyle: 'normal',
fontWeight: 100,
},
},
margin: { top: 0, bottom: 0, left: 0, right: 0 },
minFontSize: 1,
idealFontSizeJump: 1.1,
outerSizeRatio: 1,
emptySizeRatio: 0,
circlePadding: 4,
backgroundColor: 'rgba(229,229,229,1)',
}}
/>
</Chart>
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@
},
"dependencies": {
"chroma-js": "^2.1.0",
"@popperjs/core": "^2.4.0",
"classnames": "^2.2.6",
"d3-array": "^1.2.4",
"d3-collection": "^1.0.7",
Expand Down
2 changes: 1 addition & 1 deletion src/chart_types/partition_chart/layout/config/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ export const configMetadata = {
},

// other
// backgroundColor: { dflt: '#ffffff', type: 'color' },
backgroundColor: { dflt: '#ffffff', type: 'color' },
sectorLineWidth: { dflt: 1, min: 0, max: 4, type: 'number' },
sectorLineStroke: { dflt: 'white', type: 'string' },
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@
* under the License. */
const module = jest.requireActual('../../viewmodel/fill_text_layout.ts');

export const getTextColor = jest.fn(module.getTextColor);
export const getTextColorIfTextInvertible = jest.fn(module.getTextColorIfTextInvertible);
33 changes: 24 additions & 9 deletions src/chart_types/partition_chart/layout/utils/calcs.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,51 +23,66 @@ describe('calcs', () => {
it('hex input - should change white text to black when background is white', () => {
const expected = '#000';
const result = makeHighContrastColor('#fff', '#fff');
expect(result).toEqual(expected);
expect(result).toBe(expected);
});
it('rgb input - should change white text to black when background is white ', () => {
const expected = '#000';
const result = makeHighContrastColor('rgb(255, 255, 255)', 'rgb(255, 255, 255)');
expect(result).toEqual(expected);
expect(result).toBe(expected);
});
it('rgba input - should change white text to black when background is white ', () => {
const expected = '#000';
const result = makeHighContrastColor('rgba(255, 255, 255, 1)', 'rgba(255, 255, 255, 1)');
expect(result).toEqual(expected);
expect(result).toBe(expected);
});
it('word input - should change white text to black when background is white ', () => {
const expected = '#000';
const result = makeHighContrastColor('white', 'white');
expect(result).toEqual(expected);
expect(result).toBe(expected);
});
// test contrast computation
it('should provide at least 4.5 contrast', () => {
const foreground = '#fff'; // white
const background = 'rgba(255, 255, 51, 0.3)'; // light yellow
const result = '#000'; // black
expect(result).toEqual(makeHighContrastColor(foreground, background));
expect(result).toBe(makeHighContrastColor(foreground, background));
});
it('should use black text for hex value', () => {
const foreground = '#fff'; // white
const background = '#7874B2'; // Thailand color
const result = '#000'; // black
expect(result).toBe(makeHighContrastColor(foreground, background));
});
it('should switch to black text if background color is in rgba() format - Thailand', () => {
const containerBackground = 'white';
const background = 'rgba(120, 116, 178, 0.7)';
const resultForCombined = 'rgba(161, 158, 201, 1)'; // 0.3 'rgba(215, 213, 232, 1)'; // 0.5 - 'rgba(188, 186, 217, 1)'; //0.7 - ;
expect(combineColors(background, containerBackground)).toBe(resultForCombined);
const foreground = 'white';
const resultForContrastedText = '#000'; //switches to black text
expect(makeHighContrastColor(foreground, resultForCombined)).toBe(resultForContrastedText);
});
});
describe('test the combineColors function', () => {
it('should return correct RGBA with opacity greater than 0.7', () => {
const expected = 'rgba(102, 43, 206, 1)';
const result = combineColors('rgba(121, 47, 249, 0.8)', '#1c1c24');
expect(result).toEqual(expected);
expect(result).toBe(expected);
});
it('should return correct RGBA with opacity less than 0.7', () => {
const expected = 'rgba(226, 186, 187, 1)';
const result = combineColors('rgba(228, 26, 28, 0.3)', 'rgba(225, 255, 255, 1)');
expect(result).toEqual(expected);
expect(result).toBe(expected);
});
it('should return correct RGBA with the input color as a word vs rgba or hex value', () => {
const expected = 'rgba(0, 0, 255, 1)';
const result = combineColors('blue', 'black');
expect(result).toEqual(expected);
expect(result).toBe(expected);
});
it('should return the correct RGBA with hex input', () => {
const expected = 'rgba(212, 242, 210, 1)';
const result = combineColors('#D4F2D2', '#BEB7DF');
expect(result).toEqual(expected);
expect(result).toBe(expected);
});
});
});
Expand Down
21 changes: 7 additions & 14 deletions src/chart_types/partition_chart/layout/utils/calcs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,28 +141,21 @@ export function getTextColorIfTextInvertible(
? `rgb(${255 - tr}, ${255 - tg}, ${255 - tb})`
: `rgba(${255 - tr}, ${255 - tg}, ${255 - tb}, ${to})`
: textColor;
} else if (textContrast === true) {
} else if (textContrast === true && typeof textContrast !== 'number') {
return inverseForContrast
? to === undefined
? makeHighContrastColor(`rgb(${255 - tr}, ${255 - tg}, ${255 - tb})`, backgroundColor)
: makeHighContrastColor(`rgba(${255 - tr}, ${255 - tg}, ${255 - tb}, ${to})`, backgroundColor)
: makeHighContrastColor(textColor, backgroundColor);
} else if (typeof textContrast === 'number') {
return inverseForContrast
? to === undefined
? makeHighContrastColor(`rgb(${255 - tr}, ${255 - tg}, ${255 - tb})`, backgroundColor, textContrast)
: makeHighContrastColor(`rgba(${255 - tr}, ${255 - tg}, ${255 - tb}, ${to})`, backgroundColor, textContrast)
: makeHighContrastColor(textColor, backgroundColor, textContrast);
}
}

/** @internal */
export function getTextColor(shapeFillColor: Color, textColor: Color, textInvertible: boolean) {
const { r: tr, g: tg, b: tb, opacity: to } = stringToRGB(textColor);
const backgroundIsDark = colorIsDark(shapeFillColor);
const specifiedTextColorIsDark = colorIsDark(textColor);
const inverseForContrast = textInvertible && specifiedTextColorIsDark === backgroundIsDark;
return inverseForContrast
? to === undefined
? `rgb(${255 - tr}, ${255 - tg}, ${255 - tb})`
: `rgba(${255 - tr}, ${255 - tg}, ${255 - tb}, ${to})`
: textColor;
}

/** @internal */
export function integerSnap(n: number) {
return Math.floor(n);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -406,7 +406,6 @@ function fill<C>(
layer.fillLabel,
layer.shape,
);

const fillTextColor = getFillTextColor(
textColor,
textInvertible,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,6 @@ export function linkTextLayout(
const labelText = cutToLength(rawText, maxTextLength);
const valueText = valueFormatter(valueGetter(node));

// const { width, emHeightAscent, emHeightDescent } = measure(linkLabel.fontSize, [{ ...labelFontSpec, text }])[0];
// const { width: valueWidth } = measure(linkLabel.fontSize, [{ ...valueFontSpec, text: valueText }])[0];
const labelFontSpec: Font = {
fontStyle: 'normal',
fontVariant: 'normal',
Expand Down Expand Up @@ -172,7 +170,7 @@ export function linkTextLayout(
valueFontSpec,
};
})
.filter((l: LinkLabelVM) => l.text !== ''); // cull linked labels whose text was truncated to nothing;
.filter(({ text }) => text !== ''); // cull linked labels whose text was truncated to nothing;
return { linkLabels, valueFontSpec, labelFontSpec, strokeColor };

function fitText(measure: TextMeasure, desiredText: string, allottedWidth: number, fontSize: number, box: Box) {
Expand Down
2 changes: 1 addition & 1 deletion src/components/chart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -165,9 +165,9 @@ export class Chart extends React.Component<ChartProps, ChartState> {
return (
<Provider store={this.chartStore}>
<div className={chartClassNames} style={containerStyle} ref={this.chartContainerRef}>
<ChartBackground />
<ChartStatus />
<ChartResizer />
<ChartBackground />
<Legend />
<SpecsParser>{this.props.children}</SpecsParser>
<div className="echContainer">
Expand Down
2 changes: 1 addition & 1 deletion src/components/chart_background.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export class ChartBackgroundComponent extends React.Component<ChartBackgroundPro
render() {
const { backgroundStyles } = this.props;

return <div className="echChartBackground" style={{ backgroundColor: backgroundStyles!.color }} />;
return <div className="echChartBackground" style={{ background: backgroundStyles!.color }} />;
nickofthyme marked this conversation as resolved.
Show resolved Hide resolved
}
}

Expand Down
1 change: 1 addition & 0 deletions src/components/legend/_legend.scss
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@

&--debug {
background: red;
position: relative;
}

.echLegendListContainer {
Expand Down
Loading