Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(react-native): Add ability to filter story list from React-Native #4806

Merged
merged 5 commits into from
Nov 23, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions app/react-native/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,16 @@ The next thing you need to do is make Storybook UI visible in your app.
The easiest way to use Storybook is to simply replace your App with the Storybook UI, which is possible by replacing `App.js` with a single line of code:

```js
export default from "./storybook";
export default from './storybook';
```

This will get you up and running quickly, but then you lose your app!
There are multiple options here. for example, you can export conditionally:

```js
import StorybookUI from "./storybook";
import StorybookUI from './storybook';

import App from "./app";
import App from './app';

module.exports = __DEV__ ? StorybookUI : App;
```
Expand Down Expand Up @@ -125,7 +125,8 @@ You can pass these parameters to getStorybookUI call in your storybook entry poi
-- initialize storybook with a specific story. In case a valid object is passed, it will take precedence over `shouldPersistSelection. ex: `{ kind: 'Knobs', story: 'with knobs' }`
shouldPersistSelection: Boolean (true)
-- initialize storybook with the last selected story.`
)
shouldDisableKeyboardAvoidingView: Boolean (false)
-- Disable KeyboardAvoidingView wrapping Storybook's view
}
```

Expand Down
Original file line number Diff line number Diff line change
@@ -1,29 +1,21 @@
import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
import { View, ScrollView, KeyboardAvoidingView, Platform } from 'react-native';
import { View, ScrollView } from 'react-native';

import style from '../style';

export default class Wrapper extends PureComponent {
render() {
const { panels, addonSelected } = this.props;

const keyboardVerticalOffset = Platform.OS === 'ios' ? 60 : 0;

const addonKeys = Object.keys(panels);

return addonKeys.map(id => {
const selected = addonSelected === id;

return (
<View key={id} style={selected ? style.flex : style.invisible}>
<KeyboardAvoidingView
behavior={Platform.OS === 'android' ? null : 'padding'}
keyboardVerticalOffset={keyboardVerticalOffset}
style={style.flex}
>
<ScrollView style={style.flex}>{panels[id].render({ active: selected })}</ScrollView>
</KeyboardAvoidingView>
<ScrollView style={style.flex}>{panels[id].render({ active: selected })}</ScrollView>
</View>
);
});
Expand Down
89 changes: 55 additions & 34 deletions app/react-native/src/preview/components/OnDeviceUI/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
import { SafeAreaView, Animated, TouchableOpacity } from 'react-native';
import {
Keyboard,
KeyboardAvoidingView,
Platform,
SafeAreaView,
Animated,
TouchableOpacity,
} from 'react-native';
import Events from '@storybook/core-events';

import StoryListView from '../StoryListView';
Expand All @@ -22,6 +29,7 @@ import {
import style from './style';

const ANIMATION_DURATION = 300;
const IS_IOS = Platform.OS === 'ios';

export default class OnDeviceUI extends PureComponent {
constructor(props) {
Expand Down Expand Up @@ -95,10 +103,15 @@ export default class OnDeviceUI extends PureComponent {
// True if swiping between navigator and addons
slideBetweenAnimation: tabOpen + newTabOpen === PREVIEW,
});

// close the keyboard opened from a TextInput from story list or knobs
if (newTabOpen === PREVIEW) {
Keyboard.dismiss();
}
};

render() {
const { stories, events, url, isUIHidden } = this.props;
const { stories, events, url, isUIHidden, shouldDisableKeyboardAvoidingView } = this.props;
const {
tabOpen,
slideBetweenAnimation,
Expand All @@ -121,40 +134,46 @@ export default class OnDeviceUI extends PureComponent {

return (
<SafeAreaView style={style.flex}>
<AbsolutePositionedKeyboardAwareView
onLayout={this.onLayout}
previewHeight={previewHeight}
previewWidth={previewWidth}
<KeyboardAvoidingView
enabled={!shouldDisableKeyboardAvoidingView || tabOpen !== PREVIEW}
behavior={IS_IOS ? 'padding' : null}
style={style.flex}
>
<Animated.View style={previewWrapperStyles}>
<Animated.View style={previewStyles}>
<TouchableOpacity
accessible={false}
style={style.flex}
disabled={tabOpen === PREVIEW}
onPress={this.handleOpenPreview}
>
<StoryView url={url} events={events} selection={selection} storyFn={storyFn} />
</TouchableOpacity>
<AbsolutePositionedKeyboardAwareView
onLayout={this.onLayout}
previewHeight={previewHeight}
previewWidth={previewWidth}
>
<Animated.View style={previewWrapperStyles}>
<Animated.View style={previewStyles}>
<TouchableOpacity
accessible={false}
style={style.flex}
disabled={tabOpen === PREVIEW}
onPress={this.handleOpenPreview}
>
<StoryView url={url} events={events} selection={selection} storyFn={storyFn} />
</TouchableOpacity>
</Animated.View>
</Animated.View>
</Animated.View>
<Panel style={getNavigatorPanelPosition(this.animatedValue, previewWidth)}>
<StoryListView
stories={stories}
events={events}
selectedKind={selection.kind}
selectedStory={selection.story}
/>
</Panel>
<Panel style={getAddonPanelPosition(this.animatedValue, previewWidth)}>
<Addons />
</Panel>
</AbsolutePositionedKeyboardAwareView>
<Navigation
tabOpen={tabOpen}
onChangeTab={this.handleToggleTab}
initialUiVisible={!isUIHidden}
/>
<Panel style={getNavigatorPanelPosition(this.animatedValue, previewWidth)}>
<StoryListView
stories={stories}
events={events}
selectedKind={selection.kind}
selectedStory={selection.story}
/>
</Panel>
<Panel style={getAddonPanelPosition(this.animatedValue, previewWidth)}>
<Addons />
</Panel>
</AbsolutePositionedKeyboardAwareView>
<Navigation
tabOpen={tabOpen}
onChangeTab={this.handleToggleTab}
initialUiVisible={!isUIHidden}
/>
</KeyboardAvoidingView>
</SafeAreaView>
);
}
Expand All @@ -180,11 +199,13 @@ OnDeviceUI.propTypes = {
kind: PropTypes.string.isRequired,
storyFn: PropTypes.func.isRequired,
}),
shouldDisableKeyboardAvoidingView: PropTypes.bool,
};

OnDeviceUI.defaultProps = {
url: '',
tabOpen: 0,
isUIHidden: false,
initialStory: null,
shouldDisableKeyboardAvoidingView: false,
};
82 changes: 60 additions & 22 deletions app/react-native/src/preview/components/StoryListView/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import { SectionList, View, Text, TouchableOpacity } from 'react-native';
import { SectionList, Text, TextInput, TouchableOpacity, View } from 'react-native';
import Events from '@storybook/core-events';
import style from './style';

Expand Down Expand Up @@ -40,6 +40,7 @@ export default class StoryListView extends Component {

this.state = {
data: [],
originalData: [],
};

this.storyAddedHandler = this.handleStoryAdded.bind(this);
Expand Down Expand Up @@ -71,10 +72,37 @@ export default class StoryListView extends Component {
}),
{}
);
this.setState({
data,
});

this.setState({ data, originalData: data });
}
};

handleChangeSearchText = text => {
const query = text.trim();
const { originalData: data } = this.state;

if (!query) {
this.setState({ data });
return;
}

const checkValue = value => value.toLowerCase().includes(query.toLowerCase());
const filteredData = data.reduce((acc, story) => {
const hasTitle = checkValue(story.title);
const hasKind = story.data.some(kind => checkValue(kind.name));

if (hasTitle || hasKind) {
acc.push({
...story,
// in case the query matches component's title, all of its stories will be shown
data: !hasTitle ? story.data.filter(kind => checkValue(kind.name)) : story.data,
});
}

return acc;
}, []);

this.setState({ data: filteredData });
};

changeStory(kind, story) {
Expand All @@ -88,24 +116,34 @@ export default class StoryListView extends Component {
const { data } = this.state;

return (
<SectionList
testID="Storybook.ListView"
style={[style.list]}
renderItem={({ item }) => (
<ListItem
title={item.name}
kind={item.kind}
selected={item.kind === selectedKind && item.name === selectedStory}
onPress={() => this.changeStory(item.kind, item.name)}
/>
)}
renderSectionHeader={({ section: { title } }) => (
<SectionHeader title={title} selected={title === selectedKind} />
)}
keyExtractor={(item, index) => item + index}
sections={data}
stickySectionHeadersEnabled={false}
/>
<View style={style.flex}>
<TextInput
clearButtonMode="while-editing"
disableFullscreenUI
onChangeText={this.handleChangeSearchText}
placeholder="Filter"
returnKeyType="search"
style={style.searchBar}
/>
<SectionList
testID="Storybook.ListView"
style={style.flex}
renderItem={({ item }) => (
<ListItem
title={item.name}
kind={item.kind}
selected={item.kind === selectedKind && item.name === selectedStory}
onPress={() => this.changeStory(item.kind, item.name)}
/>
)}
renderSectionHeader={({ section: { title } }) => (
<SectionHeader title={title} selected={title === selectedKind} />
)}
keyExtractor={(item, index) => item + index}
sections={data}
stickySectionHeadersEnabled={false}
/>
</View>
);
}
}
Expand Down
13 changes: 10 additions & 3 deletions app/react-native/src/preview/components/StoryListView/style.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
export default {
list: {
searchBar: {
backgroundColor: '#eee',
borderRadius: 5,
fontSize: 16,
marginHorizontal: 5,
marginVertical: 5,
padding: 5,
},
flex: {
flex: 1,
},
header: {
paddingTop: 5,
paddingBottom: 5,
paddingVertical: 5,
},
headerText: {
fontSize: 20,
Expand Down
1 change: 1 addition & 0 deletions app/react-native/src/preview/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ export default class Preview {
isUIOpen={params.isUIOpen}
tabOpen={params.tabOpen}
initialStory={setInitialStory ? preview._getInitialStory() : null}
shouldDisableKeyboardAvoidingView={params.shouldDisableKeyboardAvoidingView}
/>
);
}
Expand Down