11import React from 'react' ;
2+ import raf from '@rc-component/util/lib/raf' ;
23import { Alert , Badge , Carousel , Flex , Skeleton , Typography } from 'antd' ;
34import { createStyles } from 'antd-style' ;
45import { clsx } from 'clsx' ;
@@ -18,12 +19,46 @@ const useStyle = createStyles(({ cssVar, css, cx }) => {
1819 align-items : stretch;
1920 text-decoration : none;
2021 background : ${ cssVar . colorBgContainer } ;
22+ background : color-mix (in srgb, ${ cssVar . colorBgContainer } 30% , transparent);
23+ backdrop-filter : blur (8px );
2124 border : ${ cssVar . lineWidth } solid ${ cssVar . colorBorderSecondary } ;
2225 border-radius : ${ cssVar . borderRadiusLG } ;
2326 transition : all ${ cssVar . motionDurationSlow } ;
2427 padding-block : ${ cssVar . paddingMD } ;
2528 padding-inline : ${ cssVar . paddingLG } ;
2629 box-sizing : border-box;
30+ position : relative;
31+
32+ & : before {
33+ content : '' ;
34+ inset : calc (${ cssVar . lineWidth } * -1 );
35+ position : absolute;
36+
37+ background : radial-gradient (
38+ circle 150px at var (--mouse-x , 0 ) var (--mouse-y , 0 ),
39+ ${ cssVar . colorPrimaryBorderHover } ,
40+ ${ cssVar . colorBorderSecondary }
41+ );
42+ opacity : 0 ;
43+ transition : all 0.3s ease;
44+ mask :
45+ linear-gradient (# fff 0 0 ) content-box,
46+ linear-gradient (# fff 0 0 );
47+
48+ mask-composite : subtract;
49+ -webkit-mask-composite : xor;
50+ padding : 1px ;
51+ border-radius : inherit;
52+ }
53+
54+ & : hover {
55+ backdrop-filter : blur (0px );
56+ background : color-mix (in srgb, ${ cssVar . colorBgContainer } 90% , transparent);
57+
58+ & : before {
59+ opacity : 1 ;
60+ }
61+ }
2762 ` ;
2863
2964 return {
@@ -33,12 +68,6 @@ const useStyle = createStyles(({ cssVar, css, cx }) => {
3368 height : 100% ;
3469 }
3570 ` ,
36- cardItem : css `
37- & : hover {
38- box-shadow : ${ cssVar . boxShadowCard } ;
39- border-color : transparent;
40- }
41- ` ,
4271 sliderItem : css `
4372 margin : 0 ${ cssVar . margin } ;
4473 text-align : start;
@@ -64,6 +93,9 @@ const useStyle = createStyles(({ cssVar, css, cx }) => {
6493 } ;
6594} ) ;
6695
96+ // ======================================================================
97+ // == Item ==
98+ // ======================================================================
6799interface RecommendItemProps {
68100 extra : Extra ;
69101 index : number ;
@@ -73,9 +105,47 @@ interface RecommendItemProps {
73105
74106const RecommendItem : React . FC < RecommendItemProps > = ( props ) => {
75107 const { extra, index, icons, className } = props ;
108+ const cardRef = React . useRef < HTMLAnchorElement > ( null ) ;
76109
77110 const { styles } = useStyle ( ) ;
78111
112+ // ====================== MousePos ======================
113+ const [ mousePosition , setMousePosition ] = React . useState < [ number , number ] > ( [ 0 , 0 ] ) ;
114+ const [ transMousePosition , setTransMousePosition ] = React . useState < [ number , number ] > ( [ 0 , 0 ] ) ;
115+
116+ const onMouseMove = ( e : React . MouseEvent < HTMLAnchorElement > ) => {
117+ if ( ! cardRef . current ) return ;
118+
119+ const rect = cardRef . current . getBoundingClientRect ( ) ;
120+ const x = e . clientX - rect . left ;
121+ const y = e . clientY - rect . top ;
122+
123+ setMousePosition ( [ x , y ] ) ;
124+ } ;
125+
126+ // Transition mouse position
127+ React . useEffect ( ( ) => {
128+ const [ targetX , targetY ] = mousePosition ;
129+ const [ currentX , currentY ] = transMousePosition ;
130+
131+ if ( Math . abs ( targetX - currentX ) < 0.5 && Math . abs ( targetY - currentY ) < 0.5 ) {
132+ return ;
133+ }
134+
135+ const rafId = raf ( ( ) => {
136+ setTransMousePosition ( ( ori ) => {
137+ const [ curX , curY ] = ori ;
138+ const deltaX = ( targetX - curX ) * 0.1 ;
139+ const deltaY = ( targetY - curY ) * 0.1 ;
140+
141+ return [ curX + deltaX , curY + deltaY ] ;
142+ } ) ;
143+ } ) ;
144+
145+ return ( ) => raf . cancel ( rafId ) ;
146+ } , [ mousePosition , transMousePosition ] ) ;
147+
148+ // ======================= Render =======================
79149 if ( ! extra ) {
80150 return < Skeleton key = { index } /> ;
81151 }
@@ -84,11 +154,19 @@ const RecommendItem: React.FC<RecommendItemProps> = (props) => {
84154
85155 const card = (
86156 < a
157+ ref = { cardRef }
87158 key = { extra ?. title }
88159 href = { extra . href }
89160 target = "_blank"
90161 className = { clsx ( styles . itemBase , className ) }
162+ style = {
163+ {
164+ '--mouse-x' : `${ transMousePosition [ 0 ] } px` ,
165+ '--mouse-y' : `${ transMousePosition [ 1 ] } px` ,
166+ } as React . CSSProperties
167+ }
91168 rel = "noreferrer"
169+ onMouseMove = { onMouseMove }
92170 >
93171 < Typography . Title level = { 5 } > { extra ?. title } </ Typography . Title >
94172 < Typography . Paragraph type = "secondary" style = { { flex : 'auto' } } >
@@ -114,6 +192,9 @@ const RecommendItem: React.FC<RecommendItemProps> = (props) => {
114192 return card ;
115193} ;
116194
195+ // ======================================================================
196+ // == Fallback ==
197+ // ======================================================================
117198export const BannerRecommendsFallback : React . FC = ( ) => {
118199 const { isMobile } = React . use ( SiteContext ) ;
119200
@@ -140,6 +221,9 @@ export const BannerRecommendsFallback: React.FC = () => {
140221 ) ;
141222} ;
142223
224+ // ======================================================================
225+ // == Recommends ==
226+ // ======================================================================
143227const BannerRecommends : React . FC = ( ) => {
144228 const { styles } = useStyle ( ) ;
145229 const [ , lang ] = useLocale ( ) ;
@@ -186,13 +270,7 @@ const BannerRecommends: React.FC = () => {
186270 return (
187271 < div className = { styles . container } >
188272 { mergedExtras . map ( ( extra , index ) => (
189- < RecommendItem
190- key = { `desktop-${ index } ` }
191- extra = { extra }
192- index = { index }
193- icons = { data ?. icons }
194- className = { styles . cardItem }
195- />
273+ < RecommendItem key = { `desktop-${ index } ` } extra = { extra } index = { index } icons = { data ?. icons } />
196274 ) ) }
197275 </ div >
198276 ) ;
0 commit comments