项目作者: diffcunha

项目描述 :
Theme provider for React components using CSS modules
高级语言: JavaScript
项目地址: git://github.com/diffcunha/react-css-themes.git
创建时间: 2017-05-05T15:54:09Z
项目社区:https://github.com/diffcunha/react-css-themes

开源协议:ISC License

下载


npm version
Code Climate
Test Coverage

react-css-themes

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

Table of contents

Installation

npm i --save react-css-themes

Usage [API]

withThemes(themeTypes, [themes], [defaultTheme])

Arguments:
  • themeTypes (Object) - Theme types definition
  • themes (Object) - The available themes
  • defaultTheme (Object) - The default theme
Returns:

Returns a decorator `function to make Component themeable.

Example:
  1. import React from 'react'
  2. import withThemes, { ThemeTypes } from 'react-css-themes'
  3. import light from './light.css'
  4. import dark from './dark.css'
  5. const ThemableComponent = ({ theme }) => (
  6. <div className={theme.container}>
  7. <div className={theme.heading}>Heading</div>
  8. </div>
  9. )
  10. ThemableComponent.themeTypes = {
  11. container: ThemeTypes.className,
  12. heading: ThemeTypes.className
  13. }
  14. export default withThemes({ light, dark }, light)(ThemableComponent)

ThemeTypes

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 className
  • ThemeTypes.themeOf(ThemableComponent): Define a property as a theme of another themeable compoenent
Example:
  1. import React from 'react';
  2. import { ThemeTypes } from 'react-css-themes'
  3. function MyComponent ({ theme }) {
  4. // ... do things with the props
  5. }
  6. MyComponent.themeTypes = {
  7. themeProp: ThemeTypes.className,
  8. childComponent: ThemeTypes.themeOf(ThemableComponent),
  9. }

Component.themes

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.

add(fragment)

Arguments:
  • fragment (Object) - ClassNames to add to the theme
Returns:

A new theme derived from the original theme plus the fragment

Example:
  1. let ThemableComponent = ({ theme }) => (
  2. <div className={theme.container} ></div>
  3. )
  4. ThemableComponent = withThemes({
  5. light: {
  6. container: '.container'
  7. }
  8. }, light)(ThemableComponent)
  9. /* HTML output */
  10. renderToStaticMarkup(<ThemableComponent ></ThemableComponent>)
  11. // <div class=".container"></div>
  12. // Derived theme
  13. const theme = ThemableComponent.themes.light.add({
  14. container: '.foobar'
  15. })
  16. renderToStaticMarkup(<ThemableComponent theme={theme} ></ThemableComponent>)
  17. // <div class=".container .foobar"></div>

Examples

Basic theming

  1. /* ThemableComponent.js */
  2. import React from 'react'
  3. import withThemes, { ThemeTypes } from 'react-css-themes'
  4. import light from './light.css'
  5. import dark from './dark.css'
  6. const ThemableComponent = ({ theme }) => (
  7. <div className={theme.container}>
  8. <div className={theme.heading}>Heading</div>
  9. </div>
  10. )
  11. ThemableComponent.themeTypes = {
  12. container: ThemeTypes.className,
  13. heading: ThemeTypes.className
  14. }
  15. export default withThemes({ light, dark }, light)(ThemableComponent)
  1. /* light.css */
  2. .container {
  3. background-color: white;
  4. }
  5. .heading {
  6. color: black;
  7. }
  1. /* dark.css */
  2. .container {
  3. background-color: black;
  4. }
  5. .heading {
  6. color: white;
  7. }
  1. /* View.js */
  2. import React from 'react'
  3. import ThemableComponent from './ThemableComponent'
  4. const View = () => (
  5. <div>
  6. <ThemableComponent theme={ThemableComponent.themes.light} ></ThemableComponent>
  7. <ThemableComponent theme={ThemableComponent.themes.dark} ></ThemableComponent>
  8. <ThemableComponent ></ThemableComponent> /* Default theme (light) will be used */
  9. </div>
  10. )
  11. export default View

Composing themable components

  1. /* AnotherThemableComponent.js */
  2. import React from 'react'
  3. import withThemes, { ThemeTypes } from 'react-css-themes'
  4. import themeA from './themeA.css'
  5. import themeB from './themeB.css'
  6. const THEMES = {
  7. themeA: {
  8. ...themeA,
  9. child1: ThemableComponent.themes.light,
  10. child2: ThemableComponent.themes.dark
  11. },
  12. themeB: {
  13. ...themeB,
  14. child1: ThemableComponent.themes.dark,
  15. child2: ThemableComponent.themes.light
  16. }
  17. }
  18. const AnotherThemableComponent = ({ theme }) => (
  19. <div className={theme.container}>
  20. <ThemableComponent theme={theme.child1} ></ThemableComponent>
  21. <ThemableComponent theme={theme.child2} ></ThemableComponent>
  22. </div>
  23. )
  24. AnotherThemableComponent.themeTypes = {
  25. container: ThemeTypes.className,
  26. child1: ThemeTypes.themeOf(ThemableComponent),
  27. child2: ThemeTypes.themeOf(ThemableComponent)
  28. }
  29. export default withThemes(THEMES, THEMES.themeA)(AnotherThemableComponent)

Adding classNames to a deeply nested themeable child

  1. /* AnotherThemableComponent.js */
  2. import React from 'react'
  3. import withThemes, { ThemeTypes } from 'react-css-themes'
  4. import themeA from './themeA.css'
  5. const THEMES = {
  6. themeA: {
  7. ...themeA,
  8. child: ThemableComponent.themes.light.add({
  9. container: themeA.childContainer,
  10. heading: themeA.childHeading
  11. })
  12. }
  13. }
  14. const AnotherThemableComponent = ({ theme }) => (
  15. <div className={theme.container}>
  16. <ThemableComponent theme={theme.child} ></ThemableComponent>
  17. </div>
  18. )

About

The project is authored by Diogo Cunha (@diffcunha) and Daniel Hayes (@daniel-hayes).

Comments, improvements or feedback are highly appreciated.

License

This project is licensed under the terms of the ISC license.