Skip to content

Commit 328ea58

Browse files
committed
feat(): Fixing the main screen ui
1 parent f6fafce commit 328ea58

6 files changed

Lines changed: 220 additions & 35 deletions

File tree

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
import React, { useRef, useEffect } from 'react';
2+
3+
interface Props {
4+
borderColor?: string;
5+
borderWidth?: string | number;
6+
trailLength?: number; // Adjust the length of the trail
7+
duration?: number;
8+
children?: React.ReactNode;
9+
}
10+
11+
const TrailBorderBox: React.FC<Props> = ({
12+
borderWidth = 2,
13+
trailLength = 20, // Default trail length
14+
duration = 2,
15+
children,
16+
}) => {
17+
const boxRef = useRef<HTMLDivElement>(null);
18+
19+
useEffect(() => {
20+
if (boxRef.current) {
21+
const box = boxRef.current;
22+
const width = box.offsetWidth;
23+
const height = box.offsetHeight;
24+
25+
const animateTrail = () => {
26+
let currentPosition = 0;
27+
let isHorizontal = true; // Start with horizontal movement
28+
29+
const animateSegment = () => {
30+
const segmentLength = isHorizontal ? width : height;
31+
const endPosition = currentPosition + segmentLength;
32+
33+
const trail = document.createElement('div');
34+
trail.style.position = 'absolute';
35+
trail.style.zIndex = '1'; // Ensure trail is above content but below border
36+
37+
if (isHorizontal) {
38+
trail.style.top = '0px';
39+
trail.style.left = `${currentPosition}px`;
40+
trail.style.width = `${trailLength}px`;
41+
trail.style.height = `${borderWidth}px`;
42+
} else {
43+
trail.style.left = `${borderWidth}px`;
44+
trail.style.top = `${currentPosition}px`;
45+
trail.style.width = `${borderWidth}px`;
46+
trail.style.height = `${trailLength}px`;
47+
}
48+
49+
box.appendChild(trail);
50+
51+
const animation = trail.animate(
52+
isHorizontal
53+
? [{ left: `${currentPosition}px` }, { left: `${endPosition}px` }]
54+
: [{ top: `${currentPosition}px` }, { top: `${endPosition}px` }],
55+
{
56+
duration:
57+
duration * 1000 * (segmentLength / (width * 2 + height * 2)), // Adjust duration based on segment length and total perimeter
58+
easing: 'linear',
59+
fill: 'forwards',
60+
},
61+
);
62+
63+
animation.onfinish = () => {
64+
trail.remove(); // Remove trail segment after animation
65+
currentPosition = endPosition;
66+
if (currentPosition >= (isHorizontal ? width : height)) {
67+
currentPosition = 0;
68+
isHorizontal = !isHorizontal; // Switch direction
69+
}
70+
animateSegment(); // Continue animation
71+
};
72+
};
73+
74+
animateSegment(); // Start the first segment
75+
};
76+
77+
animateTrail(); // Start the animation loop
78+
}
79+
}, [borderWidth, duration, trailLength]); // Re-run effect if props change
80+
81+
return (
82+
<div
83+
ref={boxRef}
84+
style={{
85+
border: `${borderWidth}px solid 'black'`,
86+
borderRadius: '8px',
87+
position: 'relative', // Needed for absolute positioning of trails
88+
overflow: 'hidden', // Hide trails that go outside the box during animation
89+
display: 'flex',
90+
alignItems: 'center',
91+
justifyContent: 'center',
92+
}}
93+
>
94+
{children}
95+
</div>
96+
);
97+
};
98+
99+
export default TrailBorderBox;
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { default as BorderAnimationContainer } from './BorderAnimationContainer';

src/components/CardComponent/Card.tsx

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
import { useMotionValue } from 'framer-motion';
2-
import { useState, useEffect } from 'react';
2+
import { useState, useEffect, SVGProps } from 'react';
33
import { useMotionTemplate, motion } from 'framer-motion';
44
import { Box } from '@chakra-ui/react';
55

6-
export const Icon = ({ className, ...rest }: any) => {
6+
export const Icon = ({
7+
className,
8+
isHovered,
9+
...rest
10+
}: SVGProps<SVGSVGElement> & { isHovered: boolean }) => {
711
return (
812
<svg
913
xmlns="http://www.w3.org/2000/svg"
@@ -12,8 +16,19 @@ export const Icon = ({ className, ...rest }: any) => {
1216
strokeWidth="1.5"
1317
stroke="currentColor"
1418
className={className}
19+
style={{
20+
transition: 'all 3s ease',
21+
animation: isHovered ? 'spin 3s linear infinite' : 'none',
22+
}}
1523
{...rest}
1624
>
25+
<style>
26+
{`@keyframes spin {
27+
to {
28+
transform: rotate(360deg);
29+
}
30+
}`}
31+
</style>
1732
<path strokeLinecap="round" strokeLinejoin="round" d="M12 6v12m6-6H6" />
1833
</svg>
1934
);

src/components/CardComponent/CardExport.tsx

Lines changed: 50 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useRef } from 'react';
1+
import { useRef, useState } from 'react';
22
import { useCursor } from '../Cursor';
33
import { CardBasic, Icon } from './Card';
44
import { CardExportProps } from './types';
@@ -16,30 +16,71 @@ const Card = ({
1616
link,
1717
}: CardExportProps) => {
1818
const ref = useRef<HTMLDivElement>(null);
19+
const [hovered, setHovered] = useState(false);
1920
const { setCursorInsets } = useCursor();
21+
2022
return (
2123
<Box
2224
ref={ref}
23-
onMouseEnter={() =>
25+
onMouseEnter={() => {
2426
setCursorInsets({
2527
height: 0,
2628
width: 0,
2729
top: 0,
2830
left: 0,
29-
})
30-
}
31-
onMouseLeave={() => setCursorInsets(undefined)}
31+
});
32+
setHovered(true);
33+
}}
34+
onMouseLeave={() => {
35+
setCursorInsets(undefined);
36+
setHovered(false);
37+
}}
3238
className="border border-black/[0.2] dark:border-white/[0.2] flex flex-col items-start max-w-sm p-4 relative"
3339
style={{
3440
backdropFilter: 'blur(10px)',
3541
backgroundColor: 'rgba(255, 255, 255, 0.1)',
3642
}}
43+
animation={
44+
hovered
45+
? `float 10s ease-in-out infinite alternate, wiggle 4s linear infinite alternate; /* Combined animations */`
46+
: ''
47+
}
3748
>
49+
<style>
50+
{`
51+
@keyframes float {
52+
0% { transform: translateY(0); } /* Start at original position */
53+
50% { transform: translateY(-10px); } /* Move up 10px */
54+
100% { transform: translateY(0); } /* Return to original position */
55+
}
56+
57+
@keyframes wiggle {
58+
0% { transform: rotate(0deg); }
59+
25% { transform: rotate(1deg); } /* Wiggle slightly to the right */
60+
50% { transform: rotate(0deg); }
61+
75% { transform: rotate(-1deg); } /* Wiggle slightly to the left */
62+
100% { transform: rotate(0deg); }
63+
}
64+
`}
65+
</style>
66+
3867
<CardBasic text={centerText} icon={icon && PROJECT_NAME_ICON_MAP[icon]} />
39-
<Icon className="absolute h-6 w-6 -top-3 -left-3 dark:text-white text-black" />
40-
<Icon className="absolute h-6 w-6 -bottom-3 -left-3 dark:text-white text-black" />
41-
<Icon className="absolute h-6 w-6 -top-3 -right-3 dark:text-white text-black" />
42-
<Icon className="absolute h-6 w-6 -bottom-3 -right-3 dark:text-white text-black" />
68+
<Icon
69+
className="absolute h-6 w-6 -top-3 -left-3 dark:text-white text-black"
70+
isHovered={hovered}
71+
/>
72+
<Icon
73+
className="absolute h-6 w-6 -bottom-3 -left-3 dark:text-white text-black"
74+
isHovered={hovered}
75+
/>
76+
<Icon
77+
className="absolute h-6 w-6 -top-3 -right-3 dark:text-white text-black"
78+
isHovered={hovered}
79+
/>
80+
<Icon
81+
className="absolute h-6 w-6 -bottom-3 -right-3 dark:text-white text-black"
82+
isHovered={hovered}
83+
/>
4384
<HStack
4485
justifyContent={'space-between'}
4586
width={'full'}

src/components/Timeline/Timeline.tsx

Lines changed: 52 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,52 @@
11
import { useScroll, useTransform, motion } from 'framer-motion';
2-
import { useEffect, useRef, useState } from 'react';
2+
import React, { useEffect, useRef, useState } from 'react';
33
import { TimelineEntry } from './types';
44

5+
const TimelineContent = ({
6+
title,
7+
content,
8+
}: {
9+
title: string;
10+
content: React.ReactNode;
11+
}) => {
12+
return (
13+
<div className="flex justify-start">
14+
<div className="sticky flex flex-col md:flex-row z-1 items-center top-40 self-start max-w-xs lg:max-w-sm md:w-full">
15+
<div className="h-10 absolute left-3 md:left-3 w-10 rounded-full bg-white dark:bg-black flex items-center justify-center">
16+
<div className="h-4 w-4 rounded-full bg-neutral-200 dark:bg-neutral-800 border border-neutral-300 dark:border-neutral-700 p-2" />
17+
</div>
18+
<h3 className="hidden md:block text-xl md:pl-20 md:text-5xl font-bold text-neutral-500 dark:text-neutral-500 ">
19+
{title}
20+
</h3>
21+
</div>
22+
23+
<motion.div
24+
style={{
25+
border: `1px solid gray`, // Initial border color
26+
display: 'flex',
27+
alignItems: 'center',
28+
justifyContent: 'center',
29+
}}
30+
animate={{
31+
border: `1px solid #FFFFFF2F`, // Animate border color
32+
boxShadow: `0 0 10px white`, // Animate box-shadow for color change
33+
}}
34+
transition={{
35+
duration: 2,
36+
ease: 'easeInOut',
37+
repeat: Infinity,
38+
repeatType: 'reverse',
39+
}}
40+
>
41+
<h3 className="md:hidden block text-2xl mb-4 text-left font-bold text-neutral-500 dark:text-neutral-500">
42+
{title}
43+
</h3>
44+
{content}
45+
</motion.div>
46+
</div>
47+
);
48+
};
49+
550
const Timeline = ({
651
title,
752
data,
@@ -26,7 +71,7 @@ const Timeline = ({
2671
});
2772

2873
const heightTransform = useTransform(scrollYProgress, [0, 1], [0, height]);
29-
const opacityTransform = useTransform(scrollYProgress, [0, 0.1], [0, 1]);
74+
const opacityTransform = useTransform(scrollYProgress, [0, 0.01], [0, 1]);
3075

3176
return (
3277
<div
@@ -40,28 +85,11 @@ const Timeline = ({
4085
</div>
4186
<div ref={ref} className="relative max-w-7xl mx-auto pb-20 ">
4287
{data.map((item, index) => (
43-
<div key={index} className="flex justify-start">
44-
<div className="sticky flex flex-col md:flex-row z-1 items-center top-40 self-start max-w-xs lg:max-w-sm md:w-full">
45-
<div className="h-10 absolute left-3 md:left-3 w-10 rounded-full bg-white dark:bg-black flex items-center justify-center">
46-
<div className="h-4 w-4 rounded-full bg-neutral-200 dark:bg-neutral-800 border border-neutral-300 dark:border-neutral-700 p-2" />
47-
</div>
48-
<h3 className="hidden md:block text-xl md:pl-20 md:text-5xl font-bold text-neutral-500 dark:text-neutral-500 ">
49-
{item.title}
50-
</h3>
51-
</div>
52-
53-
<div
54-
className="relative pl-20 pr-4 md:pl-4 w-full "
55-
style={{
56-
border: '1px solid gray',
57-
}}
58-
>
59-
<h3 className="md:hidden block text-2xl mb-4 text-left font-bold text-neutral-500 dark:text-neutral-500">
60-
{item.title}
61-
</h3>
62-
{item.content}{' '}
63-
</div>
64-
</div>
88+
<TimelineContent
89+
key={index}
90+
title={item.title}
91+
content={item.content}
92+
/>
6593
))}
6694
<div
6795
style={{

src/components/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
export * from './ArticleCard';
22
export * from './animateModal';
3+
export * from './BorderAnimationContainer';
34
export * from './Button';
45
export * from './CardComponent';
56
export * from './Chip';

0 commit comments

Comments
 (0)