npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

consistent-shading

v1.1.0

Published

Shade consitency for various hues, based on luminance.

Downloads

41

Readme

consistent-shading

GitHub Workflow Status NPM npm npm bundle size

Shade consitency for various hues, based on luminance. Supports both solid and transparent shades.

Installation

For the npm package, use:

npm install --save consistent-shading

For the ECMAScript module in browsers, use:

<script src="https://cdn.jsdelivr.net/npm/consistent-shading@latest/dist/esm/index.js"></script>

For the minfied module (only ~750 bytes!) in browsers, use:

<script src="https://cdn.jsdelivr.net/npm/consistent-shading@latest/dist/index.min.js"></script>

Problem

The colour spectrum differs in luminance, at maximum saturation. As such, applying the same shadows throughout your design will create uneven colouring, due to the difference in contrast.

Finding aesthetically pleasing combinations of shadows and highlights is difficult enough for one colour, but getting consistent shading with a varied pallete can be really time consuming.

Solution

The easiest solution lies in the new HCL (or LCH) colour format, which manages to separate luminance into an independent parameter.

To use this library you have to provide an ideal base colour, along with an array of ideal shades, that you have found through experimentation and determined to be fitting for your design.

After providing these in your format of choice* pick a new base colour and feed it into the generator. This will cause it to return an array of relevant, contrast consistent shades, that look pleasing, just like the shaded base colour.

Usage

Try to pick base colours that are not on either extremes of the luminance spectrum, since the generator caps at the maximum and minimum levels. (You can't obtain a color darker than black)

import { Color, ConsistentShading } from "consistent-shading";

const IdealBaseColor = new Color("hex", ["#3454D1"]);

const IdealShades = [
  new Color("rgb", [122, 143, 225]),
  new Color("lab", [31, 28, -58]),
  new Color("cmyk", [27, 22, 0, 7]),
];

const Generator = new ConsistentShading(IdealBaseColor, IdealShades);

const AnyColor = new Color("hsl", [345, 63, 51]);

Generator.generate(AnyColor);
/* => Array of Color objects, representing shades of AnyColor. */

Generator.generateAlpha(AnyColor, /* optional */ 1.5);
/* => Array of Color objects, rgba format, representing 
semi-transparent black or white shades of AnyColor. */

API Description

Color formats*

The color formats are taken directly from the color-convert package. These are as follows:

"rgb" | "hsl" | "hsv" | "hwb" | "cmyk" | "xyz" | "lab"  | "lch" | "hex" | "keyword" | "ansi16" | "ansi256" | "hcg" | "apple" | "gray";

Color class

Color is provided with two fields, one of which is the value, that is mostly a tuple of varying sizes (check this for more details), and the other is the format, which enables the library to correctly interpret your colours and convert them accordingly.

const myColor = new Color("rgb", [255, 0, 255]);

Generator class

The ConsistentShading class, which is in basic terms the shade generator and main functionality of this library (thus taking it's name), contains an important construrctor, which takes as a first paramenter the base Color and an array of shades, that are represented through an array Color[].


generate(baseColor: Color)

After it has calculated the relative luminances of the provided shades, the generate method can be used to obtain solid shades. This method has a first mandatory parameter, which is the new base color, and an optional second parameter, which specifies a preferred format for the resulting shades.


generateAlpha(baseColor: Color, threshold?: number)

To obtain alpha shadows, a binary search method was used.

The solid shades are calculated first, and then it is decided based on luminance if the base color of the rgba value should be black or white.

After the decision is made, the opacity is guessed via binary search, with a configurable threshold. If the guessed opacity of the mask is, within the threshold values, equal in luminance to the generated solid shade, it is accepted.

Higher threshold will make the generation faster, but the results will be less accurate. It is defaulted to 1, which translates to 1% opacity threshold.

Setting the threshold to a value close to 0 may result in an infinite loop.


These methods can be called as many times as it's needed, since they do not mutate any internal state of the generator object.