Skip to content

Instantly share code, notes, and snippets.

@dannyhw
Last active December 16, 2022 14:32
Show Gist options
  • Save dannyhw/92b3ff0d6ccaead9df2820a507154b87 to your computer and use it in GitHub Desktop.
Save dannyhw/92b3ff0d6ccaead9df2820a507154b87 to your computer and use it in GitHub Desktop.
React native storybook alpha v6 Expo setup
#!/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/addon-actions@6.3 \
@storybook/addon-controls@6.3 \
@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
@dannyhw
Copy link
Author

dannyhw commented Sep 11, 2021

You can pass an argument to choose your app name like setup_expo_rn_sb.sh AppName

@wjramos
Copy link

wjramos commented Dec 3, 2021

Do you happen to have a lockfile that you can share? There seems to be some issues testing rn storybook 6 because of too lax of dependencies

@dannyhw
Copy link
Author

dannyhw commented Dec 4, 2021

@wjramos I'll run it myself and see what result I get. Will let you know.

@dannyhw
Copy link
Author

dannyhw commented Dec 4, 2021

@wjramos storybook 6.4 support is currently being worked on so I recommend downgrading to 6.3 and that should fix any issues you currently have.


EDIT

Well actually I might need to update the peer dependencies, will check

@dannyhw
Copy link
Author

dannyhw commented Dec 4, 2021

@wjramos I've updated the dependency to be more strict now and it shouldn't install 6.4.

Unfortunately 6.4 has a lot of breaking changes for react native so it might take some time to make it compatible

@wjramos
Copy link

wjramos commented Dec 6, 2021

Thank you for the quick response! Going to try it out now

@MiguelNiblock
Copy link

@dannyhw I'm trying to set up storybook in my existing expo project. The problem I had with these directions is they're intended to replace the current App.tsx, so as to make your entire expo project become a storybook project. I want to add storybook to my existing app, not replace my existing app. The template adds a yarn storybook stript in package.json for this, but that doesn't work here because it uses "storybook": "start-storybook -p 6006",. Im new to storybook so I don't know where that start-storybook is supposed to come from. Could you help with setting that up????? I think most people who use expo will find this valuable since storybook can be used to test the components used in a larger app.

@MiguelNiblock
Copy link

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)

@dannyhw
Copy link
Author

dannyhw commented Jun 19, 2022

@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.

@JeffGuKang
Copy link

JeffGuKang commented Dec 16, 2022

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

storybookjs/react-native#413

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment