diff --git a/app/layout.tsx b/app/layout.tsx
index a38b174..1ff1e25 100644
--- a/app/layout.tsx
+++ b/app/layout.tsx
@@ -18,7 +18,7 @@ export default async function RootLayout({ children }: { readonly children: Reac
{children}
diff --git a/app/page.tsx b/app/page.tsx
index 97ed30c..c02b961 100644
--- a/app/page.tsx
+++ b/app/page.tsx
@@ -2,6 +2,7 @@ import { About } from '@/components/about';
import { Contacts } from '@/components/contacts';
import { Person } from '@/components/person';
import { Skills } from '@/components/skills';
+import { NeonGradientCard } from '@/components/ui/neon-gradient-card';
import { Work } from '@/components/work';
import { type Metadata } from 'next';
import { getTranslations } from 'next-intl/server';
@@ -22,12 +23,16 @@ export async function generateMetadata({ params: { locale } }: Parameters): Prom
export default function HomePage() {
return (
-
-
-
-
-
-
+
+
+
+
);
}
diff --git a/components/ui/neon-gradient-card.tsx b/components/ui/neon-gradient-card.tsx
new file mode 100644
index 0000000..3192789
--- /dev/null
+++ b/components/ui/neon-gradient-card.tsx
@@ -0,0 +1,151 @@
+"use client";
+
+import {
+ CSSProperties,
+ ReactElement,
+ ReactNode,
+ useEffect,
+ useRef,
+ useState,
+} from "react";
+
+import { cn } from "@/lib/utils";
+
+interface NeonColorsProps {
+ firstColor: string;
+ secondColor: string;
+}
+
+interface NeonGradientCardProps {
+ /**
+ * @default
+ * @type ReactElement
+ * @description
+ * The component to be rendered as the card
+ * */
+ as?: ReactElement;
+ /**
+ * @default ""
+ * @type string
+ * @description
+ * The className of the card
+ */
+ className?: string;
+
+ /**
+ * @default ""
+ * @type ReactNode
+ * @description
+ * The children of the card
+ * */
+ children?: ReactNode;
+
+ /**
+ * @default 5
+ * @type number
+ * @description
+ * The size of the border in pixels
+ * */
+ borderSize?: number;
+
+ /**
+ * @default 20
+ * @type number
+ * @description
+ * The size of the radius in pixels
+ * */
+ borderRadius?: number;
+
+ /**
+ * @default "{ firstColor: '#ff00aa', secondColor: '#00FFF1' }"
+ * @type string
+ * @description
+ * The colors of the neon gradient
+ * */
+ neonColors?: NeonColorsProps;
+
+ [key: string]: any;
+}
+
+const NeonGradientCard: React.FC = ({
+ className,
+ children,
+ borderSize = 2,
+ borderRadius = 20,
+ neonColors = {
+ firstColor: "#ff00aa",
+ secondColor: "#00FFF1",
+ },
+ ...props
+}) => {
+ const containerRef = useRef(null);
+ const [dimensions, setDimensions] = useState({ width: 0, height: 0 });
+
+ useEffect(() => {
+ const updateDimensions = () => {
+ if (containerRef.current) {
+ const { offsetWidth, offsetHeight } = containerRef.current;
+ setDimensions({ width: offsetWidth, height: offsetHeight });
+ }
+ };
+
+ updateDimensions();
+ window.addEventListener("resize", updateDimensions);
+
+ return () => {
+ window.removeEventListener("resize", updateDimensions);
+ };
+ }, []);
+
+ useEffect(() => {
+ if (containerRef.current) {
+ const { offsetWidth, offsetHeight } = containerRef.current;
+ setDimensions({ width: offsetWidth, height: offsetHeight });
+ }
+ }, [children]);
+
+ return (
+
+ );
+};
+
+export { NeonGradientCard };
diff --git a/tailwind.config.ts b/tailwind.config.ts
index 773b1e6..e55b8e6 100644
--- a/tailwind.config.ts
+++ b/tailwind.config.ts
@@ -55,6 +55,19 @@ export default {
lg: 'var(--radius)',
md: 'calc(var(--radius) - 2px)',
sm: 'calc(var(--radius) - 4px)'
+ },
+ animation: {
+ 'background-position-spin': 'background-position-spin 3000ms infinite alternate'
+ },
+ keyframes: {
+ 'background-position-spin': {
+ '0%': {
+ backgroundPosition: 'top center'
+ },
+ '100%': {
+ backgroundPosition: 'bottom center'
+ }
+ }
}
}
},