Git Product home page Git Product logo

native's Introduction

Storybook Native

All Contributors

Storybook Native is an extension of the normal web storybook that uses appetize.io to render your mobile application in an emulator that can be interacted with from your browser. It allows you to use many of the features that are available in the web storybook, such as addons, controls, etc.

It also supports using Storybook as a local development environment to develop Android and iOS apps/components, without the need for using appetize.io.

Installation

Before using this, ensure that you have installed NodeJS

If you want to use this module to render an emulator as a React component, follow the instructions here. This is recommended if you are already familiar with React and Storybook, or if you want to use features such as addons and controls.

If you want to use this module as a build tool that generates stories from metadata, follow the instructions here. This package supports limited variations of controls generation. This is recommended if you do not want to write any React code, and you will only have to write some basic JavaScript code. If you use this package, you will not have to install any extra Storybook dependencies, as they will already be included.

Configuring your mobile application

Before using this module, your mobile application must be set up to support switching between stories. There are detailed instructions on this here

Uploading your mobile application

After you have modified your application to support launch parameters or query parameters, you must upload your application to appetize.io. After the upload, you will receive a public key that can be used with Storybook Native to view and interact with your application directly from Storybook.

Setting up Storybook

Once your application is uploaded to appetize.io, you can begin setting up Storybook Native. The details for this can be found here

Examples

Examples of how to use this module as both a build tool and as a component library can be found in the examples folder. The app folder inside each example contains the source code of the application the example is for.

More example static storybooks can be found here

Local app development

Details on how to test changes that you make to your mobile application to support features such as controls can be found here

Migrating from version 1 to version 2

A full migration guide for breaking changes can be found here

Development in this repo

  • Clone this repo
  • Run yarn to install dependencies
  • yarn build && cd examples/flutter && yarn start
  • In a new tab, run yarn build whenever changes are made to any of the packages inside of the packages/ folder

Contributors โœจ

Thanks goes to these wonderful people (emoji key):


Michael Shilman

๐Ÿ“–

Adil Malik

๐Ÿ’ป ๐Ÿ“– ๐Ÿ’ก

Raj Vasikarla

๐Ÿ“– ๐Ÿ’ป

imgbot[bot]

๐Ÿ’ป

brocollie08

๐Ÿ“– ๐Ÿ’ป

Harris Borawski

๐Ÿ’ป

Josh Halvorson

๐Ÿ’ป

daisyduong-acc

๐Ÿ’ป

Ahmed na

๐Ÿ“– ๐Ÿ’ป ๐Ÿ’ก

osquitoOfTheNorth

๐Ÿ’ป

This project follows the all-contributors specification. Contributions of any kind welcome!

native's People

Contributors

ahna92 avatar amalik2 avatar brocollie08 avatar daisyduong-acc avatar hborawski avatar imgbot[bot] avatar joshhalvorson avatar osquitoofthenorth avatar shilman avatar sumwatshade avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

native's Issues

Possiblity to use storybook with expo and ios device

As I understand the native storybook needs an emulator to work / display stories.
Is there any possibility to use an actual ios device (like for example the expo->iOS functionality) to get the storybook to work?

Interact with apps on local emulator by specifying URL to their file

Ideally, create a desktop app associated with a specific URL scheme that would be opened automatically. Useful for CI environments where canary versions of apps can be tested with storybook

Example:
sb-native://app?url=URL_TO_DOWNLOAD_APP
should download the mobile app from the URL query param, open the desktop app, and start storybook

[Bug] Stories are not rendering properly based off of example

Describe the bug

Running any story yields the following error. Including this story. I followed the instructions here and have set the proper environment variable for local simulation. I am not using appetize, I'd like to connect directly to the local simulator. I have deep linking working and I can manually use it directly from the commandline already.

could not find react-redux context value; please ensure the component is wrapped in a <Provider>
Error: could not find react-redux context value; please ensure the component is wrapped in a <Provider>
    at useReduxContext2 (http://localhost:4400/@fs/Users/michael/work/node_modules/.cache/sb-vite/deps/@storybook_native-components.js?v=dd971736:2814:11)
    at useStore3 (http://localhost:4400/@fs/Users/michael/work/node_modules/.cache/sb-vite/deps/@storybook_native-components.js?v=dd971736:2835:28)
    at useDispatch3 (http://localhost:4400/@fs/Users/michael/work/node_modules/.cache/sb-vite/deps/@storybook_native-components.js?v=dd971736:2856:17)
    at useAppDispatch (http://localhost:4400/@fs/Users/michael/work/node_modules/.cache/sb-vite/deps/@storybook_native-components.js?v=dd971736:3031:44)
    at WithStore (http://localhost:4400/@fs/Users/michael/work/node_modules/.cache/sb-vite/deps/@storybook_native-components.js?v=dd971736:55506:62)
    at renderWithHooks (http://localhost:4400/@fs/Users/michael/work/node_modules/.cache/sb-vite/deps/chunk-XXNDK2BK.js?v=dd971736:12171:26)
    at mountIndeterminateComponent (http://localhost:4400/@fs/Users/michael/work/node_modules/.cache/sb-vite/deps/chunk-XXNDK2BK.js?v=dd971736:14921:21)
    at beginWork (http://localhost:4400/@fs/Users/michael/work/node_modules/.cache/sb-vite/deps/chunk-XXNDK2BK.js?v=dd971736:15902:22)
    at beginWork$1 (http://localhost:4400/@fs/Users/michael/work/node_modules/.cache/sb-vite/deps/chunk-XXNDK2BK.js?v=dd971736:19749:22)
    at performUnitOfWork (http://localhost:4400/@fs/Users/michael/work/node_modules/.cache/sb-vite/deps/chunk-XXNDK2BK.js?v=dd971736:19194:20)
import { EmulatorRenderer } from "@storybook/native-components";
import type { Meta } from '@storybook/react';
import React from "react";

export const Example = (props) => {
  return (
    <EmulatorRenderer
      apiKey={'sdfsadfsdfsdfiojoisdf'}
      platform={'ios'}
      storyParams={{ component: "button" }}
      deepLinkBaseUrl="sb-native://deep.link"
    />
  );
};



const Story: Meta = {
  title: 'Components/Cards/ArticleCard',
  component: Example,
  parameters: {
    layout: 'fullscreen',
  },
  args: {
    apiKey: 'sdfsadfsdfsdfiojoisdf',
    platform: 'ios',
    storyParams: { component: "Components/Cards/ArticleCard" },
    deepLinkBaseUrl: "sb-native://deep.link"
  },
};

export default Story;

export const Primary = {}

main.ts

import type { StorybookConfig } from '@storybook/react-vite';

const config: StorybookConfig = {
  stories: ['../lib/**/*.stories.@(js|jsx|ts|tsx|mdx)'],
  framework: '@storybook/react-vite',
  core: {
    builder: '@storybook/builder-vite',
  },
  addons: [
    '@storybook/addon-essentials',
    "@storybook/addon-docs",
    "@storybook/addon-controls",
    "@storybook/native-addon",
    // "@storybook/native-addon/dist/register.js",
  ]
};

export default config;

middleware.ts

import { middleware } from '@storybook/native-dev-middleware';

export default middleware();

preview.ts

import { DeviceDecorator } from "@storybook/native-addon";

export const decorators = [DeviceDecorator];

Steps to reproduce the behavior

  1. Go to '...'
  2. Click on '....'
  3. Scroll down to '....'
  4. See error

Expected behavior

It should render something.

Screenshots and/or logs

If applicable, add screenshots and/or logs to help explain your problem.

Environment

  • OS: [e.g. iOS] iOS
  • Node.js version: [e.g. v12.17.0] v20.11.0
  • NPM version: [e.g. 6.14.4] 10.2.4
  • Browser (if applicable): [e.g. chrome, safari] chrome

Additional context

Add any other context about the problem here.

Add hot-reload dev command

Add a command that starts up a storybook for one of the examples, and also watches for changes in packages

[Bug] EmulatorRenderer always being placed at the bottom of page

Describe the bug

When using @storybook/native-components with Storybook, the EmulatorRenderer component consistently renders at the bottom of the documentation page, regardless of its position in the MDX or TSX file. This behavior persists even when trying to intersperse the emulator with documentation blocks, limiting the ability to structure interactive documentation effectively.

Steps to reproduce the behavior

  1. Create a Storybook story using @storybook/native-components.
  2. Use EmulatorRenderer in an MDX or TSX file.
  3. Attempt to intersperse Markdown or JSX documentation blocks before and after EmulatorRenderer.
  4. Observe that EmulatorRenderer always renders at the bottom of the page in the Storybook UI.

Expected behavior

The expected behavior is for the EmulatorRenderer to respect its position within the MDX or TSX file, allowing it to be placed between documentation blocks or in specific sections of the documentation page.

Code

import { Meta } from '@storybook/addon-docs/blocks';
import { EmulatorRenderer } from "@storybook/native-components";

<Meta title="Components/POC" />

# POC Component

This section introduces the POC component, providing context and overview information.

## POC Emulator Example

Below is the POC component rendered in the emulator:

<EmulatorRenderer
  apiKey="--------------------------"
  platform="ios"
  storyParams={{ component: "poc" }}
  deepLinkBaseUrl="sb-native://deep.link"
/>

## Detailed Explanation

After experiencing the POC component in the emulator, here's a detailed explanation of its features, usage guidelines, and other relevant information.

Screenshots and/or logs

Screen.Recording.2024-01-29.at.12.02.49.mov

Environment

  • OS: MacOS Sonoma 14.2.1
  • Node.js version: v18.16.0
  • NPM version: 9.5.1
  • Browser (if applicable): Chrome
  • Browser version (if applicable): 120.0.6099.234
  • Device (if applicable): Any

Additional context

This issue significantly impacts the ability to create structured and interactive documentation using Storybook with native components, particularly when trying to provide a guided experience that integrates interactive elements with explanatory text.

Support for SauceLabs Live

Because SauceLabs Live supports mobile devices in the browser (similar to appetize), is it possible to integrate with Storybook Native?

React 18+ support

Hi Team,
We are trying to shift our web/mobile component library to storybook native, our web codebase is on react 18+.
However, the storybook native is running on react 16+ which conflict with our react 18 version, do you have plans to upgrade react version to 18?

An example using React Native and Expo would be helpful

It would be very helpful in addition to the native demos with deep linking in Swift, etc. to have an example using React Native via Expo since it is such a common framework. I can help put one together, but I am still puzzling through the docs for this repo, how best to setup the deep linking configuration, and so on. If such an example already exists (either made by the maintainers of this project or if one is known from a blog post or other resource) it would be great to know about it.

Storybook OnDeviceUI integration

Hey folks! There is an exciting opportunity here to bridge the Storybook/Native solution with the pre-existing OnDeviceUI.
I didn't see this publicly documented anywhere, and thought it would be worth sharing so folks can get a picture of how the pieces could potentially fit together.

Native Side

  1. Create a standard React-Native project
  2. Mount in the Storybook React-Native bits: npx -p @storybook/cli sb init --type react_native

Note: Don't install @storybook/react-native-server. This is the older way of controlling the React-Native UI from the web via sockets.

  1. Extend the native apps to support Deep Linking (https://github.com/storybookjs/native/blob/master/APP-CONFIG.md#1-deep-linking)
  2. Extend the native code to support DeepLink forwarding into the React-Native DeviceEventManager
// Java example
package com.storybook;

import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import com.facebook.react.ReactActivity;
import com.facebook.react.modules.core.DeviceEventManagerModule;

public class MainActivity extends ReactActivity {

  /**
   * Returns the name of the main component registered from JavaScript. This is used to schedule
   * rendering of the component.
   */
  @Override
  protected String getMainComponentName() {
    return "storybook";
  }

  // Support the deep-link
  @Override
  public void onNewIntent(Intent intent) {
    super.onNewIntent(intent);

    String link = intent.getStringExtra("component");
    Uri data = intent.getData();

    // Post the deep-link to the device event manager
    try {
      // Note: Also forward the addition args
      getReactInstanceManager()
        .getCurrentReactContext()
        .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
        .emit("storybookDeepLink", data.getQueryParameter("component"));
    } catch (Exception e) {
      // ZARDOZ SPEAKS TO YOU
    }
  }
}
  1. NPM Patch @storybook/react-native to export the Preview instance. You want to be able to do import {preview} from '@storybook/react-native';
  2. Update the React-Native entry point to respond to the storybookDeepLink on the DeviceEventEmitter and seed in the story into the OnDeviceUI Preview:
import {preview} from '@storybook/react-native';
import {DeviceEventEmitter} from 'react-native';
...
const listener = function (deepLink: Event) {
  preview._selectStoryEvent({storyId: deepLink});
};
DeviceEventEmitter.addListener('storybookDeepLink', listener);
...

Web Side

  1. Install Storybook/native, including the Dev-middleware
  2. Build a story factory that helps facade the story across platform (will run on web and native using platform extension as strategy):
// @flow
import {storiesOf} from '@storybook/react-native';
import UnimoduleStoryRenderer from '../UnimoduleStoryRenderer';
import {toId} from '@storybook/csf';

export default ({
  kind,
  story,
  component,
}: {
  kind: string,
  story: string,
  component: any,
}) => {
  storiesOf(kind, module).add(story, () =>
    UnimoduleStoryRenderer({
      component,
      deepLinkPath: toId(kind, story),
    }),
  );
};

Note: the usage of toId to assure the deep-link is marshaled correctly

  1. Create a fancy platform specific implementation of the actual renderer:
// index.native.js
// @flow
import {Platform} from 'react-native';

export default ({component}: {component: any}) => {
  return component;
};

// index.web.js
// @flow
import React from 'react';
import {Platform, View} from 'react-native';
import {DeepLinkRenderer} from '@storybook/native-components';

export default ({
  extraParams,
  component,
  deepLinkPath,
}: {
  deepLinkPath: string,
  component: any,
  extraParams: any,
}) => {
  const isOsx = process.platform === 'darwin';
  const platforms = ['android'];
  if (isOsx) {
    platforms.push('ios');
  }
  return (
    <View>
      {component}
      {platforms.map(platform => {
        const [visible, setVisible] = React.useState(true);
        return (
            <DeepLinkRenderer
              apiKey=""
              platform={platform}
              storyParams={{component: deepLinkPath}}
              deepLinkBaseUrl="sb-native://deep.link"
              extraParams={extraParams}
              context={platform}
            />
        );
      })}
    </View>
  );
};

  1. Make sure to generate your stories using react-native-storybook-loader or the fancy new build tool from https://github.com/storybookjs/native
  2. Write your story:
UnimoduleStory({
  kind: 'Alert',
  story: 'default',
  component: (
    <View>
      <Button
        title={'Default'}
        onPress={() =>
          Alert.alert(
            'Alert Title',
            'My Alert Msg',
            [
              {
                text: 'Cancel',
                onPress: () => console.log('Cancel Pressed'),
                style: 'cancel',
              },
              {text: 'OK', onPress: () => console.log('OK Pressed')},
            ],
            {cancelable: false},
          )
        }
      />
    </View>
  ),
});

Additional resources

    "react-native": "0.63.2",
    "@storybook/addon-actions": "^5.3",
    "@storybook/addon-knobs": "^5.3",
    "@storybook/addon-links": "^5.3",
    "@storybook/addon-ondevice-actions": "^5.3.23",
    "@storybook/addon-ondevice-knobs": "^5.3.25",
    "@storybook/react-native": "^5.3.25",
    "@storybook/react": "^5.3.21",
    "@storybook/native-dev-middleware": "^2.2.0",
    "@storybook/native-components": "^2.2.0",
    "@storybook/native-addon": "^2.2.0",
    "@storybook/addon-docs": "^5.3.21",

This should give you an Interlinear experience where selecting stories on the web will in-turn select on ios/android.
๐Ÿ™‡๐Ÿฝโ€โ™‚๏ธ

Rename 'knobs' prop to something else

Currently we have an optional prop called knobs that is included in renderer components for convenience. Since knobs are deprecated by Storybook now, this should be renamed something else. This will be a breaking change so it would probably be a good idea to make this change after Storybook v7 is released

"App not found, please verify URL" when attempting to install native iOS example

Describe the bug

When attempting to install the native iOS examples on a local Node JS server, the following error is received in the dashboard:
App not found, please verify URL

I believe it might be because a wrong appetize.io api key is used, but I can't find any example of how to use this key and where it should be embedded. The relevant section in the documentation says:

you must upload your application to appetize.io. After the upload, you will receive a public key that can be used with Storybook Native to view and interact with your application directly from Storybook.

So now that I have uploaded the demo app to appetize.io and received a public key, I can't understand what to do with it and how I can tell the system that this is the key that should be used.

Is there any documentation about it?

Expected behavior

I expected to see a storybook with an integrated appetize build.

Environment

  • OS: macOS Monterey
  • Node.js version: v18.7.0.
  • NPM version: [email protected]
  • Browser Chrome
  • Browser version (if applicable): Version 104.0.5112.79 (Official Build) (arm64)

Come up with a better solution for the appetize iframe

For deep linking, we want to prevent the iframe from reloading because this requires us to establish a new appetize session. When we render the iframe inside a story, it will get reloaded. The appetize iframe is rendered inside of preview-body.html to work around this issue, but it causes other problems such as the iframe still being visible in tabs other than the canvas one.

@shilman hopefully we can come up with a better solution than rendering in preview-body.html

[Bug] Native Examples Not Working/Appearing

Describe the bug

The various examples at https://github.com/storybookjs/native#examples do not work, namely the storybook examples at the following urls:
https://storybookjs.github.io/native/@storybook/native-ios-example-deep-link/index.html?path=/story/button--example
https://storybookjs.github.io/native/@storybook/native-controls-example/index.html?path=/story/button--example
https://storybookjs.github.io/native/@storybook/native-cross-platform-example/index.html?path=/story/android--button
https://storybookjs.github.io/native/@storybook/native-flutter-example/index.html?path=/story/android--button

If I follow the link to static examples, those don't seem to work either. For example, this link sends me to a non-functioning storybook: https://storybookjs.github.io/native/@storybook/native-ios-example-deep-link/index.html?path=/story/button--example

Presumably the path is incomplete?

Steps to reproduce the behavior

  1. Go to any of the links above
  2. See "App not found, please verify URL" errors

Expected behavior

I expected to see a storybook with an integrated appetize build.

Screenshots and/or logs

Screen Shot 2022-07-28 at 1 37 09 PM

Environment

  • OS: mac, 12.4
  • Node.js version: v18.6.0
  • NPM version: 8.13.2
  • Browser (if applicable): chrome
  • Browser version (if applicable): Version 103.0.5060.134 (Official Build) (x86_64)
  • Device (if applicable): macbook pro

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.