mirror of
https://github.com/streamyfin/streamyfin.git
synced 2026-01-22 11:08:03 +00:00
style(tv): add apple tv-style badges to search page
This commit is contained in:
54
components/search/TVSearchBadge.tsx
Normal file
54
components/search/TVSearchBadge.tsx
Normal file
@@ -0,0 +1,54 @@
|
||||
import React from "react";
|
||||
import { Animated, Pressable } from "react-native";
|
||||
import { Text } from "@/components/common/Text";
|
||||
import { useTVFocusAnimation } from "@/components/tv/hooks/useTVFocusAnimation";
|
||||
|
||||
export interface TVSearchBadgeProps {
|
||||
label: string;
|
||||
onPress: () => void;
|
||||
hasTVPreferredFocus?: boolean;
|
||||
}
|
||||
|
||||
export const TVSearchBadge: React.FC<TVSearchBadgeProps> = ({
|
||||
label,
|
||||
onPress,
|
||||
hasTVPreferredFocus = false,
|
||||
}) => {
|
||||
const { focused, handleFocus, handleBlur, animatedStyle } =
|
||||
useTVFocusAnimation({ scaleAmount: 1.08, duration: 150 });
|
||||
|
||||
return (
|
||||
<Pressable
|
||||
onPress={onPress}
|
||||
onFocus={handleFocus}
|
||||
onBlur={handleBlur}
|
||||
hasTVPreferredFocus={hasTVPreferredFocus}
|
||||
>
|
||||
<Animated.View
|
||||
style={[
|
||||
animatedStyle,
|
||||
{
|
||||
paddingHorizontal: 24,
|
||||
paddingVertical: 14,
|
||||
borderRadius: 24,
|
||||
backgroundColor: focused ? "#fff" : "rgba(255,255,255,0.1)",
|
||||
shadowColor: "#fff",
|
||||
shadowOffset: { width: 0, height: 0 },
|
||||
shadowOpacity: focused ? 0.4 : 0,
|
||||
shadowRadius: focused ? 12 : 0,
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Text
|
||||
style={{
|
||||
fontSize: 16,
|
||||
color: focused ? "#000" : "#fff",
|
||||
fontWeight: focused ? "600" : "400",
|
||||
}}
|
||||
>
|
||||
{label}
|
||||
</Text>
|
||||
</Animated.View>
|
||||
</Pressable>
|
||||
);
|
||||
};
|
||||
@@ -2,12 +2,13 @@ import type { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models";
|
||||
import { useAtom } from "jotai";
|
||||
import { useMemo } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Pressable, ScrollView, View } from "react-native";
|
||||
import { ScrollView, View } from "react-native";
|
||||
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
||||
import { Input } from "@/components/common/Input";
|
||||
import { Text } from "@/components/common/Text";
|
||||
import { apiAtom } from "@/providers/JellyfinProvider";
|
||||
import { getPrimaryImageUrl } from "@/utils/jellyfin/image/getPrimaryImageUrl";
|
||||
import { TVSearchBadge } from "./TVSearchBadge";
|
||||
import { TVSearchSection } from "./TVSearchSection";
|
||||
|
||||
const HORIZONTAL_PADDING = 60;
|
||||
@@ -267,28 +268,11 @@ export const TVSearchPage: React.FC<TVSearchPageProps> = ({
|
||||
}}
|
||||
>
|
||||
{exampleSearches.map((example) => (
|
||||
<Pressable
|
||||
<TVSearchBadge
|
||||
key={example}
|
||||
label={example}
|
||||
onPress={() => setSearch(example)}
|
||||
style={({ focused }) => ({
|
||||
paddingHorizontal: 20,
|
||||
paddingVertical: 12,
|
||||
borderRadius: 24,
|
||||
backgroundColor: focused
|
||||
? "#9334E9"
|
||||
: "rgba(255, 255, 255, 0.1)",
|
||||
transform: [{ scale: focused ? 1.05 : 1 }],
|
||||
})}
|
||||
>
|
||||
<Text
|
||||
style={{
|
||||
fontSize: 16,
|
||||
color: "#FFFFFF",
|
||||
}}
|
||||
>
|
||||
{example}
|
||||
</Text>
|
||||
</Pressable>
|
||||
/>
|
||||
))}
|
||||
</View>
|
||||
</View>
|
||||
|
||||
Reference in New Issue
Block a user