Usage with React
Fela was always designed with React in mind, but is not bound to React by default.
If you want to use it with React, you should also install the official React bindings for Fela(new tab).
yarn add react-fela
Passing the Renderer
In order to style components, we first need to wrap our application with the RendererProvider component.
It leverages React's context(new tab) APIs to pass our Renderer to all child components.
App.js
import { createRenderer } from 'fela'import { RendererProvider } from 'react-fela'import MyApp from './MyApp'const renderer = createRenderer()export default () => ( <RendererProvider renderer={renderer}> <MyApp /> </RendererProvider>)
Styling Components
With hooks(new tab) being added to React, styling your components with Fela has never been easier.
react-fela ships the
useFela
hook which returns an object containing a css
function. Calling that function will render all passed styles and return the generated class names.
Button.js
import React from 'react'import { useFela } from 'react-fela'function Button({ children, fontSize = 16 }) { const { css } = useFela() return ( <button className={css({ padding: 10, fontSize, color: 'darkblue', ':hover': { color: 'blue', }, })}> {children} </button> )}
Using Rules
Instead of passing style objects directly, you might want to extract your styles into rules.
The
css
function also accepts rules. We can pass our props to useFela
in order to access them inside our rules.Button.js
import React from 'react'import { useFela } from 'react-fela'const rule = ({ fontSize }) => ({ padding: 10, fontSize, color: 'darkblue', ':hover': { color: 'blue', },})function Button({ children, fontSize = 16 }) { const { css } = useFela({ fontSize }) return <button className={css(rule)}>{children}</button>}
Composition
The
css
function does not only take a single argument, but can take an array of style objects and rules.They are merged using
combineRules
thus the order of arguments matters.Button.js
import React from 'react'import { useFela } from 'react-fela'const baseStyle = ({ fontSize }) => ({ padding: 10, fontSize: 16,})const hoverStyle = { color: 'darkblue', ':hover': { color: 'blue', },}function Button({ children, fontSize = 16, extend }) { const { css } = useFela({ fontSize }) return ( <button className={css([baseStyle, hoverStyle, extend])}>{children}</button> )}// extending the Button styles for a more specific big buttonconst BigButton = ({ children }) => ( <Button fontSize={20} extend={{ padding: 16 }}> {children} </Button>)
Fonts & Keyframes
The
useFela
hook also returns our Renderer instance, so we can use that to render fonts, keyframes and static styles directly within our components.Tip: We can also use fela-plugin-embedded(new tab) to render fonts and keyframes from within our style object.
Button.js
import React from 'react'import { useFela } from 'react-fela'function Button({ children, fontSize = 16 }) { const { css, renderer } = useFela() // since fonts and keyframes are cached, they are only rendered once const fontFamily = renderer.renderFont('Arial', [ '/fonts/Arial.ttf', '/fonts/Arial.woff', '/fonts/Arial.woff2', ]) return ( <button className={css({ padding: 10, fontSize, fontFamily, color: 'darkblue', ':hover': { color: 'blue', }, })}> {children} </button> )}
Theming
Passing the Theme
In order to access our theme, we need to wrap our application with the ThemeProvider component.
Similar to the
RendererProvider
it uses React's context API to pass the theme to every child component.Tip: We can also wrap specific sub-trees with different themes e.g. if only a specific part of our application should be rendered in dark mode. Multiple nested ThemeProvider instances will automatically deep-merge the theme objects unless a
overwrite
prop is passed with false
.App.js
import { createRenderer } from 'fela'import { RendererProvider, ThemeProvider } from 'react-fela'import MyApp from './MyApp'import theme from './theme'const renderer = createRenderer()export default () => ( <RendererProvider renderer={renderer}> <ThemeProvider theme={theme}> <MyApp /> </ThemeProvider> </RendererProvider>)
Using the Theme
Next to the
css
function, useFela
also provides the current theme
object.Note: Rules get the theme passed automatically via
props.theme
.Button.js
import React from 'react'import { useFela } from 'react-fela'function Button({ children, fontSize = 16 }) { const { css, theme } = useFela() return ( <button className={css({ padding: 10, fontSize, color: theme.colors.blueDark, ':hover': { color: theme.colors.blue, }, })}> {children} </button> )}
Pre-hooks APIs
Prior to hooks, Fela shipped a couple of Higher-order and Render-props components to style React components.
While we recommend using the
useFela
hook whenever possible, they are still valid APIs and can be used interchangable.Tips & Tricks
Presentational Components
While not required, we highly recommend to split your components into presentational and container components(new tab). Where container components manage the application logic, presentational components should only describe how your application is displayed (markup & styling). They get data passed as
props
and return a representation of your view for those props.
If we strictly separate our components, we actually only use Fela for presentational components.