-
-
Notifications
You must be signed in to change notification settings - Fork 9.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[onDeviceUI] Add ability to render addons in React Native (#4381)
* Reducing the size of the ui. * Addon scrollview with addon names * Updated style, shows addons list with loaded addons. * Updated status bar, so content would not be drawn below it on android. * Added some addons to example. * Moved out of state * Fixed event on android. * Temporary disabled yellow box. * Adding two options for storybook ui: isUIOpen - whether to initially show top bar - default true. isStoryMenuOpen - should show story menu open by default - default false. * Creating rn-addons.js file inside generators. * Removed separate addon store. * Using active prop. * Rewrote addons wrapper without using modal. We cannot use modal since addons expect to be rendered all the time. So now we display the wrapper as position absolute and make it 0 0 size when it is not visible. * Fixing yellow box warnings. * Addon window by default is scrollable. * Removed yellow box disabling, cleared up example index. * Reverted accidentally deleted line. * Updated dependencies. * Dependency bump * Updated UI. Removed modal, displaying menus as panels appearing from sides. * Clearing up the style a little bit. * Temporary disabling some examples * Updating the readmes. * Updating the readme. * Added notes addon that support rn * Updated addon documentation regarding setTimeout. * Fixed proptypes issue, properly set initial tab from the props. * Reduced the amount of rerenders, if you use onDeviceUI it only listens to story change events once instead of twice. * Adding more addons. * OnDeviceUI is now set to true by default. * Updated the notes addon so it renders markdown properly. * Fixes endless cycle when initially rendering when both onDeviceUI and server are enabled. * Selection prop is not required ( it is not set when not using onDeviceUI). * Renamed rn-notes to ondevice-notes addon. * Added option to use channels as async. * Using async channel if onDeviceUI is set to true. * Updated notes documentation/tests. * Adding backgrounds addon. * Updated notes readme. * Adding ondevice knobs addon. * Updated example * Reverted accidental merge issue. * Updating documentation. * Fixed knobs entry file. * Updating documentation. * Updating documentation. * Removed packager completely. * Updated cli. * Added missing dependency. * Websocket doesn't throw red screen on connection fail anymore. * Takes children from props instead out of state.. * Fixed bug where selecting story didn't actually select it. * Removed ondeviceUI in example. * If it fails to connect it selects initial story. * Knobs are properly reset on change. * Proper import in example * Reverts to localhost if no host is defined. * Ui doesnt jump when hiding bottom bar, should handle keyboard correctly on ios. * Updated background addon to unregister on unmount. * Properly handles animations on android. * Creates channel as soon as getStorybookUI is called instead of during the render. * Displays message if no addons are loaded. * setOptions called without timeout. * Sets initial story if connection to websocket server fail. * Updating style. * Removed margin bottom. * Added swiping on the nav bar, touching preview maximizes it. * Fixed keyboard aware view. * Fixed background panel so it doesn't lose color immediately. * Uses preview width for panels. * Moving class inside preview. * All react native installations receive same template. * Removed react_native fixture. * Fixing lint. * Lint fix. * Improving performance dramatically. * Adding on device addons. * Reverted back fixtures change. * Reverting file change * Updating readmes. * Updated readme about server. * Reverted yarn.lock * Fixing propTypes. * Splitting out onDeviceUI/index to smaller components. * Splitting up onDeviceUI. * Removed unused dependency. * Properly uses whole screen for preview. * Updated visibility button. * Few code review fixes Updated readme, Renamed handlers. * Fixed where width is taken from.
- Loading branch information
Showing
34 changed files
with
1,047 additions
and
288 deletions.
There are no files selected for viewing
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,19 +1,21 @@ | ||
## Addon / Framework Support Table | ||
|
||
| | [React](app/react)|[React Native](app/react-native)|[Vue](app/vue)|[Angular](app/angular)| [Polymer](app/polymer)| [Mithril](app/mithril)| [HTML](app/html)| [Marko](app/marko)| [Svelte](app/svelte)| [Riot](app/riot)| [Ember](app/ember)| | ||
| ----------- |:-------:|:-------:|:-------:|:-------:|:-------:|:-------:|:-------:|:-------:|:-------:|:-------:|:-------:| | ||
|[a11y](addons/a11y) |+| |+|+|+|+|+|+| | |+| | ||
|[actions](addons/actions) |+|+|+|+|+|+|+|+|+|+|+| | ||
|[backgrounds](addons/backgrounds)|+| |+|+|+|+|+|+|+|+|+| | ||
|[centered](addons/centered) |+| |+|+| |+|+| |+| |+| | ||
|[events](addons/events) |+| |+|+|+|+|+|+| | |+| | ||
|[graphql](addons/graphql) |+| | | | | | | | | | | | ||
|[info](addons/info) |+| | | | | | | | | | | | ||
|[jest](addons/jest) |+| | |+| | |+| | | | | | ||
|[knobs](addons/knobs) |+|+|+|+|+|+|+|+|+|+|+| | ||
|[links](addons/links) |+|+|+|+|+|+|+| |+|+|+| | ||
|[notes](addons/notes) |+| |+|+|+|+|+| |+|+|+| | ||
|[options](addons/options) |+|+|+|+|+|+|+| |+|+|+| | ||
|[storyshots](addons/storyshots) |+|+|+|+| | |+| |+|+| | | ||
|[storysource](addons/storysource)|+| |+|+|+|+|+|+|+|+|+| | ||
|[viewport](addons/viewport) |+| |+|+|+|+|+|+|+|+|+| | ||
## Addon / Framework Support Table | ||
|
||
| | [React](app/react)|[React Native](app/react-native)|[Vue](app/vue)|[Angular](app/angular)| [Polymer](app/polymer)| [Mithril](app/mithril)| [HTML](app/html)| [Marko](app/marko)| [Svelte](app/svelte)| [Riot](app/riot)| [Ember](app/ember)| | ||
| ----------- |:-------:|:-------:|:-------:|:-------:|:-------:|:-------:|:-------:|:-------:|:-------:|:-------:|:-------:| | ||
|[a11y](addons/a11y) |+| |+|+|+|+|+|+| | |+| | ||
|[actions](addons/actions) |+|+|+|+|+|+|+|+|+|+|+| | ||
|[backgrounds](addons/backgrounds)|+|*|+|+|+|+|+|+|+|+|+| | ||
|[centered](addons/centered) |+| |+|+| |+|+| |+| |+| | ||
|[events](addons/events) |+| |+|+|+|+|+|+| | |+| | ||
|[graphql](addons/graphql) |+| | | | | | | | | | | | ||
|[info](addons/info) |+| | | | | | | | | | | | ||
|[jest](addons/jest) |+| | |+| | |+| | | | | | ||
|[knobs](addons/knobs) |+|+*|+|+|+|+|+|+|+|+|+| | ||
|[links](addons/links) |+|+|+|+|+|+|+| |+|+|+| | ||
|[notes](addons/notes) |+|+*|+|+|+|+|+| |+|+|+| | ||
|[options](addons/options) |+|+|+|+|+|+|+| |+|+|+| | ||
|[storyshots](addons/storyshots) |+|+|+|+| | |+| |+|+| | | ||
|[storysource](addons/storysource)|+| |+|+|+|+|+|+|+|+|+| | ||
|[viewport](addons/viewport) |+| |+|+|+|+|+|+|+|+|+| | ||
|
||
`*` - React Native on device addon (addons/onDevice-\<name>) |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
# Addons | ||
|
||
Storybook supports addons. You can read more about them [here](https://storybook.js.org/addons/introduction/) | ||
|
||
There is one big difference in React Native is that it has two types of addons: Addons that work in the browser | ||
and addons that work on the app itself (on device addons). | ||
|
||
## Browser addons | ||
Browser addons are default addons to storybook. You create a file called addons.js inside storybook and it is | ||
automatically added inside your browser. | ||
|
||
## On device addons | ||
On device addons are addons that are displayed in your app in addons panel. | ||
To use them you have to create a file called `rn-addons.js` next to your storybook entry. | ||
Because React Native does not dynamically resolve imports, you also have to manually import them. | ||
Example: | ||
**storybook/index.js** | ||
``` | ||
import { getStorybookUI, configure } from '@storybook/react-native'; | ||
import './rn-addons'; | ||
// import stories | ||
configure(() => { | ||
require($PATH_TO_STORIES); | ||
}, module); | ||
const StorybookUI = getStorybookUI(); | ||
export default StorybookUI; | ||
**storybook/rn-addons.js** | ||
``` | ||
import '@storybook/addon-ondevice-knobs/register'; | ||
import '@storybook/addon-ondevice-notes/register'; | ||
... | ||
``` | ||
This step is done automatically when you install Storybook for the first time and also described in [Manual Setup](https://github.com/storybooks/storybook/blob/master/app/react-native/docs/manual-setup.md) | ||
## Compatibility | ||
Addon compatibilty can be found [here](https://github.com/storybooks/storybook/blob/master/ADDONS_SUPPORT.md) | ||
## Performance of on device addons | ||
Because on device addons are inside the app, they are also rerendered on every change. This can reduce performance a lot. | ||
## Writing the on device addons | ||
On device addons use same addon store and api as web addons. The only difference in api is that you don't have `api` prop | ||
and have to rely on channel for everything. | ||
The main difference between browser and app addons is that the render has to be supported by React Native (View, Text). | ||
For more info about writing addons read [writing addons](https://storybook.js.org/addons/writing-addons/) section in | ||
storybook documentation. |
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
# Storybook server | ||
The default usage of React Native Storybook till version 4 involved starting Storybook server. | ||
Starting from v4 we do not expect user to start the server since in most cases it is not really necessary. | ||
|
||
In case you still want to run Storybook server simply call `npm run storybook` or `npx storybook start`. | ||
|
||
## Benefits of storybook server | ||
|
||
* ### Websockets connection | ||
The main benefit you get from running storybook server is that your app will be listening for websockets connection. | ||
That means that you can create your own tools that integrate with your storybook app. | ||
|
||
* ### IDE Plugins | ||
Having server running allows you to control your storybook view from inside web page or your ide. | ||
|
||
There is a plugin for [JetBrains IDEs](https://plugins.jetbrains.com/plugin/9910-storybook) and there is one | ||
for [VS Code](https://github.com/orta/vscode-react-native-storybooks). | ||
|
||
|
||
* ### Web addons | ||
There are Storybook addons that work with React Native but do not have on device implementations. | ||
|
||
|
||
|
This file contains 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
This file contains 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
This file contains 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
89 changes: 89 additions & 0 deletions
89
...react-native/src/preview/components/OnDeviceUI/absolute-positioned-keyboard-aware-view.js
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
import React, { PureComponent } from 'react'; | ||
import PropTypes from 'prop-types'; | ||
import { Platform, Keyboard, Dimensions, View } from 'react-native'; | ||
|
||
import style from './style'; | ||
|
||
// Android changes screen size when keyboard opens. | ||
// To avoid issues we use absolute positioned element with predefined screen size | ||
export default class AbsolutePositionedKeyboardAwareView extends PureComponent { | ||
componentWillMount() { | ||
this.keyboardDidShowListener = Keyboard.addListener( | ||
'keyboardDidShow', | ||
this.keyboardDidShowHandler | ||
); | ||
this.keyboardDidHideListener = Keyboard.addListener( | ||
'keyboardDidHide', | ||
this.keyboardDidHideHandler | ||
); | ||
Dimensions.addEventListener('change', this.removeKeyboardOnOrientationChange); | ||
} | ||
|
||
componentWillUnmount() { | ||
this.keyboardDidShowListener.remove(); | ||
this.keyboardDidHideListener.remove(); | ||
Dimensions.removeEventListener('change', this.removeKeyboardOnOrientationChange); | ||
} | ||
|
||
keyboardDidShowHandler = e => { | ||
if (Platform.OS === 'android') { | ||
const { previewWidth } = this.props; | ||
// There is bug in RN android that keyboardDidShow event is called simply when you go from portrait to landscape. | ||
// To make sure that this is keyboard event we check screen width | ||
if (previewWidth === e.endCoordinates.width) { | ||
this.keyboardOpen = true; | ||
} | ||
} | ||
}; | ||
|
||
// When rotating screen from portrait to landscape with keyboard open on android it calls keyboardDidShow, but doesn't call | ||
// keyboardDidHide. To avoid issues we set keyboardOpen to false immediately on keyboardChange. | ||
removeKeyboardOnOrientationChange = () => { | ||
if (Platform.OS === 'android') { | ||
this.keyboardOpen = false; | ||
} | ||
}; | ||
|
||
keyboardDidHideHandler = () => { | ||
if (this.keyboardOpen) { | ||
this.keyboardOpen = false; | ||
} | ||
}; | ||
|
||
onLayoutHandler = ({ nativeEvent }) => { | ||
if (!this.keyboardOpen) { | ||
const { width, height } = nativeEvent.layout; | ||
const { onLayout } = this.props; | ||
|
||
onLayout({ | ||
previewHeight: height, | ||
previewWidth: width, | ||
}); | ||
} | ||
}; | ||
|
||
render() { | ||
const { children, previewWidth, previewHeight } = this.props; | ||
|
||
return ( | ||
<View style={style.flex} onLayout={this.onLayoutHandler}> | ||
<View | ||
style={ | ||
previewWidth === 0 | ||
? style.flex | ||
: { position: 'absolute', width: previewWidth, height: previewHeight } | ||
} | ||
> | ||
{children} | ||
</View> | ||
</View> | ||
); | ||
} | ||
} | ||
|
||
AbsolutePositionedKeyboardAwareView.propTypes = { | ||
children: PropTypes.node.isRequired, | ||
previewWidth: PropTypes.number.isRequired, | ||
previewHeight: PropTypes.number.isRequired, | ||
onLayout: PropTypes.func.isRequired, | ||
}; |
Oops, something went wrong.