diff --git a/app/src/components/Mnemonic.tsx b/app/src/components/Mnemonic.tsx
index ad77306ee..a2ba717ef 100644
--- a/app/src/components/Mnemonic.tsx
+++ b/app/src/components/Mnemonic.tsx
@@ -2,11 +2,12 @@
// SPDX-License-Identifier: BUSL-1.1
// NOTE: Converts to Apache-2.0 on 2029-06-11 per LICENSE.
-import React, { useCallback, useState } from 'react';
+import React, { useCallback, useMemo, useState } from 'react';
import { Button, Text, XStack, YStack } from 'tamagui';
import Clipboard from '@react-native-clipboard/clipboard';
import { useSettingStore } from '@/stores/settingStore';
+import useCompactLayout from '@/hooks/useCompactLayout';
import {
black,
slate50,
@@ -25,8 +26,9 @@ interface MnemonicProps {
interface WordPill {
index: number;
word: string;
+ compact: boolean;
}
-const WordPill = ({ index, word }: WordPill) => {
+const WordPill = ({ index, word, compact }: WordPill) => {
return (
{
backgroundColor={white}
borderWidth="$0.5"
borderRadius="$2"
- padding={4}
- minWidth={26}
- gap={4}
+ padding={compact ? 3 : 4}
+ minWidth={compact ? 22 : 26}
+ gap={compact ? 3 : 4}
>
-
+
{index}
-
+
{word}
@@ -54,6 +56,34 @@ const Mnemonic = ({ words = REDACTED, onRevealWords }: MnemonicProps) => {
const [revealWords, setRevealWords] = useState(false);
const [copied, setCopied] = useState(false);
const { setHasViewedRecoveryPhrase } = useSettingStore();
+ const { isCompactWidth, selectResponsiveValues } = useCompactLayout();
+ const {
+ containerPaddingHorizontal,
+ containerPaddingVertical,
+ containerGap,
+ buttonPadding,
+ } = selectResponsiveValues({
+ containerPaddingHorizontal: {
+ compact: 18,
+ regular: 26,
+ dimension: 'width',
+ },
+ containerPaddingVertical: {
+ compact: 22,
+ regular: 28,
+ dimension: 'width',
+ },
+ containerGap: { compact: 10, regular: 12, dimension: 'width' },
+ buttonPadding: { compact: 12, regular: 16, dimension: 'width' },
+ });
+ const containerSpacing = useMemo(
+ () => ({
+ paddingHorizontal: containerPaddingHorizontal,
+ paddingVertical: containerPaddingVertical,
+ gap: containerGap,
+ }),
+ [containerGap, containerPaddingHorizontal, containerPaddingVertical],
+ );
const copyToClipboardOrReveal = useCallback(async () => {
confirmTap();
if (!revealWords) {
@@ -76,13 +106,18 @@ const Mnemonic = ({ words = REDACTED, onRevealWords }: MnemonicProps) => {
borderBottomWidth={0}
borderTopLeftRadius="$5"
borderTopRightRadius="$5"
- gap={12}
- paddingHorizontal={26}
- paddingVertical={28}
+ gap={containerSpacing.gap}
+ paddingHorizontal={containerSpacing.paddingHorizontal}
+ paddingVertical={containerSpacing.paddingVertical}
flexWrap="wrap"
>
{(revealWords ? words : REDACTED).map((word, i) => (
-
+
))}
{
borderTopWidth={0}
borderBottomLeftRadius="$5"
borderBottomRightRadius="$5"
- paddingVertical={16}
+ paddingVertical={buttonPadding}
onPress={copyToClipboardOrReveal}
width="100%"
textAlign="center"
diff --git a/app/src/hooks/useCompactLayout.ts b/app/src/hooks/useCompactLayout.ts
new file mode 100644
index 000000000..13431ed1d
--- /dev/null
+++ b/app/src/hooks/useCompactLayout.ts
@@ -0,0 +1,122 @@
+// SPDX-FileCopyrightText: 2025 Social Connect Labs, Inc.
+// SPDX-License-Identifier: BUSL-1.1
+// NOTE: Converts to Apache-2.0 on 2029-06-11 per LICENSE.
+
+import { useCallback } from 'react';
+import { useWindowDimensions } from 'react-native';
+
+export const DEFAULT_COMPACT_WIDTH = 360;
+export const DEFAULT_COMPACT_HEIGHT = 720;
+
+interface UseCompactLayoutOptions {
+ compactWidth?: number;
+ compactHeight?: number;
+}
+
+type ResponsiveDimension = 'width' | 'height' | 'any';
+
+interface ResponsivePaddingOptions {
+ min?: number;
+ max?: number;
+ percent?: number;
+}
+
+type ResponsiveValueConfig = {
+ compact: T;
+ regular: T;
+ dimension?: ResponsiveDimension;
+};
+
+const useCompactLayout = (
+ options: UseCompactLayoutOptions = {},
+): {
+ width: number;
+ height: number;
+ isCompactWidth: boolean;
+ isCompactHeight: boolean;
+ isCompact: boolean;
+ selectResponsiveValue: (
+ compactValue: T,
+ regularValue: T,
+ dimension?: ResponsiveDimension,
+ ) => T;
+ selectResponsiveValues: >>(
+ config: TConfig,
+ ) => {
+ [K in keyof TConfig]: TConfig[K] extends ResponsiveValueConfig
+ ? TValue
+ : never;
+ };
+ getResponsiveHorizontalPadding: (options?: ResponsivePaddingOptions) => number;
+} => {
+ const { width, height } = useWindowDimensions();
+ const compactWidth = options.compactWidth ?? DEFAULT_COMPACT_WIDTH;
+ const compactHeight = options.compactHeight ?? DEFAULT_COMPACT_HEIGHT;
+
+ const isCompactWidth = width < compactWidth;
+ const isCompactHeight = height < compactHeight;
+ const selectResponsiveValue = useCallback(
+ (
+ compactValue: T,
+ regularValue: T,
+ dimension: ResponsiveDimension = 'any',
+ ): T => {
+ if (dimension === 'width') {
+ return isCompactWidth ? compactValue : regularValue;
+ }
+
+ if (dimension === 'height') {
+ return isCompactHeight ? compactValue : regularValue;
+ }
+
+ return isCompactWidth || isCompactHeight ? compactValue : regularValue;
+ },
+ [isCompactHeight, isCompactWidth],
+ );
+
+ const selectResponsiveValues = useCallback(
+ >>(
+ config: TConfig,
+ ) => {
+ const entries = Object.entries(config) as Array<[
+ keyof TConfig,
+ ResponsiveValueConfig,
+ ]>;
+ const result = {} as {
+ [K in keyof TConfig]: TConfig[K] extends ResponsiveValueConfig
+ ? TValue
+ : never;
+ };
+
+ entries.forEach(([key, { compact, regular, dimension }]) => {
+ result[key] = selectResponsiveValue(compact, regular, dimension);
+ });
+
+ return result;
+ },
+ [selectResponsiveValue],
+ );
+
+ const getResponsiveHorizontalPadding = useCallback(
+ (paddingOptions: ResponsivePaddingOptions = {}): number => {
+ const { min = 16, max, percent = 0.06 } = paddingOptions;
+ const computed = width * percent;
+ const withMin = Math.max(min, computed);
+ return typeof max === 'number' ? Math.min(max, withMin) : withMin;
+ },
+ [width],
+ );
+
+ return {
+ width,
+ height,
+ isCompactWidth,
+ isCompactHeight,
+ isCompact: isCompactWidth || isCompactHeight,
+ selectResponsiveValue,
+ selectResponsiveValues,
+ getResponsiveHorizontalPadding,
+ };
+};
+
+export default useCompactLayout;
diff --git a/app/src/layouts/ExpandableBottomLayout.tsx b/app/src/layouts/ExpandableBottomLayout.tsx
index 2b46f6800..2b0506ce0 100644
--- a/app/src/layouts/ExpandableBottomLayout.tsx
+++ b/app/src/layouts/ExpandableBottomLayout.tsx
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: BUSL-1.1
// NOTE: Converts to Apache-2.0 on 2029-06-11 per LICENSE.
-import React from 'react';
+import React, { useMemo } from 'react';
import {
Dimensions,
PixelRatio,
@@ -17,6 +17,7 @@ import { View } from 'tamagui';
import { black, white } from '@/utils/colors';
import { extraYPadding } from '@/utils/constants';
+import useCompactLayout from '@/hooks/useCompactLayout';
// Get the current font scale factor
const fontScale = PixelRatio.getFontScale();
@@ -57,7 +58,17 @@ const TopSection: React.FC = ({
...props
}) => {
const { top } = useSafeAreaInsets();
- const { roundTop, ...restProps } = props;
+ const { roundTop, style: incomingStyle, ...restProps } = props;
+ const { selectResponsiveValue } = useCompactLayout({
+ compactHeight: 760,
+ });
+ const spacingStyle = useMemo(
+ () => ({
+ paddingHorizontal: selectResponsiveValue(16, 20, 'width'),
+ paddingVertical: selectResponsiveValue(16, 20, 'height'),
+ }),
+ [selectResponsiveValue],
+ );
return (
= ({
styles.topSection,
roundTop && styles.roundTop,
roundTop ? { marginTop: top } : { paddingTop: top },
+ spacingStyle,
{ backgroundColor },
+ incomingStyle,
]}
>
{children}
@@ -108,6 +121,16 @@ const BottomSection: React.FC = ({
const minBottom = safeAreaBottom + extraYPadding;
const totalBottom =
typeof incomingBottom === 'number' ? minBottom + incomingBottom : minBottom;
+ const { selectResponsiveValue } = useCompactLayout({
+ compactHeight: 760,
+ });
+ const spacingStyle = useMemo(
+ () => ({
+ paddingHorizontal: selectResponsiveValue(16, 20, 'width'),
+ paddingTop: selectResponsiveValue(18, 30, 'height'),
+ }),
+ [selectResponsiveValue],
+ );
let panelHeight: number | 'auto' = 'auto';
// set bottom section height to 38% of screen height
@@ -129,7 +152,7 @@ const BottomSection: React.FC = ({
{children}
diff --git a/app/src/screens/account/recovery/AccountRecoveryScreen.tsx b/app/src/screens/account/recovery/AccountRecoveryScreen.tsx
index 2e2c31e41..cc37069b0 100644
--- a/app/src/screens/account/recovery/AccountRecoveryScreen.tsx
+++ b/app/src/screens/account/recovery/AccountRecoveryScreen.tsx
@@ -12,10 +12,12 @@ import {
Title,
} from '@selfxyz/mobile-sdk-alpha/components';
import { BackupEvents } from '@selfxyz/mobile-sdk-alpha/constants/analytics';
+import { useSafeAreaInsets } from 'react-native-safe-area-context';
import useHapticNavigation from '@/hooks/useHapticNavigation';
import RestoreAccountSvg from '@/images/icons/restore_account.svg';
import { ExpandableBottomLayout } from '@/layouts/ExpandableBottomLayout';
+import useCompactLayout from '@/hooks/useCompactLayout';
import { black, slate600, white } from '@/utils/colors';
const AccountRecoveryScreen: React.FC = () => {
@@ -25,6 +27,30 @@ const AccountRecoveryScreen: React.FC = () => {
nextScreen: 'SaveRecoveryPhrase',
},
});
+ const { selectResponsiveValues, getResponsiveHorizontalPadding } = useCompactLayout();
+ const { bottom } = useSafeAreaInsets();
+
+ const {
+ iconSize,
+ iconPadding,
+ contentGap,
+ descriptionSize,
+ titleSize,
+ buttonStackGap,
+ buttonPaddingTop,
+ extraBottomPadding,
+ } = selectResponsiveValues({
+ iconSize: { compact: 64, regular: 80 },
+ iconPadding: { compact: '$4', regular: '$5' },
+ contentGap: { compact: '$2', regular: '$2.5' },
+ descriptionSize: { compact: 15, regular: 16 },
+ titleSize: { compact: 26, regular: 32 },
+ buttonStackGap: { compact: '$2', regular: '$2.5' },
+ buttonPaddingTop: { compact: '$4', regular: '$6' },
+ extraBottomPadding: { compact: 16, regular: 24 },
+ });
+ const horizontalPadding = getResponsiveHorizontalPadding({ percent: 0.06 });
+ const bottomPadding = bottom + extraBottomPadding;
return (
@@ -33,20 +59,28 @@ const AccountRecoveryScreen: React.FC = () => {
borderColor={slate600}
borderWidth="$1"
borderRadius="$10"
- padding="$5"
+ padding={iconPadding}
>
-
+
-
-
- Restore your Self account
-
+
+
+
+ Restore your Self account
+
+
By continuing, you certify that this passport belongs to you and is
not stolen or forged.
-
+
{
const { trackEvent } = useSelfClient();
const [mnemonic, setMnemonic] = useState();
const [restoring, setRestoring] = useState(false);
+ const { bottom } = useSafeAreaInsets();
+ const { height: screenHeight } = useCompactLayout();
+ const textAreaMinHeight = Math.max(160, screenHeight * 0.3);
const onPaste = useCallback(async () => {
const clipboard = (await Clipboard.getString()).trim();
if (ethers.Mnemonic.isValidMnemonic(clipboard)) {
@@ -111,67 +122,79 @@ const RecoverWithPhraseScreen: React.FC = () => {
]);
return (
-
-
- Your recovery phrase has 24 words. Enter the words in the correct order,
- separated by spaces.
-
-
-
-
-
- Continue
-
-
+
+
+ Your recovery phrase has 24 words. Enter the words in the correct
+ order, separated by spaces.
+
+
+
+
+
+ Continue
+
+
+
+
);
};
export default RecoverWithPhraseScreen;
const styles = StyleSheet.create({
+ flex: {
+ flex: 1,
+ },
layout: {
paddingTop: 30,
paddingLeft: 20,
paddingRight: 20,
backgroundColor: black,
- height: '100%',
},
pasteText: {
lineHeight: 20,
diff --git a/app/src/screens/app/LaunchScreen.tsx b/app/src/screens/app/LaunchScreen.tsx
index f2e42ef7f..4e67b119b 100644
--- a/app/src/screens/app/LaunchScreen.tsx
+++ b/app/src/screens/app/LaunchScreen.tsx
@@ -18,6 +18,7 @@ import { AppEvents } from '@selfxyz/mobile-sdk-alpha/constants/analytics';
import { privacyUrl, termsUrl } from '@/consts/links';
import useConnectionModal from '@/hooks/useConnectionModal';
import useHapticNavigation from '@/hooks/useHapticNavigation';
+import useCompactLayout from '@/hooks/useCompactLayout';
import IDCardPlaceholder from '@/images/icons/id_card_placeholder.svg';
import {
black,
@@ -34,6 +35,33 @@ const LaunchScreen: React.FC = () => {
const onPress = useHapticNavigation('CountryPicker');
const createMock = useHapticNavigation('CreateMock');
const { bottom } = useSafeAreaInsets();
+ const {
+ width: screenWidth,
+ height: screenHeight,
+ selectResponsiveValues,
+ getResponsiveHorizontalPadding,
+ } = useCompactLayout();
+ const cardWidth = Math.min(screenWidth * 0.8, 320);
+ const cardHeight = cardWidth * (180 / 300);
+ const {
+ titleSize,
+ bodySize,
+ heroSpacing,
+ baseTopPadding,
+ ctaPaddingTop,
+ } = selectResponsiveValues({
+ titleSize: { compact: 30, regular: 38, dimension: 'width' },
+ bodySize: { compact: 15, regular: 16, dimension: 'width' },
+ heroSpacing: { compact: 24, regular: 40, dimension: 'width' },
+ baseTopPadding: { compact: 32, regular: 60, dimension: 'width' },
+ ctaPaddingTop: { compact: 20, regular: 30, dimension: 'width' },
+ });
+ const bodyHorizontalMargin = getResponsiveHorizontalPadding({
+ percent: 0.08,
+ min: 20,
+ });
+ const topPadding = Math.max(screenHeight * 0.08, baseTopPadding);
+ const ctaPaddingHorizontal = getResponsiveHorizontalPadding({ percent: 0.07 });
const devModeTap = Gesture.Tap()
.numberOfTaps(5)
@@ -43,7 +71,7 @@ const LaunchScreen: React.FC = () => {
return (
-
+
{
borderRadius={14}
overflow="hidden"
>
-
+
{
Self is the easiest way to verify your identity safely wherever you
@@ -83,9 +111,9 @@ const LaunchScreen: React.FC = () => {
gap="$3"
width="100%"
alignItems="center"
- paddingHorizontal={20}
- paddingBottom={bottom}
- paddingTop={30}
+ paddingHorizontal={ctaPaddingHorizontal}
+ paddingBottom={bottom + 12}
+ paddingTop={ctaPaddingTop}
backgroundColor={zinc800}
>
{
const selfClient = useSelfClient();
+ const { selectResponsiveValues, getResponsiveHorizontalPadding } =
+ useCompactLayout();
+ const { headingSize, subheadingSize, verticalSpacing, sectionSpacing } =
+ selectResponsiveValues({
+ headingSize: { compact: 22, regular: 29, dimension: 'width' },
+ subheadingSize: { compact: 15, regular: 16, dimension: 'width' },
+ verticalSpacing: { compact: 16, regular: 24, dimension: 'width' },
+ sectionSpacing: { compact: '$4', regular: '$6', dimension: 'width' },
+ });
+ const paddingHorizontal = getResponsiveHorizontalPadding({ percent: 0.05 });
const { countryData, countryList, loading, userCountryCode, showSuggestion } =
useCountries();
@@ -132,12 +138,22 @@ const CountryPickerScreen: React.FC = () => {
return (
-
-
-
+
+
+
Select the country that issued your ID
-
+
Self has support for over 300 ID types. You can select the type of
ID in the next step
@@ -150,7 +166,7 @@ const CountryPickerScreen: React.FC = () => {
{
/>
SELECT AN ISSUING COUNTRY
diff --git a/app/src/screens/documents/selection/IDPickerScreen.tsx b/app/src/screens/documents/selection/IDPickerScreen.tsx
index f8d8d32d4..6c882d2d9 100644
--- a/app/src/screens/documents/selection/IDPickerScreen.tsx
+++ b/app/src/screens/documents/selection/IDPickerScreen.tsx
@@ -21,6 +21,7 @@ import PlusIcon from '@selfxyz/mobile-sdk-alpha/svgs/icons/plus.svg';
import SelfLogo from '@selfxyz/mobile-sdk-alpha/svgs/logo.svg';
import { DocumentFlowNavBar } from '@/components/NavBar/DocumentFlowNavBar';
+import useCompactLayout from '@/hooks/useCompactLayout';
import type { RootStackParamList } from '@/navigation';
import { black, slate100, slate300, slate400, white } from '@/utils/colors';
import { extraYPadding } from '@/utils/constants';
@@ -85,8 +86,27 @@ const IDPickerScreen: React.FC = () => {
const route = useRoute();
const { countryCode = '', documentTypes = [] } = route.params || {};
const bottom = useSafeAreaInsets().bottom;
+ const { selectResponsiveValues, getResponsiveHorizontalPadding } =
+ useCompactLayout();
const selfClient = useSelfClient();
+ const {
+ heroSpacing,
+ headingSize,
+ cardTitleSize,
+ descriptionSize,
+ helperTextSize,
+ sectionMarginBottom,
+ } = selectResponsiveValues({
+ heroSpacing: { compact: 32, regular: 48, dimension: 'width' },
+ headingSize: { compact: 24, regular: 29, dimension: 'width' },
+ cardTitleSize: { compact: 20, regular: 24, dimension: 'width' },
+ descriptionSize: { compact: 13, regular: 14, dimension: 'width' },
+ helperTextSize: { compact: 16, regular: 18, dimension: 'width' },
+ sectionMarginBottom: { compact: '$4', regular: '$6', dimension: 'width' },
+ });
+ const paddingHorizontal = getResponsiveHorizontalPadding({ percent: 0.05 });
+
const onSelectDocumentType = (docType: string) => {
buttonTap();
@@ -106,14 +126,14 @@ const IDPickerScreen: React.FC = () => {
backgroundColor={slate100}
paddingBottom={bottom + extraYPadding + 24}
>
-
-
-
+
+
+
{
{
{getDocumentLogo(docType)}
{getDocumentName(docType)}
{
))}
{
const navigation =
useNavigation>();
+ const { selectResponsiveValues, getResponsiveHorizontalPadding } = useCompactLayout();
+ const { bottom } = useSafeAreaInsets();
+
+ const {
+ topPadding,
+ gap,
+ stackMarginBottom,
+ titleSize,
+ descriptionSize,
+ bottomPaddingOffset,
+ contentBottomPadding,
+ } = selectResponsiveValues({
+ topPadding: { compact: 24, regular: 40 },
+ gap: { compact: 8, regular: 10 },
+ stackMarginBottom: { compact: 12, regular: 20 },
+ titleSize: { compact: 28, regular: 32 },
+ descriptionSize: { compact: 15, regular: 16 },
+ bottomPaddingOffset: { compact: 16, regular: 24 },
+ contentBottomPadding: { compact: 12, regular: 20 },
+ });
+ const horizontalPadding = getResponsiveHorizontalPadding({ percent: 0.06 });
+ const bottomPadding = bottom + bottomPaddingOffset;
return (
@@ -38,18 +62,23 @@ const AccountVerifiedSuccessScreen: React.FC = ({}) => {
renderMode="HARDWARE"
/>
-
+
- ID Verified
-
+
+ ID Verified
+
+
Your document's information is now protected by Self ID. Just scan a
participating partner's QR code to prove your identity.
diff --git a/app/src/screens/onboarding/DisclaimerScreen.tsx b/app/src/screens/onboarding/DisclaimerScreen.tsx
index 28a68253e..8072ba9d8 100644
--- a/app/src/screens/onboarding/DisclaimerScreen.tsx
+++ b/app/src/screens/onboarding/DisclaimerScreen.tsx
@@ -18,6 +18,7 @@ import { AppEvents } from '@selfxyz/mobile-sdk-alpha/constants/analytics';
import warningAnimation from '@/assets/animations/warning.json';
import { DelayedLottieView } from '@/components/DelayedLottieView';
import { ExpandableBottomLayout } from '@/layouts/ExpandableBottomLayout';
+import useCompactLayout from '@/hooks/useCompactLayout';
import type { RootStackParamList } from '@/navigation';
import { useSettingStore } from '@/stores/settingStore';
import { black, white } from '@/utils/colors';
@@ -27,6 +28,12 @@ const DisclaimerScreen: React.FC = () => {
const navigation =
useNavigation>();
const { dismissPrivacyNote } = useSettingStore();
+ const { selectResponsiveValues } = useCompactLayout({ compactHeight: 760 });
+ const { animationSize, buttonMargin, cautionSpacing } = selectResponsiveValues({
+ animationSize: { compact: '110%', regular: '125%', dimension: 'height' },
+ buttonMargin: { compact: 20, regular: 30, dimension: 'height' },
+ cautionSpacing: { compact: 6, regular: 10, dimension: 'height' },
+ });
useEffect(() => {
notificationWarning();
@@ -39,7 +46,7 @@ const DisclaimerScreen: React.FC = () => {
autoPlay
loop={false}
source={warningAnimation}
- style={styles.animation}
+ style={[styles.animation, { width: animationSize, height: animationSize }]}
cacheComposition={true}
renderMode="HARDWARE"
/>
@@ -54,12 +61,12 @@ const DisclaimerScreen: React.FC = () => {
(like passwords, Social Security numbers, or financial details)
should be trusted only if they're secure and necessary.
-
+
Always verify an app's legitimacy before sharing your data.
{
confirmTap();
dismissPrivacyNote();
diff --git a/app/src/screens/onboarding/SaveRecoveryPhraseScreen.tsx b/app/src/screens/onboarding/SaveRecoveryPhraseScreen.tsx
index 4b2b03550..433753a29 100644
--- a/app/src/screens/onboarding/SaveRecoveryPhraseScreen.tsx
+++ b/app/src/screens/onboarding/SaveRecoveryPhraseScreen.tsx
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: BUSL-1.1
// NOTE: Converts to Apache-2.0 on 2029-06-11 per LICENSE.
-import React, { useCallback, useState } from 'react';
+import React, { useCallback, useMemo, useState } from 'react';
import {
Caption,
@@ -16,6 +16,7 @@ import Mnemonic from '@/components/Mnemonic';
import useHapticNavigation from '@/hooks/useHapticNavigation';
import useMnemonic from '@/hooks/useMnemonic';
import { ExpandableBottomLayout } from '@/layouts/ExpandableBottomLayout';
+import useCompactLayout from '@/hooks/useCompactLayout';
import { useSettingStore } from '@/stores/settingStore';
import { STORAGE_NAME } from '@/utils/cloudBackup';
import { black, slate400, white } from '@/utils/colors';
@@ -24,6 +25,43 @@ const SaveRecoveryPhraseScreen: React.FC = () => {
const [userHasSeenMnemonic, setUserHasSeenMnemonic] = useState(false);
const { mnemonic, loadMnemonic } = useMnemonic();
const { cloudBackupEnabled } = useSettingStore();
+ const { selectResponsiveValues } = useCompactLayout({
+ compactHeight: 780,
+ });
+ const {
+ topPadding,
+ bottomPadding,
+ sectionGap,
+ titleFontSize,
+ titleLineHeight,
+ descriptionFontSize,
+ descriptionLineHeight,
+ } = selectResponsiveValues({
+ topPadding: { compact: 12, regular: 20, dimension: 'height' },
+ bottomPadding: { compact: 6, regular: 10, dimension: 'height' },
+ sectionGap: { compact: 6, regular: 10, dimension: 'height' },
+ titleFontSize: { compact: 26, regular: 28, dimension: 'width' },
+ titleLineHeight: { compact: 32, regular: 35, dimension: 'width' },
+ descriptionFontSize: { compact: 16, regular: 18, dimension: 'width' },
+ descriptionLineHeight: { compact: 21, regular: 23, dimension: 'width' },
+ });
+ const titleStyle = useMemo(
+ () => ({
+ paddingTop: topPadding,
+ textAlign: 'center',
+ fontSize: titleFontSize,
+ lineHeight: titleLineHeight,
+ }),
+ [titleFontSize, titleLineHeight, topPadding],
+ );
+ const descriptionStyle = useMemo(
+ () => ({
+ paddingBottom: bottomPadding,
+ fontSize: descriptionFontSize,
+ lineHeight: descriptionLineHeight,
+ }),
+ [bottomPadding, descriptionFontSize, descriptionLineHeight],
+ );
const onRevealWords = useCallback(async () => {
await loadMnemonic();
@@ -43,12 +81,12 @@ const SaveRecoveryPhraseScreen: React.FC = () => {
roundTop
backgroundColor={white}
justifyContent="space-between"
- gap={10}
+ gap={sectionGap}
>
-
+
Save your recovery phrase
-
+
This phrase is the only way to recover your account. Keep it secret,
keep it safe.
diff --git a/app/src/screens/shared/ComingSoonScreen.tsx b/app/src/screens/shared/ComingSoonScreen.tsx
index 8a480167d..952b31b17 100644
--- a/app/src/screens/shared/ComingSoonScreen.tsx
+++ b/app/src/screens/shared/ComingSoonScreen.tsx
@@ -5,6 +5,7 @@
import React, { useEffect, useMemo } from 'react';
import { XStack, YStack } from 'tamagui';
import type { RouteProp } from '@react-navigation/native';
+import { useSafeAreaInsets } from 'react-native-safe-area-context';
import { countryCodes } from '@selfxyz/common/constants';
import type { DocumentCategory } from '@selfxyz/common/types';
@@ -23,6 +24,7 @@ import { PassportEvents } from '@selfxyz/mobile-sdk-alpha/constants/analytics';
import useHapticNavigation from '@/hooks/useHapticNavigation';
import { ExpandableBottomLayout } from '@/layouts/ExpandableBottomLayout';
+import useCompactLayout from '@/hooks/useCompactLayout';
import analytics from '@/utils/analytics';
import { black, slate500, white } from '@/utils/colors';
import { sendCountrySupportNotification } from '@/utils/email';
@@ -48,6 +50,17 @@ const ComingSoonScreen: React.FC = ({ route }) => {
const selfClient = useSelfClient();
const navigateToLaunch = useHapticNavigation('Launch');
const navigateToHome = useHapticNavigation('Home');
+ const { selectResponsiveValues, getResponsiveHorizontalPadding } = useCompactLayout();
+ const { bottom } = useSafeAreaInsets();
+
+ const { topMargin, headlineSize, bodyFontSize, supportingSpacing } =
+ selectResponsiveValues({
+ topMargin: { compact: 48, regular: 100 },
+ headlineSize: { compact: 26, regular: 32 },
+ bodyFontSize: { compact: 15, regular: 17 },
+ supportingSpacing: { compact: 24, regular: 40 },
+ });
+ const sidePadding = getResponsiveHorizontalPadding({ percent: 0.06 });
const { countryName, countryCode, documentTypeText } = useMemo(() => {
try {
@@ -124,7 +137,7 @@ const ComingSoonScreen: React.FC = ({ route }) => {
flex={1}
justifyContent="center"
alignItems="center"
- marginTop={100}
+ marginTop={topMargin}
>
= ({ route }) => {
= ({ route }) => {
{documentTypeText
@@ -161,11 +174,11 @@ const ComingSoonScreen: React.FC = ({ route }) => {
Sign up for live updates.
@@ -175,8 +188,9 @@ const ComingSoonScreen: React.FC = ({ route }) => {