Skip to content

Dynamically resolve styleName in RN with support for multi-class selectors (for easier modifiers)

License

Notifications You must be signed in to change notification settings

dmapper/babel-plugin-react-native-dynamic-stylename-to-style

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Apr 27, 2020
2071f88 · Apr 27, 2020

History

66 Commits
Jan 24, 2020
Jun 24, 2018
Apr 21, 2018
Jun 22, 2018
Apr 21, 2018
Apr 21, 2018
May 25, 2018
Apr 27, 2020
Apr 21, 2018
Apr 27, 2020
Apr 27, 2020
Apr 27, 2020
Jan 20, 2019

Repository files navigation

babel-plugin-react-native-dynamic-stylename-to-style

Transform JSX styleName property to style property in react-native. The styleName attribute and syntax are based on babel-plugin-react-css-modules.

Information

This is the fork of https://github.com/kristerkari/babel-plugin-react-native-stylename-to-style

The differences are:

  1. Support resolving multi-class selectors in CSS:
import classnames from 'classnames'

function Button ({
  variant,  // [string] 'primary' | 'secondary'
  dark,     // [bool]
  disabled  // [bool]
}) {
  return (
    <Text
      styleName={classnames('button', [variant, { dark, disabled }])}
    >CLICK ME</Text>
  )
}
.button
  background-color: blue
  &.primary
    color: #ff0000
    &.disabled
      color: rgba(#ff0000, 0.5)
  &.secondary
    color: #00ff00
    &.disabled
      color: rgba(#00ff00, 0.5)
  &.disabled
    color: #777

.dark
  &.button
    background-color: purple
    &.primary
      color: white
      &.disabled
        color: #ddd
  &.disabled
    color: #eee

And what's important is that selectors` specificity is properly emulated. For example:

Styles for .button.primary.disabled (specificity 30) will override styles of .button.disabled (specificity 20), even though .button.disabled is written later in the CSS.

This simple change brings a lot more capabilities in theming your components for a dynamic look.

  1. Convert any *StyleName attribute to the according *Style attribute. This is very useful for passing the sub-element styles (which are usually exposed by react-native libraries) directly from CSS.

  2. If the styleName value is an object or an array, automatically pipe it through the classnames-like library.

  3. Support for multiple named css file imports is removed

Usage

Step 1: Install

yarn add --dev babel-plugin-react-native-dynamic-stylename-to-style

or

npm install --save-dev babel-plugin-react-native-dynamic-stylename-to-style

Step 2: Configure .babelrc

You must give one or more file extensions inside an array in the plugin options.

{
  "presets": [
    "react-native"
  ],
  "plugins": [
    ["react-native-dynamic-stylename-to-style", {
      "extensions": ["css"]
    }]
  ]
}

Syntax

Anonymous reference

Anonymous reference can be used when there is only one stylesheet import.

Single class

import "./Button.css";

<View styleName="wrapper">
  <Text>Foo</Text>
</View>;

↓ ↓ ↓ ↓ ↓ ↓

import Button from "./Button.css";

<View style={Button.wrapper}>
  <Text>Foo</Text>
</View>;

Multiple classes

import "./Button.css";

<View styleName="wrapper red-background">
  <Text>Foo</Text>
</View>;

↓ ↓ ↓ ↓ ↓ ↓

import Button from "./Button.css";

<View style={[Button.wrapper, Button["red-background"]]}>
  <Text>Foo</Text>
</View>;

Expression

import "./Button.css";
const name = "wrapper";

<View styleName={name}>
  <Text>Foo</Text>
</View>;

↓ ↓ ↓ ↓ ↓ ↓

import Button from "./Button.css";
const name = "wrapper";

<View
  style={(name || "")
    .split(" ")
    .filter(Boolean)
    .map(function(name) {
      Button[name];
    })}
>
  <Text>Foo</Text>
</View>;

Expression with ternary

import "./Button.css";

const condition = true;
const name = "wrapper";

<View styleName={condition ? name : "bar"}>
  <Text>Foo</Text>
</View>;

↓ ↓ ↓ ↓ ↓ ↓

import Button from "./Button.css";

const condition = true;
const name = "wrapper";

<View
  style={((condition ? name : "bar") || "")
    .split(" ")
    .filter(Boolean)
    .map(function(name) {
      Button[name];
    })}
>
  <Text>Foo</Text>
</View>;

with styleName and style:

import "./Button.css";

<View styleName="wrapper" style={{ height: 10 }}>
  <Text>Foo</Text>
</View>;

↓ ↓ ↓ ↓ ↓ ↓

import Button from "./Button.css";

<View style={[Button.wrapper, { height: 10 }]}>
  <Text>Foo</Text>
</View>;

About

Dynamically resolve styleName in RN with support for multi-class selectors (for easier modifiers)

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published