Universal css-in-js media queries for React Native and React
Switch branches/tags
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
lib
src
.babelrc
.editorconfig
.eslintrc
.gitignore
.watchmanconfig
LICENSE.md
README.md
package.json

README.md

Uranium

Adds media-query support to css-in-js in React Native and React.

export default () => <View css={styles.base} />

const styles = {
  base: {
    height: 120,

    '@media (min-width: 600px)': {
      height: 56,
    },
  },
}
iOS Web
iOS Uranium Example web Uranium example

Also works with android and server-side rendering

This can be used with react-native-web for a basic write-once, run-anywhere React Native app.

Installation

If using in React Native, install react-native-match-media

Make sure global.matchMedia is set:

import matchMedia from 'react-native-match-media'

// Only for native, will already be set on web
global.matchMedia = matchMedia

Then:

npm -S i tuckerconnelly/uranium

Usage

Use the css property to add styles with media queries.

Then wrap your component in Uranium

import React, { PropTypes } from 'react'
import { View } from 'react-native'
import Uranium from 'uranium'

import Shadows from './styles/Shadows'

const MyComponent = () =>
  <View css={styles.base}>
    <Text>Some text</Text>
  </View>

export default Uranium(MyComponent)


const styles = {
  base: {
    backgroundColor: 'red',

    '@media (min-width: 480px)': {
      backgroundColor: 'blue',
    }
  },
}

animate() function

Uranium adds the animate() function to make animations simple in React Native, and to take into account the current screen size/media query when animating.

It supports the following signatures:

animate(from: Object, to: Object, on: Animated.AnimatedValue)
animate(props: Array<string>, from: Object, to: Object, on: Animated.AnimatedValue)
animate(prop: string, from: number, to: number, on: AnimatedValue)

It expects the AnimatedValue to animate from 0 to 1.

Here it is used in a component:

import React from 'react'
import { View, Animated } from 'react-native'
import Uranium, { animate } from 'uranium'

class ExpandOnPress extends Component {
  state = { expanded: false }

  _expandAV = new Animated.Value(0)

  _toggleExpanded() {
    Animated.timing(this._expandAV, {
      toValue: this.state.expanded ? 0 : 1,
      duration: 300,
    })

    this.setState({ expanded: !this.state.expanded })
  }

  render() {
    return (
      <View
        css={[
          styles.base,
          animate(styles.notExpanded, styles.expanded, this._expandAV),
          animate('opacity', 0.25, 1, this._expandAV)
        ]}
        onPress={this._toggleExpanded} />
    )
  }
}

export default Uranium(ExpandOnClick)

const styles = {
  base: {
    backgroundColor: 'blue',
  },

  notExpanded: {
    width: 20,
    height: 20,
  },

  expanded: {
    width: 40,
    height: 40,
  }
}

This will animate all the styles on styles.notExpanded to all the styles on styles.expanded on the _expandAV AnimatedValue.

So width will animate from 20 to 40, and height will also animate from 20 to 40.

This also animates opacity from '0.25' to '1'.

If styles.notExpanded contained a property you didn't want to animate, like borderRadius, you could have specified specific values to animate:

animate(['width', 'height'], styles.notExpanded, styles.expanded, this._expandAV)

...

styles = {
  notExpanded: {
    width: 20,
    height: 20,
    borderRadius: 2,
  },

  expanded: {
    width: 40,
    height: 40,
  }
}

Note! The AnimatedValue must go from 0 to 1 (and vice versa).

Inspiration

Many thanks to the creators of Radium who inspired this library.

In fact, the name is a play on Radium: Universal Radium = Uranium :)

Connect

Follow the creator on Twitter, @TuckerConnelly

License

MIT