fix(desktop): refine EntryHeader and EntryTitle components for improved behavior and styling

- Updated `shouldShowMeta` logic in EntryHeader to simplify visibility conditions.
- Enhanced EntryTitle with mouse interaction effects for a more dynamic user experience.
- Added hover and movement effects to the title link for better engagement.

These changes improve the overall usability and visual feedback of the components.

Signed-off-by: Innei <tukon479@gmail.com>
This commit is contained in:
Innei 2025-04-09 23:30:59 +08:00
parent 4325c6bede
commit b90b12ee3f
No known key found for this signature in database
GPG Key ID: 0F62D33977F021F7
3 changed files with 46 additions and 9 deletions

View File

@ -1,5 +1,5 @@
import { cn, formatEstimatedMins, formatTimeToSeconds } from "@follow/utils/utils"
import { useMemo } from "react"
import { useCallback, useMemo, useRef } from "react"
import { useUISettingKey } from "~/atoms/settings/ui"
import { useWhoami } from "~/atoms/user"
@ -69,6 +69,32 @@ export const EntryTitle = ({ entryId, compact }: EntryLinkProps) => {
return formatEstimatedMins(Math.floor(durationInSeconds / 60))
}, [audioAttachment])
const titleRef = useRef<HTMLAnchorElement>(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<HTMLAnchorElement>) => {
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 ? (
@ -88,19 +114,27 @@ export const EntryTitle = ({ entryId, compact }: EntryLinkProps) => {
<div className="flex flex-col gap-2">
{/* Title Section with subtle hover effect */}
<div>
<div className="flex items-center text-sm font-medium text-zinc-800/90 dark:text-zinc-300/90">
<a
className="cursor-link flex items-center text-sm font-medium text-zinc-800/90 duration-200 hover:text-zinc-900 dark:text-zinc-300/90 dark:hover:text-zinc-100"
href={feed?.siteUrl ?? feed?.url ?? "#"}
target="_blank"
rel="noopener noreferrer"
>
<FeedIcon fallback feed={feed || inbox} entry={entry.entries} size={16} />
{getPreferredTitle(feed || inbox, entry.entries)}
</div>
</a>
<a
href={populatedFullHref ?? "#"}
target="_blank"
rel="noopener noreferrer"
ref={titleRef}
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
onMouseMove={handleMouseMove}
className={cn(
"relative select-text break-words font-medium transition-colors",
"text-2xl leading-normal",
"hover:text-zinc-900 dark:hover:text-zinc-100",
"cursor-link relative select-text break-words text-2xl font-medium leading-normal",
"inline-block transition-all duration-200 ease-out",
"before:absolute before:-inset-x-2 before:inset-y-0 before:rounded-xl before:bg-black/[0.03] before:opacity-0 before:transition-opacity hover:before:opacity-100 dark:before:bg-white/[0.07]",
)}
>
<EntryTranslation

View File

@ -21,7 +21,7 @@ function EntryHeaderImpl({ view, entryId, className, compact }: EntryHeaderProps
const hideRecentReader = useUISettingKey("hideRecentReader")
const shouldShowMeta = (hideRecentReader || !isAtTop) && !!entryTitleMeta?.title
const shouldShowMeta = !isAtTop && !!entryTitleMeta?.title
if (!entry?.entries) return null

View File

@ -1,4 +1,5 @@
/* eslint-disable react-refresh/only-export-components */
import { useScrollViewElement } from "@follow/components/ui/scroll-area/hooks.js"
import { cn } from "@follow/utils/utils"
import { createContextState } from "foxact/create-context-state"
import { useIsomorphicLayoutEffect } from "foxact/use-isomorphic-layout-effect"
@ -112,6 +113,7 @@ const BoundingDetection: Component<{
const endSetter = useSetIsEOfElement()
const startSetter = useSetIsSOfElement()
const ref = useRef<HTMLDivElement>(null)
const $scrollArea = useScrollViewElement()
useEffect(() => {
if (!ref.current) return
const $el = ref.current
@ -124,6 +126,7 @@ const BoundingDetection: Component<{
},
{
rootMargin: "0px 0px 0px 0px",
root: $scrollArea,
},
)
@ -132,7 +135,7 @@ const BoundingDetection: Component<{
observer.unobserve($el)
observer.disconnect()
}
}, [])
}, [$scrollArea, bounding, endSetter, startSetter])
return <div ref={ref} />
}