Theme provider for React components using CSS modules.
Key Features
- Themable components expose API to allow external theming
- Easy to change themes of deeply nested themable components
npm i --save react-css-themes
themeTypes(Object) - Theme types definitionthemes(Object) - The available themesdefaultTheme(Object) - The default theme
Returns a decorator `function to make Component themeable.
importReactfrom'react'importwithThemes,{ThemeTypes}from'react-css-themes'importlightfrom'./light.css'importdarkfrom'./dark.css'constThemableComponent=({ theme })=>(<divclassName={theme.container}><divclassName={theme.heading}>Heading</div></div>)ThemableComponent.themeTypes={container: ThemeTypes.className,heading: ThemeTypes.className}exportdefaultwithThemes({ light, dark },light)(ThemableComponent)ThemeTypes are used to define theme's property types. It's simillar to React PropTypes, there are 2 avaiable types:
ThemeTypes.className: Defines a property as a classNameThemeTypes.themeOf(ThemableComponent): Define a property as a theme of another themeable compoenent
importReactfrom'react';import{ThemeTypes}from'react-css-themes'functionMyComponent({ theme }){// ... do things with the props}MyComponent.themeTypes={themeProp: ThemeTypes.className,childComponent: ThemeTypes.themeOf(ThemableComponent),}The compoenent will expose a themes object property with the themes defined as keys. These themes are set by the compoenent but also expose an API to create derivated themes.
fragment(Object) - ClassNames to add to the theme
A new theme derived from the original theme plus the fragment
letThemableComponent=({ theme })=>(<divclassName={theme.container}/>)ThemableComponent=withThemes({light: {container: '.container'}},light)(ThemableComponent)/* HTML output */renderToStaticMarkup(<ThemableComponent/>)// <div class=".container"></div>// Derived themeconsttheme=ThemableComponent.themes.light.add({container: '.foobar'})renderToStaticMarkup(<ThemableComponenttheme={theme}/>)// <div class=".container .foobar"></div>/* ThemableComponent.js */importReactfrom'react'importwithThemes,{ThemeTypes}from'react-css-themes'importlightfrom'./light.css'importdarkfrom'./dark.css'constThemableComponent=({ theme })=>(<divclassName={theme.container}><divclassName={theme.heading}>Heading</div></div>)ThemableComponent.themeTypes={container: ThemeTypes.className,heading: ThemeTypes.className}exportdefaultwithThemes({ light, dark },light)(ThemableComponent)/* light.css */ .container{background-color: white} .heading{color: black}/* dark.css */ .container{background-color: black} .heading{color: white}/* View.js */importReactfrom'react'importThemableComponentfrom'./ThemableComponent'constView=()=>(<div><ThemableComponenttheme={ThemableComponent.themes.light}/><ThemableComponenttheme={ThemableComponent.themes.dark}/><ThemableComponent/> /* Default theme (light) will be used */ </div>)exportdefaultView/* AnotherThemableComponent.js */importReactfrom'react'importwithThemes,{ThemeTypes}from'react-css-themes'importthemeAfrom'./themeA.css'importthemeBfrom'./themeB.css'constTHEMES={themeA: { ...themeA,child1: ThemableComponent.themes.light,child2: ThemableComponent.themes.dark},themeB: { ...themeB,child1: ThemableComponent.themes.dark,child2: ThemableComponent.themes.light}}constAnotherThemableComponent=({ theme })=>(<divclassName={theme.container}><ThemableComponenttheme={theme.child1}/><ThemableComponenttheme={theme.child2}/></div>)AnotherThemableComponent.themeTypes={container: ThemeTypes.className,child1: ThemeTypes.themeOf(ThemableComponent),child2: ThemeTypes.themeOf(ThemableComponent)}exportdefaultwithThemes(THEMES,THEMES.themeA)(AnotherThemableComponent)/* AnotherThemableComponent.js */importReactfrom'react'importwithThemes,{ThemeTypes}from'react-css-themes'importthemeAfrom'./themeA.css'constTHEMES={themeA: { ...themeA,child: ThemableComponent.themes.light.add({container: themeA.childContainer,heading: themeA.childHeading})}}constAnotherThemableComponent=({ theme })=>(<divclassName={theme.container}><ThemableComponenttheme={theme.child}/></div>)The project is authored by Diogo Cunha (@diffcunha) and Daniel Hayes (@daniel-hayes).
Comments, improvements or feedback are highly appreciated.
This project is licensed under the terms of the ISC license.