Fasong
A more sane approach to CSS in React (and Preact)
When you love the idea of styled-components
and CSS-in-JS
, but you also kind of hate it.
Heavily inspired by how styled-components and emotion lets us write components, but without having to write CSS in JavaScript.
Usage
Installation
npm i fasong
Basic usage
import React from 'react'
import ReactDOM from 'react-dom'
import { styled } from 'fasong'
const Heading = styled('h1', 'heading')
ReactDOM.render(<Heading>Hello</Heading>, document.body)
// <h1 class="heading">Hello</h1>
Integrates with CSS modules
import React from 'react'
import ReactDOM from 'react-dom'
import { styled } from 'fasong'
import styles from './styles.css'
const Heading = styled('h1', styles.heading)
ReactDOM.render(<Heading>Hello</Heading>, document.body)
// <h1 class="heading-lkjfos">Hello</h1>
Conditionally applying classes
If fasong
recieves a function as the second argument it will be called with the component props and/or theme.
import React from 'react'
import ReactDOM from 'react-dom'
import { styled } from 'fasong'
import cx from 'classnames'
import styles from './styles.css'
const Heading = styled('h1', props =>
cx({
[styles.heading]: true,
[styles.headingDark]: props.dark
})
)
ReactDOM.render(<Heading dark>Hello</Heading>, document.body)
// <h1 class="heading-lkjfos heading--dark-lkjfos">Hello</h1>
Appending and overriding
If a consumer passes a className
prop it will be appended.
import React from 'react'
import ReactDOM from 'react-dom'
import { styled } from 'fasong'
const Heading = styled('h1', 'heading')
ReactDOM.render(
<Heading className="heading--dark">Hello</Heading>,
document.body
)
// <h1 class="heading heading--dark">Hello</h1>
import React from 'react'
import ReactDOM from 'react-dom'
import { styled } from 'fasong'
const Heading = styled('h1', 'heading')
const DarkHeading = styled(Heading, 'heading--dark')
const EvenDarkerHeading = styled(DarkHeading, 'heading--even-darker')
ReactDOM.render(
<>
<Heading>Hello</Heading>
<DarkHeading>Hello</DarkHeading>
<EvenDarkerHeading>Hello</EvenDarkerHeading>
</>,
document.body
)
// <h1 class="heading">Hello</h1>
// <h1 class="heading heading--dark">Hello</h1>
// <h1 class="heading heading--dark heading--even-darker">Hello</h1>
Theming
import React from 'react'
import ReactDOM from 'react-dom'
import { styled, Theme } from 'fasong'
const Heading = styled('h1', (props, theme) => `heading heading--${theme}`)
ReactDOM.render(
<Theme.Provider value={'sport'}>
<Heading>Hello</Heading>
</Theme.Provider>,
document.body
)
// <h1 class="heading heading--sport">Hello</h1>
Tagged template literal API
fasong
also supports using tagged template literals to construct classes.
If a interpolated value is a function it will be called with the components props
and the theme
context if present.
import React from 'react'
import ReactDOM from 'react-dom'
import { styled, Theme } from 'fasong'
const Heading = styled.h1`
heading
${Date.now() === 42 ? 'heading--dark' : ''}
${(props, theme) => `heading--${theme}`}
`
ReactDOM.render(
<Theme.Provider value={'sport'}>
<Heading>Hello</Heading>
</Theme.Provider>,
document.body
)
// <h1 class="heading heading--dark heading--sport">Hello</h1>
Preact
import styled from 'fasong/preact'
Note: fasong/preact
does not currently support automaticly extracting theming from context or the tagged template literal api. This is on the todo list.
License
MIT.