mirror of
https://github.com/zhigang1992/storybook-bug-reproduce.git
synced 2026-01-12 22:41:59 +08:00
Initial commit
Generated by create-react-native-app 3.5.1.
This commit is contained in:
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
/storybook-static
|
||||
node_modules
|
||||
.expo
|
||||
8
.storybook/main.js
Normal file
8
.storybook/main.js
Normal file
@@ -0,0 +1,8 @@
|
||||
module.exports = {
|
||||
stories: ["../stories/*"],
|
||||
addons: [
|
||||
"@storybook/addon-links",
|
||||
"@storybook/addon-actions",
|
||||
"@storybook/addon-essentials",
|
||||
],
|
||||
};
|
||||
6
.storybook/webpack.config.js
Normal file
6
.storybook/webpack.config.js
Normal file
@@ -0,0 +1,6 @@
|
||||
const { resolve } = require("path");
|
||||
const { withUnimodules } = require("@expo/webpack-config/addons");
|
||||
|
||||
module.exports = ({ config }) => {
|
||||
return withUnimodules(config, { projectRoot: resolve(__dirname, "../") });
|
||||
};
|
||||
13
App.tsx
Normal file
13
App.tsx
Normal file
@@ -0,0 +1,13 @@
|
||||
import { configure, getStorybookUI } from "@storybook/react-native";
|
||||
|
||||
configure(() => {
|
||||
// Since require.context doesn't exist in metro bundler world, we have to
|
||||
// manually import files ending in *.stories.js
|
||||
require("./stories");
|
||||
}, module);
|
||||
|
||||
export default getStorybookUI({
|
||||
// Pass AsyncStorage below if you want Storybook to open your
|
||||
// last visited story after you close and re-open your app
|
||||
asyncStorage: null
|
||||
});
|
||||
127
README.md
Normal file
127
README.md
Normal file
@@ -0,0 +1,127 @@
|
||||
# Storybook Example
|
||||
|
||||
<p>
|
||||
<!-- iOS -->
|
||||
<img alt="Supports Expo iOS" longdesc="Supports Expo iOS" src="https://img.shields.io/badge/iOS-4630EB.svg?style=flat-square&logo=APPLE&labelColor=999999&logoColor=fff" />
|
||||
<!-- Android -->
|
||||
<img alt="Supports Expo Android" longdesc="Supports Expo Android" src="https://img.shields.io/badge/Android-4630EB.svg?style=flat-square&logo=ANDROID&labelColor=A4C639&logoColor=fff" />
|
||||
<!-- Web -->
|
||||
<img alt="Supports Expo Web" longdesc="Supports Expo Web" src="https://img.shields.io/badge/web-4630EB.svg?style=flat-square&logo=GOOGLE-CHROME&labelColor=4285F4&logoColor=fff" />
|
||||
</p>
|
||||
|
||||
<img alt="expo examples" src="https://i.imgur.com/j253BeR.png">
|
||||
|
||||
You can use Storybook to test and share your component library quickly and easily! This example shows how to use Expo modules with Storybook CLI and Expo CLI.
|
||||
|
||||
## Running with Storybook CLI
|
||||
|
||||

|
||||
|
||||
> web only
|
||||
|
||||
This method runs your Expo components in a Storybook-React environment. This is different to Expo web, but may prove helpful as the Storybook-React community is more robust than the Storybook-React Native community.
|
||||
|
||||
- Create Expo project `expo init my-project`
|
||||
- You can use any template, we'll use the managed blank TypeScript project for this example.
|
||||
- `cd` into the project and run `npx -p @storybook/cli sb init --type react` to bootstrap a new React project
|
||||
- Install the expo webpack config so we can add unimodules support `yarn add -D @expo/webpack-config`
|
||||
- Create a [custom webpack config](./.storybook/webpack.config.js) `touch .storybook/webpack.config.js`
|
||||
|
||||
```js
|
||||
const { resolve } = require("path");
|
||||
const { withUnimodules } = require("@expo/webpack-config/addons");
|
||||
|
||||
module.exports = ({ config }) => {
|
||||
return withUnimodules(config, { projectRoot: resolve(__dirname, "../") });
|
||||
};
|
||||
```
|
||||
|
||||
- Run `yarn add -D @expo/webpack-config` to get the webpack-config added.
|
||||
|
||||
- Run `yarn web` to try it out!
|
||||
- The example should open to `http://localhost:6006/`
|
||||
- You may also want to add `storybook-static` to your `.gitignore`
|
||||
|
||||
### 📁 File Structure
|
||||
|
||||
```
|
||||
Expo with Storybook CLI
|
||||
├── stories
|
||||
│ └── Example.stories.js ➡️ A Storybook page to render
|
||||
├── .storybook
|
||||
│ ├── config.js ➡️ The entry point / config for a typical Storybook project.
|
||||
│ └── webpack.config.js ➡️ The custom Webpack config used to add Expo support to Storybook CLI.
|
||||
├── assets ➡️ All static assets for your project
|
||||
├── storybook-static ➡️ Generated Storybook files (should be ignored)
|
||||
└── babel.config.js ➡️ Babel config (should be using `babel-preset-expo`)
|
||||
```
|
||||
|
||||
## Running with Expo CLI
|
||||
|
||||
<img alt="storybook with expo-cli" src="https://i.imgur.com/Fpubaor.png">
|
||||
|
||||
> This method is universal :]
|
||||
|
||||
This project can be used for iOS, Android, and web! You may find that it's better to use it for native only, and to use the "Running with Storybook" method for web. Unlike the Expo + Next.js flow, you can use both web methods at the same time!
|
||||
|
||||
- Create Expo project `expo init my-project`
|
||||
- You can use any template, we'll use the managed blank TypeScript project for this example.
|
||||
- `cd` into the project and run `npx -p @storybook/cli sb init --type react` to bootstrap a new React project.
|
||||
- Install the Storybook React Native package:
|
||||
- `yarn add -D @storybook/react-native`
|
||||
- In your `App.tsx` or `App.js`
|
||||
|
||||
```ts
|
||||
import { configure, getStorybookUI } from "@storybook/react-native";
|
||||
|
||||
configure(() => {
|
||||
// Since require.context doesn't exist in metro bundler world, we have to
|
||||
// manually import files ending in *.stories.js
|
||||
require("./stories");
|
||||
}, module);
|
||||
|
||||
export default getStorybookUI();
|
||||
```
|
||||
|
||||
- Create a file for importing all of the stories ([`stories/index.js`](./stories/index.js)):
|
||||
|
||||
- `touch stories/index.js`
|
||||
- Import all of your stories in this file. Ex:
|
||||
|
||||
```js
|
||||
// stories/index.js
|
||||
import "./1-Button.stories";
|
||||
```
|
||||
|
||||
- Register your stories for React Native:
|
||||
|
||||
```diff
|
||||
// Example.stories.js
|
||||
+ import { storiesOf } from '@storybook/react-native';
|
||||
|
||||
export const text = () => ( /_ Example JSX _/ );
|
||||
|
||||
// Register your story with the `module`, name, and React functional component.
|
||||
|
||||
+ storiesOf('Button', module).add('Text', text);
|
||||
|
||||
```
|
||||
|
||||
- Now run `expo start` to see it in action!
|
||||
|
||||
### 📁 File Structure
|
||||
|
||||
```
|
||||
Storybook with Expo CLI
|
||||
├── stories
|
||||
│ ├── index.js ➡️ Native story imports
|
||||
│ └── Example.stories.js ➡️ A Storybook page to render
|
||||
├── assets ➡️ All static assets for your project
|
||||
├── App.tsx ➡️ Entry Point for universal Expo apps
|
||||
├── app.config.js ➡️ Expo config file
|
||||
└── babel.config.js ➡️ Babel config (should be using `babel-preset-expo`)
|
||||
```
|
||||
|
||||
## 📝 Notes
|
||||
|
||||
- [Storybook React Native](https://storybook.js.org/docs/guides/guide-react-native/)
|
||||
BIN
assets/retro-regular.ttf
Executable file
BIN
assets/retro-regular.ttf
Executable file
Binary file not shown.
6
babel.config.js
Normal file
6
babel.config.js
Normal file
@@ -0,0 +1,6 @@
|
||||
module.exports = function(api) {
|
||||
api.cache(true);
|
||||
return {
|
||||
presets: ['babel-preset-expo'],
|
||||
};
|
||||
};
|
||||
35
package.json
Normal file
35
package.json
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"scripts": {
|
||||
"start": "expo start",
|
||||
"android": "expo start --android",
|
||||
"ios": "expo start --ios",
|
||||
"web": "start-storybook -p 6006",
|
||||
"eject": "expo eject",
|
||||
"build-storybook": "build-storybook"
|
||||
},
|
||||
"dependencies": {
|
||||
"expo": "~38.0.0",
|
||||
"expo-constants": "~9.1.1",
|
||||
"expo-font": "~8.2.1",
|
||||
"expo-linear-gradient": "~8.2.1",
|
||||
"react": "~16.11.0",
|
||||
"react-dom": "~16.11.0",
|
||||
"react-native": "https://github.com/expo/react-native/archive/sdk-38.0.2.tar.gz",
|
||||
"react-native-web": "0.11.7"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "7.9.0",
|
||||
"@expo/webpack-config": "^0.11.11",
|
||||
"@storybook/addon-actions": "^6.0.21",
|
||||
"@storybook/addon-essentials": "^6.0.21",
|
||||
"@storybook/addon-links": "^6.0.21",
|
||||
"@storybook/client-api": "^6.0.21",
|
||||
"@storybook/react": "^6.0.21",
|
||||
"@types/react": "~16.9.41",
|
||||
"@types/react-dom": "~16.9.8",
|
||||
"@types/react-native": "~0.62.13",
|
||||
"babel-loader": "^8.0.6",
|
||||
"typescript": "^3.7.2"
|
||||
},
|
||||
"private": true
|
||||
}
|
||||
14
stories/0-Welcome.stories.js
Normal file
14
stories/0-Welcome.stories.js
Normal file
@@ -0,0 +1,14 @@
|
||||
import React from 'react';
|
||||
import { linkTo } from '@storybook/addon-links';
|
||||
import { Welcome } from '@storybook/react/demo';
|
||||
|
||||
export default {
|
||||
title: 'Welcome',
|
||||
};
|
||||
|
||||
export const toStorybook = () => <Welcome showApp={linkTo('Button')} />;
|
||||
|
||||
toStorybook.story = {
|
||||
name: 'to Storybook',
|
||||
};
|
||||
|
||||
13
stories/1-Button.stories.js
Normal file
13
stories/1-Button.stories.js
Normal file
@@ -0,0 +1,13 @@
|
||||
import React from 'react';
|
||||
import { action } from '@storybook/addon-actions';
|
||||
import { Button } from 'react-native';
|
||||
|
||||
export default {
|
||||
title: 'Button',
|
||||
};
|
||||
|
||||
export const text = () => (
|
||||
<Button title="Hello Button" onPress={action('clicked')} />
|
||||
);
|
||||
|
||||
// On-Device Register
|
||||
12
stories/2-Constants.stories.js
Normal file
12
stories/2-Constants.stories.js
Normal file
@@ -0,0 +1,12 @@
|
||||
import React from 'react';
|
||||
import Constants from 'expo-constants';
|
||||
import { Text } from 'react-native';
|
||||
|
||||
export default {
|
||||
title: 'Constants',
|
||||
};
|
||||
|
||||
export const constants = () => (
|
||||
<Text>{JSON.stringify(Constants, null, 2)}</Text>
|
||||
);
|
||||
|
||||
15
stories/3-LinearGradient.stories.js
Normal file
15
stories/3-LinearGradient.stories.js
Normal file
@@ -0,0 +1,15 @@
|
||||
import React from 'react';
|
||||
import { LinearGradient } from 'expo-linear-gradient';
|
||||
|
||||
export default {
|
||||
title: 'LinearGradient',
|
||||
};
|
||||
|
||||
export const linearGradient = () => (
|
||||
<LinearGradient
|
||||
style={{ flex: 1, height: 200 }}
|
||||
colors={['red', 'blue', 'yellow']}
|
||||
/>
|
||||
);
|
||||
|
||||
// On-Device Register
|
||||
35
stories/4-Font.stories.js
Normal file
35
stories/4-Font.stories.js
Normal file
@@ -0,0 +1,35 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import * as Font from 'expo-font';
|
||||
import { Text } from 'react-native';
|
||||
|
||||
export default {
|
||||
title: 'Font',
|
||||
};
|
||||
|
||||
export const CustomFontComponent = () => {
|
||||
const [loaded, setLoaded] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
await Font.loadAsync({
|
||||
'retro-regular': require('../assets/retro-regular.ttf')
|
||||
});
|
||||
setLoaded(true);
|
||||
})();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
loaded && (
|
||||
<Text
|
||||
style={{
|
||||
fontFamily: 'retro-regular',
|
||||
backgroundColor: 'transparent',
|
||||
fontSize: 56,
|
||||
color: '#000'
|
||||
}}
|
||||
>
|
||||
Cool new font
|
||||
</Text>
|
||||
)
|
||||
);
|
||||
}
|
||||
4
stories/index.js
Normal file
4
stories/index.js
Normal file
@@ -0,0 +1,4 @@
|
||||
import './1-Button.stories';
|
||||
import './2-Constants.stories';
|
||||
import './3-LinearGradient.stories';
|
||||
import './4-Font.stories';
|
||||
11
tsconfig.json
Normal file
11
tsconfig.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"jsx": "react-native",
|
||||
"lib": ["dom", "esnext"],
|
||||
"moduleResolution": "node",
|
||||
"noEmit": true,
|
||||
"skipLibCheck": true,
|
||||
"resolveJsonModule": true
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user