From 1ebe73cf90e8249cbf0dbcc4a9d1edfd54e93ba4 Mon Sep 17 00:00:00 2001 From: platane Date: Tue, 12 Jan 2021 00:56:50 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=9A=80svg=20dark=20mode?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/action/generateContributionSnake.ts | 4 ++ packages/demo/canvas.ts | 5 ++- .../svg-creator/__tests__/createSvg.spec.ts | 4 ++ packages/svg-creator/grid.ts | 23 ++++------ packages/svg-creator/index.ts | 42 +++++++++++++++++-- packages/svg-creator/snake.ts | 4 +- packages/svg-creator/stack.ts | 8 +--- 7 files changed, 61 insertions(+), 29 deletions(-) diff --git a/packages/action/generateContributionSnake.ts b/packages/action/generateContributionSnake.ts index 822162d..85c7369 100644 --- a/packages/action/generateContributionSnake.ts +++ b/packages/action/generateContributionSnake.ts @@ -25,6 +25,10 @@ export const generateContributionSnake = async ( colorEmpty: colorScheme[0], colorSnake: "purple", cells, + dark: { + colorEmpty: "#161b22", + colorDots: { 1: "#01311f", 2: "#034525", 3: "#0f6d31", 4: "#00c647" }, + }, }; const gifOptions = { frameDuration: 100, step: 1 }; diff --git a/packages/demo/canvas.ts b/packages/demo/canvas.ts index ee4f2d4..3aee4c4 100644 --- a/packages/demo/canvas.ts +++ b/packages/demo/canvas.ts @@ -12,10 +12,13 @@ export const drawOptions = { 2: "#40c463", 3: "#30a14e", 4: "#216e39", - 5: "orange", }, colorEmpty: "#ebedf0", colorSnake: "purple", + dark: { + colorEmpty: "#161b22", + colorDots: { 1: "#01311f", 2: "#034525", 3: "#0f6d31", 4: "#00c647" }, + }, }; const getPointedCell = (canvas: HTMLCanvasElement) => ({ diff --git a/packages/svg-creator/__tests__/createSvg.spec.ts b/packages/svg-creator/__tests__/createSvg.spec.ts index 8ac9dcc..bb3fa91 100644 --- a/packages/svg-creator/__tests__/createSvg.spec.ts +++ b/packages/svg-creator/__tests__/createSvg.spec.ts @@ -13,6 +13,10 @@ const drawOptions = { colorDots: { 1: "#9be9a8", 2: "#40c463", 3: "#30a14e", 4: "#216e39" }, colorEmpty: "#ebedf0", colorSnake: "purple", + dark: { + colorEmpty: "#161b22", + colorDots: { 1: "#01311f", 2: "#034525", 3: "#0f6d31", 4: "#00c647" }, + }, }; const gifOptions = { frameDuration: 100, step: 1 }; diff --git a/packages/svg-creator/grid.ts b/packages/svg-creator/grid.ts index 04d2766..3a0d70b 100644 --- a/packages/svg-creator/grid.ts +++ b/packages/svg-creator/grid.ts @@ -15,14 +15,7 @@ const percent = (x: number) => (x * 100).toFixed(2); export const createGrid = ( cells: (Point & { t: number | null; color: Color | Empty })[], - { - colorEmpty, - colorBorder, - sizeBorderRadius, - colorDots, - sizeDot, - sizeCell, - }: Options, + { sizeBorderRadius, sizeDot, sizeCell }: Options, duration: number ) => { const svgElements: string[] = []; @@ -31,10 +24,10 @@ export const createGrid = ( shape-rendering: geometricPrecision; rx: ${sizeBorderRadius}; ry: ${sizeBorderRadius}; - fill:${colorEmpty}; + fill: var(--ce); stroke-width: 1px; - stroke: ${colorBorder}; - animation: none ${duration}ms linear infinite; + stroke: var(--cb); + animation: none ${duration}ms linear infinite; }`, ]; @@ -47,16 +40,14 @@ export const createGrid = ( if (t !== null) { const animationName = id; - // @ts-ignore - const fill = colorDots[color]; styles.push( `@keyframes ${animationName} {` + - `${percent(t - 0.0001)}%{fill:${fill}}` + - `${percent(t + 0.0001)}%,100%{fill:${colorEmpty}}` + + `${percent(t - 0.0001)}%{fill:var(--c${color})}` + + `${percent(t + 0.0001)}%,100%{fill:var(--ce)}` + "}", - `.c.${id}{fill: ${fill};animation-name: ${animationName}}` + `.c.${id}{fill: var(--c${color}); animation-name: ${animationName}}` ); } diff --git a/packages/svg-creator/index.ts b/packages/svg-creator/index.ts index 596c192..87a6679 100644 --- a/packages/svg-creator/index.ts +++ b/packages/svg-creator/index.ts @@ -24,6 +24,12 @@ export type Options = { sizeDot: number; sizeBorderRadius: number; cells?: Point[]; + dark?: { + colorDots: Record; + colorEmpty: string; + colorBorder?: string; + colorSnake?: string; + }; }; const getCellsFromGrid = ({ width, height }: Grid) => @@ -94,10 +100,12 @@ export const createSvg = ( height, ].join(" "); - const style = elements - .map((e) => e.styles) - .flat() - .join("\n"); + const style = + generateColorVar(drawOptions) + + elements + .map((e) => e.styles) + .flat() + .join("\n"); const svg = [ h("svg", { @@ -121,3 +129,29 @@ export const createSvg = ( const optimizeCss = (css: string) => csso.minify(css).css; const optimizeSvg = (svg: string) => svg; + +const generateColorVar = (drawOptions: Options) => + ` + :root { + --cb: ${drawOptions.colorBorder}; + --cs: ${drawOptions.colorSnake}; + --ce: ${drawOptions.colorEmpty}; + ${Object.entries(drawOptions.colorDots) + .map(([i, color]) => `--c${i}:${color};`) + .join("")} + } + ` + + (drawOptions.dark + ? ` + @media (prefers-color-scheme: dark) { + :root { + --cb: ${drawOptions.dark.colorBorder || drawOptions.colorBorder}; + --cs: ${drawOptions.dark.colorSnake || drawOptions.colorSnake}; + --ce: ${drawOptions.dark.colorEmpty}; + ${Object.entries(drawOptions.dark.colorDots) + .map(([i, color]) => `--c${i}:${color};`) + .join("")} + } + } +` + : ""); diff --git a/packages/svg-creator/snake.ts b/packages/svg-creator/snake.ts index cb170cd..ea08d37 100644 --- a/packages/svg-creator/snake.ts +++ b/packages/svg-creator/snake.ts @@ -20,7 +20,7 @@ const lerp = (k: number, a: number, b: number) => (1 - k) * a + k * b; export const createSnake = ( chain: Snake[], - { sizeCell, colorSnake, sizeDot }: Options, + { sizeCell, sizeDot }: Options, duration: number ) => { const snakeN = chain[0] ? getSnakeLength(chain[0]) : 0; @@ -61,7 +61,7 @@ export const createSnake = ( const styles = [ `.s{ shape-rendering:geometricPrecision; - fill:${colorSnake}; + fill:var(--cs); animation: none linear ${duration}ms infinite }`, diff --git a/packages/svg-creator/stack.ts b/packages/svg-creator/stack.ts index d32ccf7..1bb1fce 100644 --- a/packages/svg-creator/stack.ts +++ b/packages/svg-creator/stack.ts @@ -2,7 +2,6 @@ import type { Color, Empty } from "@snk/types/grid"; import { h } from "./utils"; export type Options = { - colorDots: Record; sizeDot: number; }; @@ -10,7 +9,7 @@ const percent = (x: number) => (x * 100).toFixed(2); export const createStack = ( cells: { t: number | null; color: Color | Empty }[], - { colorDots, sizeDot }: Options, + { sizeDot }: Options, width: number, y: number, duration: number @@ -44,9 +43,6 @@ export const createStack = ( const animationName = id; const x = (nx * m).toFixed(1); - // @ts-ignore - const fill = colorDots[color]; - nx += ts.length; svgElements.push( @@ -76,7 +72,7 @@ export const createStack = ( .join("\n") + "}", - `.u.${id}{fill:${fill};animation-name:${animationName};transform-origin:${x}px 0}` + `.u.${id}{fill:var(--c${color});animation-name:${animationName};transform-origin:${x}px 0}` ); }