style(desktop): update FeedIcon component styling and enhance MagneticHoverEffect interactions

Signed-off-by: Innei <tukon479@gmail.com>
This commit is contained in:
Innei 2025-05-08 16:15:08 +08:00
parent 6694a346a0
commit 2f492c8245
No known key found for this signature in database
GPG Key ID: 0F62D33977F021F7
4 changed files with 48 additions and 19 deletions

View File

@ -142,7 +142,7 @@ export function FeedIcon({
<span
style={colorfulStyle}
className={cn(
"mask-squircle mask flex shrink-0 items-center justify-center",
"flex shrink-0 items-center justify-center rounded-sm",
"text-white",
marginClassName,
className,
@ -169,11 +169,7 @@ export function FeedIcon({
isIconLoadedSet.add(src!)
ImageElement = (
<PlatformIcon
url={siteUrl}
style={sizeStyle}
className={cn("center mask-squircle mask", className)}
>
<PlatformIcon url={siteUrl} style={sizeStyle} className={className}>
<m.img style={sizeStyle} {...(disableFadeIn || isIconLoaded ? {} : fadeInVariant)} />
</PlatformIcon>
)
@ -189,11 +185,7 @@ export function FeedIcon({
isIconLoadedSet.add(finalSrc)
ImageElement = (
<PlatformIcon
url={image}
style={sizeStyle}
className={cn("center mask-squircle mask", className)}
>
<PlatformIcon url={image} style={sizeStyle} className={className}>
<m.img
className={cn(marginClassName, className)}
style={sizeStyle}
@ -219,7 +211,7 @@ export function FeedIcon({
<PlatformIcon
url={(feed as FeedModel)?.siteUrl || fallbackUrl}
style={sizeStyle}
className={cn("center mask-squircle mask", className)}
className={className}
>
<FallbackableImage
className={cn(marginClassName, className)}

View File

@ -301,7 +301,7 @@ const ListItemImpl: Component<{
{...contextMenuProps}
>
<div className="flex min-w-0 flex-1 items-center">
<FeedIcon fallback feed={list} size={iconSize} />
<FeedIcon fallback feed={list} size={iconSize} className="mask mask-squircle" />
<EllipsisHorizontalTextWithTooltip className="truncate">
{getPreferredTitle(list)}
</EllipsisHorizontalTextWithTooltip>

View File

@ -1,5 +1,4 @@
import { RelativeTime } from "@follow/components/ui/datetime/index.jsx"
import { MagneticHoverEffect } from "@follow/components/ui/effect/MagneticHoverEffect.js"
import { EllipsisHorizontalTextWithTooltip } from "@follow/components/ui/typography/index.js"
import { cn } from "@follow/utils/utils"
import { memo } from "react"
@ -23,7 +22,11 @@ function NormalListItemImpl({
const displayTime = entry.entries.publishedAt
return (
<MagneticHoverEffect className={"group relative mx-auto flex max-w-3xl gap-2 py-4 pl-3 pr-2"}>
<div
className={
"hover:before:bg-material-ultra-thick group relative mx-auto flex max-w-3xl gap-2 py-4 pl-3 pr-2 before:pointer-events-none before:absolute before:-inset-x-2 before:inset-y-0 before:z-[-1] before:scale-0 before:rounded-xl before:opacity-0 before:transition-all before:duration-200 hover:before:scale-100 hover:before:opacity-100"
}
>
<FeedIcon feed={feed} fallback entry={entry.entries} />
<div className={"-mt-0.5 flex-1 text-base leading-tight"}>
<div className={cn("flex gap-1 text-xs font-bold", "text-text-secondary")}>
@ -59,7 +62,7 @@ function NormalListItemImpl({
/>
</div>
)}
</MagneticHoverEffect>
</div>
)
}

View File

@ -1,6 +1,6 @@
import { cn } from "@follow/utils/utils"
import * as React from "react"
import { useImperativeHandle, useRef } from "react"
import { useCallback, useImperativeHandle, useRef } from "react"
type MagneticHoverEffectProps<T extends React.ElementType> = {
as?: T
@ -22,14 +22,48 @@ export const MagneticHoverEffect = <T extends React.ElementType = "div">({
return itemRef.current as unknown as T
})
const handleMouseEnter = (e: React.MouseEvent<HTMLElement>) => {
if (!itemRef.current) return
const rect = itemRef.current.getBoundingClientRect()
const x = ((e.clientX - rect.left) / rect.width) * 100
const y = ((e.clientY - rect.top) / rect.height) * 100
itemRef.current.style.transition = "transform 0.2s cubic-bezier(0.33, 1, 0.68, 1)"
itemRef.current.style.setProperty("--origin-x", `${x}%`)
itemRef.current.style.setProperty("--origin-y", `${y}%`)
}
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<HTMLElement>) => {
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 (
<Component
ref={itemRef as any}
{...rest}
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
onMouseMove={handleMouseMove}
className={cn(
"relative",
"inline-block duration-200 ease-out",
"hover:before:bg-material-ultra-thick",
"inline-block transition-transform duration-200 ease-out will-change-transform",
"hover:before:bg-fill-tertiary",
"before:backdrop-blur-background before:absolute before:-inset-x-2 before:inset-y-0 before:z-[-1] before:scale-0 before:rounded-xl before:opacity-0 before:transition-all before:duration-200 before:[transform-origin:var(--origin-x)_var(--origin-y)] hover:before:scale-100 hover:before:opacity-100",
rest.className,
)}