Skip to content

Instantly share code, notes, and snippets.

@erictraut
Created June 18, 2017 18:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save erictraut/d76393a4f3131e9ef62cc2c22ad6c251 to your computer and use it in GitHub Desktop.
Save erictraut/d76393a4f3131e9ef62cc2c22ad6c251 to your computer and use it in GitHub Desktop.
ReactXPDrawer
/*
* This file demonstrates a basic ReactXP app.
*/
import RX = require('reactxp');
import ContentPanel from './ContentPanel';
import DrawerControl = require('./DrawerControl');
import DrawerPanel from './DrawerPanel';
const _drawerRef = 'drawer';
class App extends RX.Component<{}, null> {
render() {
return (
<DrawerControl
ref={ _drawerRef }
renderContent={ () => { return <ContentPanel onToggleDrawer={ this._onToggleDrawer } /> } }
renderDrawer={ () => { return <DrawerPanel /> } }
/>
);
}
private _onToggleDrawer = () => {
let drawer = this.refs[_drawerRef] as DrawerControl;
if (drawer) {
drawer.toggleDrawer();
}
}
}
export = App;
import RX = require('reactxp');
interface ContentPanelProps {
onToggleDrawer: () => void;
}
const styles = {
container: RX.Styles.createViewStyle({
flex: 1,
alignSelf: 'stretch',
backgroundColor: 'red'
}),
drawerText: RX.Styles.createTextStyle({
fontSize: 16,
textAlign: 'center',
marginTop: 12,
color: 'black'
}),
scroll: RX.Styles.createScrollViewStyle({
alignSelf: 'stretch',
backgroundColor: 'red',
flex: 1
})
};
export default class ContentPanel extends RX.Component<ContentPanelProps, {}> {
render() {
return (
<RX.View style={{ flex: 1, alignSelf: 'stretch' }}>
<RX.View style={{ paddingTop: 20, backgroundColor: 'blue' }}>
<RX.Button
style={{ margin: 2, borderRadius: 10, backgroundColor: 'black',
width: 20, height: 20, alignItems: 'center' }}
onPress={ this.props.onToggleDrawer }
>
<RX.Text style={{ color: 'white'}}>
H
</RX.Text>
</RX.Button>
</RX.View>
<RX.ScrollView style={ styles.scroll }>
<RX.View style={ styles.container }>
<RX.Text style={{ fontSize: 14 }}>1. This content panel has red background that should fill screen, but does not even with flex: 1 on container</RX.Text>
<RX.Text style={{ fontSize: 14 }}>2. This in turn affects the drawer height to not fill the entire available height</RX.Text>
<RX.Text style={{ fontSize: 14 }}>3. My animation does not seem to be smooth, especially on the first click</RX.Text>
</RX.View>
</RX.ScrollView>
</RX.View>
);
}
}
/*
* This file implements a basic drawer control.
*/
import RX = require('reactxp');
interface MainPanelProps extends RX.CommonStyledProps<RX.Types.ViewStyleRuleSet> {
renderDrawer: () => JSX.Element;
renderContent: () => JSX.Element;
}
// Duration (in ms) of drawer animation.
const animationDuration = 250;
// Amount that the content panel should "peek out" when the
// drawer is open, measured in pixels.
const contentPeekAmount = 100;
const styles = {
container: RX.Styles.createViewStyle({
flex: 1,
alignSelf: 'stretch'
}),
drawerContainer: RX.Styles.createViewStyle({
position: 'absolute',
marginLeft: contentPeekAmount,
top: 0,
right: 0,
bottom: 0,
left: 0
}),
contentContainer: RX.Styles.createViewStyle({
position: 'absolute',
top: 0,
right: 0,
bottom: 0,
left: 0
})
};
class MainPanel extends RX.Component<MainPanelProps, null> {
private _drawerShown = false;
private _viewWidth: number = 0;
private _animation: RX.Types.Animated.CompositeAnimation;
private _drawerTranslationValue: RX.Animated.Value;
private _contentTranslationValue: RX.Animated.Value;
private _animatedDrawerStyle: RX.Types.AnimatedViewStyleRuleSet;
private _animatedContentStyle: RX.Types.AnimatedViewStyleRuleSet;
toggleDrawer() {
this._drawerShown = !this._drawerShown;
if (this._animation) {
this._animation.stop();
}
this._animation = RX.Animated.parallel([
RX.Animated.timing(this._drawerTranslationValue, {
toValue: this._drawerShown ? -contentPeekAmount : -this._viewWidth,
easing: RX.Animated.Easing.InOut(),
duration: animationDuration
}),
RX.Animated.timing(this._contentTranslationValue, {
toValue: this._drawerShown ? this._viewWidth - contentPeekAmount : 0,
easing: RX.Animated.Easing.InOut(),
duration: animationDuration
})
]);
this._animation.start(() => {
this._animation = null;
});
}
constructor(props: MainPanelProps) {
super(props);
this._drawerTranslationValue = new RX.Animated.Value(0);
this._animatedDrawerStyle = RX.Styles.createAnimatedViewStyle({
transform: [
{
translateX: this._drawerTranslationValue
}
]
});
this._contentTranslationValue = new RX.Animated.Value(0);
this._animatedContentStyle = RX.Styles.createAnimatedViewStyle({
transform: [
{
translateX: this._contentTranslationValue
}
]
});
}
private _onLayout = (layoutInfo: RX.Types.LayoutInfo) => {
this._viewWidth = layoutInfo.width;
// Stop any animation.
if (this._animation) {
this._animation.stop();
}
// Immediately update animation values for new width.
this._drawerTranslationValue.setValue(this._drawerShown ? -contentPeekAmount : -this._viewWidth);
this._contentTranslationValue.setValue(this._drawerShown ? this._viewWidth - contentPeekAmount : 0);
}
render() {
return (
<RX.View style={ [styles.container, this.props.style] } onLayout={ this._onLayout }>
<RX.Animated.View style={ [styles.drawerContainer, this._animatedDrawerStyle] }>
{ this.props.renderDrawer() }
</RX.Animated.View>
<RX.Animated.View style={ [styles.contentContainer, this._animatedContentStyle] }>
{ this.props.renderContent() }
</RX.Animated.View>
</RX.View>
);
}
}
export = MainPanel;
import RX = require('reactxp');
const styles = {
container: RX.Styles.createViewStyle({
flex: 1,
alignSelf: 'stretch',
backgroundColor: 'green'
}),
drawerText: RX.Styles.createTextStyle({
fontSize: 16,
textAlign: 'center',
marginTop: 12,
color: 'black'
})
};
export default class DrawerPanel extends RX.Component<{}, {}> {
render() {
return (
<RX.View style={ styles.container }>
<RX.Text style={ styles.drawerText }>
Here is a drawer
</RX.Text>
</RX.View>
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment