Skip to content

Fader - a component to easily add fade look to other components #847

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

Merged
merged 11 commits into from
Aug 2, 2020
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
5 changes: 5 additions & 0 deletions demo/src/screens/MenuStructure.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,11 @@ export const navigationData = {
tags: 'scroll reach start end',
screen: 'unicorn.components.WithScrollReachedScreen'
},
{
title: 'Fader',
tags: 'scroll fader',
screen: 'unicorn.components.FaderScreen'
},
{title: 'Wizard', tags: 'wizard', screen: 'unicorn.components.WizardScreen'}
]
},
Expand Down
90 changes: 90 additions & 0 deletions demo/src/screens/componentScreens/FaderScreen.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import _ from 'lodash';
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great. Very simple and easy to understand the component 👍

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

10x

import React, {Component} from 'react';
import {StyleSheet, ScrollView} from 'react-native';
import {
Colors,
Text,
View,
Fader,
withScrollReached,
WithScrollReachedProps
} from 'react-native-ui-lib';
import {renderHeader} from '../ExampleScreenPresenter';

const numberOfItems = 3;
const faderPosition = Fader.position.BOTTOM;
const itemWidth = 100;
const itemHeight = 100;
const tintColor = undefined;

const horizontal =
faderPosition === Fader.position.LEFT ||
faderPosition === Fader.position.RIGHT;

class FaderScreen extends Component<WithScrollReachedProps> {
renderItem = (index: number) => {
return (
<View key={index} style={styles.item}>
<Text>{index + 1}</Text>
</View>
);
};

render() {
const {scrollReachedProps} = this.props;
const visible =
faderPosition === Fader.position.BOTTOM ||
faderPosition === Fader.position.RIGHT
? !scrollReachedProps.isScrollAtEnd
: !scrollReachedProps.isScrollAtStart;

return (
<View margin-10>
{renderHeader('Fader', {'marginB-10': true})}
<View center>
<View style={styles.container}>
<ScrollView
horizontal={horizontal}
style={styles.scrollView}
showsVerticalScrollIndicator={false}
showsHorizontalScrollIndicator={false}
scrollEventThrottle={16}
onScroll={scrollReachedProps.onScroll}
>
{_.times(numberOfItems, this.renderItem)}
</ScrollView>
<Fader
visible={visible}
position={faderPosition}
tintColor={tintColor}
/>
</View>
</View>
</View>
);
}
}

export default withScrollReached(FaderScreen, {
horizontal
});

const styles = StyleSheet.create({
container: {
width: horizontal ? undefined : itemWidth,
height: horizontal ? itemHeight : undefined
},
scrollView: {
width: horizontal ? 240 : undefined,
height: horizontal ? undefined : 240
},
item: {
height: itemHeight,
width: itemWidth,
backgroundColor: Colors.grey60,
borderColor: Colors.grey40,
borderWidth: 2,
alignItems: 'center',
justifyContent: 'center'
}
});
1 change: 1 addition & 0 deletions demo/src/screens/componentScreens/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,5 +60,6 @@ export function registerScreens(registrar) {
registrar('unicorn.screens.ModalScreen', () => require('./ModalScreen').default);
registrar('unicorn.components.WithScrollEnablerScreen', () => require('./WithScrollEnablerScreen').default);
registrar('unicorn.components.WithScrollReachedScreen', () => require('./WithScrollReachedScreen').default);
registrar('unicorn.components.FaderScreen', () => require('./FaderScreen').default);
}

7 changes: 6 additions & 1 deletion generatedTypes/commons/withScrollReached.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export declare type WithScrollReachedOptionsProps = {
*/
horizontal?: boolean;
/**
* Allows to b notified prior to actually reaching the start \ end of the scroll (by the threshold).
* Allows to be notified prior to actually reaching the start \ end of the scroll (by the threshold).
* Should be a positive value.
*/
threshold?: number;
Expand All @@ -26,5 +26,10 @@ export declare type WithScrollReachedProps = {
scrollReachedProps: ScrollReachedProps;
ref?: any;
};
/**
* @description: Add scroll reached which notifies on reaching start \ end of ScrollView \ FlatList
* @example: https://github.com/wix/react-native-ui-lib/blob/master/demo/src/screens/componentScreens/WithScrollReachedScreen.tsx
* @notes: Send `props.scrollReachedProps.onScroll` to your onScroll and receive via props.scrollReachedProps.isScrollAtStart props.scrollReachedProps.isScrollAtEnd
*/
declare function withScrollReached<PROPS>(WrappedComponent: React.ComponentType<PROPS & WithScrollReachedProps>, options?: WithScrollReachedOptionsProps): React.ComponentType<PROPS>;
export default withScrollReached;
31 changes: 31 additions & 0 deletions generatedTypes/components/fader/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/// <reference types="react" />
export declare enum FaderPosition {
LEFT = "LEFT",
RIGHT = "RIGHT",
TOP = "TOP",
BOTTOM = "BOTTOM"
}
export declare type FaderProps = {
/**
* Whether the fader is visible (default is true)
*/
visible?: boolean;
/**
* The position of the fader (the image is different), defaults to Fader.position.RIGHT
*/
position?: FaderPosition;
/**
* Set to change from the default size (50) of the fade view.
*/
size?: number;
/**
* Change the default (white) tint color of the fade view.
*/
tintColor?: string;
};
declare function Fader(props: FaderProps): JSX.Element;
declare namespace Fader {
var displayName: string;
var position: typeof FaderPosition;
}
export default Fader;
1 change: 1 addition & 0 deletions generatedTypes/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export {default as Overlay, OverlayTypes} from './components/overlay';
export {default as RadioButton, RadioButtonPropTypes} from './components/radioButton/RadioButton';
export {default as RadioGroup, RadioGroupPropTypes} from './components/radioButton/RadioGroup';
export {default as TabBar} from './components/TabBar';
export {default as Fader, FaderProps} from './components/fader';

/* All components with manual typings */
export {
Expand Down
7 changes: 6 additions & 1 deletion src/commons/withScrollReached.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export type WithScrollReachedOptionsProps = {
*/
horizontal?: boolean;
/**
* Allows to b notified prior to actually reaching the start \ end of the scroll (by the threshold).
* Allows to be notified prior to actually reaching the start \ end of the scroll (by the threshold).
* Should be a positive value.
*/
threshold?: number;
Expand All @@ -45,6 +45,11 @@ export type WithScrollReachedProps = {

type PropTypes = ForwardRefInjectedProps & SupportedViewsProps;

/**
* @description: Add scroll reached which notifies on reaching start \ end of ScrollView \ FlatList
* @example: https://github.com/wix/react-native-ui-lib/blob/master/demo/src/screens/componentScreens/WithScrollReachedScreen.tsx
* @notes: Send `props.scrollReachedProps.onScroll` to your onScroll and receive via props.scrollReachedProps.isScrollAtStart props.scrollReachedProps.isScrollAtEnd
*/
function withScrollReached<PROPS>(
WrappedComponent: React.ComponentType<PROPS & WithScrollReachedProps>,
options: WithScrollReachedOptionsProps = {}
Expand Down
Binary file added src/components/fader/gradientBottom.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/components/fader/gradientLeft.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/components/fader/gradientRight.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/components/fader/gradientTop.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
119 changes: 119 additions & 0 deletions src/components/fader/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
import _ from 'lodash';
import React, {useCallback} from 'react';
import {StyleSheet} from 'react-native';
import View from '../view';
import Image from '../image';

export enum FaderPosition {
LEFT = 'LEFT',
RIGHT = 'RIGHT',
TOP = 'TOP',
BOTTOM = 'BOTTOM'
}

export type FaderProps = {
/**
* Whether the fader is visible (default is true)
*/
visible?: boolean;
/**
* The position of the fader (the image is different), defaults to Fader.position.RIGHT
*/
position?: FaderPosition;
/**
* Set to change from the default size (50) of the fade view.
*/
size?: number;
/**
* Change the default (white) tint color of the fade view.
*/
tintColor?: string;
};

const DEFAULT_FADE_SIZE = 50;

function Fader(props: FaderProps) {
const getFadeSize = useCallback(() => {
return props.size || DEFAULT_FADE_SIZE;
}, [props.size]);

const fadeSize = getFadeSize();
const getStyles = useCallback(() => {
const position = props.position || FaderPosition.RIGHT;
let containerStyle, imageStyle, imageSource;
switch (position) {
case FaderPosition.LEFT:
containerStyle = {...staticStyles.containerLeft, width: fadeSize};
imageStyle = {height: '100%', width: fadeSize};
imageSource = require('./gradientLeft.png');
break;
case FaderPosition.RIGHT:
containerStyle = {...staticStyles.containerRight, width: fadeSize};
imageStyle = {height: '100%', width: fadeSize};
imageSource = require('./gradientRight.png');
break;
case FaderPosition.TOP:
containerStyle = {...staticStyles.containerTop, height: fadeSize};
imageStyle = {height: fadeSize, width: '100%'};
imageSource = require('./gradientTop.png');
break;
case FaderPosition.BOTTOM:
containerStyle = {
...staticStyles.containerBottom,
height: fadeSize
};
imageStyle = {height: fadeSize, width: '100%'};
imageSource = require('./gradientBottom.png');
break;
}

return {
containerStyle,
imageStyle,
imageSource
};
}, [fadeSize, props.position]);

const styles = getStyles();

return (
<View pointerEvents={'none'} style={styles.containerStyle}>
{(props.visible || _.isUndefined(props.visible)) && (
<Image
source={styles.imageSource}
tintColor={props.tintColor}
style={styles.imageStyle}
resizeMode={'stretch'}
/>
)}
</View>
);
}

Fader.displayName = 'Fader';
Fader.position = FaderPosition;

export default Fader;

const staticStyles = StyleSheet.create({
containerTop: {
position: 'absolute',
top: 0,
width: '100%'
},
containerBottom: {
position: 'absolute',
bottom: 0,
width: '100%'
},
containerLeft: {
position: 'absolute',
left: 0,
height: '100%'
},
containerRight: {
position: 'absolute',
right: 0,
height: '100%'
}
});
3 changes: 3 additions & 0 deletions src/components/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ export default {
get Drawer() {
return require('./drawer').default;
},
get Fader() {
return require('./fader').default;
},
get FeatureHighlight() {
return require('./featureHighlight').default;
},
Expand Down
3 changes: 3 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ export default {
get Drawer() {
return require('./components/drawer').default;
},
get Fader() {
return require('./components/fader').default;
},
get FloatingButton() {
return require('./components/floatingButton').default;
},
Expand Down
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export {default as Overlay, OverlayTypes} from './components/overlay';
export {default as RadioButton, RadioButtonPropTypes} from './components/radioButton/RadioButton';
export {default as RadioGroup, RadioGroupPropTypes} from './components/radioButton/RadioGroup';
export {default as TabBar} from './components/TabBar';
export {default as Fader, FaderProps, FaderLocation} from './components/fader';

//================ Manual typings (all those exports should be removed one day) ==========
export {
Expand Down
1 change: 1 addition & 0 deletions typings/components/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export * from './Carousel';
export * from './ColorPicker';
export * from './ConnectionStatusBar';
export * from './Dialog';
export * from './Fader';
export * from './FeatureHighlight';
export * from './FloatingButton';
export * from './Hint';
Expand Down