feat(Theme): enhance theming and UI consistency across components
All checks were successful
Frontend CI / build-and-push-web (push) Successful in 8m15s
Frontend CI / ota-android (push) Successful in 10m56s
Frontend CI / build-android-apk (push) Successful in 1h3m22s

- Updated app.json to set userInterfaceStyle to automatic for improved theme adaptability.
- Refactored layout components to utilize useAppColors for dynamic theming, ensuring consistent color usage.
- Introduced SystemChrome component to manage system UI background color based on theme.
- Enhanced TabsLayout, ProfileStackLayout, and other components to leverage new theming structure.
- Improved QRCodeScanner, SearchBar, and CommentItem styles to align with the updated theme system.
- Consolidated styles in SystemMessageItem and TabBar for better maintainability and visual coherence.
This commit is contained in:
lafay
2026-03-25 05:16:54 +08:00
parent 90d834695f
commit 4ee3079b9f
86 changed files with 6777 additions and 5890 deletions

View File

@@ -3,7 +3,7 @@
* 支持多种变体、尺寸、加载状态和图标
*/
import React from 'react';
import React, { useMemo } from 'react';
import {
TouchableOpacity,
ActivityIndicator,
@@ -13,7 +13,7 @@ import {
TextStyle,
} from 'react-native';
import { MaterialCommunityIcons } from '@expo/vector-icons';
import { colors, borderRadius, spacing, fontSizes, shadows } from '../../theme';
import { borderRadius, spacing, fontSizes, useAppColors, type AppColors } from '../../theme';
import Text from './Text';
type ButtonVariant = 'primary' | 'secondary' | 'outline' | 'text' | 'danger';
@@ -27,12 +27,86 @@ interface ButtonProps {
size?: ButtonSize;
disabled?: boolean;
loading?: boolean;
icon?: string; // MaterialCommunityIcons name
icon?: string;
iconPosition?: IconPosition;
fullWidth?: boolean;
style?: ViewStyle;
}
function createButtonStyles(colors: AppColors) {
return StyleSheet.create({
base: {
justifyContent: 'center',
alignItems: 'center',
borderRadius: borderRadius.md,
},
content: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
},
size_sm: {
paddingVertical: spacing.sm,
paddingHorizontal: spacing.md,
minHeight: 32,
},
size_md: {
paddingVertical: spacing.md,
paddingHorizontal: spacing.lg,
minHeight: 40,
},
size_lg: {
paddingVertical: spacing.lg,
paddingHorizontal: spacing.xl,
minHeight: 48,
},
primary: {
backgroundColor: colors.primary.main,
},
secondary: {
backgroundColor: colors.secondary.main,
},
outline: {
backgroundColor: 'transparent',
borderWidth: 1,
borderColor: colors.primary.main,
},
text: {
backgroundColor: 'transparent',
shadowColor: 'transparent',
elevation: 0,
},
danger: {
backgroundColor: colors.error.main,
},
disabled: {
backgroundColor: colors.background.disabled,
borderColor: colors.background.disabled,
},
fullWidth: {
width: '100%',
},
textBase: {
fontWeight: '600',
},
textSize_sm: {
fontSize: fontSizes.sm,
},
textSize_md: {
fontSize: fontSizes.md,
},
textSize_lg: {
fontSize: fontSizes.lg,
},
iconLeft: {
marginRight: spacing.sm,
},
iconRight: {
marginLeft: spacing.sm,
},
});
}
const Button: React.FC<ButtonProps> = ({
title,
onPress,
@@ -45,11 +119,12 @@ const Button: React.FC<ButtonProps> = ({
fullWidth = false,
style,
}) => {
// 获取按钮样式
const colors = useAppColors();
const styles = useMemo(() => createButtonStyles(colors), [colors]);
const getButtonStyle = (): ViewStyle[] => {
const baseStyle: ViewStyle[] = [styles.base, styles[`size_${size}`]];
// 变体样式
switch (variant) {
case 'primary':
baseStyle.push(styles.primary);
@@ -68,12 +143,10 @@ const Button: React.FC<ButtonProps> = ({
break;
}
// 禁用状态
if (disabled || loading) {
baseStyle.push(styles.disabled);
}
// 全宽度
if (fullWidth) {
baseStyle.push(styles.fullWidth);
}
@@ -81,7 +154,6 @@ const Button: React.FC<ButtonProps> = ({
return baseStyle;
};
// 获取文本样式
const getTextStyle = (): TextStyle => {
const baseStyle: TextStyle = {
...styles.textBase,
@@ -109,7 +181,6 @@ const Button: React.FC<ButtonProps> = ({
return baseStyle;
};
// 获取图标大小
const getIconSize = (): number => {
switch (size) {
case 'sm':
@@ -121,7 +192,6 @@ const Button: React.FC<ButtonProps> = ({
}
};
// 获取图标颜色
const getIconColor = (): string => {
if (disabled || loading) {
return colors.text.disabled;
@@ -150,9 +220,9 @@ const Button: React.FC<ButtonProps> = ({
{loading ? (
<ActivityIndicator
size="small"
color={variant === 'outline' || variant === 'text'
? colors.primary.main
: colors.text.inverse}
color={
variant === 'outline' || variant === 'text' ? colors.primary.main : colors.text.inverse
}
/>
) : (
<View style={styles.content}>
@@ -179,82 +249,4 @@ const Button: React.FC<ButtonProps> = ({
);
};
const styles = StyleSheet.create({
base: {
justifyContent: 'center',
alignItems: 'center',
borderRadius: borderRadius.md,
},
content: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
},
// 尺寸样式
size_sm: {
paddingVertical: spacing.sm,
paddingHorizontal: spacing.md,
minHeight: 32,
},
size_md: {
paddingVertical: spacing.md,
paddingHorizontal: spacing.lg,
minHeight: 40,
},
size_lg: {
paddingVertical: spacing.lg,
paddingHorizontal: spacing.xl,
minHeight: 48,
},
// 变体样式
primary: {
backgroundColor: colors.primary.main,
},
secondary: {
backgroundColor: colors.secondary.main,
},
outline: {
backgroundColor: 'transparent',
borderWidth: 1,
borderColor: colors.primary.main,
},
text: {
backgroundColor: 'transparent',
shadowColor: 'transparent',
elevation: 0,
},
danger: {
backgroundColor: colors.error.main,
},
// 禁用状态
disabled: {
backgroundColor: colors.background.disabled,
borderColor: colors.background.disabled,
},
// 全宽度
fullWidth: {
width: '100%',
},
// 文本样式
textBase: {
fontWeight: '600',
},
textSize_sm: {
fontSize: fontSizes.sm,
},
textSize_md: {
fontSize: fontSizes.md,
},
textSize_lg: {
fontSize: fontSizes.lg,
},
// 图标样式
iconLeft: {
marginRight: spacing.sm,
},
iconRight: {
marginLeft: spacing.sm,
},
});
export default Button;