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

https://github.com/murat-mehmet/react-native-design-mode

A Lightweight Storybook Alternative for Effortless View Design.
https://github.com/murat-mehmet/react-native-design-mode

alternative design react-native storybook

Last synced: 11 months ago
JSON representation

A Lightweight Storybook Alternative for Effortless View Design.

Awesome Lists containing this project

README

          

# 🛠️ React Native Design Mode - Simplify Creating Views

[![npm version](https://badge.fury.io/js/react-native-design-mode.svg)](https://badge.fury.io/js/react-native-design-mode)
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)


A Lightweight Storybook Alternative for Effortless View Design.





# Table of Contents

1. 📄 [Description](#-description)
2. 🚀 [Features](#-features)
3. ⚙ [Installation](#-installation)
4. 🏁 [Getting Started](#-getting-started)
5. 💡 [Usage](#-usage)
- 🎨 [Creating Designs](#-creating-designs)
- 🔄 [Moving Between Designs](#-moving-between-designs)
- 🔧 [Creating Designs with Variants](#-creating-designs-with-variants)
- 📁 [Categorized List View](#-categorized-list-view)
- 🎈 [Draggable Floating Button](#-draggable-floating-button)
6. ⚙ [Configuration](#-configuration)
- 📄 [`main.js`](#-mainjs)
- 📄 [`index.js`](#-indexjs)
- 📄 [`designer.requires.js`](#-designerrequiresjs)
- 📄 [`preview.js`](#-previewjs)
7. 👊 [Contributing](#-contributing)
8. 📛 [License](#-license)
9. 📧 [Contact](#-contact)

## 📄 Description
React Native Design Mode is a developer-friendly package that streamlines the process of creating views without the need to navigate through the entire app flow. If you've found Storybook to be a bit heavy for your simple projects, this package offers a lightweight alternative with all the features you need.

Heavily inspired by storybook project so most things are similar.

## 🚀 Features

- Effortless design mode toggle with a floating button
- Allows developer to focus more on quickly designing views
- Lightweight and efficient implementation
- Familiar structure that is inspired by Storybook

## ⚙ Installation

You can install the package via npm or yarn:

```bash
npm install react-native-design-mode
# or
yarn add react-native-design-mode
```

## 🏁 Getting Started
Run CLI to quickly install designer into your project.
```bash
designer install
```

It does two things:
1. Creates a `.designer` folder in your project root with required files in it.
2. Adds `designer update` command to the prestart script.
+ Note:
You can use `-c` flag to change the designer folder. Run `designer help install` for details.

After running the command you will have the following folder structure
```
├── project root
│ └── 📁 .designer
│ ├── 📄 designer.requires.js
│ ├── 📄 index.js
│ ├── 📄 main.js
│ └── 📄 preview.js
```
## 💡 Usage
Import the designer file
```js
import Designer from "./.designer";
```
Add `Designer` component in your `App.tsx`
```jsx
const App = () => {
return (
<>




>
);
}
```
Or use it directly in your `index.js` file
```js
AppRegistry.registerComponent(appName, () => Designer);
```

#### Now you are ready to create your first design!

### 🎨 Creating designs
Imagine you have a `Login.tsx` screen that you want to design.

To achieve this, all you have to do is create a new file named `Login.design.tsx` right next to the `Login.tsx`.
```typescript jsx
// src/Login.design.tsx

import Login from './Login';

export default {
title: 'Login',
component: Login,
}
```
Once you've added the new design file, you'll need to update the design list.

You can do this in two ways:
- Use the command-line interface (CLI) to manually update the list. (Recommended)
```bash
designer update
```
- Restart the bundler, which will automatically trigger the prestart script
```bash
npm start
```

Great news! You're all set! Open the app, and you'll see the Login screen right in design mode. Now you can start designing and refining the layout with ease.

### 🔄 Moving between designs

While we are on the design selection screen, floating button works like a toggle to switch design mode on/off.

After you select a design, we can click on floating button to go back to design list.




### 🔧 Creating designs with variants

We can easily create different variants of a design by exporting more design objects.
```typescript jsx
// src/Login.design.tsx

import Login from './Login';

export default {
title: 'Login',
component: Login,
}

// export default variant
export const Basic = {}

// export another variant
export const Dark = () =>
```

### 📁 Categorized list view

We can categorize our views infinitely by adding group names in titles



```typescript jsx
// src/Login.design.tsx

import Login from './Login';

export default {
title: 'Authentication/Login',
component: Login,
}
```

### 🎈 Draggable floating button

We have the flexibility to position the floating button on the screen edges, ensuring it won't obstruct our view design process.




- Note: To make the floating button draggable on android,
make sure you use either `GestureHandlerRootView` or `gestureHandlerRootHOC`. Check [installation docs for RNGH](https://docs.swmansion.com/react-native-gesture-handler/docs/installation#js)

## ⚙ Configuration
### 📄 `main.js`
```js
module.exports = {
designs: ["../src/**/*.design.@(js|jsx|ts|tsx)"],
};
```
- `designs`: This is an array that defines the location of our design files. By default, we use a glob pattern to load all *.design.js files inside the src directory and its subdirectories. You may need to adjust the path based on your project structure.
- `excludePaths`: This is an array of path patterns that will be excluded from loading. By default it is `['**/node_modules']`

### 📄 `index.js`
```js
import { getDesignModeUI } from "react-native-design-mode";

if (__DEV__) {
require('./designer.requires');
}

const Designer = getDesignModeUI();

export default Designer;
```
All designs are imported here. Designs are stripped out by bundler when building for production so you dont have to worry about it.

### 📄 `designer.requires.js`
```js
/* do not change this file, it is auto generated by design mode. */

import { context } from "react-native-design-mode";

context.initialize();
// ...
```
This is an auto generated file by `design update` command which will be automatically executed on every `npm run start`.

It is imported in `.designer/index.js` and contains all designs of your project.

You shouldn't modify this file as it will be overwritten.

### 📄 `preview.js`
```js
import React from "react";
import { SafeAreaProvider } from "react-native-safe-area-context";

export const decorators = [
// Add SafeAreaProvider to all designs
(Component, ctx) => (



),
];
```
This file is completely optional but it will help us create global declarations for all of our designs.
- `decorators`: This is an array of functions of Elements or Components that will be applied on every design.
We can use it to create wrappers like `SafeAreaProvider` or `Navigator`

Check this example where we apply navigator conditionally.
```js
// .designer/preview.js

const Stack = createStackNavigator();

export const decorators = [
(Component, ctx) => {
if (ctx.parameters.withNavigation)
return (





);
return Component;
},
];

// src/Login.design.tsx

export default {
title: "Login",
component: Login,
parameters: {
withNavigation: true
}
};
```
- `parameters`: Global parameters that will be applied on all designs.
#### Parameter: `designer`
This is a special parameter which can config features of our designer.
Currently there is only one feature:

##### Theme Switcher

To enable theme switcher feature, add a `themeSwitcher` parameter like in example:
```js
export const parameters = {
designer: {
themeSwitcher: {
set: (ctx, value) => {
// here you can set your theme
// value is true for dark, false for light
},
value: false, // initial value
}
}
}

```

- `loaders`: This is an object of promise functions that will be executed before displaying any design. The loaded results can be accessed from `ctx.loaded` field.

Example
```js
// .designer/preview.js

export const loaders = {
stores: async () => getStores(),
};

// example of accesing "loaded" field in decorators
export const decorators = [
(Component, ctx) => {
return (
{/* <-- */}


);
},
];

// src/Login.design.tsx

// example of accessing "loaded" field in designs
export default {
title: "Login",
component: Login,
prepare: (ctx) => {
// Do something with ctx.loaded.stores
}
};
```

## 👊 Contributing
Contributions are welcome! If you find a bug or want to add a new feature, feel free to submit a pull request. For major changes, please open an issue first to discuss the proposed changes.

## 📛 License
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.

## 📧 Contact
If you have any questions or need assistance, feel free to open an issue.

Happy coding!