Last active
December 16, 2022 14:32
-
-
Save dannyhw/92b3ff0d6ccaead9df2820a507154b87 to your computer and use it in GitHub Desktop.
React native storybook alpha v6 Expo setup
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
set -e | |
APP_NAME=${1:-RNStorybookAlpha} | |
echo "APP_NAME: $APP_NAME" | |
npm install --global expo-cli | |
expo init -t expo-template-blank-typescript $APP_NAME | |
cd $APP_NAME | |
expo install @storybook/react-native@next \ | |
@storybook/addon-ondevice-actions@next \ | |
@storybook/addon-ondevice-controls@next \ | |
@storybook/addon-ondevice-backgrounds@next \ | |
@storybook/addon-ondevice-notes@next \ | |
@storybook/[email protected] \ | |
@storybook/[email protected] \ | |
@react-native-async-storage/async-storage \ | |
@react-native-community/datetimepicker \ | |
@react-native-community/slider | |
echo "const { getDefaultConfig } = require('expo/metro-config'); | |
const defaultConfig = getDefaultConfig(__dirname); | |
defaultConfig.resolver.resolverMainFields = [ | |
'sbmodern', | |
...defaultConfig.resolver.resolverMainFields, | |
]; | |
defaultConfig.transformer.getTransformOptions = async () => ({ | |
transform: { | |
experimentalImportSupport: false, | |
inlineRequires: false, | |
}, | |
}); | |
defaultConfig.watchFolders = [...defaultConfig.watchFolders, './.storybook']; | |
module.exports = defaultConfig; | |
" > metro.config.js; | |
mkdir .storybook | |
mkdir components | |
echo "module.exports = { | |
stories: [ | |
'../components/**/*.stories.?(ts|tsx|js|jsx)' | |
], | |
addons: [ | |
'@storybook/addon-ondevice-notes', | |
'@storybook/addon-ondevice-controls', | |
'@storybook/addon-ondevice-backgrounds', | |
'@storybook/addon-ondevice-actions', | |
], | |
};" > .storybook/main.js | |
echo "import {withBackgrounds} from '@storybook/addon-ondevice-backgrounds'; | |
export const decorators = [withBackgrounds]; | |
export const parameters = { | |
backgrounds: [ | |
{name: 'plain', value: 'white', default: true}, | |
{name: 'warm', value: 'hotpink'}, | |
{name: 'cool', value: 'deepskyblue'}, | |
], | |
};" > .storybook/preview.js | |
echo "import { getStorybookUI } from '@storybook/react-native'; | |
import './storybook.requires'; | |
const StorybookUIRoot = getStorybookUI({}); | |
export default StorybookUIRoot;" > .storybook/Storybook.tsx | |
echo "import StorybookUIRoot from './.storybook/Storybook'; | |
export { StorybookUIRoot as default };" > App.tsx | |
node -e 'const fs = require("fs"); | |
const packageJSON = require("./package.json"); | |
packageJSON.scripts = { | |
...packageJSON.scripts, | |
prestart: "sb-rn-get-stories", | |
"storybook-watcher": "sb-rn-watcher" | |
}; | |
fs.writeFile("./package.json", JSON.stringify(packageJSON, null, 2), function writeJSON(err) { | |
if (err) return console.log(err); | |
console.log(JSON.stringify(packageJSON)); | |
console.log("writing to " + "./package.json"); | |
});'; | |
mkdir components/Button; | |
echo "import React from 'react'; | |
import {TouchableOpacity, Text, StyleSheet} from 'react-native'; | |
interface MyButtonProps { | |
onPress: () => void; | |
text: string; | |
} | |
export const MyButton = ({onPress, text}: MyButtonProps) => { | |
return ( | |
<TouchableOpacity style={styles.container} onPress={onPress}> | |
<Text style={styles.text}>{text}</Text> | |
</TouchableOpacity> | |
); | |
}; | |
const styles = StyleSheet.create({ | |
container: { | |
paddingHorizontal: 16, | |
paddingVertical: 8, | |
backgroundColor: 'violet', | |
}, | |
text: {color: 'black'}, | |
}); | |
" > components/Button/Button.tsx; | |
echo "import React from 'react'; | |
import {ComponentStory, ComponentMeta} from '@storybook/react-native'; | |
import {MyButton} from './Button'; | |
const MyButtonMeta: ComponentMeta<typeof MyButton> = { | |
title: 'MyButton', | |
component: MyButton, | |
argTypes: { | |
onPress: {action: 'pressed the button'}, | |
}, | |
args: { | |
text: 'Hello world', | |
}, | |
}; | |
export default MyButtonMeta; | |
type MyButtonStory = ComponentStory<typeof MyButton>; | |
export const Basic: MyButtonStory = args => <MyButton {...args} />; | |
" > components/Button/Button.stories.tsx | |
yarn sb-rn-get-stories |
@MiguelNiblock you can optionally export storybook in app.tsx based on a env variable for example. Also start-storybook is a web thing, in react native storybook is a component so you just put it in your app somewhere or optionally export it from app.tsx as the main ui and then run your app as normal like yarn ios etc. You could look at the way ignite does it, they use the dev menu to toggle it for example.
Need to change default CLI option for background addon as
echo "import {withBackgrounds} from '@storybook/addon-ondevice-backgrounds';
export const decorators = [withBackgrounds];
export const parameters = {
backgrounds: {
default: 'plain',
values: [
{ name: 'plain', value: 'white' },
{ name: 'warm', value: 'hotpink' },
{ name: 'cool', value: 'deepskyblue' },
],
},
};" > .storybook/preview.js
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I tried modifying the
expo start
command by providing the path to the ./.storybook/Storybook file, but expo only allows starting the project from one specific App.tsx file. expo/expo-cli#4091 (comment)