Getting Started
Out of the starting gate, there are a number of things you must manage to setup your color themes. This is not so much a reflection of the tw-themes utility, but rather the nature of the beast. tw-themes itself is easy to use, and simplifies a number of burdensome details.
Want to see tw-themes in action? ... take a peek at the See It Live section.
First: You must determine the Context Colors that you will use in your application.
You use Context Colors in your markup. They are abstract (e.g.
primary
/secondary
) in the sense that they have meaning in the context of your application. The Context Colors you use is completely up to you. There are a number of philosophies to consider in this process, which are discussed in Context Colors, Color Shading, Shade Inversion, Dark Mode, and Color Systems.The end result of this step will be your tw-themes
Schema
. For sake of example, let's say we will be using the following Context Colors (remember this definition can be whatever you desire):Our Schema:
const schema = ['primaryLight', 'primary', 'primaryDark', 'secondaryLight', 'secondary', 'secondaryDark', 'onLight', 'onDark', 'accentBorder', 'backdrop', ];
Next: We need to apply Real Colors to the process.
This is accomplished through Themes. You will typically define multiple themes (that are changeable at run-time), but starting out we can get by with one. At least one theme is required, else our system would have no color at all.
Themes
map Real Colors to your Context Colors at run-time. It's that simple! In this example, we use the tailwind color pallet for our real colors.Our Initial Theme:
const themes = { 'Cool Gray': { contextColors: { 'primaryLight': 'coolGray-300', 'primary': 'coolGray-500', 'primaryDark': 'coolGray-900', 'secondaryLight': 'orange-300', 'secondary': 'orange-500', 'secondaryDark': 'orange-900', 'onLight': 'black', 'onDark': 'white', 'accentBorder': 'coolGray-600', 'backdrop': 'coolGray-100', }, }, };
Next: We must pull these two aspects together and initialize our application with color themes.
This is accomplished through the
initTwThemes()
function. This fuses the relationship between ourSchema
andThemes
, and initializes tw-themes making it available for use in the application.We place this in a separate module to provide a "single source of truth".
colorTheme.js
import {initTwThemes} from 'tw-themes'; const schema = ['primaryLight', 'primary', 'primaryDark', 'secondaryLight', 'secondary', 'secondaryDark', 'onLight', 'onDark', 'accentBorder', 'backdrop', ]; const themes = { 'Cool Gray': { contextColors: { 'primaryLight': 'coolGray-300', 'primary': 'coolGray-500', 'primaryDark': 'coolGray-900', 'secondaryLight': 'orange-300', 'secondary': 'orange-500', 'secondaryDark': 'orange-900', 'onLight': 'black', 'onDark': 'white', 'accentBorder': 'coolGray-600', 'backdrop': 'coolGray-100', }, }, }; const TwThemes = initTwThemes(schema, themes); export default TwThemes;
Please Note that our module exports the
TwThemes
object (returned frominitTwThemes()
). This object contains the remaining tw-themes API, and can be used by other aspects of our application.Because this module executes
initTwThemes()
in-line (i.e. in module scope), the mere act of importing it will initialize our system. As a result, this module must be imported very early in our application start-up process.main.js
import './layout/colorTheme'; // initialize our color themes EARLY in our app's life-cycle ... snip snip
Last: We must define our new Context Colors to tailwind.
Remember, tailwind requires a build process, that is driven from
tailwind.config.js
. Fortunately tw-themes provides a utility function you may use to provide this definition. Because ourcolorTheme.js
module promotes a "single source of truth", we can be assured that tailwind has the latest up-to-date information.tailwind.config.js
import TwThemes from './src/layout/colorTheme'; export default { ... snip snip // define our abstract Context Colors theme: { extend: { colors: TwThemes.colorConfig(), }, }, ... snip snip };
HINT: Having trouble with this snippet, due to ES Modules? Please refer to A Note on ES Modules in Tailwind Configuration.
Finally: You are free to use your Context Colors in your markup.
Your Context Colors can be used in all the standard tailwind color directives (ex:
bg-primaryDark
,text-onDark
, etc.).At this point, you will want to fully flesh out your system, insuring that only your abstract Context Colors are used.
Bonus: Shade Inversion
tw-themes offers a unique feature that allows you to invert the shades of your theme at run-time (light-to-dark, and dark-to-light). This has the effect of doubling the number of color themes available, and potentially supporting an automatic dark mode theme (depending on how your colors are implemented).
If your themes are seeded with tailwind colors, you can play with this option (only tailwind colors support shade inversion - custom colors simply no-op). Simply add a UI control (somewhere in your app) that invokes the
toggleInvertShade()
function.Later: You will want to define multiple color themes.
You can supply additional color themes by simply adding them in your
Themes
structure.Once you do this, you will need to provide a UI Control to change the active theme.
For a quick start, tw-themes provides some convenience functions that allow you to quickly toggle through all your themes. You may chose to use these utilities, or build your own UI control.
Example (in Svelte):
<button on:click={TwThemes.activateNextTheme}>Next Theme</button> <button on:click={TwThemes.activatePriorTheme}>Prior Theme</button> <button on:click={TwThemes.toggleInvertShade}>Toggle Shade</button>
The syntax (above) will vary depending on the front-end framework you are using. The relevant point is: you merely need to invoke one of the appropriate
TwThemes
functions.