xref: /expo/home/menu/DevMenuOnboarding.tsx (revision dfd15ebd)
1import { borderRadius } from '@expo/styleguide-native';
2import { View, Text, Button, useExpoTheme, Spacer } from 'expo-dev-client-components';
3import { isDevice } from 'expo-device';
4import React from 'react';
5import { Platform, StyleSheet, TouchableOpacity as TouchableOpacityRN } from 'react-native';
6import { TouchableOpacity as TouchableOpacityGH } from 'react-native-gesture-handler';
7
8type Props = {
9  onClose: () => void;
10};
11
12// When rendered inside bottom sheet, touchables from RN don't work on Android, but the ones from GH don't work on iOS.
13const TouchableOpacity = Platform.OS === 'android' ? TouchableOpacityGH : TouchableOpacityRN;
14
15const KEYBOARD_CODES: { [key: string]: string } = {
16  ios: '^\u2318Z',
17  android: '\u2318M on macOS or Ctrl+M on other platforms',
18};
19
20const ONBOARDING_MESSAGE = (() => {
21  let fragment;
22  if (isDevice) {
23    if (Platform.OS === 'ios') {
24      fragment =
25        'you can shake your device or long press anywhere on the screen with three fingers';
26    } else {
27      fragment = 'you can shake your device';
28    }
29  } else {
30    fragment = `in a simulator you can press ${KEYBOARD_CODES[Platform.OS]}`;
31  }
32  return `Since this is your first time opening Expo Go, we wanted to show you this menu and let you know that ${fragment} to get back to it at any time.`;
33})();
34
35export function DevMenuOnboarding({ onClose }: Props) {
36  const theme = useExpoTheme();
37
38  return (
39    <View style={styles.onboardingContainer}>
40      <View style={styles.onboardingBackground} bg="default" />
41      <View style={styles.onboardingTopMargin} />
42      <View>
43        <Text type="InterBold" align="center" size="large">
44          Hello there, friend! ��
45        </Text>
46        <Spacer.Vertical size="small" />
47        <Text type="InterRegular" align="center" style={styles.onboardingTooltip}>
48          {ONBOARDING_MESSAGE}
49        </Text>
50        <Spacer.Vertical size="medium" />
51        <TouchableOpacity
52          style={[styles.onboardingButton, { backgroundColor: theme.button.primary.background }]}
53          onPress={onClose}>
54          <Button.Text type="InterSemiBold" color="primary">
55            Got it
56          </Button.Text>
57        </TouchableOpacity>
58      </View>
59    </View>
60  );
61}
62
63const styles = StyleSheet.create({
64  onboardingContainer: {
65    flex: 1,
66    paddingHorizontal: 36,
67    position: 'absolute',
68    top: 0,
69    right: 0,
70    bottom: 0,
71    left: 0,
72    zIndex: 2,
73  },
74  onboardingBackground: {
75    borderTopLeftRadius: borderRadius.large,
76    borderTopRightRadius: borderRadius.large,
77    position: 'absolute',
78    top: 0,
79    right: 0,
80    bottom: 0,
81    left: 0,
82    opacity: 0.9,
83  },
84  onboardingTopMargin: {
85    // Moves the actual onboarding content a little bit down.
86    // This percentage value is also a percentage of screen's height.
87    height: '20%',
88  },
89  onboardingTooltip: {
90    lineHeight: 20,
91    textAlign: 'center',
92  },
93  onboardingButton: {
94    alignItems: 'center',
95    marginVertical: 12,
96    paddingVertical: 12,
97    borderRadius: 4,
98  },
99});
100