mirror of
https://github.com/selfxyz/self.git
synced 2026-02-19 02:24:25 -05:00
refactor(app): share homescreen card dimensions (#1733)
* refactor(app): share homescreen card dimensions * formatting * fix logic
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
|
||||
import type { FC } from 'react';
|
||||
import React from 'react';
|
||||
import { Dimensions, Image, StyleSheet } from 'react-native';
|
||||
import { Image } from 'react-native';
|
||||
import { Text, XStack, YStack } from 'tamagui';
|
||||
|
||||
import {
|
||||
@@ -18,6 +18,8 @@ import { dinot } from '@selfxyz/mobile-sdk-alpha/constants/fonts';
|
||||
|
||||
import SelfLogoUnverified from '@/assets/images/self_logo_unverified.svg';
|
||||
import WavePatternBody from '@/assets/images/wave_pattern_body.png';
|
||||
import { cardStyles } from '@/components/homescreen/cardStyles';
|
||||
import { useCardDimensions } from '@/hooks/useCardDimensions';
|
||||
|
||||
interface EmptyIdCardProps {
|
||||
onRegisterPress: () => void;
|
||||
@@ -32,32 +34,23 @@ interface EmptyIdCardProps {
|
||||
* - Pill-shaped white button with gray border
|
||||
*/
|
||||
const EmptyIdCard: FC<EmptyIdCardProps> = ({ onRegisterPress }) => {
|
||||
const { width: screenWidth } = Dimensions.get('window');
|
||||
|
||||
// Card dimensions (matching IdCardLayout)
|
||||
const cardWidth = screenWidth * 0.95 - 16;
|
||||
const cardHeight = cardWidth * 0.635;
|
||||
const borderRadius = 12;
|
||||
|
||||
// Figma exact dimensions (scaled from 353px reference width)
|
||||
const scale = cardWidth / 353;
|
||||
const headerHeight = 67 * scale;
|
||||
const figmaPadding = 14 * scale;
|
||||
const logoSize = 32 * scale;
|
||||
const headerGap = 12 * scale;
|
||||
|
||||
// Font sizes from Figma
|
||||
const fontSize = {
|
||||
header: 20 * scale, // 20px in Figma
|
||||
subtitle: 7 * scale, // 7px in Figma
|
||||
button: 16 * scale, // 16px in Figma
|
||||
};
|
||||
const {
|
||||
cardWidth,
|
||||
borderRadius,
|
||||
scale,
|
||||
headerHeight,
|
||||
figmaPadding,
|
||||
logoSize,
|
||||
headerGap,
|
||||
expandedAspectRatio,
|
||||
fontSize,
|
||||
} = useCardDimensions();
|
||||
|
||||
return (
|
||||
<YStack width="100%" alignItems="center" justifyContent="center">
|
||||
<YStack
|
||||
width={cardWidth}
|
||||
height={cardHeight}
|
||||
aspectRatio={expandedAspectRatio}
|
||||
borderRadius={borderRadius}
|
||||
overflow="hidden"
|
||||
borderWidth={1}
|
||||
@@ -114,11 +107,11 @@ const EmptyIdCard: FC<EmptyIdCardProps> = ({ onRegisterPress }) => {
|
||||
</YStack>
|
||||
|
||||
{/* Body Section - White background with wave pattern */}
|
||||
<YStack style={styles.body}>
|
||||
<YStack style={[cardStyles.body, { backgroundColor: white }]}>
|
||||
{/* Wave pattern background - exact same as unverified_human.png */}
|
||||
<Image
|
||||
source={WavePatternBody}
|
||||
style={styles.wavePattern}
|
||||
style={cardStyles.wavePattern}
|
||||
resizeMode="cover"
|
||||
/>
|
||||
|
||||
@@ -158,22 +151,4 @@ const EmptyIdCard: FC<EmptyIdCardProps> = ({ onRegisterPress }) => {
|
||||
);
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
body: {
|
||||
flex: 1,
|
||||
position: 'relative',
|
||||
overflow: 'hidden',
|
||||
backgroundColor: 'white',
|
||||
},
|
||||
wavePattern: {
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
},
|
||||
});
|
||||
|
||||
export default EmptyIdCard;
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
import type { FC } from 'react';
|
||||
import React from 'react';
|
||||
import { Dimensions, Image, StyleSheet } from 'react-native';
|
||||
import { Image } from 'react-native';
|
||||
import { Text, XStack, YStack } from 'tamagui';
|
||||
|
||||
import {
|
||||
@@ -17,6 +17,8 @@ import { dinot } from '@selfxyz/mobile-sdk-alpha/constants/fonts';
|
||||
|
||||
import SelfLogoInactive from '@/assets/images/self_logo_inactive.svg';
|
||||
import WavePatternBody from '@/assets/images/wave_pattern_body.png';
|
||||
import { cardStyles } from '@/components/homescreen/cardStyles';
|
||||
import { useCardDimensions } from '@/hooks/useCardDimensions';
|
||||
|
||||
/**
|
||||
* Expired state card shown when user's identity document has expired.
|
||||
@@ -27,31 +29,23 @@ import WavePatternBody from '@/assets/images/wave_pattern_body.png';
|
||||
* - Black "EXPIRED ID" badge in bottom right
|
||||
*/
|
||||
const ExpiredIdCard: FC = () => {
|
||||
const { width: screenWidth } = Dimensions.get('window');
|
||||
|
||||
// Card dimensions (matching IdCardLayout)
|
||||
const cardWidth = screenWidth * 0.95 - 16;
|
||||
const cardHeight = cardWidth * 0.635;
|
||||
const borderRadius = 12;
|
||||
|
||||
// Figma exact dimensions (scaled from 353px reference width)
|
||||
const scale = cardWidth / 353;
|
||||
const headerHeight = 67 * scale;
|
||||
const figmaPadding = 14 * scale;
|
||||
const logoSize = 32 * scale;
|
||||
const headerGap = 12 * scale;
|
||||
|
||||
// Font sizes from Figma
|
||||
const fontSize = {
|
||||
header: 20 * scale, // 20px in Figma
|
||||
subtitle: 7 * scale, // 7px in Figma
|
||||
};
|
||||
const {
|
||||
cardWidth,
|
||||
borderRadius,
|
||||
scale,
|
||||
headerHeight,
|
||||
figmaPadding,
|
||||
logoSize,
|
||||
headerGap,
|
||||
expandedAspectRatio,
|
||||
fontSize,
|
||||
} = useCardDimensions();
|
||||
|
||||
return (
|
||||
<YStack width="100%" alignItems="center" justifyContent="center">
|
||||
<YStack
|
||||
width={cardWidth}
|
||||
height={cardHeight}
|
||||
aspectRatio={expandedAspectRatio}
|
||||
borderRadius={borderRadius}
|
||||
overflow="hidden"
|
||||
borderWidth={1}
|
||||
@@ -113,11 +107,11 @@ const ExpiredIdCard: FC = () => {
|
||||
</YStack>
|
||||
|
||||
{/* Body Section - White background with wave pattern */}
|
||||
<YStack flex={1} position="relative" overflow="hidden">
|
||||
<YStack style={cardStyles.body}>
|
||||
{/* Wave pattern background */}
|
||||
<Image
|
||||
source={WavePatternBody}
|
||||
style={styles.wavePattern}
|
||||
style={cardStyles.wavePattern}
|
||||
resizeMode="cover"
|
||||
/>
|
||||
|
||||
@@ -133,7 +127,7 @@ const ExpiredIdCard: FC = () => {
|
||||
>
|
||||
<Text
|
||||
fontFamily={dinot}
|
||||
fontSize={10 * scale}
|
||||
fontSize={fontSize.badge}
|
||||
fontWeight="500"
|
||||
color={white}
|
||||
letterSpacing={0.6}
|
||||
@@ -148,16 +142,4 @@ const ExpiredIdCard: FC = () => {
|
||||
);
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
wavePattern: {
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
},
|
||||
});
|
||||
|
||||
export default ExpiredIdCard;
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
import type { FC } from 'react';
|
||||
import React from 'react';
|
||||
import { Dimensions, Image, StyleSheet } from 'react-native';
|
||||
import { Image, StyleSheet } from 'react-native';
|
||||
import LinearGradient from 'react-native-linear-gradient';
|
||||
import { Text, XStack, YStack } from 'tamagui';
|
||||
|
||||
@@ -31,7 +31,9 @@ import DevCardWave from '@/assets/images/dev_card_wave.svg';
|
||||
import SelfLogoPending from '@/assets/images/self_logo_pending.svg';
|
||||
import WaveOverlay from '@/assets/images/wave_overlay.png';
|
||||
import { getSecurityLevel } from '@/components/homescreen/cardSecurityBadge';
|
||||
import { cardStyles } from '@/components/homescreen/cardStyles';
|
||||
import KycIdCard from '@/components/homescreen/KycIdCard';
|
||||
import { useCardDimensions } from '@/hooks/useCardDimensions';
|
||||
import { getBackgroundIndex } from '@/utils/cardBackgroundSelector';
|
||||
import { getDocumentAttributes } from '@/utils/documentAttributes';
|
||||
|
||||
@@ -292,6 +294,19 @@ const IdCardLayout: FC<IdCardLayoutAttributes> = ({
|
||||
selected,
|
||||
hidden,
|
||||
}) => {
|
||||
// Call hooks at the top, before any conditional returns
|
||||
const {
|
||||
cardWidth,
|
||||
cardHeight,
|
||||
borderRadius,
|
||||
scale,
|
||||
headerHeight,
|
||||
figmaPadding,
|
||||
logoSize,
|
||||
headerGap,
|
||||
fontSize,
|
||||
} = useCardDimensions(selected);
|
||||
|
||||
if (!idDocument) {
|
||||
return null;
|
||||
}
|
||||
@@ -302,13 +317,6 @@ const IdCardLayout: FC<IdCardLayoutAttributes> = ({
|
||||
<KycIdCard idDocument={idDocument} selected={selected} hidden={hidden} />
|
||||
);
|
||||
}
|
||||
|
||||
const { width: screenWidth } = Dimensions.get('window');
|
||||
|
||||
// Card dimensions (matching Figma: 353x224 for expanded, 353x67 for header only)
|
||||
const cardWidth = screenWidth * 0.95 - 16;
|
||||
const cardHeight = selected ? cardWidth * 0.635 : cardWidth * 0.19;
|
||||
const borderRadius = 12;
|
||||
const padding = cardWidth * 0.04;
|
||||
|
||||
// Get document attributes
|
||||
@@ -358,14 +366,7 @@ const IdCardLayout: FC<IdCardLayoutAttributes> = ({
|
||||
// Bottom label (uses demonym: "AMERICAN PASSPORT")
|
||||
const bottomLabel = `${countryDemonym} ${getDocumentTypeLabel()}`;
|
||||
|
||||
// Figma exact dimensions (scaled from 353px reference width)
|
||||
const scale = cardWidth / 353;
|
||||
const headerHeight = 67 * scale;
|
||||
const bodyHeight = 157 * scale;
|
||||
const figmaPadding = 14 * scale;
|
||||
const logoCircleSize = 32 * scale;
|
||||
const logoIconSize = 32 * scale;
|
||||
const headerGap = 12 * scale;
|
||||
const bodyHeight = cardHeight - headerHeight;
|
||||
|
||||
// Get truncated selfId for display (e.g., "0xd9..b94")
|
||||
const getTruncatedId = (): string => {
|
||||
@@ -397,15 +398,6 @@ const IdCardLayout: FC<IdCardLayoutAttributes> = ({
|
||||
|
||||
const truncatedId = getTruncatedId();
|
||||
|
||||
// Font sizes
|
||||
const fontSize = {
|
||||
header: cardWidth * 0.057, // 20px at 353px width
|
||||
subtitle: cardWidth * 0.02, // 7px at 353px width
|
||||
badge: cardWidth * 0.028, // 10px at 353px width
|
||||
bottomLabel: cardWidth * 0.043, // 15px at 353px width
|
||||
bottomId: cardWidth * 0.028, // 10px at 353px width
|
||||
};
|
||||
|
||||
return (
|
||||
<YStack width="100%" alignItems="center" justifyContent="center">
|
||||
<YStack
|
||||
@@ -442,22 +434,19 @@ const IdCardLayout: FC<IdCardLayoutAttributes> = ({
|
||||
{isMockDocument ? (
|
||||
// Dev card: Self logo (white) in grey circle - exact Figma asset
|
||||
<YStack
|
||||
width={logoCircleSize}
|
||||
height={logoCircleSize}
|
||||
borderRadius={logoCircleSize / 2}
|
||||
width={logoSize}
|
||||
height={logoSize}
|
||||
borderRadius={logoSize / 2}
|
||||
backgroundColor={DEV_LOGO_BG}
|
||||
alignItems="center"
|
||||
justifyContent="center"
|
||||
overflow="hidden"
|
||||
>
|
||||
<DevCardLogo width={logoIconSize} height={logoIconSize} />
|
||||
<DevCardLogo width={logoSize} height={logoSize} />
|
||||
</YStack>
|
||||
) : (
|
||||
// Real document: Country flag
|
||||
<RoundFlag
|
||||
countryCode={nationalityCode}
|
||||
size={logoCircleSize}
|
||||
/>
|
||||
<RoundFlag countryCode={nationalityCode} size={logoSize} />
|
||||
)}
|
||||
{/* Text container */}
|
||||
<YStack gap={2}>
|
||||
@@ -488,7 +477,7 @@ const IdCardLayout: FC<IdCardLayoutAttributes> = ({
|
||||
// Empty spacer matching Figma (85x19)
|
||||
<YStack width={85 * scale} height={19 * scale} />
|
||||
) : (
|
||||
<SelfLogoPending width={logoCircleSize} height={logoCircleSize} />
|
||||
<SelfLogoPending width={logoSize} height={logoSize} />
|
||||
)}
|
||||
</XStack>
|
||||
</LinearGradient>
|
||||
@@ -509,7 +498,7 @@ const IdCardLayout: FC<IdCardLayoutAttributes> = ({
|
||||
// Dev card body - solid indigo background with wave pattern (exact Figma)
|
||||
<YStack
|
||||
style={[
|
||||
styles.body,
|
||||
cardStyles.body,
|
||||
{ backgroundColor: DEV_BODY_COLOR, height: bodyHeight },
|
||||
]}
|
||||
>
|
||||
@@ -531,11 +520,11 @@ const IdCardLayout: FC<IdCardLayoutAttributes> = ({
|
||||
</YStack>
|
||||
) : (
|
||||
// Real document body - gradient background with wave overlay
|
||||
<YStack style={styles.body}>
|
||||
<YStack style={cardStyles.body}>
|
||||
{/* Gradient background */}
|
||||
<Image
|
||||
source={cardBackground}
|
||||
style={styles.backgroundImage}
|
||||
style={cardStyles.backgroundImage}
|
||||
resizeMode="cover"
|
||||
/>
|
||||
{/* Wave pattern overlay */}
|
||||
@@ -608,20 +597,6 @@ const styles = StyleSheet.create({
|
||||
justifyContent: 'center',
|
||||
width: '100%',
|
||||
},
|
||||
body: {
|
||||
flex: 1,
|
||||
position: 'relative',
|
||||
overflow: 'hidden',
|
||||
},
|
||||
backgroundImage: {
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
},
|
||||
waveOverlay: {
|
||||
position: 'absolute',
|
||||
top: -10,
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
import type { FC } from 'react';
|
||||
import React from 'react';
|
||||
import { Dimensions, Image, StyleSheet, View } from 'react-native';
|
||||
import { Image, View } from 'react-native';
|
||||
import LinearGradient from 'react-native-linear-gradient';
|
||||
import { Text, XStack, YStack } from 'tamagui';
|
||||
|
||||
@@ -17,6 +17,8 @@ import { dinot, plexMono } from '@selfxyz/mobile-sdk-alpha/constants/fonts';
|
||||
|
||||
import CardBackgroundId1 from '@/assets/images/card_background_id1.png';
|
||||
import SelfLogoPending from '@/assets/images/self_logo_pending.svg';
|
||||
import { cardStyles } from '@/components/homescreen/cardStyles';
|
||||
import { useCardDimensions } from '@/hooks/useCardDimensions';
|
||||
|
||||
interface KycIdCardProps {
|
||||
idDocument: KycData;
|
||||
@@ -118,21 +120,18 @@ const KycIdCard: FC<KycIdCardProps> = ({
|
||||
const docTitle = getKycDocTitle(idType);
|
||||
const countryAdj = getCountryAdjective(country);
|
||||
|
||||
const { width: screenWidth } = Dimensions.get('window');
|
||||
|
||||
// Card dimensions (matching IdCard: 353x224 for expanded, 353x67 for header only)
|
||||
const cardWidth = screenWidth * 0.95 - 16;
|
||||
const cardHeight = selected ? cardWidth * 0.635 : cardWidth * 0.19;
|
||||
const borderRadius = 12;
|
||||
const {
|
||||
cardWidth,
|
||||
cardHeight,
|
||||
borderRadius,
|
||||
headerHeight,
|
||||
figmaPadding,
|
||||
logoSize,
|
||||
headerGap,
|
||||
fontSize,
|
||||
} = useCardDimensions(selected);
|
||||
const padding = cardWidth * 0.04;
|
||||
|
||||
// Figma exact dimensions (scaled from 353px reference width)
|
||||
const scale = cardWidth / 353;
|
||||
const headerHeight = 67 * scale;
|
||||
const figmaPadding = 14 * scale;
|
||||
const logoCircleSize = 32 * scale;
|
||||
const headerGap = 12 * scale;
|
||||
|
||||
// Get truncated ID for display (e.g., "0xD123..345")
|
||||
const getTruncatedId = (): string => {
|
||||
if (idNumber && idNumber.length > 10) {
|
||||
@@ -152,15 +151,6 @@ const KycIdCard: FC<KycIdCardProps> = ({
|
||||
// Bottom label (e.g., "US DRIVERS LICENSE")
|
||||
const bottomLabel = `${countryAdj} ${docTitle}`;
|
||||
|
||||
// Font sizes (matching IdCard exactly)
|
||||
const fontSize = {
|
||||
header: cardWidth * 0.057, // 20px at 353px width
|
||||
subtitle: cardWidth * 0.02, // 7px at 353px width
|
||||
badge: cardWidth * 0.028, // 10px at 353px width
|
||||
bottomLabel: cardWidth * 0.043, // 15px at 353px width
|
||||
bottomId: cardWidth * 0.028, // 10px at 353px width
|
||||
};
|
||||
|
||||
return (
|
||||
<YStack width="100%" alignItems="center" justifyContent="center">
|
||||
<YStack
|
||||
@@ -194,7 +184,7 @@ const KycIdCard: FC<KycIdCardProps> = ({
|
||||
{/* Logo + Text */}
|
||||
<XStack alignItems="center" gap={headerGap}>
|
||||
{/* Country flag */}
|
||||
<RoundFlag countryCode={country} size={logoCircleSize} />
|
||||
<RoundFlag countryCode={country} size={logoSize} />
|
||||
|
||||
{/* Text container */}
|
||||
<YStack gap={2}>
|
||||
@@ -221,20 +211,17 @@ const KycIdCard: FC<KycIdCardProps> = ({
|
||||
</XStack>
|
||||
|
||||
{/* Self logo on right */}
|
||||
<SelfLogoPending
|
||||
width={logoCircleSize * 0.56 * 5}
|
||||
height={logoCircleSize}
|
||||
/>
|
||||
<SelfLogoPending width={logoSize * 0.56 * 5} height={logoSize} />
|
||||
</LinearGradient>
|
||||
</View>
|
||||
|
||||
{/* Body Section - Colorful wave pattern (same as IdCard real documents) */}
|
||||
{selected && (
|
||||
<YStack flex={1} position="relative" overflow="hidden">
|
||||
<YStack style={cardStyles.body}>
|
||||
{/* Pre-composited background image (colorful gradient + chrome wave) */}
|
||||
<Image
|
||||
source={CardBackgroundId1}
|
||||
style={styles.backgroundImage}
|
||||
style={cardStyles.backgroundImage}
|
||||
resizeMode="cover"
|
||||
/>
|
||||
|
||||
@@ -296,16 +283,4 @@ const KycIdCard: FC<KycIdCardProps> = ({
|
||||
);
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
backgroundImage: {
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
},
|
||||
});
|
||||
|
||||
export default KycIdCard;
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
import type { FC } from 'react';
|
||||
import React from 'react';
|
||||
import { Dimensions, Image, StyleSheet } from 'react-native';
|
||||
import { Image } from 'react-native';
|
||||
import { Text, XStack, YStack } from 'tamagui';
|
||||
|
||||
import {
|
||||
@@ -20,6 +20,8 @@ import { dinot } from '@selfxyz/mobile-sdk-alpha/constants/fonts';
|
||||
|
||||
import SelfLogoPending from '@/assets/images/self_logo_pending.svg';
|
||||
import WavePatternPending from '@/assets/images/wave_pattern_pending.png';
|
||||
import { cardStyles } from '@/components/homescreen/cardStyles';
|
||||
import { useCardDimensions } from '@/hooks/useCardDimensions';
|
||||
|
||||
interface PendingIdCardProps {
|
||||
onClick?: () => void;
|
||||
@@ -35,31 +37,23 @@ interface PendingIdCardProps {
|
||||
* - Yellow "Pending" badge in bottom right
|
||||
*/
|
||||
const PendingIdCard: FC<PendingIdCardProps> = ({ onClick }) => {
|
||||
const { width: screenWidth } = Dimensions.get('window');
|
||||
|
||||
// Card dimensions (matching IdCardLayout)
|
||||
const cardWidth = screenWidth * 0.95 - 16;
|
||||
const cardHeight = cardWidth * 0.635;
|
||||
const borderRadius = 12;
|
||||
|
||||
// Figma exact dimensions (scaled from 353px reference width)
|
||||
const scale = cardWidth / 353;
|
||||
const headerHeight = 67 * scale;
|
||||
const figmaPadding = 14 * scale;
|
||||
const logoSize = 32 * scale;
|
||||
const headerGap = 12 * scale;
|
||||
|
||||
// Font sizes from Figma
|
||||
const fontSize = {
|
||||
header: 20 * scale, // 20px in Figma
|
||||
subtitle: 7 * scale, // 7px in Figma
|
||||
};
|
||||
const {
|
||||
cardWidth,
|
||||
borderRadius,
|
||||
scale,
|
||||
headerHeight,
|
||||
figmaPadding,
|
||||
logoSize,
|
||||
headerGap,
|
||||
expandedAspectRatio,
|
||||
fontSize,
|
||||
} = useCardDimensions();
|
||||
|
||||
return (
|
||||
<YStack width="100%" alignItems="center" justifyContent="center">
|
||||
<YStack
|
||||
width={cardWidth}
|
||||
height={cardHeight}
|
||||
aspectRatio={expandedAspectRatio}
|
||||
borderRadius={borderRadius}
|
||||
overflow="hidden"
|
||||
borderWidth={1}
|
||||
@@ -129,11 +123,11 @@ const PendingIdCard: FC<PendingIdCardProps> = ({ onClick }) => {
|
||||
</YStack>
|
||||
|
||||
{/* Body Section */}
|
||||
<YStack flex={1} position="relative" overflow="hidden">
|
||||
<YStack style={cardStyles.body}>
|
||||
{/* Wave pattern background */}
|
||||
<Image
|
||||
source={WavePatternPending}
|
||||
style={styles.wavePattern}
|
||||
style={cardStyles.wavePattern}
|
||||
resizeMode="cover"
|
||||
/>
|
||||
|
||||
@@ -149,7 +143,7 @@ const PendingIdCard: FC<PendingIdCardProps> = ({ onClick }) => {
|
||||
>
|
||||
<Text
|
||||
fontFamily={dinot}
|
||||
fontSize={10 * scale}
|
||||
fontSize={fontSize.badge}
|
||||
fontWeight="500"
|
||||
color={amber700}
|
||||
letterSpacing={0.6}
|
||||
@@ -164,16 +158,4 @@ const PendingIdCard: FC<PendingIdCardProps> = ({ onClick }) => {
|
||||
);
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
wavePattern: {
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
},
|
||||
});
|
||||
|
||||
export default PendingIdCard;
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
import type { FC } from 'react';
|
||||
import React from 'react';
|
||||
import { Dimensions, Image, StyleSheet } from 'react-native';
|
||||
import { Image } from 'react-native';
|
||||
import { Text, XStack, YStack } from 'tamagui';
|
||||
|
||||
import {
|
||||
@@ -16,6 +16,8 @@ import { dinot } from '@selfxyz/mobile-sdk-alpha/constants/fonts';
|
||||
|
||||
import SelfLogoInactive from '@/assets/images/self_logo_inactive.svg';
|
||||
import WavePatternBody from '@/assets/images/wave_pattern_body.png';
|
||||
import { cardStyles } from '@/components/homescreen/cardStyles';
|
||||
import { useCardDimensions } from '@/hooks/useCardDimensions';
|
||||
|
||||
interface UnregisteredIdCardProps {
|
||||
onRegisterPress: () => void;
|
||||
@@ -33,32 +35,23 @@ interface UnregisteredIdCardProps {
|
||||
const UnregisteredIdCard: FC<UnregisteredIdCardProps> = ({
|
||||
onRegisterPress,
|
||||
}) => {
|
||||
const { width: screenWidth } = Dimensions.get('window');
|
||||
|
||||
// Card dimensions (matching IdCardLayout)
|
||||
const cardWidth = screenWidth * 0.95 - 16;
|
||||
const cardHeight = cardWidth * 0.635;
|
||||
const borderRadius = 12;
|
||||
|
||||
// Figma exact dimensions (scaled from 353px reference width)
|
||||
const scale = cardWidth / 353;
|
||||
const headerHeight = 67 * scale;
|
||||
const figmaPadding = 14 * scale;
|
||||
const logoSize = 32 * scale;
|
||||
const headerGap = 12 * scale;
|
||||
|
||||
// Font sizes from Figma
|
||||
const fontSize = {
|
||||
header: 20 * scale, // 20px in Figma
|
||||
subtitle: 7 * scale, // 7px in Figma
|
||||
button: 16 * scale, // 16px in Figma
|
||||
};
|
||||
const {
|
||||
cardWidth,
|
||||
borderRadius,
|
||||
scale,
|
||||
headerHeight,
|
||||
figmaPadding,
|
||||
logoSize,
|
||||
headerGap,
|
||||
expandedAspectRatio,
|
||||
fontSize,
|
||||
} = useCardDimensions();
|
||||
|
||||
return (
|
||||
<YStack width="100%" alignItems="center" justifyContent="center">
|
||||
<YStack
|
||||
width={cardWidth}
|
||||
height={cardHeight}
|
||||
aspectRatio={expandedAspectRatio}
|
||||
borderRadius={borderRadius}
|
||||
overflow="hidden"
|
||||
borderWidth={1}
|
||||
@@ -120,11 +113,11 @@ const UnregisteredIdCard: FC<UnregisteredIdCardProps> = ({
|
||||
</YStack>
|
||||
|
||||
{/* Body Section - White background with wave pattern */}
|
||||
<YStack style={styles.body}>
|
||||
<YStack style={[cardStyles.body, { backgroundColor: white }]}>
|
||||
{/* Wave pattern background */}
|
||||
<Image
|
||||
source={WavePatternBody}
|
||||
style={styles.wavePattern}
|
||||
style={cardStyles.wavePattern}
|
||||
resizeMode="cover"
|
||||
/>
|
||||
|
||||
@@ -162,22 +155,4 @@ const UnregisteredIdCard: FC<UnregisteredIdCardProps> = ({
|
||||
);
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
body: {
|
||||
flex: 1,
|
||||
position: 'relative',
|
||||
overflow: 'hidden',
|
||||
backgroundColor: 'white',
|
||||
},
|
||||
wavePattern: {
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
},
|
||||
});
|
||||
|
||||
export default UnregisteredIdCard;
|
||||
|
||||
31
app/src/components/homescreen/cardStyles.ts
Normal file
31
app/src/components/homescreen/cardStyles.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
// 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 { StyleSheet } from 'react-native';
|
||||
|
||||
export const cardStyles = StyleSheet.create({
|
||||
backgroundImage: {
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
},
|
||||
wavePattern: {
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
},
|
||||
body: {
|
||||
flex: 1,
|
||||
position: 'relative',
|
||||
overflow: 'hidden',
|
||||
},
|
||||
});
|
||||
81
app/src/hooks/useCardDimensions.ts
Normal file
81
app/src/hooks/useCardDimensions.ts
Normal file
@@ -0,0 +1,81 @@
|
||||
// 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 { useWindowDimensions } from 'react-native';
|
||||
|
||||
const CARD_WIDTH_FACTOR = 0.95;
|
||||
const CARD_HORIZONTAL_OFFSET = 16;
|
||||
|
||||
// Figma reference dimensions
|
||||
const FIGMA_CARD_WIDTH = 353;
|
||||
const FIGMA_CARD_HEIGHT = 224;
|
||||
const FIGMA_HEADER_HEIGHT = 67;
|
||||
const FIGMA_PADDING = 14;
|
||||
const FIGMA_LOGO_SIZE = 32;
|
||||
const FIGMA_HEADER_GAP = 12;
|
||||
const FIGMA_HEADER_FONT_SIZE = 20;
|
||||
const FIGMA_SUBTITLE_FONT_SIZE = 7;
|
||||
const FIGMA_BADGE_FONT_SIZE = 10;
|
||||
const FIGMA_BOTTOM_LABEL_FONT_SIZE = 15;
|
||||
const FIGMA_BOTTOM_ID_FONT_SIZE = 10;
|
||||
const FIGMA_BUTTON_FONT_SIZE = 16;
|
||||
const FIGMA_BORDER_RADIUS = 12;
|
||||
|
||||
export interface CardDimensions {
|
||||
cardWidth: number;
|
||||
cardHeight: number;
|
||||
borderRadius: number;
|
||||
scale: number;
|
||||
headerHeight: number;
|
||||
figmaPadding: number;
|
||||
logoSize: number;
|
||||
headerGap: number;
|
||||
expandedAspectRatio: number;
|
||||
collapsedAspectRatio: number;
|
||||
fontSize: CardFontSizes;
|
||||
}
|
||||
|
||||
export interface CardFontSizes {
|
||||
header: number;
|
||||
subtitle: number;
|
||||
badge: number;
|
||||
bottomLabel: number;
|
||||
bottomId: number;
|
||||
button: number;
|
||||
}
|
||||
|
||||
export function useCardDimensions(selected = true): CardDimensions {
|
||||
const { width } = useWindowDimensions();
|
||||
|
||||
const cardWidth = width * CARD_WIDTH_FACTOR - CARD_HORIZONTAL_OFFSET;
|
||||
const scale = cardWidth / FIGMA_CARD_WIDTH;
|
||||
|
||||
const expandedAspectRatio = FIGMA_CARD_WIDTH / FIGMA_CARD_HEIGHT;
|
||||
const collapsedAspectRatio = FIGMA_CARD_WIDTH / FIGMA_HEADER_HEIGHT;
|
||||
|
||||
return {
|
||||
cardWidth,
|
||||
cardHeight: selected
|
||||
? cardWidth / expandedAspectRatio
|
||||
: cardWidth / collapsedAspectRatio,
|
||||
borderRadius: FIGMA_BORDER_RADIUS,
|
||||
scale,
|
||||
headerHeight: FIGMA_HEADER_HEIGHT * scale,
|
||||
figmaPadding: FIGMA_PADDING * scale,
|
||||
logoSize: FIGMA_LOGO_SIZE * scale,
|
||||
headerGap: FIGMA_HEADER_GAP * scale,
|
||||
expandedAspectRatio,
|
||||
collapsedAspectRatio,
|
||||
fontSize: {
|
||||
header: FIGMA_HEADER_FONT_SIZE * scale,
|
||||
subtitle: FIGMA_SUBTITLE_FONT_SIZE * scale,
|
||||
badge: FIGMA_BADGE_FONT_SIZE * scale,
|
||||
bottomLabel: FIGMA_BOTTOM_LABEL_FONT_SIZE * scale,
|
||||
bottomId: FIGMA_BOTTOM_ID_FONT_SIZE * scale,
|
||||
button: FIGMA_BUTTON_FONT_SIZE * scale,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export default useCardDimensions;
|
||||
Reference in New Issue
Block a user