Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/ExodusMovement/shakl

A utility to create styled components in React Native.
https://github.com/ExodusMovement/shakl

react-native styled-components

Last synced: about 1 month ago
JSON representation

A utility to create styled components in React Native.

Awesome Lists containing this project

README

        

# Shakl

[![npm version](https://badge.fury.io/js/shakl.svg)](https://badge.fury.io/js/shakl) [![Build Status](https://travis-ci.org/sonaye/shakl.svg?branch=master)](https://travis-ci.org/sonaye/shakl)

Shakl logo

## Features

- Exposes basic [primitives](#primitives) such as `View`, `Text` and `Touchable`,
- Supports static and [dynamic styles](#dynamic-styles) (based on props).
- Supports component extension using [`extend()`](#extending-styles) and [`attrs()`](#custom-props).
- Supports component composition using [`withComponent()`](#wrapping-another-component) and [`withChild()`](#wrapping-a-child).
- Uses regular inline styles under the hood (performance boost).
- Works [with React DOM](#usage-with-react-dom) too, same simple API, same benefits.
- No dependencies, all just React goodness.
- ~2 KB in size, with less than 100 lines of code.

### Benchmark

Time required to create a simple styled component (in ms).

Shakl Benchmark

## Install

```bash
yarn add shakl
```

## Usage

### Creating a styled component

```js
import styled from 'shakl'

const Foo = styled(View)({ flex: 1 })

//
```

### Primitives

By default, React Native's `View`, `Text`, and `TouchableOpacity` are exposed to you, they can be directly used.

```js
styled.View({ flex: 1 })
styled.Text({ color: 'blue' })
styled.Touchable({ padding: 10 })

// equivalent to
styled(View)({ flex: 1 })
styled(Text)({ color: 'blue' })
styled(TouchableOpacity)({ padding: 10 })
```

### Dynamic styles

```js
const Foo = styled.View((props) => ({ padding: props.padded ? 10 : 0 }))

//
//
```

### Extending styles

```js
const Title = styled.Text({ fontSize: 20 })
//

const BoldTitle = Title.extend({ fontWeight: 'bold' })
//

const RedBoldTitle = BoldTitle.extend({ color: 'red' })
//

const RedHeadline = styled(RedBoldTitle)({ fontSize: 28 }) // this works too
```

### Custom props

```js
const Foo = styled.Text({ color: 'blue' }).attrs({ numberOfLines: 1 })
//

// attrs({ .. }) only overwrites the `defaultProps` of the component
// for dynamic props however we can pass it a function

const MyText = styled.Text({ color: 'red' }).attrs((props) => ({
numberOfLines: props.oneLiner ? 1 : 3
}))

// equivalent to
//
//
```

### Wrapping another component

```js
const Button = styled(TouchableOpacity)({ flex: 1 })
const HighlightedButton = Button.withComponent(TouchableHighlight)

// equivalent to
const Button = (props) =>

const HighlightedButton = (props) => (

)
```

### Wrapping a child

```js
const ButtonText = styled.Text({ color: 'blue' })
const Button = styled.Touchable({ flex: 1 }).withChild(ButtonText)

// equivalent to
const Button = ({ children, ...props }) => (

{children}

)

// to pass a ref to a child, use the `childRef` prop on the parent
// to pass custom props to a child, use `.withChild(Child, childProps)`
const CardText = styled.Text({ color: 'blue' })
const Card = styled.View({ flex: 1 }).withChild(CardText, { numberOfLines: 3 })

// equivalent to
const Card = ({ children, childRef, ...props }) => (


{children}


)

// you can also access parent props by passing a function `.withChild(Child, (parentProps) => childProps)`
const Card = styled.View({ flex: 1 }).withChild(CardText, (parentProps) => ({
numberOfLines: parentProps.onLiner ? 1 : 3
}))

//
// {children}
//

//
// {children}
//
```

### Using refs

```js
const List = styled(FlatList)({ flex: 1 })

// based on React's forwardRef API (16.3.0)

// this.list.scrollTo({ y: 0 })
// or this.list.current.scrollTo({ y: 0 }) (with React.createRef)
```

### Using a custom display name for debugging

```js
styled(View, { name: 'YetAnotherView' })
```

Default display names are `styled(View)`, `styled(Text)`, `styled(Touchable)`, `styled(Component)`, etc.

### Using propTypes and defaultProps

```js
const Foo = styled.View({ flex: 1 })

Foo.propTypes = { .. }
Foo.defaultProps = { .. }
```

### Usage with React DOM

Shakl is internally decoupled from React Native and can be used in the DOM.

```js
import styled from 'shakl'

// no exposed primitives however, feel free to add your own
const styled.div = styled('div')

const Foo = styled.div({ background: '#eee' })

//


```

[![Edit shakl](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/52kw0jrn94?module=%2Fsrc%2FExample.js)

### Testing with Jest

Since Shakl supports both React Native and the DOM, we need to explicitly tell Jest that we are testing for React Native, otherwise it will test against the DOM by default, which causes exposed primitives to fail (`.. shakl.default.View is not a function ..` error).

```js
// add the follwing to your Jest configuration when testing for React Native
"moduleNameMapper": {
"shakl": "/node_modules/shakl/lib/rn.js"
}
```