React Native Storybook for Vega

Storybook 9 for Vega!

So Iโ€™ve been working on making a lite version of the storybook ui that can work in more places and as a result of that its now possible to run react native storybook on Vega. You can even build your own UI and pass it to the customui propery if you donโ€™t like my version :grinning_face_with_smiling_eyes:.

There is still some rough edges and any help to better support TV is appreciated.
You will find that there are more libraries included than you might expect and thats because of a limitation around the metro version that doesnโ€™t work with optional requires. However this can improve over time.

How?

Follow these steps:

1. Generate a new project if you donโ€™t have one

kepler project generate --template ksAppV0.72 --name keplersampleapp --packageId com.amazondeveloper.keplersampleapp --outputDir keplerstorybook

2. Add storybook

npm create storybook@latest -- --yes --type react_native --package-manager npm

Now add the lite mode UI package for better compatibility with Vega and the async storage package:

npm i -D @storybook/react-native-ui-lite @amzn/react-native-async-storage__async-storage

3. update metro config

Update metro config with the following:

const {getDefaultConfig, mergeConfig} = require('@react-native/metro-config');

const defaultConfig = getDefaultConfig(__dirname);
/**
 * Metro configuration
 * https://facebook.github.io/metro/docs/configuration
 *
 * @type {import('metro-config').MetroConfig}
 */
const config = {
  resolver: {
    // ๐Ÿ‘‡ add this
    unstable_enablePackageExports: true,
    sourceExts: [...defaultConfig.resolver.sourceExts, 'mjs'],
  },
};

const finalConfig = mergeConfig(defaultConfig, config);

// ๐Ÿ‘‡ add this
const withStorybook = require('@storybook/react-native/metro/withStorybook');

// ๐Ÿ‘‡ add this
module.exports = withStorybook(finalConfig, {
  docTools: false, // important to set this to false otherwise code not compatible with Vega will be added
});

Note if your project doesnโ€™t work with package exports enabled you wonโ€™t be able to use storybook without some workarounds. This is because custom resolvers are not supported in the current version of metro used by kepler.

4. Update storybook config

update .rnstorybook/index.tsx

// .rnstorybook/index.tsx
import {view} from './storybook.requires';
// ๐Ÿ‘‡ add this instead of the @react-native-async-storage/async-storage
import AsyncStorage from '@amzn/react-native-async-storage__async-storage'; 

 // ๐Ÿ‘‡ add this
import {LiteUI} from '@storybook/react-native-ui-lite';


const StorybookUIRoot = view.getStorybookUI({
  // ๐Ÿ‘‡ add this
  storage: {
    getItem: AsyncStorage.getItem,
    setItem: AsyncStorage.setItem,
  };
  CustomUIComponent: LiteUI, // ๐Ÿ‘ˆ add this
});

export default StorybookUIRoot;

5. Update generate script

update to have the -D flag which disables doctools which are unsupported currently in kepler

"scripts": {
   "storybook-generate": "sb-rn-get-stories -D"
}

6. Add storybook to your app entry point

You might want to conditionally load storybook based on an environment variable or some other condition, but to quickly get running we will just load it directly.
In your app entry point App.tsx add the StorybookUI component:

import React from 'react';
import {View} from 'react-native';
// ๐Ÿ‘‡ add this
import StorybookUI from '../.rnstorybook';

const fill = {flex: 1};

export const App = () => {
  return (
    <View style={fill}>
       {/* ๐Ÿ‘‡ add this  */}
      <StorybookUI />
    </View>
  );
};

7. Run storybook

Now run Vega as normal, you can also logic to switch between storybook and your app or add it in a separate route.

Thank you!

please feel free to give feedback and I hope its useful to some of you :slight_smile:

for general guidance on react native storybook checkout Getting started | React Native Storybook