Skip to content

Commit

Permalink
Improve default line plot colors, notably in dark mode
Browse files Browse the repository at this point in the history
  • Loading branch information
axelboc committed Mar 11, 2022
1 parent d59ff71 commit 17470fa
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 31 deletions.
2 changes: 0 additions & 2 deletions apps/storybook/src/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,6 @@ body {
}

body {
--h5w-line--color: var(--secondary-dark);
--h5w-line--colorAux: var(--secondary);
--h5w-matrix--fontFamily: var(--monospace);
--h5w-matrix-cell--bgColorAlt: var(--secondary-light-bg);
--h5w-matrix-indexCell--bgColor: var(--primary-bg);
Expand Down
8 changes: 7 additions & 1 deletion packages/app/src/setupTests.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,15 @@ class ResizeObserver {
disconnect() {}
}

// Fake `ResizeObserver` support
window.ResizeObserver = ResizeObserver;

window.matchMedia = (query) => ({
matches: false,
media: query,
addEventListener: jest.fn(),
removeEventListener: jest.fn(),
});

// Fake properties to avoid Re-flex warnings
// https://github.com/leefsmp/Re-Flex/issues/27
// https://github.com/jsdom/jsdom/issues/135
Expand Down
30 changes: 19 additions & 11 deletions packages/lib/src/vis/hooks.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ScaleType, getBounds, getValidDomainForScale } from '@h5web/shared';
import type { Domain, AnyNumArray } from '@h5web/shared';
import { useEventListener } from '@react-hookz/web';
import { useEventListener, useMediaQuery } from '@react-hookz/web';
import { useFrame, useThree } from '@react-three/fiber';
import { useCallback, useMemo, useState } from 'react';
import type { RefCallback } from 'react';
Expand Down Expand Up @@ -83,22 +83,30 @@ export function useWheelCapture() {
useEventListener(domElement, 'wheel', onWheel, { passive: false });
}

export function useCSSCustomProperties(...names: string[]): {
colors: string[];
refCallback: RefCallback<HTMLElement>;
} {
export function useCustomColors(
properties: Record<`--h5w-${string}`, string | string[]>
): [string[], RefCallback<HTMLElement>] {
const [styles, setStyles] = useState<CSSStyleDeclaration>();
const isDark = useMediaQuery('(prefers-color-scheme: dark)');

// https://reactjs.org/docs/hooks-faq.html#how-can-i-measure-a-dom-node
const refCallback: RefCallback<HTMLElement> = useCallback(
(elem) => setStyles(elem ? window.getComputedStyle(elem) : undefined),
[setStyles]
);

return {
colors: names.map((name) => {
return styles ? styles.getPropertyValue(name).trim() : 'transparent';
}),
refCallback,
};
if (!styles) {
// Return `transparent` colors on initial render
return [Object.keys(properties).map(() => 'transparent'), refCallback];
}

const colors = Object.entries(properties).map(([name, defaultColors]) => {
const [light, dark] = Array.isArray(defaultColors)
? defaultColors
: [defaultColors, defaultColors];

return styles.getPropertyValue(name).trim() || (isDark ? dark : light);
});

return [colors, refCallback];
}
37 changes: 20 additions & 17 deletions packages/lib/src/vis/line/LineVis.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,7 @@ import type { NdArray } from 'ndarray';
import { useMemo } from 'react';
import type { ReactElement, ReactNode } from 'react';

import {
useAxisDomain,
useCSSCustomProperties,
useValueToIndexScale,
} from '../hooks';
import { useAxisDomain, useCustomColors, useValueToIndexScale } from '../hooks';
import type { AxisParams } from '../models';
import Pan from '../shared/Pan';
import ResetZoomButton from '../shared/ResetZoomButton';
Expand All @@ -32,9 +28,13 @@ import styles from './LineVis.module.css';
import type { TooltipData } from './models';
import { CurveType } from './models';

const DEFAULT_CURVE_COLOR = 'midnightblue';
const DEFAULT_AUX_COLORS =
'orangered, forestgreen, crimson, mediumslateblue, sienna';
// Default line colors in the following format: `[<light-mode>, <dark-mode>]`
// Inspired by Matplotlib palette: https://matplotlib.org/stable/gallery/color/named_colors.html
const DEFAULT_CURVE_COLOR = ['darkblue', 'deepskyblue'];
const DEFAULT_AUX_COLORS = [
'orangered, forestgreen, red, mediumorchid, olive',
'orange, lightgreen, red, violet, gold',
];

interface Props {
dataArray: NdArray<NumArray>;
Expand Down Expand Up @@ -99,18 +99,21 @@ function LineVis(props: Props) {
return domain ? extendDomain(domain, 0.05, scaleType) : DEFAULT_DOMAIN;
}, [scaleType, domain]);

const {
colors: [curveColor, rawAuxColor],
refCallback: rootRef,
} = useCSSCustomProperties('--h5w-line--color', '--h5w-line--colorAux');
const [[curveColor, auxColorList], rootRef] = useCustomColors({
'--h5w-line--color': DEFAULT_CURVE_COLOR,
'--h5w-line--colorAux': DEFAULT_AUX_COLORS,
});

// Support comma-separated list of auxiliary colors
const auxColors = (rawAuxColor || DEFAULT_AUX_COLORS)
.split(',')
.map((col) => col.trim());
const auxColors = auxColorList.split(',').map((col) => col.trim());

return (
<figure ref={rootRef} className={styles.root} aria-label={title}>
<figure
ref={rootRef}
className={styles.root}
aria-label={title}
data-keep-canvas-colors
>
<VisCanvas
title={title}
abscissaConfig={{
Expand Down Expand Up @@ -162,7 +165,7 @@ function LineVis(props: Props) {
ordinates={dataArray.data}
errors={errorsArray?.data}
showErrors={showErrors}
color={curveColor || DEFAULT_CURVE_COLOR}
color={curveColor}
curveType={curveType}
/>
{auxArrays.map((array, i) => (
Expand Down

0 comments on commit 17470fa

Please sign in to comment.