Giter VIP home page Giter VIP logo

postcss-themed's Introduction

postcss-themed

PostCSS plugin for adding multiple themes to CSS files.

npm styled with prettier

Will create class overrides for legacy browsers and use CSS variables for modern browsers.

๐Ÿš€ Supports light and dark color schemes

๐Ÿš€ Create component level themes

๐Ÿš€ Supports scoping CSS Variable names to mitigate conflicts

Contributing

We appreciate any and all pull requests!

Setup

First install the dependencies.

yarn

Then write a test for your changes and run the test command! That's it!.

yarn test

Usage

const config = {
  default: {
    color: 'white'
  },
  other: {
    color: 'black'
  }
};

or for per theme light and dark modes:

const config = {
  default: {
    light: {
      color: 'white'
    },
    dark: {
      color: 'black'
    }
  },
  // Can still just have one level which defaults to light
  other: {
    color: 'purple'
  },
  more: {
    light: {
      color: 'red'
    },
    dark: {
      color: 'blue'
    }
  }
};
postcss([require('postcss-themed')({ config })]);

See PostCSS docs for examples for your environment.

Using Theme Variables

Input

.foo {
  color: @theme color;
  border: @theme border-width solid @theme color;
}

Output

.foo {
  color: white;
  border: 1px solid white;
}
.other .foo {
  color: black;
  border: 10px solid black;
}

Component themes

Define a component level theme in either commonjs or typescript. A file names themes.(js|ts) must be co-located with the themeable CSS file.

themes.js

module.exports = (theme) => ({
  default: {
    border: `1px solid ${theme.default.color}`
  }
  other: {
    border: `1px solid ${theme.other.color}`
  }
});

themes.ts

import { Theme } from '@your/themes';

const CardTheme = (theme: Theme): Theme => ({
  default: {
    border: '1px solid red'
  },
  other: {
    border: `1px solid ${theme.other.color}`
  }
});

export default CardTheme;

or provide a function to locate the theme function

Theme Resolution

By default this plugin will looks for a sibling theme.js or theme.ts. You can customize the lookup behavior by supplying your own theme resolution function.

postcss([
  require('postcss-themed')({
    config,
    resolveTheme: cssFileName => {
      // return a function like the ones above
    }
  })
]);

Now you can use @theme border in your CSS file.

Theming Root class

Only needed when targeting legacy environments that do not support CSS Variables.

Input

:theme-root(.foo) {
  border: 1px solid @theme color;
}

or by nesting

Input

:theme-root {
  &.foo {
    border: 1px solid @theme color;
  }
}

Output

.foo {
  border: 1px solid white;
}
.foo.other {
  border: 1px solid black;
}

Options

modules

This plugin also support scoping your CSS Variable names in a very similar way to CSS Modules. This option should be used when targeting browsers with css variables to avoid name collisions.

You can use any of the tokens listed here to create a scoped name. The token [local] is also available which is the name of the original theme variable.

postcss([
  require('postcss-themed')({
    config,
    modules: '[folder]-[name]-[local]'
  })
]);

You can also supply your own function for scoping variable names, again following the API from CSS Modules. If PostCSS does not have a path for the file both the path and css will return an empty string.

postcss([
  require('postcss-themed')({
    config,
    modules: (name: string, filePath: string, css: string) => {
      const hash = crypto
        .createHash('md5')
        .update(css)
        .digest('hex')
        .slice(0, 6);
      return `${filePath}-${name}-${hash}`;
    }
  })
]);

defaultTheme

An optional parameter to change the name of the default theme (where no extra classes are added to the selector). It defaults to default, and also corresponds to the only required key in your theme.ts files.

forceEmptyThemeSelectors - only legacy

By default this plugin will not produce class names for theme that have no component level configuration if there are no styles. (ex: you have 3 themes but your component only uses 1, then only 1 extra set of classnames is produced).

You can use the forceEmptyThemeSelectors to force these empty classes to be added. If you use this option you should also use some form of css minification that can get rid of the empty classes. If you don't your CSS will be bloated.

This feature is useful if your are converting your css-modules to typescript and need the generated typescript file to include all of the possible themes.

postcss([
  require('postcss-themed')({ config, forceEmptyThemeSelectors: true })
]);

forceSingleTheme

This is a niche option which only inserts a single theme. At first glance, this may seem strange because this plugin primarily allows you to support many themes in a single CSS file. This option helps if you want to generate many CSS files, each with their own theme. You'll run PostCSS multiple times, switching the single theme. In practice, we use this to generate extra CSS files for teams that only need a single theme. The main CSS file still has all of them, but teams can optionally use the one that only has the theme they need.

It is still recommended to set defaultTheme with this option, as any missing variables will be merged with the default.

Usage

const config = {
  default: {
    light: {
      color: 'purple'
    },
    dark: {
      color: 'black'
    }
  },
  chair: {
    light: {
      color: 'beige'
    },
    dark: {
      color: 'dark-purple'
    }
  }
};

postcss([
  require('postcss-themed')({
    config,
    defaultTheme: 'default',
    forceSingleTheme: 'chair'
  })
]);

Input

.test {
  color: @theme color;
}

Output

.test {
  color: var(--color);
}

:root {
  --color: beige;
}

.dark {
  --color: dark-purple;
}

As you can see in the above example, only one theme will be generated using this option.

optimizeSingleTheme

This option should only be used in conjunction with forceSingleTheme. By default forceSingleTheme will always add CSS variables, since many users still want to be able to modify and override them. However, if you are not going to be modifying them, we can optimize the single theme further by removing variables when possible. If only a light theme is specified, this config option will just do in-place replacement of the theme variables.

Usage

const config = {
  default: {
    color: 'purple'
  },
  chair: {
    color: 'beige'
  }
};

postcss([
  require('postcss-themed')({
    config,
    defaultTheme: 'default',
    forceSingleTheme: 'chair',
    optimizeSingleTheme: true
  })
]);

Input

.test {
  color: @theme color;
}

Output

.test {
  color: beige;
}

Debug

This package uses the npm package debug to log errors while it's running.

Simply set the DEBUG environment variable to postcss-themed.

DEBUG=postcss-themed postcss input.css -o output.css

Contributors โœจ

Thanks goes to these wonderful people (emoji key):


Tyler Krupicka

๐Ÿ’ป โš ๏ธ ๐Ÿ“–

Andrew Lisowski

๐Ÿ’ป โš ๏ธ ๐Ÿ“–

Adam Dierkens

๐Ÿ’ป

This project follows the all-contributors specification. Contributions of any kind welcome!

postcss-themed's People

Contributors

tylerkrupicka avatar hipstersmoothie avatar adierkens avatar

Watchers

James Cloos avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.