forked from Ivasoft/mattermost-mobile
fix some design pr feedback
This commit is contained in:
@@ -37,16 +37,16 @@ const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => ({
|
||||
},
|
||||
footerButtonsContainer: {
|
||||
flexDirection: 'column',
|
||||
height: 150,
|
||||
marginTop: 15,
|
||||
height: 120,
|
||||
marginTop: 25,
|
||||
marginBottom: 15,
|
||||
width: '100%',
|
||||
marginHorizontal: 10,
|
||||
alignItems: 'center',
|
||||
},
|
||||
}));
|
||||
|
||||
const AnimatedButton = Animated.createAnimatedComponent(Pressable);
|
||||
const BUTTON_SIZE = 80;
|
||||
const BUTTON_SIZE = 100;
|
||||
|
||||
const FooterButtons = ({
|
||||
theme,
|
||||
@@ -115,7 +115,7 @@ const FooterButtons = ({
|
||||
<FormattedText
|
||||
id='mobile.onboarding.next'
|
||||
defaultMessage='Next'
|
||||
style={buttonTextStyle(theme, 'm', 'primary', 'default')}
|
||||
style={buttonTextStyle(theme, 'lg', 'primary', 'default')}
|
||||
/>
|
||||
<CompassIcon
|
||||
name='arrow-forward-ios'
|
||||
@@ -129,7 +129,7 @@ const FooterButtons = ({
|
||||
<FormattedText
|
||||
id='mobile.onboarding.sign_in_to_get_started'
|
||||
defaultMessage='Sign in to get started'
|
||||
style={buttonTextStyle(theme, 's', 'primary', 'default')}
|
||||
style={buttonTextStyle(theme, 'lg', 'primary', 'default')}
|
||||
/>
|
||||
</Animated.View>
|
||||
);
|
||||
@@ -139,7 +139,7 @@ const FooterButtons = ({
|
||||
<AnimatedButton
|
||||
testID='mobile.onboaring.next'
|
||||
onPress={nextSlideHandler}
|
||||
style={[styles.button, buttonBackgroundStyle(theme, 'm', 'primary', 'default'), resizeStyle]}
|
||||
style={[styles.button, buttonBackgroundStyle(theme, 'lg', 'primary', 'default'), resizeStyle]}
|
||||
>
|
||||
{nextButtonText}
|
||||
{signInButtonText}
|
||||
@@ -147,12 +147,12 @@ const FooterButtons = ({
|
||||
<AnimatedButton
|
||||
testID='mobile.onboaring.sign_in'
|
||||
onPress={signInHandler}
|
||||
style={[styles.button, buttonBackgroundStyle(theme, 'm', 'link', 'default'), opacitySignInButton]}
|
||||
style={[styles.button, buttonBackgroundStyle(theme, 'lg', 'link', 'default'), opacitySignInButton]}
|
||||
>
|
||||
<FormattedText
|
||||
id='mobile.onboarding.sign_in'
|
||||
defaultMessage='Sign in'
|
||||
style={buttonTextStyle(theme, 's', 'primary', 'inverted')}
|
||||
style={buttonTextStyle(theme, 'lg', 'primary', 'inverted')}
|
||||
/>
|
||||
</AnimatedButton>
|
||||
</View>
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import React, {useCallback, useEffect, useRef} from 'react';
|
||||
import {View, ListRenderItemInfo, useWindowDimensions, SafeAreaView, ScrollView, Animated as AnimatedRN, StyleSheet} from 'react-native';
|
||||
import Animated, {Easing, useAnimatedRef, useAnimatedScrollHandler, useDerivedValue, useSharedValue} from 'react-native-reanimated';
|
||||
import React, {useCallback} from 'react';
|
||||
import {View, ListRenderItemInfo, useWindowDimensions, SafeAreaView, ScrollView, StyleSheet} from 'react-native';
|
||||
import Animated, {useAnimatedRef, useAnimatedScrollHandler, useDerivedValue, useSharedValue} from 'react-native-reanimated';
|
||||
|
||||
import {storeOnboardingViewedValue} from '@actions/app/global';
|
||||
import {Screens} from '@app/constants';
|
||||
@@ -45,27 +45,14 @@ const Onboarding = ({
|
||||
const slidesRef = useAnimatedRef<ScrollView>();
|
||||
|
||||
const scrollX = useSharedValue(0);
|
||||
const scrollAnimation = useRef(new AnimatedRN.Value(0));
|
||||
|
||||
const currentIndex = useDerivedValue(() => Math.round(scrollX.value / width));
|
||||
|
||||
useEffect(() => {
|
||||
scrollAnimation.current?.addListener((animation) => {
|
||||
slidesRef.current?.scrollTo({
|
||||
x: animation.value,
|
||||
animated: false,
|
||||
});
|
||||
});
|
||||
return () => scrollAnimation.current.removeAllListeners();
|
||||
}, []);
|
||||
|
||||
const moveToSlide = useCallback((slideIndexToMove: number) => {
|
||||
AnimatedRN.timing(scrollAnimation.current, {
|
||||
toValue: (slideIndexToMove * width),
|
||||
duration: Math.abs(currentIndex.value - slideIndexToMove) * 200,
|
||||
useNativeDriver: true,
|
||||
easing: Easing.linear,
|
||||
}).start();
|
||||
slidesRef.current?.scrollTo({
|
||||
x: (slideIndexToMove * width),
|
||||
animated: true,
|
||||
});
|
||||
}, [currentIndex.value]);
|
||||
|
||||
const nextSlide = useCallback(() => {
|
||||
|
||||
@@ -47,6 +47,8 @@ const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => ({
|
||||
paginatorContainer: {
|
||||
flexDirection: 'row',
|
||||
height: 15,
|
||||
justifyContent: 'space-between',
|
||||
width: 120,
|
||||
},
|
||||
}));
|
||||
|
||||
@@ -59,7 +61,7 @@ const Paginator = ({
|
||||
const styles = getStyleSheet(theme);
|
||||
return (
|
||||
<View style={styles.paginatorContainer}>
|
||||
{[...Array(dataLength)].map((item: number, index: number) => {
|
||||
{[...Array(dataLength)].map((_, index: number) => {
|
||||
return (
|
||||
<Dot
|
||||
key={`key-${index.toString()}`}
|
||||
@@ -82,7 +84,12 @@ type DotProps = {
|
||||
};
|
||||
|
||||
// this has to be extracted as a component since the useAnimatedStyle hook cant be used inside a loop
|
||||
const Dot = ({index, scrollX, theme, moveToSlide}: DotProps) => {
|
||||
const Dot = ({
|
||||
index,
|
||||
scrollX,
|
||||
theme,
|
||||
moveToSlide,
|
||||
}: DotProps) => {
|
||||
const {width} = useWindowDimensions();
|
||||
const styles = getStyleSheet(theme);
|
||||
const inputRange = [(index - 1) * width, index * width, (index + 1) * width];
|
||||
@@ -108,7 +115,10 @@ const Dot = ({index, scrollX, theme, moveToSlide}: DotProps) => {
|
||||
});
|
||||
|
||||
return (
|
||||
<TouchableOpacity onPress={() => moveToSlide(index)}>
|
||||
<TouchableOpacity
|
||||
onPress={() => moveToSlide(index)}
|
||||
hitSlop={{top: 8, left: 8, right: 8, bottom: 8}}
|
||||
>
|
||||
<Animated.View style={styles.fixedDot}/>
|
||||
<Animated.View style={[styles.outerDot, outerDotOpacity]}/>
|
||||
<Animated.View style={[styles.dot, dotOpacity]}/>
|
||||
|
||||
@@ -17,20 +17,26 @@ type Props = {
|
||||
};
|
||||
|
||||
const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => ({
|
||||
image: {
|
||||
justifyContent: 'center',
|
||||
maxHeight: 180,
|
||||
},
|
||||
title: {
|
||||
fontWeight: '600',
|
||||
marginBottom: 5,
|
||||
height: 100,
|
||||
color: theme.centerChannelColor,
|
||||
textAlign: 'center',
|
||||
fontFamily: 'Metropolis-SemiBold',
|
||||
paddingHorizontal: 20,
|
||||
},
|
||||
fontTitle: {
|
||||
fontSize: 40,
|
||||
marginTop: 32,
|
||||
...typography('Heading', 1000, 'SemiBold'),
|
||||
},
|
||||
fontFirstTitle: {
|
||||
fontSize: 66,
|
||||
...typography('Heading', 1200, 'SemiBold'),
|
||||
paddingTop: 40,
|
||||
},
|
||||
widthLastSlide: {
|
||||
paddingHorizontal: 50,
|
||||
},
|
||||
firstSlideInitialPosition: {
|
||||
left: 200,
|
||||
@@ -39,17 +45,10 @@ const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => ({
|
||||
description: {
|
||||
textAlign: 'center',
|
||||
paddingHorizontal: 20,
|
||||
fontFamily: 'Open Sans',
|
||||
height: 80,
|
||||
color: changeOpacity(theme.centerChannelColor, 0.64),
|
||||
...typography('Body', 200, 'Regular'),
|
||||
},
|
||||
image: {
|
||||
justifyContent: 'center',
|
||||
height: 60,
|
||||
maxHeight: 180,
|
||||
width: 60,
|
||||
},
|
||||
itemContainer: {
|
||||
flex: 1,
|
||||
alignItems: 'center',
|
||||
@@ -58,6 +57,7 @@ const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => ({
|
||||
}));
|
||||
|
||||
const FIRST_SLIDE = 0;
|
||||
const LAST_SLIDE = 3;
|
||||
const FIRST_LOAD_ELEMENTS_POSITION = 400;
|
||||
|
||||
const SlideItem = ({theme, item, scrollX, index}: Props) => {
|
||||
@@ -77,11 +77,11 @@ const SlideItem = ({theme, item, scrollX, index}: Props) => {
|
||||
|
||||
useEffect(() => {
|
||||
if (index === FIRST_SLIDE) {
|
||||
initialImagePosition.value = withTiming(0, {duration: 1000});
|
||||
initialTitlePosition.value = withTiming(0, {duration: 1250});
|
||||
initialDescriptionPosition.value = withTiming(0, {duration: 1500});
|
||||
initialImagePosition.value = withTiming(0, {duration: 500});
|
||||
initialTitlePosition.value = withTiming(0, {duration: 700});
|
||||
initialDescriptionPosition.value = withTiming(0, {duration: 900});
|
||||
|
||||
initialElementsOpacity.value = withTiming(1, {duration: 1500});
|
||||
initialElementsOpacity.value = withTiming(1, {duration: 900});
|
||||
setFirstLoad(false);
|
||||
}
|
||||
}, []);
|
||||
@@ -175,6 +175,7 @@ const SlideItem = ({theme, item, scrollX, index}: Props) => {
|
||||
<View style={[styles.itemContainer, {width}]}>
|
||||
<Animated.View
|
||||
style={[
|
||||
styles.image,
|
||||
translateImage,
|
||||
opacity,
|
||||
translateFirstImageOnLoad,
|
||||
@@ -188,6 +189,7 @@ const SlideItem = ({theme, item, scrollX, index}: Props) => {
|
||||
style={[
|
||||
styles.title,
|
||||
(index === FIRST_SLIDE ? styles.fontFirstTitle : styles.fontTitle),
|
||||
(index === LAST_SLIDE ? styles.widthLastSlide : undefined),
|
||||
translateTitle,
|
||||
opacity,
|
||||
translateFirstTitleOnLoad,
|
||||
@@ -202,6 +204,7 @@ const SlideItem = ({theme, item, scrollX, index}: Props) => {
|
||||
translateDescription,
|
||||
opacity,
|
||||
(index === FIRST_SLIDE && firstLoad ? styles.firstSlideInitialPosition : undefined),
|
||||
(index === LAST_SLIDE ? styles.widthLastSlide : undefined),
|
||||
translateFirstDescriptionOnLoad,
|
||||
]}
|
||||
>
|
||||
|
||||
@@ -15,9 +15,10 @@ import TeamCommunicationSvg from './illustrations/team_communication';
|
||||
const styles = StyleSheet.create({
|
||||
image: {
|
||||
justifyContent: 'center',
|
||||
height: 60,
|
||||
maxHeight: 180,
|
||||
width: 60,
|
||||
height: 200,
|
||||
},
|
||||
lastSlideImage: {
|
||||
height: 250,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -26,7 +27,7 @@ const useSalidesData = () => {
|
||||
const callsSvg = (<CallsSvg styles={styles.image}/>);
|
||||
const chatSvg = (<ChatSvg styles={styles.image}/>);
|
||||
const teamCommunicationSvg = (<TeamCommunicationSvg styles={styles.image}/>);
|
||||
const integrationsSvg = (<IntegrationsSvg styles={styles.image}/>);
|
||||
const integrationsSvg = (<IntegrationsSvg styles={[styles.image, styles.lastSlideImage]}/>);
|
||||
|
||||
const slidesData: OnboardingItem[] = [
|
||||
{
|
||||
@@ -46,7 +47,7 @@ const useSalidesData = () => {
|
||||
},
|
||||
{
|
||||
title: intl.formatMessage({id: 'onboarding.integrations', defaultMessage: 'Integrate with tools you love'}),
|
||||
description: intl.formatMessage({id: 'onboarding.integrations_description', defaultMessage: 'Go beyond chat with tightly-integratedproduct solutions matched to common development processes.'}),
|
||||
description: intl.formatMessage({id: 'onboarding.integrations_description', defaultMessage: 'Go beyond chat with tightly-integrated product solutions matched to common development processes.'}),
|
||||
image: integrationsSvg,
|
||||
},
|
||||
];
|
||||
|
||||
@@ -6,7 +6,7 @@ import {StyleSheet, TextStyle} from 'react-native';
|
||||
// type FontFamilies = 'OpenSans' | 'Metropolis';
|
||||
type FontTypes = 'Heading' | 'Body';
|
||||
type FontStyles = 'SemiBold' | 'Regular' | 'Light';
|
||||
type FontSizes = 25 | 50 | 75 | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | 1000;
|
||||
type FontSizes = 25 | 50 | 75 | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | 1000 | 1200;
|
||||
|
||||
const fontFamily = StyleSheet.create({
|
||||
OpenSans: {
|
||||
@@ -30,6 +30,11 @@ const fontStyle = StyleSheet.create({
|
||||
});
|
||||
|
||||
const fontSize = StyleSheet.create({
|
||||
1200: {
|
||||
fontSize: 66,
|
||||
lineHeight: 48,
|
||||
letterSpacing: -0.02,
|
||||
},
|
||||
1000: {
|
||||
fontSize: 40,
|
||||
lineHeight: 48,
|
||||
|
||||
@@ -656,7 +656,7 @@
|
||||
"onboarding.calls": "Start secure audio calls instantly",
|
||||
"onboarding.calls_description": "When typing isn’t fast enough, switch from channel-based chat to secure audio calls with a single tap.",
|
||||
"onboarding.integrations": "Integrate with tools you love",
|
||||
"onboarding.integrations_description": "Go beyond chat with tightly-integratedproduct solutions matched to common development processes.",
|
||||
"onboarding.integrations_description": "Go beyond chat with tightly-integrated product solutions matched to common development processes.",
|
||||
"onboarding.realtime_collaboration": "Collaborate in real-time",
|
||||
"onboarding.realtime_collaboration_description": "Persistent channels, direct messaging, and file sharing works seamlessly so you can stay connected, wherever you are.",
|
||||
"onboarding.welcome": "Welcome",
|
||||
|
||||
Reference in New Issue
Block a user