Usage with ReasonML
The Reason bindings ship with some core Fela APIs, React hooks and all plugins, enhancers and presets.
Note: If you want to use older APIs such as
createComponent
or connect
, we recommend using bs-react-fela(new tab) instead.yarn add reason-fela# you'll also need at least fela and react-felayarn add fela react-fela
In your
bsconfig.json
, include "reason-fela"
in the bs-dependencies
.Creating a Fela renderer
First let's create our Fela Renderer instance. We can pass all the config options that the Fela renderer accepts.
FelaRenderer.re
open Fela;/* you can also use all plugins and enhancers via Fela.Plugins and Fela.Enhancers e.g. Fela.Plugins.prefixer, Fela.Enhancers.web */let renderer = Renderer.make( RendererConfig.make( ~plugins=Presets.web, ~selectorPrefix="reason-", () ))
Passing the Renderer
Now that we have the renderer, we need to provide it to our app.
We can also optionally pass a theme down here, which is useful for dynamic theming.
Tip: If we just want to define some static theme properties, one can also leverage a
Theme.re
module and access it directly due to all files/modules being globally available.App.re
open ReactFela;let theme = { "colors": { "primary": "blue", "secondary": "red" }};[@react.component]let make = (~children) => <RendererProvider renderer> <ThemeProvider theme> children </ThemeProvider> </RendererProvider>
Using the Hooks
Now that our app is aware of the renderer, we can use the provided hooks in any component. The hooks are similar to react-fela's useFela, but split into 3 different hooks for convenience.
RedText.re
open ReactFela;[@react.component]let make = (~children) => { let css = useFela(); let theme = useTheme(); let renderer = useRenderer(); /* we can also do stuff we the renderer */ renderer##renderStatic(Fela.style({"backgroundColor": "red"}), "body"); <div className={css([ Fela.style({"fontSize": "18pt", "color": theme##colors##primary}), ])}> "I'm red"->React.string </div>;};
Convenience Hooks
ReactFela also includes two convenience hooks
useFela1
and useFela2
that take just 1 or 2 parameters respectively instead of passing a list.open ReactFela;[@react.component]let make = (~children) => { let css1 = useFela1(); let css2 = useFela2(); <div className={css1(Fela.style({"color": "red"}))}> <div className={css2( Fela.style({"color": "red"}), Fela.style({"color": "red"}), )} /> </div>;};
Server-side Rendering
If we're running a universal app, we also want to make sure that styles are correctly rendered and rehydrated when doing server-side rendering.
Therefore, reason-fela also provides bindings to fela-dom.
Server.re
open Fela.Dom;let htmlString = renderToMarkup(renderer);let sheetList = renderToSheetList(renderer);sheetList -> Belt.Array.forEach(({type_, css, media, support, rehydration}) => { /* render your style nodes here */});
Using bs-css-core
You can also opt-in bs-css-core(new tab) module which was forked from bs-css(new tab) for a more convenient, type-safe API.
yarn add @astrada/bs-css-core
In your
bsconfig.json
, include "@astrada/bs-css-core"
in the bs-dependencies
.Now the only thing we need is a type converter which can be done using the
"%identity"
helper. You probably want to create a new utility mode e.g. FelaUtils
that looks sth. like this:FelaUtils.re
external fromBsCssCore: Css.style => Fela.style = "%identity";
Now we can use it in our components:
RedText.re
open ReactFela;open FelaUtils;open Css;[@react.component]let make = (~children) => { let css = useFela(); let theme = useTheme(); let renderer = useRenderer(); /* we can also do stuff we the renderer */ renderer##renderStatic( fromBsCssCore(style([backgroundColor(black)])), "body", ); <div className={css([ fromBsCssCore( style([fontSize(pt(18)), color(theme##colors##primary)]), ), ])}> "I'm red"->React.string </div>;};