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(getColor): improves custom color scale generation #1798
base: next
Are you sure you want to change the base?
Conversation
const _colors = scale([PALETTE.white, _hue, PALETTE.black]) | ||
.correctLightness() | ||
.colors(PALETTE_SIZE + 2); // add 2 to account for the white and black endpoints removed below | ||
|
||
_hue = _colors.reduce<Record<number, string>>((_retVal, color, index) => { | ||
if (index > 0 && index <= PALETTE_SIZE) { | ||
_retVal[index * 100] = color; | ||
} | ||
|
||
return _retVal; | ||
}, {}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add this style of hue generation to the sandbox for comparison? If it isn't a compelling difference, I'd prefer to retain this for being more straightforward and imperative with respect to Garden's palette size. Garden design will be able to help us evaluate the trade-offs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added to the Sandbox under Chroma 12 Current
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome. Thanks so much.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ze-flo did you look at https://color2k.com/#get-scale or rule it out?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Excellent suggestion! π― π₯ π
Using a binary search and a 100 color scale, color2k
outputs excellent results despite its tiny footprint. I think we have a winner! πΎ π π₯³
Check out the new and improved demo.
|
||
import type { ChromaStatic } from 'chroma-js'; | ||
|
||
// @ts-expect-error Ignoring missing type definition |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given the status of chroma-js
is @ts-ignore
the better choice here? https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-9.html#ts-ignore-or-ts-expect-error
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, it's preferable to add a chroma-js.d.ts
under /utils/build and update the tsconfig.json accordingly.
* | ||
* @returns An offset-based color palette. | ||
*/ | ||
export function getCustomColorScale(hue: string) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fwiw, I'm less interested in exposing another theming utility and more about containing the chroma-js
import gnarliness to a dedicated location (under types
, or a new chroma-js
folder, or something π€·). For example, here's a compact version of a file that deals with the valid
function...
/**
* Copyright Zendesk, Inc.
*
* Use of this source code is governed under the Apache License, Version 2.0
* found at http://www.apache.org/licenses/LICENSE-2.0.
*/
import type { ChromaStatic } from 'chroma-js';
import { default as _valid } from 'chroma-js/src/utils/valid';
import 'chroma-js/src/io/hex';
export const valid = _valid as ChromaStatic['valid'];
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I love the chroma-js
folder idea. In that case, I would move getCustomColorScale
to getColor
.
- Where would you recommend I create it?
- Would
chroma-js.d.ts
live in that new folder or/utils/build
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool π . Here's what I'd recommend...
- add a
chroma-js
folder undertheming/src/utils
that looks something like the screenshot below - in
getColor
simplyimport { scale, valid } from './chroma-js';
- add the new
chroma-js.d.ts
under the project/utils/build
with simple module declarations that clear the TS errors - depending on design feedback, either leave
getColor
(nearly) as it is onnext
, or add a localtoScale
function similar to the other local functions that invokesscale
and portions out the hue shades based on your target contrast ratios algorithm. I want to avoid the notion that Garden could provide a dedicated color scale utility outside of thegetColor
internals
Description
getCustomColorScale
: generates a color scale from hue that closely aligns with the desired ratio for the offset.isValidColor
: an alias forchroma.valid
getColor
to usegetCustomColorScale
@zendeskgarden/react-theming
bundle size by selecting parts ofchroma-js
that are relevant to our needs.Detail
Cherry-picking only the parts needed to validate a color and generate a multistep color scale helped reduce
chroma-js
's footprint considerably.BEFORE
AFTER
Garden's color palette were generated using Leonardo using the following offset-based contrast ratios.
To generate a color scale with the precise contrast ratios listed above, @adobe/leonardo-contrast-colors was considered. However at 30kb gzipped, it isn't a good option. Instead, by leveraging
chroma-js
and importing only the parts needed to generate a color scale, I was able to reproduce a palette very similar to one created by Leonardo.This sandbox highlights different methods for generating colors.
I implemented
getCustomColorScale
following theChroma 100 Cherry-picked
method (see sandbox). It aligns contrast ratios closely withLeonardo
without incurring the additional bundle cost. Using a binary search to find the nearest ratio per offset (Chroma 48 Find nearest
) could improve accuracy but is a much slower algorithm.Update
Generating a 100 color scale with Color2K and finding the nearest match using a binary search offered excellent results while only adding 791b to the bundle. π₯
The new demo includes a description, pros, and cons for each solution. Also notice a delta between closest match and offset-pinned target contrast ratio for color step.
Checklist
π design updates will be Garden Designer approved (add the designer as a reviewer)npm start
)β¬ οΈ renders as expected with reversed (RTL) directionπ€ renders as expected with Bedrock CSS (?bedrock
)