UI tweaks (#771)

This commit is contained in:
Leendert de Borst
2025-05-06 12:41:53 +02:00
parent e6ab1be77f
commit e714d8563c
13 changed files with 104 additions and 79 deletions

View File

@@ -439,6 +439,10 @@ export default function AddEditCredentialScreen() : React.ReactNode {
padding: 10,
paddingLeft: 0,
},
headerLeftButtonText: {
color: colors.primary,
fontSize: 20,
},
headerRightButton: {
padding: 10,
paddingRight: 0,
@@ -492,7 +496,7 @@ export default function AddEditCredentialScreen() : React.ReactNode {
onPress={() => router.back()}
style={styles.headerLeftButton}
>
<ThemedText style={{ color: colors.primary }}>Cancel</ThemedText>
<ThemedText style={styles.headerLeftButtonText}>Cancel</ThemedText>
</TouchableOpacity>
),
/**
@@ -507,7 +511,7 @@ export default function AddEditCredentialScreen() : React.ReactNode {
</TouchableOpacity>
),
});
}, [navigation, mode, handleSubmit, onSubmit, colors.primary, isEditMode, router, styles.headerLeftButton, styles.headerRightButton]);
}, [navigation, mode, handleSubmit, onSubmit, colors.primary, isEditMode, router, styles.headerLeftButton, styles.headerLeftButtonText, styles.headerRightButton]);
return (
<>

View File

@@ -190,13 +190,12 @@ export default function CredentialsScreen() : React.ReactNode {
},
content: {
flex: 1,
marginTop: 36,
padding: 16,
paddingTop: 0,
},
contentContainer: {
paddingBottom: 40,
paddingTop: 4,
paddingTop: 42,
},
emptyText: {
color: colors.textMuted,

View File

@@ -165,12 +165,11 @@ export default function EmailsScreen() : React.ReactNode {
},
content: {
flex: 1,
marginTop: 22,
padding: 16,
},
contentContainer: {
paddingBottom: 40,
paddingTop: 4,
paddingTop: 26,
},
emptyText: {
color: colors.textMuted,

View File

@@ -56,13 +56,16 @@ export default function AutoLockScreen() : React.ReactNode {
borderBottomWidth: StyleSheet.hairlineWidth,
flexDirection: 'row',
paddingHorizontal: 16,
paddingVertical: 16,
paddingVertical: 14,
},
optionContainer: {
backgroundColor: colors.accentBackground,
borderRadius: 10,
margin: 16,
},
optionLast: {
borderBottomWidth: 0,
},
optionText: {
color: colors.text,
flex: 1,
@@ -83,21 +86,24 @@ export default function AutoLockScreen() : React.ReactNode {
</ThemedText>
</View>
<View style={styles.optionContainer}>
{timeoutOptions.map((option) => (
<TouchableOpacity
key={option.value}
style={styles.option}
onPress={() => {
setAutoLockTimeout(option.value);
setAutoLockTimeoutState(option.value);
}}
>
<ThemedText style={styles.optionText}>{option.label}</ThemedText>
{autoLockTimeout === option.value && (
<Ionicons name="checkmark" size={24} style={styles.selectedIcon} />
)}
</TouchableOpacity>
))}
{timeoutOptions.map((option, index) => {
const isLast = index === timeoutOptions.length - 1;
return (
<TouchableOpacity
key={option.value}
style={[styles.option, isLast && styles.optionLast]}
onPress={() => {
setAutoLockTimeout(option.value);
setAutoLockTimeoutState(option.value);
}}
>
<ThemedText style={styles.optionText}>{option.label}</ThemedText>
{autoLockTimeout === option.value && (
<Ionicons name="checkmark" size={20} style={styles.selectedIcon} />
)}
</TouchableOpacity>
);
})}
</View>
</ThemedScrollView>
</ThemedView>

View File

@@ -111,12 +111,11 @@ export default function SettingsScreen() : React.ReactNode {
},
content: {
flex: 1,
marginTop: 22,
padding: 16,
},
scrollContent: {
paddingBottom: 40,
paddingTop: 4,
paddingTop: 26,
},
scrollView: {
flex: 1,
@@ -159,7 +158,7 @@ export default function SettingsScreen() : React.ReactNode {
alignItems: 'center',
flex: 1,
flexDirection: 'row',
paddingVertical: 12,
paddingVertical: 10,
},
settingItemIcon: {
alignItems: 'center',

View File

@@ -115,16 +115,6 @@ export default function IosAutofillScreen() : React.ReactNode {
Open iOS Settings
</ThemedText>
</TouchableOpacity>
{shouldShowIosAutofillReminder && (
<TouchableOpacity
style={styles.secondaryButton}
onPress={handleAlreadyConfigured}
>
<ThemedText style={styles.secondaryButtonText}>
I already configured it
</ThemedText>
</TouchableOpacity>
)}
</View>
<ThemedText style={styles.instructionStep}>
2. Go to &quot;General&quot;
@@ -141,6 +131,18 @@ export default function IosAutofillScreen() : React.ReactNode {
<ThemedText style={styles.warningText}>
Note: You&apos;ll need to authenticate with Face ID/Touch ID or your device passcode when using autofill.
</ThemedText>
<View style={styles.buttonContainer}>
{shouldShowIosAutofillReminder && (
<TouchableOpacity
style={styles.secondaryButton}
onPress={handleAlreadyConfigured}
>
<ThemedText style={styles.secondaryButtonText}>
I already configured it
</ThemedText>
</TouchableOpacity>
)}
</View>
</View>
</ThemedScrollView>
</ThemedView>

View File

@@ -156,6 +156,9 @@ export default function VaultUnlockSettingsScreen() : React.ReactNode {
justifyContent: 'space-between',
marginBottom: 4,
},
optionLast: {
borderBottomWidth: 0,
},
optionText: {
color: colors.text,
fontSize: 16,
@@ -197,7 +200,7 @@ export default function VaultUnlockSettingsScreen() : React.ReactNode {
)}
</TouchableOpacity>
<View style={styles.option}>
<View style={[styles.option, styles.optionLast]}>
<View style={styles.optionHeader}>
<ThemedText style={styles.optionText}>Password</ThemedText>
<Switch

View File

@@ -44,9 +44,7 @@ export function EmailCard({ email }: EmailCardProps) : React.ReactNode {
const styles = StyleSheet.create({
emailCard: {
backgroundColor: colors.accentBackground,
borderColor: colors.accentBorder,
borderRadius: 8,
borderWidth: 1,
elevation: 3,
marginBottom: 12,
padding: 12,

View File

@@ -37,9 +37,7 @@ export function CredentialCard({ credential }: CredentialCardProps) : React.Reac
const styles = StyleSheet.create({
credentialCard: {
backgroundColor: colors.accentBackground,
borderColor: colors.accentBorder,
borderRadius: 8,
borderWidth: 1,
marginBottom: 8,
padding: 12,
},

View File

@@ -52,9 +52,7 @@ const FormInputCopyToClipboard: React.FC<FormInputCopyToClipboardProps> = ({
},
inputContainer: {
backgroundColor: colors.accentBackground,
borderColor: colors.accentBorder,
borderRadius: 8,
borderWidth: 1,
marginBottom: 12,
padding: 12,
},

View File

@@ -77,7 +77,7 @@ const ValidatedFormFieldComponent = forwardRef<ValidatedFormFieldRef, ValidatedF
alignItems: 'center',
backgroundColor: colors.background,
borderColor: colors.accentBorder,
borderRadius: 4,
borderRadius: 6,
borderWidth: 1,
flexDirection: 'row',
},

View File

@@ -1,11 +1,14 @@
import React from 'react';
import { StyleSheet, Platform, Animated, TouchableOpacity } from 'react-native';
import { StyleSheet, Platform, Animated, TouchableOpacity, useColorScheme } from 'react-native';
import { Stack } from 'expo-router';
import MaterialIcons from '@expo/vector-icons/MaterialIcons';
import { BlurView } from 'expo-blur';
import { ThemedText } from '@/components/themed/ThemedText';
import { useColors } from '@/hooks/useColorScheme';
const AnimatedBlurView = Animated.createAnimatedComponent(BlurView);
type HeaderButton = {
icon: keyof typeof MaterialIcons.glyphMap;
onPress: () => void;
@@ -29,10 +32,11 @@ export function CollapsibleHeader({
showNavigationHeader = false,
alwaysVisible = false,
headerButtons = []
}: CollapsibleHeaderProps) : React.ReactNode {
}: CollapsibleHeaderProps): React.ReactNode {
const colors = useColors();
const colorScheme = useColorScheme();
// Calculate header opacity based on scroll position and transform
// Calculate header opacity and transforms based on scroll
const headerOpacity = scrollY.interpolate({
inputRange: [10, 60],
outputRange: [0, 1],
@@ -45,12 +49,13 @@ export function CollapsibleHeader({
extrapolate: 'clamp',
});
const headerTransform = alwaysVisible ? 0 : headerOpacity.interpolate({
inputRange: [0, 1],
outputRange: [-20, 0],
});
const headerTransform = alwaysVisible
? 0
: headerOpacity.interpolate({
inputRange: [0, 1],
outputRange: [-20, 0],
});
// Interpolate the header background color and border
const headerBackground = headerOpacity.interpolate({
inputRange: [0, 1],
outputRange: [colors.background, colors.accentBackground],
@@ -63,6 +68,7 @@ export function CollapsibleHeader({
height: Platform.OS === 'ios' ? 100 : 64,
justifyContent: 'center',
left: 0,
overflow: 'hidden',
paddingBottom: Platform.OS === 'ios' ? 12 : 16,
paddingTop: Platform.OS === 'ios' ? 60 : 0,
position: 'absolute',
@@ -92,7 +98,6 @@ export function CollapsibleHeader({
},
headerButton: {
bottom: Platform.OS === 'ios' ? 6 : 16,
color: colors.primary,
padding: 4,
position: 'absolute',
},
@@ -106,37 +111,53 @@ export function CollapsibleHeader({
return (
<>
{showNavigationHeader ? (
<Stack.Screen options={{
title: title,
headerShown: false,
}} />
) : null}
{showNavigationHeader && (
<Stack.Screen options={{ title, headerShown: false }} />
)}
<Animated.View
style={[
styles.floatingHeader,
{
backgroundColor: headerBackground,
transform: [{
translateY: headerTransform
}]
}
transform: [{ translateY: headerTransform }],
},
]}
>
<Animated.View style={[
styles.floatingTitleContainer,
{ opacity: alwaysVisible ? titleOpacity : headerOpacity },
]}>
{Platform.OS === 'ios' ? (
colorScheme === 'dark' ? (
<AnimatedBlurView
tint="dark"
intensity={80}
style={[StyleSheet.absoluteFill, { opacity: headerOpacity }]}
/>
) : (
<AnimatedBlurView
tint="light"
intensity={100}
style={[StyleSheet.absoluteFill, { opacity: headerOpacity }]}
/>
)
) : (
<Animated.View
style={[StyleSheet.absoluteFill, { backgroundColor: headerBackground }]}
/>
)}
<Animated.View
style={[
styles.floatingTitleContainer,
{ opacity: alwaysVisible ? titleOpacity : headerOpacity },
]}
>
<ThemedText style={styles.floatingTitle}>{title}</ThemedText>
</Animated.View>
{headerButtons.map((button, index) => (
{headerButtons.map((button, idx) => (
<TouchableOpacity
key={`${button.icon}-${index}`}
key={`${button.icon}-${idx}`}
style={[
styles.headerButton,
button.position === 'left' ? styles.leftButton : styles.rightButton
button.position === 'left' ? styles.leftButton : styles.rightButton,
]}
onPress={button.onPress}
>
@@ -147,12 +168,10 @@ export function CollapsibleHeader({
<Animated.View
style={[
styles.headerBorder,
{
opacity: headerOpacity
}
{ opacity: headerOpacity },
]}
/>
</Animated.View>
</>
);
}
}

View File

@@ -30,9 +30,9 @@ export const Colors = {
white: '#ffffff',
text: '#ECEDEE',
textMuted: '#9BA1A6',
background: '#111827',
accentBackground: '#1f2937',
accentBorder: '#4b5563',
background: '#000',
accentBackground: '#202020',
accentBorder: '#444',
errorBackground: '#3d1a1e',
errorBorder: '#9c2530',
errorText: '#fae1e3',
@@ -40,8 +40,8 @@ export const Colors = {
icon: '#9BA1A6',
tabIconDefault: '#9BA1A6',
tabIconSelected: '#f49541',
headerBackground: '#1f2937',
tabBarBackground: '#1f2937',
headerBackground: '#202020',
tabBarBackground: '#202020',
primary: '#f49541',
primarySurfaceText: '#ffffff',
secondary: '#6b7280',