Skip to main content

Styling

Styling — Vivid Module

This package is in abstraction on top of @rexlabs/element-styles, using emotion as the CSS-in-JS solution of choice. It mainly, additionally to the element styles utils, provides a StyleSheet method that abstracts out the construction of the style object.

Getting Started

Install Dependency

yarn add @rexlabs/styling

Usage Examples

import { StylesProvider, StyleSheet, styled } from '@rexlabs/styling';

const defaultStyles = StyleSheet({
container: {
background: 'green',
padding: '20px'
},
inner: {
color: 'blue',
fontWeight: 'bold'
}
});

function Example({ styles: s }) {
return (
<div {...s('container')}>
<span {...s('inner')}>Example</span>
</div>
);
}

const StyledExample = styled(defaultStyles)(Example);

function App() {
return (
<StylesProvider>
<StyledExample />
</StylesProvider>
);
}

Token utilities

Some utilities are included to help with creating tokens and their specific targets in an easier and more consistent way.

import React from 'react';

import {
StylesProvider,
StyleSheet,
text,
padding,
margin,
border
} from '@rexlabs/styling';

const defaultStyles = StyleSheet({
container: {
// Abnormal - API showcase
...padding.styles({
target: 'component.container',
all: 'xxxs',
x: ({ token }) => token('spacing.xxl'),
y: 'm',
top: 'l',
right: 'm',
bottom: 'm',
left: 'xxl'
}),
...margin.styles({
target: 'component.container'
// all,
// x,
// y,
// top,
// right,
// bottom.
// left
}),
...border.styles({
target: ['menu.container', 'component.container'],
all: {
width: 'thin',
style: ({ token }) => token('border.style.solid'), // defaults to 'solid'
color: ({ token }) => token('color.secondary.idle.default'),
radius: 'medium'
},
top: {
radius: 'small'
},
// right,
bottom: {
right: {
radius: 'medium'
}
}
// left
})
},
label: {
...text.styles({
target: 'component.label',
fallback: 'small.default',
color: ({ token }) => token('color.primary.idle.default'),
font: {
family: 'normal.default'
// size
// weight
},
// lineHeight,
// letterSpacing,
// textDecoration
icon: {
color: ({ token }) => token('color.secondary.idle.default'),
size: ({ token }) => token('icon.size.m')
}
})
},
// Normal case
inner: {
...padding.styles({
target: 'component.inner',
x: 'm',
y: 'l'
}),
...border.styles({
target: 'component.inner',
all: {
width: 'thin',
color: ({ token }) => token('color.primary.idle.default'),
radius: 'medium'
}
}),
...text.styles({
target: 'component.inner',
fallback: 'normal.default'
})
}
});

const tokens = {
...padding.tokens({
// Same as above
})
};

function Component(props) {
return <StylesProvider tokens={tokens}>{props.children}</StylesProvider>;
}

API Docs

StyleSheet(object)

Turns an object of styles into an object of class names using emotions css method. The keys of the object are the identifiers the style util created by the styled HOC will use to apply the styles, the values are style objects for that key, which the StyleSheet method will turn into proper class names.

For individual CSS attributes you can also pass in a function as the value, which allows you to use features like "tokens", e.g.

const defaultStyles = StyleSheet({
container: {
padding: '20px',
background: ({ token }) => token('colors.primary')
}
});

insertCss(string)

Useful to inject global css rules. Simply pass in a css string of the styles you want to inject, e.g.

insertCss(`
html {
background: yellow;
}

button {
&:active {
color: red;
}
}
`);

reset()

Basic css reset, currently using this set of CSS rules.

styled & StylesProvider

See @rexlabs/element-styles.

Hooks

useMode()

The useMode hook will return an array of all the currently active mode names

import React from 'react';

import { styled, StyleSheet, useMode } from '@rexlabs/styling';

const defaultStyles = StyleSheet({
container: {
// ... styles
},
containerDark: {
// ... dark mode styles
}
});

function Component() {
const modes = useMode();
return (
<div {...s('container', { containerDar: modes.includes('dark') })}>
<Content />
</div>
);
}

export default styled(defaultStyles)(Component);

useModeTokens(object, array)

The useModeTokens hook will allow you to declare a components base tokens, as well as all of it's possible modes, and returns a tokens object that includes all of the correct tokens for the currently active modes.

import React from 'react';
import { StylesProvider, useModeTokens } from '@rexlabs/styling';

const baseTokens = {
button: {
margin: {
right: 100
}
}
};

const compactTokens = {
button: {
margin: {
right: 50
}
}
};

const darkTokens = {
button: {
background: {
color: 'darkblue'
}
}
};

export default function Component() {
// The order that you list the mode tokens in here
// will be the order that they are merged in
const tokens = useModeTokens(baseTokens, [
{ mode: 'dark', tokens: darkTokens },
{ mode: 'compact', tokens: compactTokens }
]);
return (
<StylesProvider tokens={tokens}>
<StyledComponent />
</StylesProvider>
);
}

Upgrade Guide

Version 1.x to 2.0.0

  • search and remove uses of createCssClass as this is no longer available.
  • Pseudo elements won't render if content isn't double quoted eg: content: '" "'. (pseudo elements should also be &:: although : works its prob best to be consistent and update all to the correct format ;))
  • Styling merging has changed. Passing styles to a component will be overwritten by your global component styles. To fix this use a styles provider or as a quick fix you can add !important the css.
  • When passing in style objects ensure they are wrapped with StyleSheet().
  • Setting a class name changes from ‘<span {…s.with(‘innerSwitch’)(‘inner’) />to<span {…s.with(‘innerSwitch’)({ className: ‘inner’ }) />`
  • Previously when setting a style if you put a string as number it would assume it was pixels, this is not the case anymore so don’t forget your units.
  • make sure you're using @rexlabs/loading-spinner > 2.x, v1.x the spinner would be disppearing mid animation.
  • check your animations one of my animations failed due to keyframes having a name eg: keyframes('dash', { ... }) wasn't working but worked when I changed to keyframes({ ... })

Version 3.x to 4.0.0

  • The mq utility has changed
    • mq is no longer a function
    • mq.breakpoints.{mobile|tablet|desktop} are no longer functions
    • This utility has been brought more in line with the other token utilities and has mq.styles({ target, queries, styles }) function that will return the styles needed for that media query
    • It also has an mq.styles.combine([{ target, queries, styles }]) function that takes multiple media queries and combines them so they can work on the one element

Development

Install dependencies

$ yarn

Available Commands

$ yarn test               # runs all units tests
$ yarn test:watch # runs unit tests when files change
$ yarn build # bundles the package for production

Roadmap

  • Double check old API (e.g. static StyleSheet.* methods) + document dropped and deprecated functionality
  • Test new packages in apps
  • Check what needs to be done for RN support

Copyright © 2019 Rex Software All Rights Reserved.