From 709cf9c2608791c64fd9456f139b043cc9b0383d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Estev=C3=A3o=20Lucas?= Date: Sun, 18 Nov 2018 22:26:42 -0500 Subject: [PATCH 1/5] feat(react-native): add filter bar --- .../preview/components/StoryListView/index.js | 81 ++++++++++++++----- .../preview/components/StoryListView/style.js | 13 ++- 2 files changed, 69 insertions(+), 25 deletions(-) diff --git a/app/react-native/src/preview/components/StoryListView/index.js b/app/react-native/src/preview/components/StoryListView/index.js index a53522b648ec..bcc6387429cc 100644 --- a/app/react-native/src/preview/components/StoryListView/index.js +++ b/app/react-native/src/preview/components/StoryListView/index.js @@ -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'; @@ -40,6 +40,7 @@ export default class StoryListView extends Component { this.state = { data: [], + originalData: [], }; this.storyAddedHandler = this.handleStoryAdded.bind(this); @@ -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) { @@ -88,24 +116,33 @@ export default class StoryListView extends Component { const { data } = this.state; return ( - ( - this.changeStory(item.kind, item.name)} - /> - )} - renderSectionHeader={({ section: { title } }) => ( - - )} - keyExtractor={(item, index) => item + index} - sections={data} - stickySectionHeadersEnabled={false} - /> + + + ( + this.changeStory(item.kind, item.name)} + /> + )} + renderSectionHeader={({ section: { title } }) => ( + + )} + keyExtractor={(item, index) => item + index} + sections={data} + stickySectionHeadersEnabled={false} + /> + ); } } diff --git a/app/react-native/src/preview/components/StoryListView/style.js b/app/react-native/src/preview/components/StoryListView/style.js index fe376bbb1813..5cac48f5cabc 100644 --- a/app/react-native/src/preview/components/StoryListView/style.js +++ b/app/react-native/src/preview/components/StoryListView/style.js @@ -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, From 5d1dac6f2ee7fd2f1148f2357ec8b1c1ce35d602 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Estev=C3=A3o=20Lucas?= Date: Sun, 18 Nov 2018 22:35:09 -0500 Subject: [PATCH 2/5] feat: wrap storybook on react-native with KeyboardAvoidingView --- app/react-native/readme.md | 9 +- .../preview/components/OnDeviceUI/index.js | 89 ++++++++++++------- app/react-native/src/preview/index.js | 1 + 3 files changed, 61 insertions(+), 38 deletions(-) diff --git a/app/react-native/readme.md b/app/react-native/readme.md index cfc38cc38b43..4cc408d447b0 100644 --- a/app/react-native/readme.md +++ b/app/react-native/readme.md @@ -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; ``` @@ -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 } ``` diff --git a/app/react-native/src/preview/components/OnDeviceUI/index.js b/app/react-native/src/preview/components/OnDeviceUI/index.js index 8d1e82887e66..b8622555a2db 100644 --- a/app/react-native/src/preview/components/OnDeviceUI/index.js +++ b/app/react-native/src/preview/components/OnDeviceUI/index.js @@ -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'; @@ -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) { @@ -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 === 0) { + Keyboard.dismiss(); + } }; render() { - const { stories, events, url, isUIHidden } = this.props; + const { stories, events, url, isUIHidden, shouldDisableKeyboardAvoidingView } = this.props; const { tabOpen, slideBetweenAnimation, @@ -121,40 +134,46 @@ export default class OnDeviceUI extends PureComponent { return ( - - - - - - + + + + + + + - - - - - - - - - + + + + + + + + + ); } @@ -180,6 +199,7 @@ OnDeviceUI.propTypes = { kind: PropTypes.string.isRequired, storyFn: PropTypes.func.isRequired, }), + shouldDisableKeyboardAvoidingView: PropTypes.bool, }; OnDeviceUI.defaultProps = { @@ -187,4 +207,5 @@ OnDeviceUI.defaultProps = { tabOpen: 0, isUIHidden: false, initialStory: null, + shouldDisableKeyboardAvoidingView: false, }; diff --git a/app/react-native/src/preview/index.js b/app/react-native/src/preview/index.js index e01cb14b4767..f7c0b9e9ac72 100644 --- a/app/react-native/src/preview/index.js +++ b/app/react-native/src/preview/index.js @@ -115,6 +115,7 @@ export default class Preview { isUIOpen={params.isUIOpen} tabOpen={params.tabOpen} initialStory={setInitialStory ? preview._getInitialStory() : null} + shouldDisableKeyboardAvoidingView={params.shouldDisableKeyboardAvoidingView} /> ); } From 54ccc611db246e2ddf2128c33b02d40ed800cfcb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Estev=C3=A3o=20Lucas?= Date: Sun, 18 Nov 2018 22:36:06 -0500 Subject: [PATCH 3/5] remove KeyboardAvoidingView from addons wrapper --- .../preview/components/OnDeviceUI/addons/wrapper.js | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/app/react-native/src/preview/components/OnDeviceUI/addons/wrapper.js b/app/react-native/src/preview/components/OnDeviceUI/addons/wrapper.js index 9874e510bdca..1b01c00a0c14 100644 --- a/app/react-native/src/preview/components/OnDeviceUI/addons/wrapper.js +++ b/app/react-native/src/preview/components/OnDeviceUI/addons/wrapper.js @@ -1,6 +1,6 @@ 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'; @@ -8,8 +8,6 @@ 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 => { @@ -17,13 +15,7 @@ export default class Wrapper extends PureComponent { return ( - - {panels[id].render({ active: selected })} - + {panels[id].render({ active: selected })} ); }); From 2fe9e71120a44091a791e1cb925e5aa17e24e48e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Estev=C3=A3o=20Lucas?= Date: Mon, 19 Nov 2018 11:38:19 -0500 Subject: [PATCH 4/5] fix: only disable KeyboardAvoidingView with shouldDisableKeyboardAvoidingView param on preview tab --- app/react-native/src/preview/components/OnDeviceUI/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/react-native/src/preview/components/OnDeviceUI/index.js b/app/react-native/src/preview/components/OnDeviceUI/index.js index b8622555a2db..bba3360275a9 100644 --- a/app/react-native/src/preview/components/OnDeviceUI/index.js +++ b/app/react-native/src/preview/components/OnDeviceUI/index.js @@ -105,7 +105,7 @@ export default class OnDeviceUI extends PureComponent { }); // close the keyboard opened from a TextInput from story list or knobs - if (newTabOpen === 0) { + if (newTabOpen === PREVIEW) { Keyboard.dismiss(); } }; @@ -135,7 +135,7 @@ export default class OnDeviceUI extends PureComponent { return ( From d0d0eba29d72ce899837af5dffb2705cdd491a03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Estev=C3=A3o=20Lucas?= Date: Thu, 22 Nov 2018 22:17:36 -0500 Subject: [PATCH 5/5] change from Fragment to View and add disableFullscreenUI --- .../src/preview/components/StoryListView/index.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/react-native/src/preview/components/StoryListView/index.js b/app/react-native/src/preview/components/StoryListView/index.js index bcc6387429cc..750f26ab9c08 100644 --- a/app/react-native/src/preview/components/StoryListView/index.js +++ b/app/react-native/src/preview/components/StoryListView/index.js @@ -116,9 +116,10 @@ export default class StoryListView extends Component { const { data } = this.state; return ( - + - + ); } }