# Freyja A full-featured functional CSS-in-JS solution, adapted from [CXS](https://github.com/cxs-css/cxs) to make it suitable for production websites. You provide a function accepting component `props` and your application's `theme`, and returning a map of styles (`(theme, props, helpers) => ({key1: style, key2: style})`), and `useStyles` will return a map of classnames (like `{key1: className, key2: className}`). - Everything CXS has plus: - React hook API - An efficient functional design for complex components - Server-side rendering and client-side hydration - Comprehensive and performant vendor prefixing - Animation keyframes - Ordered media-queries to ensure correct cascade precedence ## How to use Install via `npm i freyja`. Create your styled component. ```js import useStyles from 'freyja' // this could be in a separate file if you like const titleStyles = ({font, scale}, {color}, {animation}) => ({ wrapper: { textAlign: 'center', padding: scale.large }, title: { color, fontFamily: font.display, animationName: animation({ from: { opacity: 0 }, to: { opacity: 1 } }) } }) const Title = props => { const styles = useStyles(titleStyles, props) const {text, children} = props return ( <div className={styles.wrapper}> <h1 className={styles.title}>{text || children}</h1> </div> ) } export default Title // use like: <Title color={'red'} text={'My first title'} /> ``` Wrap your app in a `ThemeProvider` (must have only 1 child). Multiple `ThemeProviders` can be nested, with merged themes only accessible to children within the nested provider: ```js import {ThemeProvider, animation} from 'freyja' const theme = { font: { display: 'Merriweather', copy: 'Helvetica' }, scale: { small: 12, medium: 16, large: 24 }, animations: { spin: animation({ // create named animations with full keyframe support from: { transform: 'rotate(0deg)' }, to: { transform: 'rotate(360deg)' } }) } } const App = ({children}) => ( <ThemeProvider theme={theme}> <>{children}</> </ThemeProvider> ) export default App ``` ### Server-side rendering Simply call the `styleTags` dehydration function to receive a string of `style` tags to insert in your document. Styles will automatically be hydrated on the client. If rendering your views with React on the server, `StyleComponents` can be used in the `<head>`, like: `<head><StyleComponents /></head>` ```js import React from 'react' import {renderToString} from 'react-dom/server' import {styleTags} from 'freyja' import App from './App' const renderMiddleware = (req, res) => { const appHTML = renderToString(<App />) const appStyleTags = styleTags() // must be called AFTER renderToString() res.send(` <!doctype html> <html> <head> ${appStyleTags} </head> <body> ${appHTML} </body> </html> `) } ```