Refactor components for consistent styling and improve button animations

This commit is contained in:
zimplexing
2025-07-08 19:52:20 +08:00
parent 504f12067b
commit 74ad0872cb
7 changed files with 89 additions and 66 deletions

View File

@@ -45,7 +45,6 @@ export const EpisodeSelectionModal: React.FC<EpisodeSelectionModalProps> = () =>
isSelected={selectedEpisodeGroup === groupIndex}
style={styles.episodeGroupButton}
textStyle={styles.episodeGroupButtonText}
variant="primary"
/>
))}
</View>
@@ -56,6 +55,7 @@ export const EpisodeSelectionModal: React.FC<EpisodeSelectionModalProps> = () =>
(selectedEpisodeGroup + 1) * episodeGroupSize
)}
numColumns={5}
contentContainerStyle={styles.episodeList}
keyExtractor={(_, index) => `episode-${selectedEpisodeGroup * episodeGroupSize + index}`}
renderItem={({ item, index }) => {
const absoluteIndex = selectedEpisodeGroup * episodeGroupSize + index;
@@ -71,8 +71,6 @@ export const EpisodeSelectionModal: React.FC<EpisodeSelectionModalProps> = () =>
);
}}
/>
<StyledButton text="关闭" onPress={onClose} style={styles.closeButton} />
</View>
</View>
</Modal>
@@ -87,22 +85,25 @@ const styles = StyleSheet.create({
backgroundColor: "transparent",
},
modalContent: {
width: 400,
width: 600,
height: "100%",
backgroundColor: "rgba(0, 0, 0, 0.85)",
padding: 20,
},
modalTitle: {
color: "white",
marginBottom: 20,
marginBottom: 12,
textAlign: "center",
fontSize: 18,
fontWeight: "bold",
},
episodeList: {
justifyContent: "flex-start",
},
episodeItem: {
paddingVertical: 12,
paddingVertical: 2,
margin: 4,
flex: 1,
width: "18%",
},
episodeItemText: {
fontSize: 14,
@@ -111,20 +112,13 @@ const styles = StyleSheet.create({
flexDirection: "row",
flexWrap: "wrap",
justifyContent: "center",
marginBottom: 15,
paddingHorizontal: 10,
},
episodeGroupButton: {
paddingHorizontal: 12,
paddingVertical: 6,
borderRadius: 15,
margin: 5,
paddingHorizontal: 6,
margin: 8,
},
episodeGroupButtonText: {
fontSize: 12,
},
closeButton: {
padding: 15,
marginTop: 20,
},
});

View File

@@ -1,7 +1,17 @@
import React from "react";
import { Pressable, StyleSheet, StyleProp, ViewStyle, PressableProps, TextStyle, useColorScheme } from "react-native";
import {
Animated,
Pressable,
StyleSheet,
StyleProp,
ViewStyle,
PressableProps,
TextStyle,
useColorScheme,
} from "react-native";
import { ThemedText } from "./ThemedText";
import { Colors } from "@/constants/Colors";
import { useButtonAnimation } from "@/hooks/useButtonAnimation";
interface StyledButtonProps extends PressableProps {
children?: React.ReactNode;
@@ -21,8 +31,10 @@ export const StyledButton: React.FC<StyledButtonProps> = ({
textStyle,
...rest
}) => {
const colorScheme = useColorScheme() ?? "light";
const colorScheme = useColorScheme() ?? "dark";
const colors = Colors[colorScheme];
const [isFocused, setIsFocused] = React.useState(false);
const animationStyle = useButtonAnimation(isSelected, isFocused);
const variantStyles = {
default: StyleSheet.create({
@@ -56,7 +68,6 @@ export const StyledButton: React.FC<StyledButtonProps> = ({
},
selectedButton: {
backgroundColor: "rgba(0, 122, 255, 0.3)",
transform: [{ scale: 1.1 }],
},
selectedText: {
color: colors.link,
@@ -79,10 +90,9 @@ export const StyledButton: React.FC<StyledButtonProps> = ({
const styles = StyleSheet.create({
button: {
paddingHorizontal: 15,
paddingHorizontal: 16,
paddingVertical: 10,
borderRadius: 8,
margin: 5,
borderWidth: 2,
borderColor: "transparent",
flexDirection: "row",
@@ -92,7 +102,6 @@ export const StyledButton: React.FC<StyledButtonProps> = ({
focusedButton: {
backgroundColor: colors.link,
borderColor: colors.background,
transform: [{ scale: 1.1 }],
elevation: 5,
shadowColor: colors.link,
shadowOffset: { width: 0, height: 0 },
@@ -113,30 +122,33 @@ export const StyledButton: React.FC<StyledButtonProps> = ({
});
return (
<Pressable
style={({ focused }) => [
styles.button,
variantStyles[variant].button,
isSelected && (variantStyles[variant].selectedButton ?? styles.selectedButton),
focused && (variantStyles[variant].focusedButton ?? styles.focusedButton),
style,
]}
{...rest}
>
{text ? (
<ThemedText
style={[
styles.text,
variantStyles[variant].text,
isSelected && (variantStyles[variant].selectedText ?? styles.selectedText),
textStyle,
]}
>
{text}
</ThemedText>
) : (
children
)}
</Pressable>
<Animated.View style={[animationStyle, style]}>
<Pressable
onFocus={() => setIsFocused(true)}
onBlur={() => setIsFocused(false)}
style={({ focused }) => [
styles.button,
variantStyles[variant].button,
isSelected && (variantStyles[variant].selectedButton ?? styles.selectedButton),
focused && (variantStyles[variant].focusedButton ?? styles.focusedButton),
]}
{...rest}
>
{text ? (
<ThemedText
style={[
styles.text,
variantStyles[variant].text,
isSelected && (variantStyles[variant].selectedText ?? styles.selectedText),
textStyle,
]}
>
{text}
</ThemedText>
) : (
children
)}
</Pressable>
</Animated.View>
);
};