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

@nfq/colors

v2.0.4

Published

<div id="top"></div>

Downloads

489

Readme

@nfq/colors

npm version npm downloads BundlePhobia GitHub issues GitHub contributors GitHub license EsLint Horusec Cypress



About the project: License: MIT

@nfq/colors is a comprehensive theming solution for React applications. It provides utilities for generating theme configurations, manipulating colors, and applying theme-specific styles.

Installation

To install the package run

npm install @nfq/colors

if you are in yarn

yarn add @nfq/colors

or on pnpm

pnpm install @nfq/colors

PeerDependencies

The following PeerDependencies are needed so the component does work:

  • react >= 18
  • react-dom >= 18
  • styled-components >= 5

Usage

import {
    Color,
    darken,
    generateThemes,
    lighten,
    translucify,
    useThemeColors
} from '@nfq/color';

Generating Themes

// Any global config file in your project. (e.g. src/utils/themes.ts)
import {generateThemes, lighten} from '@nfq/colors';

import type {GetThemeType} from '@nfq/colors';

const BaseColors = {
    light: {
        primary: '#ffffff',
        secondary: '#cccccc'
    } as const,
    dark: {
        primary: '#000000',
        secondary: '#333333'
    } as const
} as const;

const DerivedColors = {
    light: {
        primaryLight: lighten(BaseColors.light.primary, 0.1)
    } as const,
    dark: {
        primaryLight: lighten(BaseColors.dark.primary, 0.1)
    } as const
} as const;

const Shadows = {
    light: {
        boxShadow: '0px 4px 10px rgba(0, 0, 0, 0.1)'
    } as const,
    dark: {
        boxShadow: '0px 4px 10px rgba(0, 0, 0, 0.4)'
    } as const
};

export type BaseColorsType = GetThemeType<typeof BaseColors>;
export const {
    globalCss,
    shadows,
    themeColors,
    themes
} = generateThemes({
    baseColors: BaseColors,
    derivedColors: DerivedColors,
    shadows: Shadows,
    defaultTheme: 'light',
    prefersDarkTheme: 'dark'
});

The generateThemes function takes one config argument. (Documentation: Configuration). The baseColors option contains theme colors for any theme you want. The names of the themes are defined by it's respective property name. The derivedColors option contains any additional colors that are derived from the base colors. The shadows option contains the shadow styles for the light and dark themes. The defaultTheme defines the default theme to use if none is explicitely set. If you only need the colors and autocomplete feature, you can skip theme names. You can just add your colors in baseColors, derivedColors, and shadows. If none of your objects use a theme name, you can leave out the other options.

Themes must have the same color key definitions as all other themes. To mitigate the process you can use an Shared color Object. This object is used as a base for all themes and then you can override some only partially. If you want to use the same color in all themes you can define it like this:

const SharedColors = {
    primary: '#ffffff',
    secondary: '#cccccc'
} as const;

const BaseColors = {
    light: {
        ...SharedColors
    } as const,
    dark: {
        ...SharedColors,
        primary: '#000000'
    } as const
} as const;

With this definition the secondary color of the dark theme will be the same as in the light theme, and only the primary color will be different.

The BaseColorsType type is a type that contains the colors of the base colors object. It is used to provide autocompletion and assurance that only these colors are used in the darken, lighten and translucify functions.

The generateThemes function returns an object with the following properties:

  • globalCss: The global CSS styles you need to add to your global css so the css vars are defined.
  • shadowColors: The shadow styles for the themes remapped to css vars.
  • themeColors: The full (Base and Derived) theme colors for the themes remapped to css vars.
  • themes: The default theme name. (Its only used to provide autocompletion in your IDE after you did the step Typescript Autocompletion)

Using the generated Themes in Styled Components.

// in the file in which you create your Theme for the styled components ThemeProvider. (e.g. src/utils/globalStyles.ts)
import {createGlobalStyle} from 'styled-components';
import {globalCss, shadows, themeColors} from 'src/utils/themes.ts';

import type {DefaultTheme} from 'styled-components';

export const theme: DefaultTheme = {
    boxShadows: shadows,
    colors: themeColors
};

export const GlobalStyle = createGlobalStyle`
    ${globalCss}
`;

The globalCss is the global css used to define your css vars and theme selectors. These have to get injected to your global css. The themeColors include all the available colors across all themes. They get remapped to css vars and can be accessed with the styled components theme object later. The shadows include all the available shadow styles across all themes. They get remapped to css vars and can be accessed with the styled components theme object later.

(Optional) Typescript Autocompletion

Create a file in your project that overrides the styled components DefaultTheme interface. For example a styled.d.ts file in your project folder. Add the following code to the file:

// import the styled components types
import 'styled-components';
// import HTMLAttributes from react
import {HTMLAttributes} from 'react';

import type {BaseColorsType, shadows, themeColors, themes} from 'src/utils/themes.ts';

// and extend them!
declare module 'styled-components' {
    export interface DefaultTheme {
        boxShadows: typeof shadows;
        colors: typeof themeColors;
    }

    export interface NFQColors {
        themeBaseColors: BaseColorsType;
        themeFullColors: typeof themeColors;
    }
}

declare module 'react' {
    interface HTMLAttributes<T> {
      // extends React's HTMLAttributes
      'data-nfq-theme'?: typeof themes;
    }
}

With this configuration you have access to the theme.colors object and the theme.boxShadows object in your styled components and you have autocompletion for the theme names in your IDE. Also the data-nfq-theme attribute is added to the HTMLAttributes so you can use it in your components to override current theme for this component.

After that you can add the file to your includes in the tsconfig.json file like this:

{
    "include": [
        "src/**/*.ts",
        "src/**/*.tsx",
        "src/styled.d.ts"
    ]
}

Personal Recommendation

To get the most out of the autocompletion you can also add comments like this to your color definition Objects:

const BaseColors = {
    light: {
        /** Primary color for light theme. ![#ffffff](https://via.placeholder.com/12/ffffff/ffffff.png) `#ffffff`. */
        primary: '#ffffff',
        /** Secondary color for light theme. ![#cccccc](https://via.placeholder.com/12/cccccc/cccccc.png) `#cccccc`. */
        secondary: '#cccccc'
    } as const,
    dark: {
        /** Primary color for dark theme. ![#000000](https://via.placeholder.com/12/000000/000000.png) `#000000`. */
        primary: '#000000',
        /** Secondary color for dark theme. ![#333333](https://via.placeholder.com/12/333333/333333.png) `#333333`. */
        secondary: '#333333'
    } as const
} as const;

With this you can see the color in your IDE and also the hex code of the color. Also Intellisense and Typescript do merge the comments for the different themes so you can see the colors for all themes in one place.

Usage in Styled components

import styled from 'styled-components';

const StyledComponent = styled.div`
    background-color: ${({theme}) => theme.colors.primary};
    box-shadow: ${({theme}) => theme.boxShadows.boxShadow};
`;

As we added the keys color and boxShadows to the styled components theme used in the ThemeProvider we can access them in the styled components theme object.

Color Manipulation

import { darken, lighten, translucify } from '@nfq/colors';

const primaryColor = '#ff0000';

const darkerColor = darken(primaryColor, 20);
const lighterColor = lighten(primaryColor, 20);
const translucentColor = translucify(primaryColor, 50);

These methods are mostly used for theme generation. They create derived colors from your base colors. The darken and lighten functions take a color and a percentage as arguments. They return a darker or lighter shade of the color. The translucify function also takes a color and a percentage as arguments. It returns a translucent version of the color. More on that in the Utilities section.

Using Theme Colors in Components

import { useThemeColors } from '@nfq/colors';

const MyComponent = () => {
  const themeColors = useThemeColors();

  return (
    <div style={{ backgroundColor: themeColors.primary }}>
      This div uses the primary theme color!
    </div>
  );
};

The useThemeColors hook returns the theme colors for the current theme. You can use it to access the theme colors in your components. It's only a shortcut for:

import {useTheme} from 'styled-components';

const MyComponent = () => {
  const theme = useTheme();

  return (
    <div style={{ backgroundColor: theme.colors.primary }}>
      This div uses the primary theme color!
    </div>
  );
};

The Color component

import {Color, useThemeColors} from '@nfq/colors';

const MyComponent = () => {
    const themeColors = useThemeColors();

    return (
        <div>
            <p>
                <Color $color={themeColors.primary}>This text has different</Color>{' '}
                <Color $color={themeColors.primary}>colors from our theme!</Color>
            </p>
        </div>
    );
};

The Color component is a styled component that takes a color prop and applies the color to the text. It is used to apply colors to text in your components. It is a span element with a color transition property, which is automatically added. It also provides you with type checking, so you can't use a color in it that's not defined in your theme.

Forcing a Theme

const MyComponent = () => {
    const themeColors = useThemeColors();

    return (
        <div data-nfq-theme="light">
            <p>
                This text has different colors from our theme!
            </p>
        </div>
    );
};

With the data-nfq-theme attribute you can force a theme on a html component and all it's children. This is useful if you want to use a theme for a component that is different from the current theme. Or you want to switch themes inbetween the components.


Props/Params

Color Component

| Prop | type | required | Description | | ------ | ------------------------- | :----------------: | -------------------------------------------------- | | $color | ThemeColor | :white_check_mark: | The color that should be used for its text content |

lighten

| Param | type | required | Description | | ------ | ----------------------- | :----------------: | ------------------------------------- | | color | BaseColor | :white_check_mark: | The color that should be made lighter | | amount | number | :white_check_mark: | The amount of lightening in percent |

darken

| Param | type | required | Description | | ------ | ----------------------- | :----------------: | ------------------------------------ | | color | BaseColor | :white_check_mark: | The color that should be made darker | | amount | number | :white_check_mark: | The amount of darkening in percent |

translucify

| Param | type | required | Description | | ------ | ----------------------- | :----------------: | ------------------------------------------------------- | | color | BaseColor | :white_check_mark: | The color that should be made more translucent | | amount | number | :white_check_mark: | The amount of opacity in percent that should be removed |

generateThemes

| Param | type | required | Description | | ------ | ----------------------------- | :----------------: | --------------------------------- | | config | ConfigObject | :white_check_mark: | The config object for your themes |


Types

BaseColor

All values of colors in your BaseColors object.

ThemeColor

All values of colors in your BaseColors and DerivedColors object.

ThemeUnion

type ThemeConfig = {[key: string]: {[key: string]: string}};
type NoThemeConfig = {[key: string]: string};
type ThemeUnion = NoThemeConfig | ThemeConfig;

ConfigObject

type ConfigObject = {
    baseColors: ThemeUnion;
    derivedColors: ThemeUnion;
    shadows: ThemeUnion;
    defaultTheme?: 'Union' | 'of' | 'your' | 'themes'; // Only optional if all color objects dont have an theme name
    prefersDarkTheme?: 'Union' | 'of' | 'your' | 'themes';
    highContrastTheme?: 'Union' | 'of' | 'your' | 'themes';
    lowContrastTheme?: 'Union' | 'of' | 'your' | 'themes';
    customContrastTheme?: 'Union' | 'of' | 'your' | 'themes';
};

Utilities

lighten utility

const DemoComponent = styled.div`
    background: ${({theme}) => lighten(theme.colors.header, 50)};
`;

The lighten function is a utility that lightens a given color by a specified percentage. It utilizes the CSS color-mix function to mix the provided color with white, achieving the desired lightening effect. This function is especially beneficial for generating hover or active states for UI elements, ensuring consistent color manipulation across the application.

darken utility

const DemoComponent = styled.div`
    background: ${({theme}) => darken(theme.colors.header, 50)};
`;

The darken function is a utility that darkens a given color by a specified percentage. It leverages the CSS color-mix function to mix the provided color with black, achieving the desired darkening effect. This function is particularly useful for generating hover or active states for UI elements, ensuring consistent color manipulation across the application.

translucify utility

const DemoComponent = styled.div`
    background: ${({theme}) => translucify(theme.colors.header, 50)};
`;

The translucify function is a utility designed to make a given color translucent by blending it with transparency. By leveraging the CSS color-mix function, it combines the provided color with a transparent color, resulting in a translucent version of the original color. This function is particularly useful for creating semi-transparent overlays, backgrounds, or other UI elements that require a touch of transparency.


Configuration

You can define some things about the themes that can be generated. Here all options you can define:

baseColors

The Base of your theme. You can define the colors for each theme you want to use. The theme names are the property names of the object. The colors are the property values of the theme objects. You can define as many themes as you like. If you dont want to generate themes you can define the color names directly instead of the theme names. The BaseColors is used as base for the DerivedColors.

derivedColors

The Derived colors of your theme. You can define the colors for each theme you want to use. The theme names are the property names of the object. The colors are the property values of the theme objects. You can define as many themes as you like. The DerivedColors, as the name suggests, are for colors that are derived from the BaseColors through the darken, lighten and tranmslucify utilities. The baseColors and derivedColors are merged to one object for the themes.

shadows

The shadow styles for the different themes. You can define the shadow styles for each theme you want to use. The theme names are the property names of the object. The shadow styles are the property values of the theme objects. You can define as many themes as you like. If you dont want to generate themes you can define the shadow names directly instead of the theme names.

defaultTheme

Defines the default theme to use if none is explicitely set. If you dont define themes in any of your objects you must omit this option.

prefersDarkTheme

Defines the theme to use if the user has prefers-color-sheme: dark active. You can omit this option if you dont want your themes css to not react to user preference. If you dont define themes in any of your objects you must omit this option. (This media query can be overridden by the data-nfq-theme attribute)

highContrastTheme

Defines the theme to use if the user has prefers-contrast: more active. You can omit this option if you dont want your themes css to not react to user preference. If you dont define themes in any of your objects you must omit this option. (This media query can't be overridden by the data-nfq-theme attribute)

lowContrastTheme

Defines the theme to use if the user has prefers-contrast: less active. You can omit this option if you dont want your themes css to not react to user preference. If you dont define themes in any of your objects you must omit this option. (This media query can't be overridden by the data-nfq-theme attribute)

customContrastTheme

Defines the theme to use if the user has prefers-contrast: custom active. You can omit this option if you dont want your themes css to not react to user preference. If you dont define themes in any of your objects you must omit this option. (This media query can't be overridden by the data-nfq-theme attribute)

Contributions

Christoph Kruppe - [email protected]


License

The licence used is: GitHub license
Click on licence badge for licence details.


Questions

If you have any furter questions please contact me.