From feba117ba3294b8cd7bb1eacbb4deb4029abaad9 Mon Sep 17 00:00:00 2001 From: Innei Date: Wed, 9 Apr 2025 23:56:21 +0800 Subject: [PATCH] feat(desktop): integrate MagneticHoverEffect into MarkdownLink and EntryTitle components - Replaced standard anchor tags with MagneticHoverEffect for enhanced visual feedback on hover. - Removed custom mouse event handlers from EntryTitle, simplifying the component's code while maintaining hover effects. These changes improve user interaction and visual appeal across the affected components. Signed-off-by: Innei --- .../ui/markdown/renderers/MarkdownLink.tsx | 8 ++- .../entry-content/components/EntryTitle.tsx | 46 +++----------- .../src/ui/effect/MagneticHoverEffect.tsx | 60 +++++++++++++++++++ 3 files changed, 72 insertions(+), 42 deletions(-) create mode 100644 packages/components/src/ui/effect/MagneticHoverEffect.tsx diff --git a/apps/desktop/src/renderer/src/components/ui/markdown/renderers/MarkdownLink.tsx b/apps/desktop/src/renderer/src/components/ui/markdown/renderers/MarkdownLink.tsx index 5052fc8b3..ce227134e 100644 --- a/apps/desktop/src/renderer/src/components/ui/markdown/renderers/MarkdownLink.tsx +++ b/apps/desktop/src/renderer/src/components/ui/markdown/renderers/MarkdownLink.tsx @@ -1,3 +1,4 @@ +import { MagneticHoverEffect } from "@follow/components/ui/effect/MagneticHoverEffect.js" import { Tooltip, TooltipContent, @@ -31,9 +32,10 @@ export const MarkdownLink = (props: LinkProps) => { return ( - { {typeof props.children === "string" && ( )} - + {!!props.href && ( diff --git a/apps/desktop/src/renderer/src/modules/entry-content/components/EntryTitle.tsx b/apps/desktop/src/renderer/src/modules/entry-content/components/EntryTitle.tsx index 0e449d66c..59dba3c38 100644 --- a/apps/desktop/src/renderer/src/modules/entry-content/components/EntryTitle.tsx +++ b/apps/desktop/src/renderer/src/modules/entry-content/components/EntryTitle.tsx @@ -1,5 +1,6 @@ -import { cn, formatEstimatedMins, formatTimeToSeconds } from "@follow/utils/utils" -import { useCallback, useMemo, useRef } from "react" +import { MagneticHoverEffect } from "@follow/components/ui/effect/MagneticHoverEffect.js" +import { formatEstimatedMins, formatTimeToSeconds } from "@follow/utils/utils" +import { useMemo } from "react" import { useUISettingKey } from "~/atoms/settings/ui" import { useWhoami } from "~/atoms/user" @@ -69,32 +70,6 @@ export const EntryTitle = ({ entryId, compact }: EntryLinkProps) => { return formatEstimatedMins(Math.floor(durationInSeconds / 60)) }, [audioAttachment]) - const titleRef = useRef(null) - - const handleMouseEnter = () => { - if (!titleRef.current) return - titleRef.current.style.transition = "transform 0.2s cubic-bezier(0.33, 1, 0.68, 1)" - } - - const handleMouseLeave = () => { - if (!titleRef.current) return - titleRef.current.style.transform = "translate(0px, 0px)" - titleRef.current.style.transition = "transform 0.4s cubic-bezier(0.33, 1, 0.68, 1)" - } - - const handleMouseMove = useCallback((e: React.MouseEvent) => { - if (!titleRef.current) return - const rect = titleRef.current.getBoundingClientRect() - - const centerX = rect.left + rect.width / 2 - const centerY = rect.top + rect.height / 2 - - const distanceX = (e.clientX - centerX) * 0.05 - const distanceY = (e.clientY - centerY) * 0.05 - - titleRef.current.style.transform = `translate(${distanceX}px, ${distanceY}px)` - }, []) - if (!entry) return null return compact ? ( @@ -123,26 +98,19 @@ export const EntryTitle = ({ entryId, compact }: EntryLinkProps) => { {getPreferredTitle(feed || inbox, entry.entries)} - - + {/* Meta Information with improved layout */} diff --git a/packages/components/src/ui/effect/MagneticHoverEffect.tsx b/packages/components/src/ui/effect/MagneticHoverEffect.tsx new file mode 100644 index 000000000..2eda09aa3 --- /dev/null +++ b/packages/components/src/ui/effect/MagneticHoverEffect.tsx @@ -0,0 +1,60 @@ +import { cn } from "@follow/utils/utils" +import * as React from "react" +import { useCallback, useRef } from "react" + +type MagneticHoverEffectProps = { + as?: T + children: React.ReactNode +} & Omit, "as" | "children"> + +export const MagneticHoverEffect = ({ + as, + children, + ...rest +}: MagneticHoverEffectProps) => { + const Component = as || "div" + + const itemRef = useRef(null) + + const handleMouseEnter = () => { + if (!itemRef.current) return + itemRef.current.style.transition = "transform 0.2s cubic-bezier(0.33, 1, 0.68, 1)" + } + + const handleMouseLeave = () => { + if (!itemRef.current) return + itemRef.current.style.transform = "translate(0px, 0px)" + itemRef.current.style.transition = "transform 0.4s cubic-bezier(0.33, 1, 0.68, 1)" + } + + const handleMouseMove = useCallback((e: React.MouseEvent) => { + if (!itemRef.current) return + const rect = itemRef.current.getBoundingClientRect() + + const centerX = rect.left + rect.width / 2 + const centerY = rect.top + rect.height / 2 + + const distanceX = (e.clientX - centerX) * 0.05 + const distanceY = (e.clientY - centerY) * 0.05 + + itemRef.current.style.transform = `translate(${distanceX}px, ${distanceY}px)` + }, []) + + return ( + + {children} + + ) +}