provide-theme
v1.0.0
Published
Provides interchangeable themes as classes, images, and icons to React components.
Downloads
22
Maintainers
Readme
provide-theme
Provides interchangeable themes as classes, images, and icons to React components.
Each theme should simply be a bundled CSS file and a bundled JS file containing a mapping of the class names (as classes
), at the very least. This means you can bundle your themes using plain CSS, inline styles, css-modules
, jss
, or any other format of your choosing. The system behind this provider is designed with code-splitting in mind so that you're only loading the selected theme when you need it.
Table of contents
Installation
npm install provide-theme --save
Actions
Your components may be provided the following actions
as propTypes
:
setThemes (Object themes)
This should typically only be used server-side. You probably won't ever need to call this action since your themes
reducer is typically set via the initial state.
setThemesFiles (Object themesFiles)
You probably won't ever need to call this action as well, since your themesFiles
reducer is typically set via the initial state. The client uses the themesFiles
reducer to know which files to load for their selected theme.
initTheme (String themeName, Object themeFiles, Object theme)
This is typically used to initialize the theme before rendering the app so that components can immediately have the the theme's classes
, images
, icons
, etc. It is automatically called via an enhancer
when the store
is created. On the client, it will find any matching link
and script
elements matching the themeFiles
so that their respective reducers
may be properly initialized after server-side rendering.
loadTheme (String themeName, Object themeFiles)
This is typically used client-side to load a theme dynamically and is likely the only action
you'll ever need to call within your components.
Reducers
Your components may also be provided the following reduced propTypes
:
themes
An object containing all themes. You'll probably never need this, and if you do, it is probably best to limit it to the server.
themesFiles
An object containing a mapping of the themes' names to their respective jsFile
and cssFile
. You probably won't use this within your components, as it's mostly used internally for dynamically loading themes on the client.
themeFiles
An object containing the currently selected theme's jsFile
and cssFile
. You probably won't use this within your components, as it's mostly used internally for dynamically loading themes on the client.
themeName
The currently selected theme's name.
theme
This object contains the currently selected theme's properties: classes
, images
, icons
, and any other custom properties you may need.
classes
A mapping of simplified class names to their namespaced versions. Derived from the theme
object. This has its own reducer to minimize the amount of boilerplate required when retrieving your theme's properties within your components.
images
Derived from the theme
object. This has its own reducer to minimize the amount of boilerplate required when retrieving your theme's properties within your components.
icons
Derived from the theme
object. This has its own reducer to minimize the amount of boilerplate required when retrieving your theme's properties within your components.
link
The current theme's respective link
element, mostly used internally when dynamically loading themes on the client. This element gets removed and another put in its place when changing themes.
script
The current theme's respective script
element, mostly used internally when dynamically loading themes on the client. This element gets removed and another put in its place when changing themes.
Hot reloading
This provider includes an export you can use to hot reload your bundled themes when in the development environment.
reloadTheme (String themeName, Object theme)
You can use this with something like webpack's module.hot.accept
function.
// src/themes/dark/dark.js
import classes from './dark.css';
export default {
classes
};
if (process.env.NODE_ENV !== 'production') {
if (module.hot) {
const reloadTheme = require('provide-theme').reloadTheme;
module.hot.accept('./dark.css', () => {
reloadTheme('DarkTheme', {
classes: require('./dark.css')
});
});
}
}
Quick example
import React from 'react';
import { render } from 'react-dom';
import { App } from './components/index';
import * as providers from './providers/index';
import themesFiles from './themes/files';
const themeName = Object.keys(themesFiles).shift();
const themeFiles = themesFiles[themeName];
const defaultProps = {
providers: {
...providers,
theme: {
...providers.theme,
state: {
themesFiles,
themeFiles,
themeName
}
}
}
};
render(<App { ...defaultProps } />, document.getElementById('root'));
And for an example of bundled themes in their most basic form, see test/themes
.
And for an example of how to select a different theme, see bloggur
's ThemeSelector
component.
Full example with server rendering
See bloggur
. Protip: Remember that you can include images with your theme's bundle and that React can handle svg
(vector graphics) elements, so it's good practice to use them where possible!