jsx() Addon

jsx() is a 5th generation interface for creating styling blocks — components similar to "styled components", but which are more powerful.

const Button = jsx('button', {
    display: 'inline-block',
    borderRadius: '3px',
    padding: '0.5rem 0',
    margin: '0.5rem 1rem',
    width: '11rem',
    background: 'transparent',
    color: 'white',
    border: '2px solid white',
});

<Button>Click me!</Button>

Nota Bene

To use this interface you need to provide the hyperscript function h of your virtual DOM library when creating a nano-css instance. In case of React, this is the createElement function:

import {create} from 'nano-css';
import {createElement} from 'react';

const nano = create({
    h: createElement
});

Optionally, you can name your styling block:

const Button = jsx('button', css, 'MyButton');

Styling blocks pass all their props to the underlying element:

<Button
    disabled
    aria-label="something"
    onClick={() => {}}
>
    Click me!
</Button>

However, some props have special meaning and are not passed through:

  • css — a CSS-like object of dynamic style overrides
  • $as — allows to overwrite the underlying element type
  • $ref — allows to pass a ref to the underlying element

Add custom styling:

<Button css={{background: primary ? 'blue' : 'grey'}}>Click me!</Button>

Overwrite underlying element type:

<Button $as='a'>Click me!</Button>
// <a>Click me!</a>

Component as a Type

You can pass components as an element type.

const Button = jsx(MyComp, css);

where

const MyComp = (props) => {
    return <button {...props} />
};

Composition

The above feature of passing component as a type allows you to do composition.

const BaseButton = jsx('button', {
    color: 'red',
    border: '1px solid red',
});

const SmallButton = jsx(BaseButton, {
    fontSize: '11px',
});

However, composition of styling blocks is not something that is encouraged, instead you might consider using dynamic styling css prop:

const BaseButton = jsx('button', {
    color: 'red',
    border: '1px solid red',
});

const Button = (props) => {
    const {small, ...rest} = props;
    const css = {};

    if (small) {
        css.fontSize = '11px';
    }

    return <BaseButton {...rest} css={css} />;
};

Changing Element Type

Let's say you created a <button> component like so.

const Button = jsx('button', {
    display: 'inline-block',
    borderRadius: '3px',
    padding: '0.5rem 0',
    margin: '0.5rem 1rem',
    width: '11rem',
    background: 'transparent',
    color: 'white',
    border: '2px solid white',
});

But you wanted to have the same looking button, which used <a> tag instead. Just wrap it in another component and overwrite the $as prop.

const Link = (props) => Button({
    ...props,
    $as: 'a'
});

<Link>Click me!</Link>
// <a>Click me!</a>

Other libraries provide a method like withComponent:

const Link = withComponent(Button, 'a');

You can make one yourself:

const withComponent = (styledComp, comp) => (props) => styledComp({
    ...props,
    $as: comp
});

Installation

Simply install jsx addon and its dependencies:

Read more about the Addon Installation.