1010 import { SiBluesky } from ' svelte-icons-pack/si' ;
1111 import { SiSoundcloud } from ' svelte-icons-pack/si' ;
1212 import { SiLastdotfm } from ' svelte-icons-pack/si' ;
13+ import { onMount } from ' svelte' ;
14+
15+ let mounted = false ;
1316
1417 const iconComponents = {
1518 linkedin: { component: Linkedin, isLucide: true },
2326
2427 // Calculate positions for icons in a circle
2528 function getIconPosition (index , total ) {
26- const angle = (index * 360 / total) - 90 ; // Start from top
27- const radius = 140 ; // Distance from center
29+ const angle = (index * 360 / total) - 90 ; // Position around circle
30+ const radius = 140 ; // Fixed radius
2831 const radian = angle * Math .PI / 180 ;
2932 const x = Math .cos (radian) * radius;
3033 const y = Math .sin (radian) * radius;
31- return ` transform: translate( ${ x } px, ${ y } px) ` ;
34+ return { x, y } ;
3235 }
36+
37+ onMount (() => {
38+ // Trigger animation after a short delay
39+ setTimeout (() => {
40+ mounted = true ;
41+ }, 100 );
42+ });
3343 </script >
3444
3545<svelte:head >
5464 </div >
5565 </div >
5666
57- <!-- Social Icons arranged in circle -->
67+ <!-- Social Icons carousel container -->
5868 <div class =" absolute inset-0 flex items-center justify-center" >
59- {#each socials as social , index (social .name )}
60- <a
61- href ={social .url }
62- target =" _blank"
63- rel =" noopener noreferrer"
64- title ={social .name }
65- style ={getIconPosition (index , socials .length )}
66- class =" absolute p-3 rounded-full
67- bg-transparent text-gray-400
68- hover:text-neon-cyan
69- border border-gray-800 hover:border-neon-cyan/50
70- transition-all duration-300
71- hover:shadow-[0_0_20px_rgba(0,255,255,0.3)]
72- flex items-center justify-center"
73- >
74- {#if iconComponents [social .icon ].isLucide }
75- <svelte:component
76- this ={iconComponents [social .icon ].component }
77- class =" w-7 h-7 transition-transform duration-300 hover:scale-110"
78- />
79- {:else }
80- <div class =" w-7 h-7 flex items-center justify-center transition-transform duration-300 hover:scale-110" >
81- <Icon src ={iconComponents [social .icon ].component } size =" 28" />
82- </div >
83- {/if }
84- </a >
85- {/each }
69+ <div class ="absolute inset-0 {mounted ? ' carousel-stop' : ' carousel-spin' }" >
70+ {#each socials as social , index (social .name )}
71+ {@const pos = getIconPosition (index , socials .length )}
72+ <a
73+ href ={social .url }
74+ target =" _blank"
75+ rel =" noopener noreferrer"
76+ title ={social .name }
77+ style ="transform: translate( {pos .x }px, {pos .y }px); transition-delay: {index * 75 }ms; opacity: {mounted ? 1 : 0 }"
78+ class =" absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 p-3 rounded-full
79+ bg-transparent text-gray-400
80+ hover:text-neon-cyan
81+ border border-gray-800 hover:border-neon-cyan/50
82+ hover:shadow-[0_0_20px_rgba(0,255,255,0.3)]
83+ flex items-center justify-center
84+ transition-opacity duration-700 ease-out
85+ {mounted ? '' : 'pointer-events-none'}"
86+ >
87+ {#if iconComponents [social .icon ].isLucide }
88+ <svelte:component
89+ this ={iconComponents [social .icon ].component }
90+ class =" w-7 h-7 transition-transform duration-300 hover:scale-110"
91+ />
92+ {:else }
93+ <div class =" w-7 h-7 flex items-center justify-center transition-transform duration-300 hover:scale-110" >
94+ <Icon src ={iconComponents [social .icon ].component } size =" 28" />
95+ </div >
96+ {/if }
97+ </a >
98+ {/each }
99+ </div >
86100 </div >
87101 </div >
88102 </div >
105119 padding : 0 ;
106120 background-color : #0a0a0f ;
107121 }
122+
123+ :global(.carousel-spin ) {
124+ animation : carousel-rotate 2s cubic-bezier (0.4 , 0.0 , 0.2 , 1 ) forwards ;
125+ }
126+
127+ :global(.carousel-stop ) {
128+ transform : rotate (0deg );
129+ }
130+
131+ @keyframes carousel-rotate {
132+ from {
133+ transform : rotate (360deg );
134+ }
135+ to {
136+ transform : rotate (0deg );
137+ }
138+ }
108139 </style >
0 commit comments