Skip to content

Commit

Permalink
Theme-aware static rendering (#894)
Browse files Browse the repository at this point in the history
* remove flow fix me

* copy docs

* clean docs

* add staticStyle to useFela for theme-aware styles

* update docs
  • Loading branch information
robinweser committed Apr 6, 2022
1 parent 2e19a19 commit f9468b6
Show file tree
Hide file tree
Showing 8 changed files with 105 additions and 85 deletions.
2 changes: 2 additions & 0 deletions packages/fela-bindings/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import ThemeProviderFactory from './ThemeProviderFactory'
import withThemeFactory from './withThemeFactory'
import feFactory from './feFactory'
import renderToNodeListFactory from './renderToNodeListFactory'
import useFelaFactory from './useFelaFactory'

export {
connectFactory,
Expand All @@ -18,4 +19,5 @@ export {
withThemeFactory,
feFactory,
renderToNodeListFactory,
useFelaFactory,
}
49 changes: 49 additions & 0 deletions packages/fela-bindings/src/useFelaFactory.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { combineRules } from 'fela'

function getPropsWithTheme(props, theme) {
if (props) {
return {
...props,
theme,
}
}

return {
theme,
}
}

export default function useFelaFactory(
RendererContext,
ThemeContext,
useContext
) {
return function useFela(props) {
const renderer = useContext(RendererContext)
const theme = useContext(ThemeContext) || {}

if (!renderer) {
throw new Error(
'The "useFela" hook can only be used inside a "RendererProvider"'
)
}

// we add the theme to props so that it can be used within styles
const propsWithTheme = getPropsWithTheme(props, theme)

function css(...rules) {
return renderer.renderRule(combineRules(...rules), propsWithTheme)
}

function staticStyle(style, selector) {
return renderer.renderStatic(style, selector, propsWithTheme)
}

return {
renderer,
theme,
css,
staticStyle,
}
}
}
4 changes: 2 additions & 2 deletions packages/fela/src/createRenderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -148,11 +148,11 @@ export default function createRenderer(config = {}) {
return renderer.cache[fontReference].fontFamily
},

renderStatic(staticStyle, selector) {
renderStatic(staticStyle, selector, props = {}) {
const staticReference = generateStaticReference(staticStyle, selector)

if (!renderer.cache.hasOwnProperty(staticReference)) {
const cssDeclarations = cssifyStaticStyle(staticStyle, renderer)
const cssDeclarations = cssifyStaticStyle(staticStyle, renderer, props)

const change = {
type: STATIC_TYPE,
Expand Down
5 changes: 3 additions & 2 deletions packages/fela/src/cssifyStaticStyle.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,16 @@ import { processStyleWithPlugins, STATIC_TYPE } from 'fela-utils'

import minifyCSSString from './minifyCSSString'

export default function cssifyStaticStyle(staticStyle, renderer) {
export default function cssifyStaticStyle(staticStyle, renderer, props) {
if (typeof staticStyle === 'string') {
return minifyCSSString(staticStyle)
}

const processedStaticStyle = processStyleWithPlugins(
renderer,
staticStyle,
STATIC_TYPE
STATIC_TYPE,
props
)

return cssifyObject(processedStaticStyle)
Expand Down
31 changes: 3 additions & 28 deletions packages/preact-fela/src/useFela.js
Original file line number Diff line number Diff line change
@@ -1,31 +1,6 @@
// $FlowFixMe
import { useContext } from 'preact/hooks'
import { combineRules } from 'fela'
import { useFelaFactory } from 'fela-bindings'

import { RendererContext, ThemeContext } from './context'
import { ThemeContext, RendererContext } from './context'

export default function useFela(props = {}) {
const renderer = useContext(RendererContext)
const theme = useContext(ThemeContext) || {}

if (!renderer) {
throw new Error(
'The "useFela" hook can only be used inside a "RendererProvider"'
)
}

const propsWithTheme = {
...props,
theme,
}

function css(...rules) {
return renderer.renderRule(combineRules(...rules), propsWithTheme)
}

return {
renderer,
theme,
css,
}
}
export default useFelaFactory(RendererContext, ThemeContext, useContext)
41 changes: 3 additions & 38 deletions packages/react-fela/src/useFela.js
Original file line number Diff line number Diff line change
@@ -1,41 +1,6 @@
import { useContext } from 'react'
import { combineRules } from 'fela'
import { useFelaFactory } from 'fela-bindings'

import { RendererContext, ThemeContext } from './context'
import { ThemeContext, RendererContext } from './context'

function getPropsWithTheme(props, theme) {
if (props) {
return {
...props,
theme,
}
}

return {
theme,
}
}

export default function useFela(props) {
const renderer = useContext(RendererContext)
const theme = useContext(ThemeContext) || {}

if (!renderer) {
throw new Error(
'The "useFela" hook can only be used inside a "RendererProvider"'
)
}

// we add the theme to props so that it can be used within styles
const propsWithTheme = getPropsWithTheme(props, theme)

function css(...rules) {
return renderer.renderRule(combineRules(...rules), propsWithTheme)
}

return {
renderer,
theme,
css,
}
}
export default useFelaFactory(RendererContext, ThemeContext, useContext)
10 changes: 5 additions & 5 deletions website/docs/latest/api/fela/renderer.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -178,11 +178,11 @@ Renders static styles.

### Arguments;;renderStatic-arguments

| Argument | Type | Description |
| -------- | ---------------------- | ----------------------------------------------------------------------------- |
| style | _string_<br />_Object_ | Either a pure CSS string or an object of style declarations. |
| selector | _string_ | If `style` is passed as an object you **must** specify a `selector` selector. |
| props | _Object?_ | |
| Argument | Type | Description |
| -------- | ---------------------- | ------------------------------------------------------------------------------ |
| style | _string_<br />_Object_ | Either a pure CSS string or an object of style declarations. |
| selector | _string_ | If `style` is passed as an object you **must** specify a `selector` selector. |
| props | _Object?_ | An object of props that is passed to the plugins processing the style objects. |

### Example;;renderStatic-example

Expand Down
48 changes: 38 additions & 10 deletions website/docs/latest/api/react-fela/useFela.mdx
Original file line number Diff line number Diff line change
@@ -1,28 +1,29 @@
# useFela

useFela is React [hook](https://reactjs.org/docs/hooks-intro.html) that provides a universal `css` function. It also provides access to both renderer and theme.
useFela is React [hook](https://reactjs.org/docs/hooks-intro.html) that provides a universal `css` function as well as a `staticStyle` function. It also provides access to both renderer and theme.

## Arguments

| Argument | Type | Default |
| -------- | -------- | ------------------------------------------------ |
| props | _Object_ | An object of props that is used to render rules. |
| Argument | Type | Default |
| -------- | -------- | ------------------------------------------------------------------ |
| props | _Object_ | An object of props that is used to render rules and static styles. |

## Returns

(_Object_): The hook interface

## Interface

| Property | Type | Description |
| -------- | ------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| css | _function_ | A function that accepts a list of [style object](basics/rules/style-object) and/or [rule](basics/rules) and returns a single className. |
| theme | _Object_ | The theme object which is passed down via context |
| renderer | _[Renderer](api/fela/renderer)_ | The renderer that is passed down via context |
| Property | Type | Description |
| ----------- | ------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| css | _function_ | A function that accepts a list of [style object](basics/rules/style-object) and/or [rule](basics/rules) and returns a single className. |
| staticStyle | _function_ | A function that accepts the same arguments as [renderStatic](api/fela/renderer#renderStatic). |
| theme | _Object_ | The theme object which is passed down via context. |
| renderer | _[Renderer](api/fela/renderer)_ | The renderer that is passed down via context. |

## Imports

> **Note**: Due to lack of support for hooks, useFela is currently only available for react-fela and preact-fela.
> **Note**: Due to lack of support for hooks in Inferno, useFela is currently only available for React and Preact.
```javascript
import { useFela } from 'react-fela'
Expand Down Expand Up @@ -78,3 +79,30 @@ function RedOnBlue({ children, customStyle }) {
// Usage
const Usage = <RedOnBlue customStyle={{ fontSize: 12 }} />
```

### Accessing theme

```javascript
function WithTheme() {
const { theme } = useFela()

return <div>Primary color is {theme.colors.primary}</div>
}
```

### Rendering static styles

```javascript
function WithTheme() {
const { staticStyle } = useFela()

staticStyle(
{
backgroundColor: 'blue',
},
'body'
)

return <div>Primary color is {theme.colors.primary}</div>
}
```

1 comment on commit f9468b6

@vercel
Copy link

@vercel vercel bot commented on f9468b6 Apr 6, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.