diff --git a/app/screens/onboarding/footer_buttons.tsx b/app/screens/onboarding/footer_buttons.tsx
index 2b381be04..1c89ee5bf 100644
--- a/app/screens/onboarding/footer_buttons.tsx
+++ b/app/screens/onboarding/footer_buttons.tsx
@@ -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 = ({
);
@@ -139,7 +139,7 @@ const FooterButtons = ({
{nextButtonText}
{signInButtonText}
@@ -147,12 +147,12 @@ const FooterButtons = ({
diff --git a/app/screens/onboarding/index.tsx b/app/screens/onboarding/index.tsx
index 44e011da9..830cd1f6a 100644
--- a/app/screens/onboarding/index.tsx
+++ b/app/screens/onboarding/index.tsx
@@ -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();
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(() => {
diff --git a/app/screens/onboarding/paginator.tsx b/app/screens/onboarding/paginator.tsx
index ca1aa8297..69a9ef906 100644
--- a/app/screens/onboarding/paginator.tsx
+++ b/app/screens/onboarding/paginator.tsx
@@ -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 (
- {[...Array(dataLength)].map((item: number, index: number) => {
+ {[...Array(dataLength)].map((_, index: number) => {
return (
{
+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 (
- moveToSlide(index)}>
+ moveToSlide(index)}
+ hitSlop={{top: 8, left: 8, right: 8, bottom: 8}}
+ >
diff --git a/app/screens/onboarding/slide.tsx b/app/screens/onboarding/slide.tsx
index 4bc19ea2c..020fec814 100644
--- a/app/screens/onboarding/slide.tsx
+++ b/app/screens/onboarding/slide.tsx
@@ -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) => {
{
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,
]}
>
diff --git a/app/screens/onboarding/slides_data.tsx b/app/screens/onboarding/slides_data.tsx
index 467fa2887..b5d2eed8f 100644
--- a/app/screens/onboarding/slides_data.tsx
+++ b/app/screens/onboarding/slides_data.tsx
@@ -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 = ();
const chatSvg = ();
const teamCommunicationSvg = ();
- const integrationsSvg = ();
+ const integrationsSvg = ();
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,
},
];
diff --git a/app/utils/typography.ts b/app/utils/typography.ts
index 812bf5f35..50ecbf763 100644
--- a/app/utils/typography.ts
+++ b/app/utils/typography.ts
@@ -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,
diff --git a/assets/base/i18n/en.json b/assets/base/i18n/en.json
index 5be3baffa..562926c8a 100644
--- a/assets/base/i18n/en.json
+++ b/assets/base/i18n/en.json
@@ -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",