Fresh start

This commit is contained in:
yznahmad 2025-06-08 03:53:12 +03:00
commit 96aca96116
63 changed files with 19295 additions and 0 deletions

43
.gitignore vendored Normal file
View File

@ -0,0 +1,43 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.*
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/versions
# testing
/coverage
# next.js
/.next/
/out/
# production
/build
# misc
.DS_Store
*.pem
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*
# env files (can opt-in for committing if needed)
.env*
# vercel
.vercel
# typescript
*.tsbuildinfo
next-env.d.ts
.vercel

36
README.md Normal file
View File

@ -0,0 +1,36 @@
This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
## Getting Started
First, run the development server:
```bash
npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun dev
```
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
You can start editing the page by modifying `app/page.js`. The page auto-updates as you edit the file.
This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel.
## Learn More
To learn more about Next.js, take a look at the following resources:
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome!
## Deploy on Vercel
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details.

114
app/Approach.js Normal file
View File

@ -0,0 +1,114 @@
"use client";
import React from "react";
import { AnimatePresence, motion } from "motion/react";
import { CanvasRevealEffect } from "./components/canvas-reveal-effect";
import { Button } from "./components/Button";
export function CanvasRevealEffectDemo() {
return (
<div className="bg-[#010217]">
<h1 className="font-bold text-3xl text-center text-white">
My <span className="text-fuchsia-300">approach</span>
</h1>
<div className="py-20 flex flex-col lg:flex-row items-center justify-center gap-6 px-8">
<Card
title="Development & Progress"
description="Once we agree on the plan, I cue my lofi playlist and dive into coding. From selection to polished code, I keep you updated every step."
buttonText="Phase 1"
>
<CanvasRevealEffect
animationSpeed={5.1}
containerClassName="bg-emerald-900"
/>
</Card>
<Card
title="Launch & Delivery"
description="After polishing the code and final checks, I ensure smooth delivery and deployment, keeping everything transparent and simple."
buttonText="Phase 2"
>
<CanvasRevealEffect
animationSpeed={3}
containerClassName="bg-black"
colors={[
[236, 72, 153],
[232, 121, 249],
]}
dotSize={2}
/>
<div className="absolute inset-0 [mask-image:radial-gradient(400px_at_center,white,transparent)] bg-black/50 dark:bg-black/90" />
</Card>
<Card
title="Post-Launch Support"
description="I'm available for maintenance, updates, and improvements even after launch. Long-term support is part of the deal."
buttonText="Phase 3"
>
<CanvasRevealEffect
animationSpeed={3}
containerClassName="bg-sky-600"
colors={[[125, 211, 252]]}
/>
</Card>
</div>
</div>
);
}
const Card = ({ title, description, children, buttonText }) => {
const [hovered, setHovered] = React.useState(false);
return (
<div
onMouseEnter={() => setHovered(true)}
onMouseLeave={() => setHovered(false)}
className="max-w-xs w-full mx-auto p-4 relative h-[30rem] rounded-xl flex flex-col justify-between bg-[linear-gradient(103.4deg,_#04071D_16.66%,_#0C0E23_81.61%)]"
>
{/* الزوائد في الزوايا */}
<span className="absolute -top-4 -left-2 text-gray-600 text-5xl font-thin z-20">
+
</span>
<span className="absolute -top-4 -right-1 text-gray-600 text-5xl font-thin z-20">
+
</span>
<span className="absolute -bottom-1 -left-1 text-gray-600 text-5xl font-thin z-20">
+
</span>
<span className="absolute -bottom-1 right-1 text-gray-600 text-5xl font-thin z-20">
+
</span>
{/* خلفية تأثير الحركة */}
<AnimatePresence>
{hovered && (
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
className="absolute inset-0 z-0"
>
{children}
</motion.div>
)}
</AnimatePresence>
{/* محتوى الكارت */}
<div className="relative z-10 flex flex-col justify-between h-full text-center">
{hovered && (
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.4 }}
>
<h2 className="text-white font-bold text-lg mb-2">{title}</h2>
<p className="text-gray-300 text-sm">{description}</p>
</motion.div>
)}
{/* زر مخصص لكل كارت */}
<div className="flex justify-center mt-auto relative bottom-48">
<Button className="w-36 text-sm">{buttonText}</Button>
</div>
</div>
</div>
);
};

39
app/Col2.js Normal file
View File

@ -0,0 +1,39 @@
"use client";
import React from "react";
import SimpleGlobe from "./components/Moon"; // عدل المسار حسب مكان الملف
export default function Col2() {
return (
<div className="col flex flex-col gap-10 px-4 sm:px-6 lg:px-8">
{/* القسم الأول */}
<div className="bg-[#010217] border border-gray-500 p-5 relative min-h-[200px] overflow-hidden rounded-md">
<h1 className="text-white text-xl sm:text-2xl lg:text-3xl font-bold relative top-5 left-5 max-w-full">
I'm very flexible with time <br /> zone communications
</h1>
<div className="relative top-4 flex justify-center">
<img src={"/mo.png"} alt="Moon Image" className="max-w-full h-auto" />
</div>
</div>
{/* القسم الثاني */}
<div className="bg-[#010217] border border-gray-500 grid grid-cols-1 md:grid-cols-2 items-center rounded-md">
<div className="text-white p-5">
<p className="font-thin text-gray-400 mb-3">
I constantly try to improve <br />
<span className="font-bold text-4xl text-white whitespace-nowrap">
My tech stack
</span>
</p>
</div>
<div className="p-5 flex justify-center">
<img
src={"/group.png"}
alt="Group Image"
className="max-w-full h-auto"
/>
</div>
</div>
</div>
);
}

72
app/Footer.js Normal file
View File

@ -0,0 +1,72 @@
import { GridBackgroundDemo } from "./components/Line";
import { FaFacebookF, FaTwitter, FaInstagram } from "react-icons/fa";
function Footer() {
return (
<footer className="relative w-full overflow-hidden">
{/* الجريد جوه الفوتر نفسه */}
<div className="absolute inset-0 -z-10">
<GridBackgroundDemo />
</div>
<div className="flex flex-col items-center justify-center py-16 px-6 w-full min-h-[16rem]">
<p className="font-bold text-white sm:text-lg md:text-3xl text-center z-10 max-w-3xl">
Ready to take <span className="text-fuchsia-300">your</span> digital
<br />
presence to the next level
</p>
<p className="text-gray-300 mt-4 text-xs z-10 max-w-3xl text-center">
Reach out to me today and let's discuss how I can help you achieve
your goal
</p>
<button
className="mt-10 z-10 px-6 py-3 rounded-md font-semibold text-white
backdrop-blur-md bg-gradient-to-r from-white/10 to-white/5 border border-white/10
hover:text-white transition-all duration-300"
>
Contact Me Now
</button>
{/* السطر السفلي */}
<div className="grid sm:grid-cols-1 sm:items-center md:flex justify-between items-center w-full max-w-screen-xl relative top-10 text-xs px-4 text-white gap-6">
<p className="whitespace-nowrap ">
© 2024 Admin Khadeja. All rights reserved.
</p>
<div className="flex space-x-3 ">
<a
href="https://facebook.com"
target="_blank"
rel="noopener noreferrer"
aria-label="Facebook"
className="hover:text-fuchsia-300 transition-colors bg-[#0d1449] p-2"
>
<FaFacebookF className="w-4 h-4" />
</a>
<a
href="https://twitter.com"
target="_blank"
rel="noopener noreferrer"
aria-label="Twitter"
className="hover:text-fuchsia-300 transition-colors bg-[#0d1449] p-2"
>
<FaTwitter className="w-4 h-4" />
</a>
<a
href="https://instagram.com"
target="_blank"
rel="noopener noreferrer"
aria-label="Instagram"
className="hover:text-fuchsia-300 transition-colors bg-[#0d1449] p-2"
>
<FaInstagram className="w-4 h-4" />
</a>
</div>
</div>
</div>
</footer>
);
}
export default Footer;

56
app/Hero.js Normal file
View File

@ -0,0 +1,56 @@
import React from "react";
import { Spotlight } from "./components/SpotLight";
import { GridBackgroundDemo } from "./components/Line";
import { Button } from "./components/Button";
import { TextGenerateEffect } from "./components/text-generate-effect";
import { FloatingNav } from "./components/Navbar";
function Hero() {
return (
<div className="relative bg-[#010217] overflow-hidden p-4 h-screen flex flex-col justify-center items-center">
<FloatingNav />
{/* خلفية الخطوط */}
<GridBackgroundDemo />
{/* Spotlights */}
<Spotlight
className="absolute top-[20%] left-[80px] opacity-70 z-10 pointer-events-none"
fill="white"
/>
<Spotlight
className="absolute top-[20%] left-[240px] opacity-20 z-10 pointer-events-none"
fill="purple"
/>
<Spotlight
className="absolute top-[10%] left-[90%] opacity-100 z-30 pointer-events-none"
fill="white"
/>
{/* المحتوى النصي */}
<div className="absolute top-50 left-1/2 transform -translate-x-1/2 z-40 text-white text-center px-4">
<h1 className="capitalize">dynamic web magic with next.js</h1>
<TextGenerateEffect className="text-[#caccdc] text-center font-bold sm:text-xl md:text-4xl capitalize">
<>
<p className="text-[#caccdc] ">
{" "}
transforming concepts into seamless
</p>{" "}
<span className="text-fuchsia-300 text-5xl">user experiences</span>
<h1 className="text-sm font-normal mt-3 text-[#caccdc] ">
Hi, I'm Adrian, a Next.js developer based in Croatia.
</h1>
</>
</TextGenerateEffect>
</div>
{/* زرار Show my Work */}
<div className="flex relative bottom-10 z-40">
<Button className={"w-52"}>Show my Work</Button>
</div>
</div>
);
}
export default Hero;

32
app/Main.js Normal file
View File

@ -0,0 +1,32 @@
import React from "react";
import Col2 from "./Col2";
function Main() {
return (
<div className="bg-[#010217] flex flex-col lg:flex-row w-full p-4 sm:p-6 lg:p-20 gap-6 relative">
{/* القسم الأيسر */}
<div className="relative border border-gray-500 bg-[#050511a2] w-full lg:w-1/2 p-4 flex flex-col items-center justify-center">
{/* الصورة */}
<div className="w-full max-w-[400px]">
<img
src="/eaarth.png"
alt="img4"
className="w-full object-contain"
/>
</div>
{/* النص */}
<p className="text-white font-bold text-xl sm:text-2xl lg:text-3xl text-center max-w-[400px] absolute bottom-16 left-6">
I prioritize client collaboration, fostering open communication
</p>
</div>
{/* القسم الأيمن */}
<div className="w-full lg:w-1/2">
<Col2 />
</div>
</div>
);
}
export default Main;

22
app/Work.js Normal file
View File

@ -0,0 +1,22 @@
import React from "react";
import Work2 from "./Work2";
function Work() {
return (
<div className="bg-red ">
<h1 className="font-bold text-3xl text-white text-center">
My <span className="text-fuchsia-300">work experience</span>
</h1>
<div className="w-full px-4 mt-5 mb-5">
<div className=" sm:grid-col-1 md:grid grid-cols-2 gap-10 items-center justify-center mt-16 max-w-4xl mx-auto p-2 ">
<Work2 src="/st.png" />
<Work2 src="/st.png" />
<Work2 src="/sss.png" />
<Work2 src="/ss.png" />
</div>
</div>
</div>
);
}
export default Work;

23
app/Work2.js Normal file
View File

@ -0,0 +1,23 @@
import React from "react";
import Image from "next/image";
function Work2(props) {
return (
<div className="relative flex justify-center">
<div className="animated-corner-card">
<div className="flex items-center justify-center w-full h-full z-10 relative">
<Image
src={props.src}
alt="img"
width={400}
height={100}
className="object-contain"
/>
</div>
<span className="corner-glow" />
</div>
</div>
);
}
export default Work2;

91
app/components/3d-pin.js Normal file
View File

@ -0,0 +1,91 @@
'use client';
import React, { useState } from 'react';
import { motion } from 'framer-motion'; // صححنا الاستيراد من 'motion/react'
import { cn } from '@/lib/utils';
export const PinContainer = ({
children,
title,
href,
className,
containerClassName
}) => {
const [transform, setTransform] = useState('translate(-50%,-50%) rotateX(0deg)');
const onMouseEnter = () => {
setTransform('translate(-50%,-50%) rotateX(40deg) scale(0.8)');
};
const onMouseLeave = () => {
setTransform('translate(-50%,-50%) rotateX(0deg) scale(1)');
};
return (
<div
role="link"
onClick={() => window.open(href || '/', '_blank')}
className={cn('relative group/pin z-50 cursor-pointer', containerClassName)}
onMouseEnter={onMouseEnter}
onMouseLeave={onMouseLeave}
>
<div
style={{
perspective: '1000px',
transform: 'rotateX(70deg) translateZ(0deg)',
}}
className="absolute left-1/2 top-1/2 ml-[0.09375rem] mt-4 -translate-x-1/2 -translate-y-1/2"
>
<div
style={{ transform }}
className="absolute left-1/2 p-4 top-1/2 flex justify-start items-start rounded-2xl shadow-[0_8px_16px_rgb(0_0_0/0.4)] bg-black border border-white/[0.1] group-hover/pin:border-white/[0.2] transition duration-700 overflow-hidden"
>
<div className={cn('relative z-50', className)}>{children}</div>
</div>
</div>
<PinPerspective title={title} />
</div>
);
};
export const PinPerspective = ({ title }) => {
return (
<motion.div className="pointer-events-none w-96 h-80 flex items-center justify-center opacity-0 group-hover/pin:opacity-100 z-[60] transition duration-500">
<div className="w-full h-full -mt-7 flex-none inset-0">
<div className="absolute top-0 inset-x-0 flex justify-center">
<div className="relative flex space-x-2 items-center z-10 rounded-full bg-zinc-950 py-0.5 px-4 ring-1 ring-white/10">
<span className="relative z-20 text-white text-xs font-bold inline-block py-0.5">
{title}
</span>
<span className="absolute -bottom-0 left-[1.125rem] h-px w-[calc(100%-2.25rem)] bg-gradient-to-r from-emerald-400/0 via-emerald-400/90 to-emerald-400/0 transition-opacity duration-500 group-hover/btn:opacity-40" />
</div>
</div>
<div
style={{
perspective: '1000px',
transform: 'rotateX(70deg) translateZ(0)',
}}
className="absolute left-1/2 top-1/2 ml-[0.09375rem] mt-4 -translate-x-1/2 -translate-y-1/2"
>
<>
{[0, 2, 4].map((delay) => (
<motion.div
key={delay}
initial={{ opacity: 0, scale: 0, x: '-50%', y: '-50%' }}
animate={{ opacity: [0, 1, 0.5, 0], scale: 1, z: 0 }}
transition={{ duration: 6, repeat: Infinity, delay }}
className="absolute left-1/2 top-1/2 h-[11.25rem] w-[11.25rem] rounded-full bg-sky-500/[0.08] shadow-[0_8px_16px_rgb(0_0_0/0.4)]"
/>
))}
</>
</div>
<>
<motion.div className="absolute right-1/2 bottom-1/2 bg-gradient-to-b from-transparent to-cyan-500 translate-y-[14px] w-px h-20 group-hover/pin:h-40 blur-[2px]" />
<motion.div className="absolute right-1/2 bottom-1/2 bg-gradient-to-b from-transparent to-cyan-500 translate-y-[14px] w-px h-20 group-hover/pin:h-40" />
<motion.div className="absolute right-1/2 translate-x-[1.5px] bottom-1/2 bg-cyan-600 translate-y-[14px] w-[4px] h-[4px] rounded-full z-40 blur-[3px]" />
<motion.div className="absolute right-1/2 translate-x-[0.5px] bottom-1/2 bg-cyan-300 translate-y-[14px] w-[2px] h-[2px] rounded-full z-40" />
</>
</div>
</motion.div>
);
};

View File

@ -0,0 +1,145 @@
"use client";
import { cn } from "@/lib/utils";
import { useEffect, useRef, useState } from "react";
export const BackgroundGradientAnimation = ({
gradientBackgroundStart = "rgb(108, 0, 162)",
gradientBackgroundEnd = "rgb(0, 17, 82)",
firstColor = "18, 113, 255",
secondColor = "221, 74, 255",
thirdColor = "100, 220, 255",
fourthColor = "200, 50, 50",
fifthColor = "180, 180, 50",
pointerColor = "140, 100, 255",
size = "80%",
blendingValue = "hard-light",
children,
className,
interactive = true,
containerClassName
}) => {
const interactiveRef = useRef(null);
const [curX, setCurX] = useState(0);
const [curY, setCurY] = useState(0);
const [tgX, setTgX] = useState(0);
const [tgY, setTgY] = useState(0);
useEffect(() => {
document.body.style.setProperty("--gradient-background-start", gradientBackgroundStart);
document.body.style.setProperty("--gradient-background-end", gradientBackgroundEnd);
document.body.style.setProperty("--first-color", firstColor);
document.body.style.setProperty("--second-color", secondColor);
document.body.style.setProperty("--third-color", thirdColor);
document.body.style.setProperty("--fourth-color", fourthColor);
document.body.style.setProperty("--fifth-color", fifthColor);
document.body.style.setProperty("--pointer-color", pointerColor);
document.body.style.setProperty("--size", size);
document.body.style.setProperty("--blending-value", blendingValue);
}, []);
useEffect(() => {
function move() {
if (!interactiveRef.current) {
return;
}
setCurX(curX + (tgX - curX) / 20);
setCurY(curY + (tgY - curY) / 20);
interactiveRef.current.style.transform = `translate(${Math.round(curX)}px, ${Math.round(curY)}px)`;
}
move();
}, [tgX, tgY]);
const handleMouseMove = (event) => {
if (interactiveRef.current) {
const rect = interactiveRef.current.getBoundingClientRect();
setTgX(event.clientX - rect.left);
setTgY(event.clientY - rect.top);
}
};
const [isSafari, setIsSafari] = useState(false);
useEffect(() => {
setIsSafari(/^((?!chrome|android).)*safari/i.test(navigator.userAgent));
}, []);
return (
<div
className={cn(
"h-screen w-screen relative overflow-hidden top-0 left-0 bg-[linear-gradient(40deg,var(--gradient-background-start),var(--gradient-background-end))]",
containerClassName
)}>
<svg className="hidden">
<defs>
<filter id="blurMe">
<feGaussianBlur in="SourceGraphic" stdDeviation="10" result="blur" />
<feColorMatrix
in="blur"
mode="matrix"
values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 18 -8"
result="goo" />
<feBlend in="SourceGraphic" in2="goo" />
</filter>
</defs>
</svg>
<div className={cn("", className)}>{children}</div>
<div
className={cn(
"gradients-container h-full w-full blur-lg",
isSafari ? "blur-2xl" : "[filter:url(#blurMe)_blur(40px)]"
)}>
<div
className={cn(
`absolute [background:radial-gradient(circle_at_center,_var(--first-color)_0,_var(--first-color)_50%)_no-repeat]`,
`[mix-blend-mode:var(--blending-value)] w-[var(--size)] h-[var(--size)] top-[calc(50%-var(--size)/2)] left-[calc(50%-var(--size)/2)]`,
`[transform-origin:center_center]`,
`animate-first`,
`opacity-100`
)}></div>
<div
className={cn(
`absolute [background:radial-gradient(circle_at_center,_rgba(var(--second-color),_0.8)_0,_rgba(var(--second-color),_0)_50%)_no-repeat]`,
`[mix-blend-mode:var(--blending-value)] w-[var(--size)] h-[var(--size)] top-[calc(50%-var(--size)/2)] left-[calc(50%-var(--size)/2)]`,
`[transform-origin:calc(50%-400px)]`,
`animate-second`,
`opacity-100`
)}></div>
<div
className={cn(
`absolute [background:radial-gradient(circle_at_center,_rgba(var(--third-color),_0.8)_0,_rgba(var(--third-color),_0)_50%)_no-repeat]`,
`[mix-blend-mode:var(--blending-value)] w-[var(--size)] h-[var(--size)] top-[calc(50%-var(--size)/2)] left-[calc(50%-var(--size)/2)]`,
`[transform-origin:calc(50%+400px)]`,
`animate-third`,
`opacity-100`
)}></div>
<div
className={cn(
`absolute [background:radial-gradient(circle_at_center,_rgba(var(--fourth-color),_0.8)_0,_rgba(var(--fourth-color),_0)_50%)_no-repeat]`,
`[mix-blend-mode:var(--blending-value)] w-[var(--size)] h-[var(--size)] top-[calc(50%-var(--size)/2)] left-[calc(50%-var(--size)/2)]`,
`[transform-origin:calc(50%-200px)]`,
`animate-fourth`,
`opacity-70`
)}></div>
<div
className={cn(
`absolute [background:radial-gradient(circle_at_center,_rgba(var(--fifth-color),_0.8)_0,_rgba(var(--fifth-color),_0)_50%)_no-repeat]`,
`[mix-blend-mode:var(--blending-value)] w-[var(--size)] h-[var(--size)] top-[calc(50%-var(--size)/2)] left-[calc(50%-var(--size)/2)]`,
`[transform-origin:calc(50%-800px)_calc(50%+800px)]`,
`animate-fifth`,
`opacity-100`
)}></div>
{interactive && (
<div
ref={interactiveRef}
onMouseMove={handleMouseMove}
className={cn(
`absolute [background:radial-gradient(circle_at_center,_rgba(var(--pointer-color),_0.8)_0,_rgba(var(--pointer-color),_0)_50%)_no-repeat]`,
`[mix-blend-mode:var(--blending-value)] w-full h-full -top-1/2 -left-1/2`,
`opacity-70`
)}></div>
)}
</div>
</div>
);
};

89
app/components/Button.js Normal file
View File

@ -0,0 +1,89 @@
"use client";
import React, { useState, useEffect } from "react";
import { motion } from "motion/react";
import { cn } from "@/lib/utils";
export function Button({
children,
containerClassName,
className,
as: Tag = "button",
duration = 1,
clockwise = true,
...props
}) {
const [hovered, setHovered] = useState(false);
const [direction, setDirection] = useState("TOP");
const rotateDirection = (currentDirection) => {
const directions = ["TOP", "LEFT", "BOTTOM", "RIGHT"];
const currentIndex = directions.indexOf(currentDirection);
const nextIndex = clockwise
? (currentIndex - 1 + directions.length) % directions.length
: (currentIndex + 1) % directions.length;
return directions[nextIndex];
};
const movingMap = {
TOP: "radial-gradient(20.7% 50% at 50% 0%, hsl(0, 0%, 100%) 0%, rgba(255, 255, 255, 0) 100%)",
LEFT: "radial-gradient(16.6% 43.1% at 0% 50%, hsl(0, 0%, 100%) 0%, rgba(255, 255, 255, 0) 100%)",
BOTTOM:
"radial-gradient(20.7% 50% at 50% 100%, hsl(0, 0%, 100%) 0%, rgba(255, 255, 255, 0) 100%)",
RIGHT:
"radial-gradient(16.2% 41.199999999999996% at 100% 50%, hsl(0, 0%, 100%) 0%, rgba(255, 255, 255, 0) 100%)",
};
const highlight =
"radial-gradient(75% 181.15942028985506% at 50% 50%, #3275F8 0%, rgba(255, 255, 255, 0) 100%)";
useEffect(() => {
if (!hovered) {
const interval = setInterval(() => {
setDirection((prevState) => rotateDirection(prevState));
}, duration * 1000);
return () => clearInterval(interval);
}
}, [hovered]);
return (
<Tag
onMouseEnter={(event) => {
setHovered(true);
}}
onMouseLeave={() => setHovered(false)}
className={cn(
"relative flex rounded-full border content-center bg-black/20 hover:bg-black/10 transition duration-500 dark:bg-white/20 items-center flex-col flex-nowrap gap-10 h-min justify-center overflow-visible p-px decoration-clone w-fit",
containerClassName
)}
{...props}
>
<div
className={cn(
"w-auto text-white z-10 bg-black px-4 py-2 rounded-[inherit]",
className
)}
>
{children}
</div>
<motion.div
className={cn(
"flex-none inset-0 overflow-hidden absolute z-0 rounded-[inherit]"
)}
style={{
filter: "blur(2px)",
position: "absolute",
width: "100%",
height: "100%",
}}
initial={{ background: movingMap[direction] }}
animate={{
background: hovered
? [movingMap[direction], highlight]
: movingMap[direction],
}}
transition={{ ease: "linear", duration: duration ?? 1 }}
/>
<div className="bg-black absolute z-1 flex-none inset-[2px] rounded-[100px]" />
</Tag>
);
}

21
app/components/Line.js Normal file
View File

@ -0,0 +1,21 @@
export function GridBackgroundDemo({ children }) {
return (
<div className="relative flex h-[50rem] w-full items-center justify-center bg-[#010217]">
<div
className="absolute inset-0"
style={{
backgroundSize: "40px 40px",
backgroundImage:
"linear-gradient(to right, #2b2b3d 1px, transparent 1px), linear-gradient(to bottom, #2b2b3d 1px, transparent 1px)",
// شيل الـ mask عشان لا يخفي النص
// maskImage: "radial-gradient(ellipse at center, transparent 20%, black 80%)",
// WebkitMaskImage: "radial-gradient(ellipse at center, transparent 20%, black 80%)",
opacity: 0.3, // خفف من وضوح الشبكة عشان النص يبان
}}
/>
<div className="relative z-10 w-full flex justify-center px-4">
{children}
</div>
</div>
);
}

View File

@ -0,0 +1,594 @@
"use client";
import React, { useEffect, useRef, useState } from "react";
import { motion, useScroll, useTransform } from "motion/react";
import { cn } from "@/lib/utils";
import {
IconBrightnessDown,
IconBrightnessUp,
IconCaretRightFilled,
IconCaretUpFilled,
IconChevronUp,
IconMicrophone,
IconMoon,
IconPlayerSkipForward,
IconPlayerTrackNext,
IconPlayerTrackPrev,
IconTable,
IconVolume,
IconVolume2,
IconVolume3,
} from "@tabler/icons-react";
import { IconSearch } from "@tabler/icons-react";
import { IconWorld } from "@tabler/icons-react";
import { IconCommand } from "@tabler/icons-react";
import { IconCaretLeftFilled } from "@tabler/icons-react";
import { IconCaretDownFilled } from "@tabler/icons-react";
export const MacbookScroll = ({
src,
showGradient,
title,
badge
}) => {
const ref = useRef(null);
const { scrollYProgress } = useScroll({
target: ref,
offset: ["start start", "end start"],
});
const [isMobile, setIsMobile] = useState(false);
useEffect(() => {
if (window && window.innerWidth < 768) {
setIsMobile(true);
}
}, []);
const scaleX = useTransform(scrollYProgress, [0, 0.3], [1.2, isMobile ? 1 : 1.5]);
const scaleY = useTransform(scrollYProgress, [0, 0.3], [0.6, isMobile ? 1 : 1.5]);
const translate = useTransform(scrollYProgress, [0, 1], [0, 1500]);
const rotate = useTransform(scrollYProgress, [0.1, 0.12, 0.3], [-28, -28, 0]);
const textTransform = useTransform(scrollYProgress, [0, 0.3], [0, 100]);
const textOpacity = useTransform(scrollYProgress, [0, 0.2], [1, 0]);
return (
<div
ref={ref}
className="flex min-h-[200vh] shrink-0 scale-75 transform -translate-x-36 -translate-y-32 flex-col items-center justify-start py-0 [perspective:800px] sm:w-[500px] md:w-full md:py-80">
<motion.h2
style={{
translateY: textTransform,
opacity: textOpacity,
}}
className="mb-20 text-center text-3xl font-bold text-neutral-800 dark:text-white">
</motion.h2>
{/* Lid */}
<Lid
src={'/2.jpg'}
scaleX={scaleX}
scaleY={scaleY}
rotate={rotate}
translate={translate} />
{/* Base area */}
<div
className="relative -z-10 h-[22rem] w-[32rem] overflow-hidden rounded-2xl bg-gray-200 dark:bg-[#272729]">
{/* above keyboard bar */}
<div className="relative h-10 w-full">
<div className="absolute inset-x-0 mx-auto h-4 w-[80%] bg-[#050505]" />
</div>
<div className="relative flex">
<div className="mx-auto h-full w-[10%] overflow-hidden">
<SpeakerGrid />
</div>
<div className="mx-auto h-full w-[80%]">
<Keypad />
</div>
<div className="mx-auto h-full w-[10%] overflow-hidden">
<SpeakerGrid />
</div>
</div>
<Trackpad />
<div
className="absolute inset-x-0 bottom-0 mx-auto h-2 w-20 rounded-tl-3xl rounded-tr-3xl bg-gradient-to-t from-[#272729] to-[#050505]" />
{showGradient && (
<div
className="absolute inset-x-0 bottom-0 z-50 h-40 w-full bg-gradient-to-t from-white via-white to-transparent dark:from-black dark:via-black"></div>
)}
{badge && <div className="absolute bottom-4 left-4">{badge}</div>}
</div>
</div>
);
};
export const Lid = ({
scaleX,
scaleY,
rotate,
translate,
src
}) => {
return (
<div className="relative [perspective:800px]">
<div
style={{
transform: "perspective(800px) rotateX(-25deg) translateZ(0px)",
transformOrigin: "bottom",
transformStyle: "preserve-3d",
}}
className="relative h-[12rem] w-[32rem] rounded-2xl bg-[#010101] p-2">
<div
style={{
boxShadow: "0px 2px 0px 2px #171717 inset",
}}
className="absolute inset-0 flex items-center justify-center rounded-lg bg-[#010101]">
<span className="text-white">
<AceternityLogo />
</span>
</div>
</div>
<motion.div
style={{
scaleX: scaleX,
scaleY: scaleY,
rotateX: rotate,
translateY: translate,
transformStyle: "preserve-3d",
transformOrigin: "top",
}}
className="fixed inset-0 h-80 w-[32rem] rounded-2xl bg-[#010101] p-2">
<div className="absolute inset-0 rounded-lg bg-[#272729]" />
<img
src={"/22.jpg"}
alt="aceternity logo"
className="fixed inset-0 h-full w-full rounded-lg object-cover object-left-top" />
</motion.div>
</div>
);
};
export const Trackpad = () => {
return (
<div
className="mx-auto my-1 h-32 w-[40%] rounded-xl"
style={{
boxShadow: "0px 0px 1px 1px #00000020 inset",
}}></div>
);
};
export const Keypad = () => {
return (
<div
className="mx-1 h-full [transform:translateZ(0)] rounded-md bg-[#050505] p-1 [will-change:transform]">
{/* First Row */}
<div className="mb-[2px] flex w-full shrink-0 gap-[2px]">
<KBtn
className="w-10 items-end justify-start pb-[2px] pl-[4px]"
childrenClassName="items-start">
esc
</KBtn>
<KBtn>
<IconBrightnessDown className="h-[6px] w-[6px]" />
<span className="mt-1 inline-block">F1</span>
</KBtn>
<KBtn>
<IconBrightnessUp className="h-[6px] w-[6px]" />
<span className="mt-1 inline-block">F2</span>
</KBtn>
<KBtn>
<IconTable className="h-[6px] w-[6px]" />
<span className="mt-1 inline-block">F3</span>
</KBtn>
<KBtn>
<IconSearch className="h-[6px] w-[6px]" />
<span className="mt-1 inline-block">F4</span>
</KBtn>
<KBtn>
<IconMicrophone className="h-[6px] w-[6px]" />
<span className="mt-1 inline-block">F5</span>
</KBtn>
<KBtn>
<IconMoon className="h-[6px] w-[6px]" />
<span className="mt-1 inline-block">F6</span>
</KBtn>
<KBtn>
<IconPlayerTrackPrev className="h-[6px] w-[6px]" />
<span className="mt-1 inline-block">F7</span>
</KBtn>
<KBtn>
<IconPlayerSkipForward className="h-[6px] w-[6px]" />
<span className="mt-1 inline-block">F8</span>
</KBtn>
<KBtn>
<IconPlayerTrackNext className="h-[6px] w-[6px]" />
<span className="mt-1 inline-block">F8</span>
</KBtn>
<KBtn>
<IconVolume3 className="h-[6px] w-[6px]" />
<span className="mt-1 inline-block">F10</span>
</KBtn>
<KBtn>
<IconVolume2 className="h-[6px] w-[6px]" />
<span className="mt-1 inline-block">F11</span>
</KBtn>
<KBtn>
<IconVolume className="h-[6px] w-[6px]" />
<span className="mt-1 inline-block">F12</span>
</KBtn>
<KBtn>
<div
className="h-4 w-4 rounded-full bg-gradient-to-b from-neutral-900 from-20% via-black via-50% to-neutral-900 to-95% p-px">
<div className="h-full w-full rounded-full bg-black" />
</div>
</KBtn>
</div>
{/* Second row */}
<div className="mb-[2px] flex w-full shrink-0 gap-[2px]">
<KBtn>
<span className="block">~</span>
<span className="mt-1 block">`</span>
</KBtn>
<KBtn>
<span className="block">!</span>
<span className="block">1</span>
</KBtn>
<KBtn>
<span className="block">@</span>
<span className="block">2</span>
</KBtn>
<KBtn>
<span className="block">#</span>
<span className="block">3</span>
</KBtn>
<KBtn>
<span className="block">$</span>
<span className="block">4</span>
</KBtn>
<KBtn>
<span className="block">%</span>
<span className="block">5</span>
</KBtn>
<KBtn>
<span className="block">^</span>
<span className="block">6</span>
</KBtn>
<KBtn>
<span className="block">&</span>
<span className="block">7</span>
</KBtn>
<KBtn>
<span className="block">*</span>
<span className="block">8</span>
</KBtn>
<KBtn>
<span className="block">(</span>
<span className="block">9</span>
</KBtn>
<KBtn>
<span className="block">)</span>
<span className="block">0</span>
</KBtn>
<KBtn>
<span className="block">&mdash;</span>
<span className="block">_</span>
</KBtn>
<KBtn>
<span className="block">+</span>
<span className="block"> = </span>
</KBtn>
<KBtn
className="w-10 items-end justify-end pr-[4px] pb-[2px]"
childrenClassName="items-end">
delete
</KBtn>
</div>
{/* Third row */}
<div className="mb-[2px] flex w-full shrink-0 gap-[2px]">
<KBtn
className="w-10 items-end justify-start pb-[2px] pl-[4px]"
childrenClassName="items-start">
tab
</KBtn>
<KBtn>
<span className="block">Q</span>
</KBtn>
<KBtn>
<span className="block">W</span>
</KBtn>
<KBtn>
<span className="block">E</span>
</KBtn>
<KBtn>
<span className="block">R</span>
</KBtn>
<KBtn>
<span className="block">T</span>
</KBtn>
<KBtn>
<span className="block">Y</span>
</KBtn>
<KBtn>
<span className="block">U</span>
</KBtn>
<KBtn>
<span className="block">I</span>
</KBtn>
<KBtn>
<span className="block">O</span>
</KBtn>
<KBtn>
<span className="block">P</span>
</KBtn>
<KBtn>
<span className="block">{`{`}</span>
<span className="block">{`[`}</span>
</KBtn>
<KBtn>
<span className="block">{`}`}</span>
<span className="block">{`]`}</span>
</KBtn>
<KBtn>
<span className="block">{`|`}</span>
<span className="block">{`\\`}</span>
</KBtn>
</div>
{/* Fourth Row */}
<div className="mb-[2px] flex w-full shrink-0 gap-[2px]">
<KBtn
className="w-[2.8rem] items-end justify-start pb-[2px] pl-[4px]"
childrenClassName="items-start">
caps lock
</KBtn>
<KBtn>
<span className="block">A</span>
</KBtn>
<KBtn>
<span className="block">S</span>
</KBtn>
<KBtn>
<span className="block">D</span>
</KBtn>
<KBtn>
<span className="block">F</span>
</KBtn>
<KBtn>
<span className="block">G</span>
</KBtn>
<KBtn>
<span className="block">H</span>
</KBtn>
<KBtn>
<span className="block">J</span>
</KBtn>
<KBtn>
<span className="block">K</span>
</KBtn>
<KBtn>
<span className="block">L</span>
</KBtn>
<KBtn>
<span className="block">{`:`}</span>
<span className="block">{`;`}</span>
</KBtn>
<KBtn>
<span className="block">{`"`}</span>
<span className="block">{`'`}</span>
</KBtn>
<KBtn
className="w-[2.85rem] items-end justify-end pr-[4px] pb-[2px]"
childrenClassName="items-end">
return
</KBtn>
</div>
{/* Fifth Row */}
<div className="mb-[2px] flex w-full shrink-0 gap-[2px]">
<KBtn
className="w-[3.65rem] items-end justify-start pb-[2px] pl-[4px]"
childrenClassName="items-start">
shift
</KBtn>
<KBtn>
<span className="block">Z</span>
</KBtn>
<KBtn>
<span className="block">X</span>
</KBtn>
<KBtn>
<span className="block">C</span>
</KBtn>
<KBtn>
<span className="block">V</span>
</KBtn>
<KBtn>
<span className="block">B</span>
</KBtn>
<KBtn>
<span className="block">N</span>
</KBtn>
<KBtn>
<span className="block">M</span>
</KBtn>
<KBtn>
<span className="block">{`<`}</span>
<span className="block">{`,`}</span>
</KBtn>
<KBtn>
<span className="block">{`>`}</span>
<span className="block">{`.`}</span>
</KBtn>
<KBtn>
<span className="block">{`?`}</span>
<span className="block">{`/`}</span>
</KBtn>
<KBtn
className="w-[3.65rem] items-end justify-end pr-[4px] pb-[2px]"
childrenClassName="items-end">
shift
</KBtn>
</div>
{/* sixth Row */}
<div className="mb-[2px] flex w-full shrink-0 gap-[2px]">
<KBtn className="" childrenClassName="h-full justify-between py-[4px]">
<div className="flex w-full justify-end pr-1">
<span className="block">fn</span>
</div>
<div className="flex w-full justify-start pl-1">
<IconWorld className="h-[6px] w-[6px]" />
</div>
</KBtn>
<KBtn className="" childrenClassName="h-full justify-between py-[4px]">
<div className="flex w-full justify-end pr-1">
<IconChevronUp className="h-[6px] w-[6px]" />
</div>
<div className="flex w-full justify-start pl-1">
<span className="block">control</span>
</div>
</KBtn>
<KBtn className="" childrenClassName="h-full justify-between py-[4px]">
<div className="flex w-full justify-end pr-1">
<OptionKey className="h-[6px] w-[6px]" />
</div>
<div className="flex w-full justify-start pl-1">
<span className="block">option</span>
</div>
</KBtn>
<KBtn className="w-8" childrenClassName="h-full justify-between py-[4px]">
<div className="flex w-full justify-end pr-1">
<IconCommand className="h-[6px] w-[6px]" />
</div>
<div className="flex w-full justify-start pl-1">
<span className="block">command</span>
</div>
</KBtn>
<KBtn className="w-[8.2rem]"></KBtn>
<KBtn className="w-8" childrenClassName="h-full justify-between py-[4px]">
<div className="flex w-full justify-start pl-1">
<IconCommand className="h-[6px] w-[6px]" />
</div>
<div className="flex w-full justify-start pl-1">
<span className="block">command</span>
</div>
</KBtn>
<KBtn className="" childrenClassName="h-full justify-between py-[4px]">
<div className="flex w-full justify-start pl-1">
<OptionKey className="h-[6px] w-[6px]" />
</div>
<div className="flex w-full justify-start pl-1">
<span className="block">option</span>
</div>
</KBtn>
<div
className="mt-[2px] flex h-6 w-[4.9rem] flex-col items-center justify-end rounded-[4px] p-[0.5px]">
<KBtn className="h-3 w-6">
<IconCaretUpFilled className="h-[6px] w-[6px]" />
</KBtn>
<div className="flex">
<KBtn className="h-3 w-6">
<IconCaretLeftFilled className="h-[6px] w-[6px]" />
</KBtn>
<KBtn className="h-3 w-6">
<IconCaretDownFilled className="h-[6px] w-[6px]" />
</KBtn>
<KBtn className="h-3 w-6">
<IconCaretRightFilled className="h-[6px] w-[6px]" />
</KBtn>
</div>
</div>
</div>
</div>
);
};
export const KBtn = ({
className,
children,
childrenClassName,
backlit = true
}) => {
return (
<div
className={cn(
"[transform:translateZ(0)] rounded-[4px] p-[0.5px] [will-change:transform]",
backlit && "bg-white/[0.2] shadow-xl shadow-white"
)}>
<div
className={cn(
"flex h-6 w-6 items-center justify-center rounded-[3.5px] bg-[#0A090D]",
className
)}
style={{
boxShadow:
"0px -0.5px 2px 0 #0D0D0F inset, -0.5px 0px 2px 0 #0D0D0F inset",
}}>
<div
className={cn(
"flex w-full flex-col items-center justify-center text-[5px] text-neutral-200",
childrenClassName,
backlit && "text-white"
)}>
{children}
</div>
</div>
</div>
);
};
export const SpeakerGrid = () => {
return (
<div
className="mt-2 flex h-40 gap-[2px] px-[0.5px]"
style={{
backgroundImage:
"radial-gradient(circle, #08080A 0.5px, transparent 0.5px)",
backgroundSize: "3px 3px",
}}></div>
);
};
export const OptionKey = ({
className
}) => {
return (
<svg
fill="none"
version="1.1"
id="icon"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 32 32"
className={className}>
<rect stroke="currentColor" strokeWidth={2} x="18" y="5" width="10" height="2" />
<polygon
stroke="currentColor"
strokeWidth={2}
points="10.6,5 4,5 4,7 9.4,7 18.4,27 28,27 28,25 19.6,25 " />
<rect
id="_Transparent_Rectangle_"
className="st0"
width="32"
height="32"
stroke="none" />
</svg>
);
};
const AceternityLogo = () => {
return (
<svg
width="66"
height="65"
viewBox="0 0 66 65"
fill="none"
xmlns="http://www.w3.org/2000/svg"
className="h-3 w-3 text-white">
<path
d="M8 8.05571C8 8.05571 54.9009 18.1782 57.8687 30.062C60.8365 41.9458 9.05432 57.4696 9.05432 57.4696"
stroke="currentColor"
strokeWidth="15"
strokeMiterlimit="3.86874"
strokeLinecap="round" />
</svg>
);
};

77
app/components/Moon.js Normal file
View File

@ -0,0 +1,77 @@
"use client";
import React, { useRef, useEffect } from "react";
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
export default function SimpleGlobe() {
const mountRef = useRef(null);
useEffect(() => {
const width = 400;
const height = 400;
// إنشاء المشهد
const scene = new THREE.Scene();
// الكاميرا
const camera = new THREE.PerspectiveCamera(75, width / height, 0.1, 1000);
camera.position.z = 3;
// الرندرر
const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
renderer.setSize(width, height);
mountRef.current.appendChild(renderer.domElement);
// الكرة الزرقاء
const geometry = new THREE.SphereGeometry(1, 32, 32);
const material = new THREE.MeshStandardMaterial({
color: "#007bff",
metalness: 0.3,
roughness: 0.7,
});
const sphere = new THREE.Mesh(geometry, material);
scene.add(sphere);
// إضاءة
const ambientLight = new THREE.AmbientLight(0xffffff, 1);
scene.add(ambientLight);
// تحكم الماوس
const controls = new OrbitControls(camera, renderer.domElement);
controls.enableDamping = true; // يجعل الحركة سلسة
controls.dampingFactor = 0.05;
// دالة التحديث والرسوم
const animate = () => {
requestAnimationFrame(animate);
sphere.rotation.y += 0.005; // دوران تلقائي بسيط
controls.update(); // تحديث تحكمات الماوس
renderer.render(scene, camera);
};
animate();
// تنظيف عند إزالة المكون
return () => {
controls.dispose();
mountRef.current.removeChild(renderer.domElement);
renderer.dispose();
};
}, []);
return (
<div
ref={mountRef}
style={{
width: "400px",
height: "400px",
margin: "0 auto",
backgroundColor: "#010217",
}}
/>
);
}

99
app/components/Navbar.js Normal file
View File

@ -0,0 +1,99 @@
"use client";
import React, { useState } from "react";
import {
motion,
AnimatePresence,
useScroll,
useMotionValueEvent,
} from "motion/react";
import { cn } from "@/lib/utils";
const HomeIcon = () => <span>🏠</span>;
const ServicesIcon = () => <span>🛠</span>;
const ProductsIcon = () => <span>📦</span>;
const ContactIcon = () => <span>📞</span>;
export const FloatingNav = ({
navItems = [],
className,
}) => {
const { scrollYProgress } = useScroll();
const [visible, setVisible] = useState(false);
useMotionValueEvent(scrollYProgress, "change", (current) => {
if (typeof current === "number") {
let direction = current - scrollYProgress.getPrevious();
if (scrollYProgress.get() < 0.05) {
setVisible(false);
} else {
if (direction < 0) {
setVisible(true);
} else {
setVisible(false);
}
}
}
});
return (
<AnimatePresence mode="wait">
<motion.nav
initial={{ opacity: 1, y: -100 }}
animate={{ y: visible ? 0 : -100, opacity: visible ? 1 : 0 }}
transition={{ duration: 0.2 }}
className={cn(
"flex max-w-fit fixed top-10 inset-x-0 mx-auto rounded-full shadow-lg z-[5000] pr-8 pl-8 py-2 items-center justify-center space-x-12", // space-x-12 لمسافة واسعة بين الروابط
"bg-[rgba(23,18,40,0.74)] text-white backdrop-blur-sm", // لون كحلي بنفسجي غامق مع شفافية وخلفية ضبابية
className
)}
>
{navItems.map((navItem, idx) => (
<a
key={`link=${idx}`}
href={navItem.link}
className={cn(
"relative flex items-center space-x-2 hover:text-[rgba(221,74,255,0.9)] transition-colors duration-300 ease-in-out font-semibold text-sm"
)}
>
<span className="block sm:hidden">{navItem.icon}</span>
<span className="hidden sm:block">{navItem.name}</span>
</a>
))}
<button
type="button"
className=" text-white px-5 py-2 rounded-full font-semibold relative "
>
<div className="flex gap-6">
<span>Home</span>
<span>service</span>
<span>Products</span>
<span>Contact</span>
</div>
<span className="absolute inset-x-0 w-1/2 mx-auto -bottom-px bg-gradient-to-r from-transparent via-purple-400 to-transparent h-px" />
</button>
</motion.nav>
</AnimatePresence>
);
};
// مثال الاستخدام مع 4 روابط
export default function App() {
const navItems = [
{ name: "Home", link: "/", icon: <HomeIcon /> },
{ name: "Services", link: "/services", icon: <ServicesIcon /> },
{ name: "Products", link: "/products", icon: <ProductsIcon /> },
{ name: "Contact", link: "/contact", icon: <ContactIcon /> },
];
return (
<>
<FloatingNav navItems={navItems} />
<div style={{ height: "200vh", paddingTop: 150 }}>
<h1 className="text-white text-center">
Scroll down and up to see the navbar appear/disappear
</h1>
</div>
</>
);
}

View File

@ -0,0 +1,43 @@
import React from "react";
import { cn } from "@/lib/utils";
export const Spotlight = ({
className,
fill
}) => {
return (
<svg
className={cn(
"animate-spotlight pointer-events-none absolute z-[1] h-[169%] w-[138%] lg:w-[84%] opacity-0",
className
)}
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 3787 2842"
fill="none">
<g filter="url(#filter)">
<ellipse
cx="1924.71"
cy="273.501"
rx="1924.71"
ry="273.501"
transform="matrix(-0.822377 -0.568943 -0.568943 0.822377 3631.88 2291.09)"
fill={fill || "white"}
fillOpacity="0.21"></ellipse>
</g>
<defs>
<filter
id="filter"
x="0.860352"
y="0.838989"
width="3785.16"
height="2840.26"
filterUnits="userSpaceOnUse"
colorInterpolationFilters="sRGB">
<feFlood floodOpacity="0" result="BackgroundImageFix"></feFlood>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"></feBlend>
<feGaussianBlur stdDeviation="151" result="effect1_foregroundBlur_1065_8"></feGaussianBlur>
</filter>
</defs>
</svg>
);
};

View File

@ -0,0 +1,264 @@
"use client";;
import { cn } from "@/lib/utils";
import { Canvas, useFrame, useThree } from "@react-three/fiber";
import React, { useMemo, useRef } from "react";
import * as THREE from "three";
export const CanvasRevealEffect = ({
animationSpeed = 0.4,
opacities = [0.3, 0.3, 0.3, 0.5, 0.5, 0.5, 0.8, 0.8, 0.8, 1],
colors = [[0, 255, 255]],
containerClassName,
dotSize,
showGradient = true
}) => {
return (
<div className={cn("h-full relative bg-white w-full", containerClassName)}>
<div className="h-full w-full">
<DotMatrix
colors={colors ?? [[0, 255, 255]]}
dotSize={dotSize ?? 3}
opacities={
opacities ?? [0.3, 0.3, 0.3, 0.5, 0.5, 0.5, 0.8, 0.8, 0.8, 1]
}
shader={`
float animation_speed_factor = ${animationSpeed.toFixed(1)};
float intro_offset = distance(u_resolution / 2.0 / u_total_size, st2) * 0.01 + (random(st2) * 0.15);
opacity *= step(intro_offset, u_time * animation_speed_factor);
opacity *= clamp((1.0 - step(intro_offset + 0.1, u_time * animation_speed_factor)) * 1.25, 1.0, 1.25);
`}
center={["x", "y"]} />
</div>
{showGradient && (
<div className="absolute inset-0 bg-gradient-to-t from-gray-950 to-[84%]" />
)}
</div>
);
};
const DotMatrix = ({
colors = [[0, 0, 0]],
opacities = [0.04, 0.04, 0.04, 0.04, 0.04, 0.08, 0.08, 0.08, 0.08, 0.14],
totalSize = 4,
dotSize = 2,
shader = "",
center = ["x", "y"],
}) => {
const uniforms = React.useMemo(() => {
let colorsArray = [
colors[0],
colors[0],
colors[0],
colors[0],
colors[0],
colors[0],
];
if (colors.length === 2) {
colorsArray = [
colors[0],
colors[0],
colors[0],
colors[1],
colors[1],
colors[1],
];
} else if (colors.length === 3) {
colorsArray = [
colors[0],
colors[0],
colors[1],
colors[1],
colors[2],
colors[2],
];
}
return {
u_colors: {
value: colorsArray.map((color) => [
color[0] / 255,
color[1] / 255,
color[2] / 255,
]),
type: "uniform3fv",
},
u_opacities: {
value: opacities,
type: "uniform1fv",
},
u_total_size: {
value: totalSize,
type: "uniform1f",
},
u_dot_size: {
value: dotSize,
type: "uniform1f",
},
};
}, [colors, opacities, totalSize, dotSize]);
return (
<Shader
source={`
precision mediump float;
in vec2 fragCoord;
uniform float u_time;
uniform float u_opacities[10];
uniform vec3 u_colors[6];
uniform float u_total_size;
uniform float u_dot_size;
uniform vec2 u_resolution;
out vec4 fragColor;
float PHI = 1.61803398874989484820459;
float random(vec2 xy) {
return fract(tan(distance(xy * PHI, xy) * 0.5) * xy.x);
}
float map(float value, float min1, float max1, float min2, float max2) {
return min2 + (value - min1) * (max2 - min2) / (max1 - min1);
}
void main() {
vec2 st = fragCoord.xy;
${
center.includes("x")
? "st.x -= abs(floor((mod(u_resolution.x, u_total_size) - u_dot_size) * 0.5));"
: ""
}
${
center.includes("y")
? "st.y -= abs(floor((mod(u_resolution.y, u_total_size) - u_dot_size) * 0.5));"
: ""
}
float opacity = step(0.0, st.x);
opacity *= step(0.0, st.y);
vec2 st2 = vec2(int(st.x / u_total_size), int(st.y / u_total_size));
float frequency = 5.0;
float show_offset = random(st2);
float rand = random(st2 * floor((u_time / frequency) + show_offset + frequency) + 1.0);
opacity *= u_opacities[int(rand * 10.0)];
opacity *= 1.0 - step(u_dot_size / u_total_size, fract(st.x / u_total_size));
opacity *= 1.0 - step(u_dot_size / u_total_size, fract(st.y / u_total_size));
vec3 color = u_colors[int(show_offset * 6.0)];
${shader}
fragColor = vec4(color, opacity);
fragColor.rgb *= fragColor.a;
}`}
uniforms={uniforms}
maxFps={60} />
);
};
const ShaderMaterial = ({
source,
uniforms,
maxFps = 60
}) => {
const { size } = useThree();
const ref = useRef();
let lastFrameTime = 0;
useFrame(({ clock }) => {
if (!ref.current) return;
const timestamp = clock.getElapsedTime();
if (timestamp - lastFrameTime < 1 / maxFps) {
return;
}
lastFrameTime = timestamp;
const material = ref.current.material;
const timeLocation = material.uniforms.u_time;
timeLocation.value = timestamp;
});
const getUniforms = () => {
const preparedUniforms = {};
for (const uniformName in uniforms) {
const uniform = uniforms[uniformName];
switch (uniform.type) {
case "uniform1f":
preparedUniforms[uniformName] = { value: uniform.value, type: "1f" };
break;
case "uniform3f":
preparedUniforms[uniformName] = {
value: new THREE.Vector3().fromArray(uniform.value),
type: "3f",
};
break;
case "uniform1fv":
preparedUniforms[uniformName] = { value: uniform.value, type: "1fv" };
break;
case "uniform3fv":
preparedUniforms[uniformName] = {
value: uniform.value.map((v) =>
new THREE.Vector3().fromArray(v)),
type: "3fv",
};
break;
case "uniform2f":
preparedUniforms[uniformName] = {
value: new THREE.Vector2().fromArray(uniform.value),
type: "2f",
};
break;
default:
console.error(`Invalid uniform type for '${uniformName}'.`);
break;
}
}
preparedUniforms["u_time"] = { value: 0, type: "1f" };
preparedUniforms["u_resolution"] = {
value: new THREE.Vector2(size.width * 2, size.height * 2),
}; // Initialize u_resolution
return preparedUniforms;
};
// Shader material
const material = useMemo(() => {
const materialObject = new THREE.ShaderMaterial({
vertexShader: `
precision mediump float;
in vec2 coordinates;
uniform vec2 u_resolution;
out vec2 fragCoord;
void main(){
float x = position.x;
float y = position.y;
gl_Position = vec4(x, y, 0.0, 1.0);
fragCoord = (position.xy + vec2(1.0)) * 0.5 * u_resolution;
fragCoord.y = u_resolution.y - fragCoord.y;
}
`,
fragmentShader: source,
uniforms: getUniforms(),
glslVersion: THREE.GLSL3,
blending: THREE.CustomBlending,
blendSrc: THREE.SrcAlphaFactor,
blendDst: THREE.OneFactor,
});
return materialObject;
}, [size.width, size.height, source]);
return (
<mesh ref={ref}>
<planeGeometry args={[2, 2]} />
<primitive object={material} attach="material" />
</mesh>
);
};
const Shader = ({ source, uniforms, maxFps = 60 }) => {
return (
<Canvas className="absolute inset-0 h-full w-full">
<ShaderMaterial source={source} uniforms={uniforms} maxFps={maxFps} />
</Canvas>
);
};

View File

@ -0,0 +1,89 @@
"use client";
import React, { useState, useEffect } from "react";
import { motion } from "motion/react";
import { cn } from "@/lib/utils";
export function HoverBorderGradient({
children,
containerClassName,
className,
as: Tag = "button",
duration = 1,
clockwise = true,
...props
}) {
const [hovered, setHovered] = useState(false);
const [direction, setDirection] = useState("TOP");
const rotateDirection = (currentDirection) => {
const directions = ["TOP", "LEFT", "BOTTOM", "RIGHT"];
const currentIndex = directions.indexOf(currentDirection);
const nextIndex = clockwise
? (currentIndex - 1 + directions.length) % directions.length
: (currentIndex + 1) % directions.length;
return directions[nextIndex];
};
const movingMap = {
TOP: "radial-gradient(20.7% 50% at 50% 0%, hsl(0, 0%, 100%) 0%, rgba(255, 255, 255, 0) 100%)",
LEFT: "radial-gradient(16.6% 43.1% at 0% 50%, hsl(0, 0%, 100%) 0%, rgba(255, 255, 255, 0) 100%)",
BOTTOM:
"radial-gradient(20.7% 50% at 50% 100%, hsl(0, 0%, 100%) 0%, rgba(255, 255, 255, 0) 100%)",
RIGHT:
"radial-gradient(16.2% 41.199999999999996% at 100% 50%, hsl(0, 0%, 100%) 0%, rgba(255, 255, 255, 0) 100%)",
};
const highlight =
"radial-gradient(75% 181.15942028985506% at 50% 50%, #3275F8 0%, rgba(255, 255, 255, 0) 100%)";
useEffect(() => {
if (!hovered) {
const interval = setInterval(() => {
setDirection((prevState) => rotateDirection(prevState));
}, duration * 1000);
return () => clearInterval(interval);
}
}, [hovered]);
return (
<Tag
onMouseEnter={(event) => {
setHovered(true);
}}
onMouseLeave={() => setHovered(false)}
className={cn(
"relative flex rounded-full border content-center bg-black/20 hover:bg-black/10 transition duration-500 dark:bg-white/20 items-center flex-col flex-nowrap gap-10 h-min justify-center overflow-visible p-px decoration-clone w-fit",
containerClassName
)}
{...props}
>
<div
className={cn(
"w-auto text-white z-10 bg-black px-4 py-2 rounded-[inherit]",
className
)}
>
{children}
</div>
<motion.div
className={cn(
"flex-none inset-0 overflow-hidden absolute z-0 rounded-[inherit]"
)}
style={{
filter: "blur(2px)",
position: "absolute",
width: "100%",
height: "100%",
}}
initial={{ background: movingMap[direction] }}
animate={{
background: hovered
? [movingMap[direction], highlight]
: movingMap[direction],
}}
transition={{ ease: "linear", duration: duration ?? 1 }}
/>
<div className="bg-black absolute z-1 flex-none inset-[2px] rounded-[100px]" />
</Tag>
);
}

View File

@ -0,0 +1,104 @@
"use client";
import { cn } from "@/lib/utils";
import React, { useEffect, useState } from "react";
export const InfiniteMovingCards = ({
items,
direction = "left",
speed = "fast",
pauseOnHover = true,
className,
}) => {
const containerRef = React.useRef(null);
const scrollerRef = React.useRef(null);
const [start, setStart] = useState(false);
useEffect(() => {
addAnimation();
}, []);
function addAnimation() {
if (containerRef.current && scrollerRef.current) {
const scrollerContent = Array.from(scrollerRef.current.children);
scrollerContent.forEach((item) => {
const duplicatedItem = item.cloneNode(true);
if (scrollerRef.current) {
scrollerRef.current.appendChild(duplicatedItem);
}
});
getDirection();
getSpeed();
setStart(true);
}
}
const getDirection = () => {
if (containerRef.current) {
containerRef.current.style.setProperty(
"--animation-direction",
direction === "left" ? "forwards" : "reverse"
);
}
};
const getSpeed = () => {
if (containerRef.current) {
const duration =
speed === "fast" ? "20s" : speed === "normal" ? "40s" : "80s";
containerRef.current.style.setProperty("--animation-duration", duration);
}
};
return (
<div
ref={containerRef}
className={cn(
"scroller relative z-20 max-w-7xl overflow-hidden [mask-image:linear-gradient(to_right,transparent,white_20%,white_80%,transparent)]",
className
)}
>
<ul
ref={scrollerRef}
className={cn(
"flex w-max min-w-full shrink-0 flex-nowrap gap-4 py-4",
start && "animate-scroll",
pauseOnHover && "hover:[animation-play-state:paused]"
)}
>
{items.map((item) => (
<li
key={item.name}
className="relative w-[350px] max-w-full shrink-0 rounded-2xl border border-b-0 border-zinc-200 px-8 py-6 md:w-[450px] dark:border-zinc-700"
style={{
background:
"linear-gradient(103.4deg, #04071D 16.66%, #0C0E23 81.61%)",
}}
>
<blockquote>
<div
aria-hidden="true"
className="pointer-events-none absolute -top-0.5 -left-0.5 -z-1 h-[calc(100%_+_4px)] w-[calc(100%_+_4px)] user-select-none"
></div>
<span className="relative z-20 text-sm leading-[1.6] font-normal text-white">
{item.quote}
</span>
<div className="relative z-20 mt-6 flex flex-row items-center">
<span className="flex flex-col gap-1">
<span className="text-sm leading-[1.6] font-normal text-white/70">
{item.name}
</span>
<span className="text-sm leading-[1.6] font-normal text-white/70">
{item.title}
</span>
</span>
</div>
</blockquote>
</li>
))}
</ul>
</div>
);
};

View File

@ -0,0 +1,55 @@
"use client";
import React, { useEffect } from "react";
import { useAnimate, stagger } from "motion/react";
import { cn } from "@/lib/utils";
export const TextGenerateEffect = ({
children,
className,
filter = true,
duration = 0.5
}) => {
const [scope, animate] = useAnimate();
useEffect(() => {
animate("span", {
opacity: 1,
filter: filter ? "blur(0px)" : "none",
}, {
duration: duration,
delay: stagger(0.2),
});
}, [scope, animate, filter, duration]);
// هنا نحول كل طفل (child) لعنصر <motion.span> لعمل تأثير الحركة
const renderWords = () => {
return (
<div ref={scope}>
{React.Children.map(children, (child, idx) => {
return (
<span
key={idx}
className="dark:text-white text-black opacity-0"
style={{
filter: filter ? "blur(10px)" : "none",
}}
>
{child}
</span>
);
})}
</div>
);
};
return (
<div className={cn("font-bold", className)}>
<div className="mt-4">
<div className="dark:text-white text-black text-5xl leading-snug tracking-wide">
{renderWords()}
</div>
</div>
</div>
);
};

12942
app/data/globe.json Normal file

File diff suppressed because it is too large Load Diff

BIN
app/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

271
app/globals.css Normal file
View File

@ -0,0 +1,271 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
/* ------------------------------
Root Variables + Animations
------------------------------- */
@layer base {
:root {
--animate-spotlight: spotlight 2s ease 0.75s 1 forwards;
/* Animation Variables for gradients */
--animate-first: moveVertical 30s ease infinite;
--animate-second: moveInCircle 20s reverse infinite;
--animate-third: moveInCircle 40s linear infinite;
--animate-fourth: moveHorizontal 40s ease infinite;
--animate-fifth: moveInCircle 20s ease infinite;
}
body {
background-color: #000319;
}
/* Spotlight animation */
@keyframes spotlight {
0% {
opacity: 0;
transform: translate(-72%, -62%) scale(0.5);
}
100% {
opacity: 1;
transform: translate(-50%, -40%) scale(1);
}
}
/* Gradient animation: horizontal movement */
@keyframes moveHorizontal {
0% {
transform: translateX(-50%) translateY(-10%);
}
50% {
transform: translateX(50%) translateY(10%);
}
100% {
transform: translateX(-50%) translateY(-10%);
}
}
/* Gradient animation: vertical movement */
@keyframes moveVertical {
0% {
transform: translateY(-50%);
}
50% {
transform: translateY(50%);
}
100% {
transform: translateY(-50%);
}
}
/* Gradient animation: circular rotation */
@keyframes moveInCircle {
0% {
transform: rotate(0deg);
}
50% {
transform: rotate(180deg);
}
100% {
transform: rotate(360deg);
}
}
/* Scroll animation for InfiniteMovingCards */
@keyframes scroll {
0% {
transform: translateX(0%);
}
100% {
transform: translateX(-50%);
}
}
}
/* ------------------------------
Utility Classes
------------------------------- */
@layer utilities {
.animate-spotlight {
animation: var(--animate-spotlight);
}
.animate-first {
animation: var(--animate-first);
}
.animate-second {
animation: var(--animate-second);
}
.animate-third {
animation: var(--animate-third);
}
.animate-fourth {
animation: var(--animate-fourth);
}
.animate-fifth {
animation: var(--animate-fifth);
}
/* Utility class for infinite horizontal scroll */
.animate-scroll {
animation: scroll var(--animation-duration, 40s) linear infinite;
animation-direction: var(--animation-direction, forwards);
}
}
.work-card-with-border {
position: relative;
width: 400px;
height: 150px;
background: linear-gradient(103.4deg, #04071d 16.66%, #0c0e23 81.61%);
border-radius: 12px;
overflow: hidden;
z-index: 0;
}
/* الطبقة المتحركة */
.work-card-with-border::before {
content: "";
position: absolute;
top: -2px;
left: -2px;
width: calc(100% + 4px);
height: calc(100% + 4px);
background: conic-gradient(
from 0deg,
#ffffff 0deg,
transparent 90deg,
#ffffff 180deg,
transparent 270deg,
#ffffff 360deg
);
border-radius: 12px;
animation: rotate-border 4s linear infinite;
z-index: 1;
pointer-events: none;
mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
-webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
mask-composite: exclude;
-webkit-mask-composite: destination-out;
padding: 2px;
}
.animated-corner-card {
position: relative;
width: 400px;
height: 150px;
background: linear-gradient(103.4deg, #04071d 16.66%, #0c0e23 81.61%);
border-radius: 12px;
overflow: hidden;
}
/* الخط الرفيع الأبيض مع اللمعة */
.corner-line {
position: absolute;
background: linear-gradient(
90deg,
rgba(255, 255, 255, 0) 0%,
rgba(255, 255, 255, 0.8) 50%,
rgba(255, 255, 255, 0) 100%
);
filter: drop-shadow(0 0 4px rgba(255, 255, 255, 0.8));
animation: shine 2s linear infinite;
z-index: 10;
}
/* الخط الأفقي */
.corner-line-horizontal {
height: 2px;
width: 40px;
}
/* الخط العمودي */
.corner-line-vertical {
width: 2px;
height: 40px;
}
/* تحريك اللمعة */
@keyframes shine {
0% {
background-position: 0% 50%;
}
100% {
background-position: 200% 50%;
}
}
/* زوايا وتحديد أماكن الخطوط */
/* أعلى يسار */
.corner-top-left .corner-line-horizontal {
top: 0;
left: 0;
}
.corner-top-left .corner-line-vertical {
top: 0;
left: 0;
}
/* أعلى يمين */
.corner-top-right .corner-line-horizontal {
top: 0;
right: 0;
background: linear-gradient(
270deg,
rgba(255, 255, 255, 0) 0%,
rgba(255, 255, 255, 0.8) 50%,
rgba(255, 255, 255, 0) 100%
);
animation: shine 2s linear infinite;
}
.corner-top-right .corner-line-vertical {
top: 0;
right: 0;
}
/* أسفل يمين */
.corner-bottom-right .corner-line-horizontal {
bottom: 0;
right: 0;
background: linear-gradient(
270deg,
rgba(255, 255, 255, 0) 0%,
rgba(255, 255, 255, 0.8) 50%,
rgba(255, 255, 255, 0) 100%
);
animation: shine 2s linear infinite;
}
.corner-bottom-right .corner-line-vertical {
bottom: 0;
right: 0;
background: linear-gradient(
180deg,
rgba(255, 255, 255, 0) 0%,
rgba(255, 255, 255, 0.8) 50%,
rgba(255, 255, 255, 0) 100%
);
animation: shine 2s linear infinite;
}
/* أسفل يسار */
.corner-bottom-left .corner-line-horizontal {
bottom: 0;
left: 0;
}
.corner-bottom-left .corner-line-vertical {
bottom: 0;
left: 0;
background: linear-gradient(
180deg,
rgba(255, 255, 255, 0) 0%,
rgba(255, 255, 255, 0.8) 50%,
rgba(255, 255, 255, 0) 100%
);
animation: shine 2s linear infinite;
}

42
app/infinte.js Normal file
View File

@ -0,0 +1,42 @@
"use client";
import React from "react";
import { InfiniteMovingCards } from "./components/infinitemovingcards";
const testimonials = [
{
quote:
"Collaborating with Adrian was an absolute pleasure His professionalism promptness and dedication to delivering exceptional results were evident throughout our project Adrians enthusiasm for every facet of development truly stands out If youre seeking to elevate your website and elevate your brand Adrian is the ideal partner",
name: "Michel joen",
title: "Marketing Director",
img: "/gf.png",
},
{
quote:
"Collaborating with Adrian was an absolute pleasure His professionalism promptness and dedication to delivering exceptional results were evident throughout our project Adrians enthusiasm for every facet of development truly stands out If youre seeking to elevate your website and elevate your brand Adrian is the ideal partner",
name: "joenista michkel",
title: "Product Manager",
img: "/gf.png",
},
{
quote:
"Collaborating with Adrian was an absolute pleasure His professionalism promptness and dedication to delivering exceptional results were evident throughout our project Adrians enthusiasm for every facet of development truly stands out If youre seeking to elevate your website and elevate your brand Adrian is the ideal partner",
name: "jomana adel",
title: "Marketing Director",
img: "/gf.png",
},
];
export default function Home() {
return (
<div>
<main className="mt-20 mb-20">
<p className="text-white text-center font-bold sm:text-xl md:text-2xl mb-5">
Kind words from{" "}
<span className="text-fuchsia-400">satisfied clients</span>
</p>
<InfiniteMovingCards items={testimonials} />
</main>
</div>
);
}

29
app/layout.js Normal file
View File

@ -0,0 +1,29 @@
import { Geist, Geist_Mono } from "next/font/google";
import "./globals.css";
const geistSans = Geist({
variable: "--font-geist-sans",
subsets: ["latin"],
});
const geistMono = Geist_Mono({
variable: "--font-geist-mono",
subsets: ["latin"],
});
export const metadata = {
title: "Create Next App",
description: "Generated by create next app",
};
export default function RootLayout({ children }) {
return (
<html lang="en">
<body
className={`${geistSans.variable} ${geistMono.variable} antialiased`}
>
{children}
</body>
</html>
);
}

6
app/lib/utils.js Normal file
View File

@ -0,0 +1,6 @@
import { clsx } from "clsx";
import { twMerge } from "tailwind-merge";
export function cn(...inputs) {
return twMerge(clsx(inputs));
}

22
app/page.js Normal file
View File

@ -0,0 +1,22 @@
import Approach from "./Approach";
import Hero from "./Hero";
import Main from "./Main";
import { CanvasRevealEffectDemo } from "./Approach";
import X from "./x";
import Infinte from "./infinte";
import Work from "./Work";
import Footer from "./Footer";
export default function Home() {
return (
<div>
<Hero />
<Main />
<CanvasRevealEffectDemo />
<X />
<Infinte />
<Work />
<Footer />
</div>
);
}

298
app/x.js Normal file
View File

@ -0,0 +1,298 @@
"use client";
import React from "react";
import { PinContainer } from "./components/3d-pin";
export default function HomePage() {
return (
<div>
<p className="font-bold mb-5 text-white sm:text-2xl md:text-3xl text-center z-[1000] mt-5">
A small selection of
<span className="text-[#CBACF9]"> recent project</span>
</p>
<main className="min-h-screen w-[80%] mx-auto grid grid-cols-1 md:grid md:grid-cols-2 gap-x-0 gap-y-52 place-items-center bg-[#010217] py-20">
<PinContainer>
<div
className="w-[400px] h-[400px] text-white text-lg font-bold space-y-5 flex flex-col justify-between p-5 rounded-xl"
style={{
background:
"linear-gradient(103.4deg, #04071D 16.66%, #0C0E23 81.61%)",
}}
>
<div className="space-y-4">
<div className="relative w-[500px] h-[200px]">
{/* الصورة الخلفية */}
<img
src="/f.png"
alt="bg image"
className=" w-full h-full object-cover "
/>
{/* الصورة الأمامية */}
<img
src="/1.png"
alt="ai content image"
className="absolute bottom-0 left-20 w-[230px] h-[180px] z-10"
/>
</div>
<p className="font-bold">AI Image SaaS - Canva Application</p>
<p className="font-normal text-sm text-[#BEC1DD]">
A REAL Software-as-a-Service app with AI features and a payments
and credits system using the latest tech stack.
</p>
</div>
<div className="flex justify-between items-center">
<div className="flex items-center gap-4">
<img
src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/typescript/typescript-original.svg"
alt="TypeScript"
className="w-5 h-5"
/>
<img
src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/nextjs/nextjs-original.svg"
alt="Next.js"
className="w-5 h-5 invert"
/>
<img
src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/javascript/javascript-original.svg"
alt="JavaScript"
className="w-5 h-5"
/>
<img
src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/vuejs/vuejs-original.svg"
alt="Vue.js"
className="w-5 h-5"
/>
<img
src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/html5/html5-original.svg"
alt="HTML5"
className="w-5 h-5"
/>
<img
src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/css3/css3-original.svg"
alt="CSS3"
className="w-5 h-5"
/>
</div>
<p className="text-[#CBACF9] font-thin">check live site</p>
</div>
</div>
</PinContainer>
<PinContainer>
<div
className="w-[400px] h-[400px] text-white text-lg font-bold flex flex-col justify-between p-5 rounded-xl bg-cover bg-center"
style={{
background:
"linear-gradient(103.4deg, #04071D 16.66%, #0C0E23 81.61%)",
}}
>
<div className="space-y-4 flex flex-col items-center">
<div className="relative w-[500px] h-[200px]">
{/* الصورة الخلفية */}
<img
src="/f.png"
alt="bg image"
className="absolute inset-0 w-full h-full object-cover "
/>
{/* الصورة الأمامية */}
<img
src="/99.png"
alt="ai content image"
className="absolute bottom-0 left-32 w-[250px] h-[180px] z-10"
/>
</div>
<p className="font-bold relative z-10 -left-10">
Yoom - Video Conferencing App
</p>
<p className="font-normal text-sm relative z-10 text-[#BEC1DD] ">
Simplify your video conferencing experience with Yoom.
Seamlessly connect with colleagues and friends.
</p>
</div>
<div className="flex justify-between items-center">
<div className="flex items-center gap-4">
<img
src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/typescript/typescript-original.svg"
alt="TypeScript"
className="w-5 h-5"
/>
<img
src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/nextjs/nextjs-original.svg"
alt="Next.js"
className="w-5 h-5 invert"
/>
<img
src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/javascript/javascript-original.svg"
alt="JavaScript"
className="w-5 h-5"
/>
<img
src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/vuejs/vuejs-original.svg"
alt="Vue.js"
className="w-5 h-5"
/>
<img
src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/html5/html5-original.svg"
alt="HTML5"
className="w-5 h-5"
/>
<img
src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/css3/css3-original.svg"
alt="CSS3"
className="w-5 h-5"
/>
</div>
<p className="text-[#CBACF9] font-thin">check live site</p>
</div>
</div>
</PinContainer>
<PinContainer>
<div
className="w-[400px] h-[400px] text-white text-lg font-bold space-y-5 flex flex-col justify-between p-5 rounded-xl"
style={{
background:
"linear-gradient(103.4deg, #04071D 16.66%, #0C0E23 81.61%)",
}}
>
<div className="space-y-4">
<div className="relative w-[500px] h-[200px]">
{/* الصورة الخلفية */}
<img
src="/f.png"
alt="bg image"
className="absolute inset-0 w-full h-full object-cover "
/>
{/* الصورة الأمامية */}
<img
src="/234.png"
alt="ai content image"
className="absolute bottom-0 left-16 w-[250px] h-[180px] z-10"
/>
</div>
<p className="font-bold">3D Solar System Planets to Explore</p>
<p className="font-normal text-sm text-[#BEC1DD]">
Explore the wonders of our solar system with this captivating 3D
simulation of the planets using Three.js.
</p>
</div>
<div className="flex justify-between items-center">
<div className="flex items-center gap-4">
<img
src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/typescript/typescript-original.svg"
alt="TypeScript"
className="w-5 h-5"
/>
<img
src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/nextjs/nextjs-original.svg"
alt="Next.js"
className="w-5 h-5 invert"
/>
<img
src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/javascript/javascript-original.svg"
alt="JavaScript"
className="w-5 h-5"
/>
<img
src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/vuejs/vuejs-original.svg"
alt="Vue.js"
className="w-5 h-5"
/>
<img
src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/html5/html5-original.svg"
alt="HTML5"
className="w-5 h-5"
/>
<img
src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/css3/css3-original.svg"
alt="CSS3"
className="w-5 h-5"
/>
</div>
<p className="text-[#CBACF9] font-thin">check live site</p>
</div>
</div>
</PinContainer>
<PinContainer>
<div
className="w-[400px] h-[400px] text-white text-lg font-bold space-y-5 flex flex-col justify-between p-5 rounded-xl"
style={{
background:
"linear-gradient(103.4deg, #04071D 16.66%, #0C0E23 81.61%)",
}}
>
<div className="space-y-4">
<div className="relative w-[500px] h-[200px]">
{/* الصورة الخلفية */}
<img
src="/f.png"
alt="bg image"
className="absolute inset-0 w-full h-full object-cover "
/>
{/* الصورة الأمامية */}
<img
src="/66.png"
alt="ai content image"
className="absolute bottom-0 left-16 w-[250px] h-[180px] z-10"
/>
</div>
<p className="font-bold">Animated Apple Iphone 3D Website</p>
<p className="font-normal text-sm text-[#BEC1DD]">
Recreated the Apple iPhone 15 Pro website, combining GSAP
animations and Three.js 3D effects.
</p>
</div>
<div className="flex justify-between items-center">
<div className="flex items-center gap-4">
<img
src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/typescript/typescript-original.svg"
alt="TypeScript"
className="w-5 h-5"
/>
<img
src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/nextjs/nextjs-original.svg"
alt="Next.js"
className="w-5 h-5 invert"
/>
<img
src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/javascript/javascript-original.svg"
alt="JavaScript"
className="w-5 h-5"
/>
<img
src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/vuejs/vuejs-original.svg"
alt="Vue.js"
className="w-5 h-5"
/>
<img
src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/html5/html5-original.svg"
alt="HTML5"
className="w-5 h-5"
/>
<img
src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/css3/css3-original.svg"
alt="CSS3"
className="w-5 h-5"
/>
</div>
<p className="text-[#CBACF9] font-thin">check live site</p>
</div>
</div>
</PinContainer>
</main>
</div>
);
}

8
jsconfig.json Normal file
View File

@ -0,0 +1,8 @@
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["./*"]
}
}
}

6
lib/utils.js Normal file
View File

@ -0,0 +1,6 @@
import { clsx } from "clsx";
import { twMerge } from "tailwind-merge";
export function cn(...inputs) {
return twMerge(clsx(inputs));
}

4
next.config.mjs Normal file
View File

@ -0,0 +1,4 @@
/** @type {import('next').NextConfig} */
const nextConfig = {};
export default nextConfig;

3487
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

35
package.json Normal file
View File

@ -0,0 +1,35 @@
{
"name": "my-next-app",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint"
},
"dependencies": {
"@react-three/drei": "^10.1.2",
"@react-three/fiber": "^9.0.0-alpha.8",
"clsx": "^2.1.1",
"motion": "^12.12.2",
"next": "15.1.8",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"react-icons": "^5.5.0",
"tailwind-merge": "^3.3.0",
"three": "^0.177.0",
"three-globe": "^2.42.11"
},
"devDependencies": {
"postcss": "^8",
"tailwindcss": "^3.4.1"
},
"description": "This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).",
"main": "index.js",
"directories": {
"lib": "lib"
},
"author": "",
"license": "ISC"
}

8
postcss.config.mjs Normal file
View File

@ -0,0 +1,8 @@
/** @type {import('postcss-load-config').Config} */
const config = {
plugins: {
tailwindcss: {},
},
};
export default config;

BIN
public/1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 MiB

BIN
public/2.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

BIN
public/22.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

BIN
public/234.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

BIN
public/66.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 MiB

BIN
public/99.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

7
public/Frame.svg Normal file
View File

@ -0,0 +1,7 @@
<svg width="212" height="40" viewBox="0 0 212 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M65.8897 30.6819C69.0056 30.6819 70.5779 29.0729 71.2631 27.9772H71.5718C71.7074 29.1409 72.5297 30.2366 74.1381 30.2366H77.1833V26.812H76.3971C75.8489 26.812 75.5748 26.5041 75.5748 26.0256V12.2954H71.5358V14.487H71.2285C70.4423 13.3912 68.7993 11.8502 65.7873 11.8502C60.9966 11.8502 57.4365 15.8212 57.4365 21.2653C57.4365 26.7094 61.0644 30.6819 65.8897 30.6819ZM66.6081 26.7788C63.7677 26.7788 61.5448 24.6899 61.5448 21.3C61.5448 17.978 63.6999 15.72 66.5749 15.72C69.3128 15.72 71.605 17.7395 71.605 21.3C71.605 24.3473 69.6533 26.7788 66.6081 26.7788ZM79.5692 37.1942H83.6068V27.9772H83.9141C84.6671 29.0729 86.2755 30.6819 89.4592 30.6819C94.2498 30.6819 97.7408 26.6414 97.7408 21.2653C97.7408 15.8559 94.0104 11.8502 89.1851 11.8502C86.1053 11.8502 84.5979 13.5271 83.8795 14.4523H83.5722V12.2954H79.5678L79.5692 37.1942ZM88.6038 26.8814C85.8312 26.8814 83.5376 24.8272 83.5376 21.2653C83.5376 18.218 85.4893 15.6507 88.5345 15.6507C91.3763 15.6507 93.5993 17.8769 93.5993 21.2653C93.5993 24.5873 91.4441 26.8814 88.6038 26.8814ZM99.8252 37.1942H103.864V27.9772H104.172C104.925 29.0729 106.533 30.6819 109.715 30.6819C114.506 30.6819 117.664 26.6414 117.664 21.2653C117.664 15.8559 114.266 11.8502 109.441 11.8502C106.361 11.8502 104.855 13.5271 104.137 14.4523H103.828V12.2954H99.8252V37.1942ZM108.86 26.8814C106.087 26.8814 103.795 24.8272 103.795 21.2653C103.795 18.218 105.745 15.6507 108.791 15.6507C111.632 15.6507 113.857 17.8769 113.857 21.2653C113.857 24.5873 111.7 26.8814 108.86 26.8814ZM123.004 30.653H128.718L131.969 16.5802H132.175L135.425 30.653H141.108L145.656 12.7118H141.586L138.335 26.8193H138.026L134.776 12.7103H129.403L126.117 26.8193H125.81L122.593 12.7103H118.28L123.004 30.653ZM147.703 30.653H151.742V21.7857C151.742 18.3958 153.314 16.307 156.258 16.307H158.037V12.2665H156.703C154.409 12.2665 152.664 13.8422 151.98 15.3485H151.706V12.7118H147.703V30.653ZM178.078 30.653H181.227V27.0578H178.113C176.881 27.0578 176.367 26.5099 176.367 25.2436V16.2723H181.432V12.7118H176.367V7.67825H172.535V12.7118H169.181V16.2723H172.295V25.2783C172.295 29.0787 174.587 30.653 178.078 30.653ZM192.061 30.6819C195.791 30.6819 199.077 28.8315 200.24 25.1019L196.544 24.21C195.893 26.1962 194.012 27.224 192.027 27.224C189.083 27.224 187.133 25.3057 187.098 22.2931H200.685V21.1627C200.685 15.8212 197.366 11.8502 191.89 11.8502C187.064 11.8502 182.924 15.6507 182.924 21.3C182.924 26.7788 186.585 30.6819 192.061 30.6819ZM187.133 19.3485C187.372 17.1916 189.323 15.376 191.89 15.376C194.354 15.376 196.374 16.917 196.579 19.3485H187.133Z" fill="#EDEDF0"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M167.384 30.6528H163.345V16.2721H160.198V12.7116H167.384V30.6528Z" fill="#EDEDF0"/>
<path d="M165.066 10.2207C166.538 10.2207 167.633 9.12493 167.633 7.68658C167.633 6.28436 166.538 5.18716 165.066 5.18716C163.594 5.18716 162.499 6.28291 162.499 7.68802C162.499 9.12493 163.594 10.2207 165.066 10.2207Z" fill="#EDEDF0"/>
<path d="M45.5297 26.254V34.1729H25.78C20.0258 34.1729 15.0015 30.9883 12.314 26.254C11.1249 24.1556 10.426 21.8143 10.27 19.4063L10.27 17.2668C10.3401 16.1679 10.5243 15.0792 10.8196 14.0186C12.666 7.36887 18.6655 2.50013 25.7786 2.50013C32.896 2.50013 38.8941 7.37176 40.7391 14.0171H32.2945C30.9097 11.8502 28.5093 10.4176 25.78 10.4176C23.0508 10.4176 20.6518 11.8502 19.2656 14.0171C18.8371 14.6844 18.5113 15.4124 18.2991 16.1768C18.1046 16.8801 18.0066 17.6067 18.0077 18.3365C18.0045 19.4116 18.2189 20.4761 18.6379 21.4657C19.0569 22.4554 19.6719 23.3496 20.4456 24.0943C21.877 25.4802 23.7897 26.2546 25.78 26.254H45.5297Z" fill="#FD366E"/>
<path d="M45.5297 16.1753V24.0942H31.113C31.887 23.3496 32.5022 22.4555 32.9215 21.4658C33.3407 20.4762 33.5554 19.4116 33.5524 18.3365C33.5531 17.6066 33.4545 16.88 33.2595 16.1768L45.5297 16.1753Z" fill="#FD366E"/>
</svg>

After

Width:  |  Height:  |  Size: 3.8 KiB

BIN
public/cld-main-logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

BIN
public/creative.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

BIN
public/eaarth.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

BIN
public/f.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 176 KiB

1
public/file.svg Normal file
View File

@ -0,0 +1 @@
<svg fill="none" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M14.5 13.5V5.41a1 1 0 0 0-.3-.7L9.8.29A1 1 0 0 0 9.08 0H1.5v13.5A2.5 2.5 0 0 0 4 16h8a2.5 2.5 0 0 0 2.5-2.5m-1.5 0v-7H8v-5H3v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1M9.5 5V2.12L12.38 5zM5.13 5h-.62v1.25h2.12V5zm-.62 3h7.12v1.25H4.5zm.62 3h-.62v1.25h7.12V11z" clip-rule="evenodd" fill="#666" fill-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 391 B

BIN
public/gf.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 822 KiB

BIN
public/gggggg.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 176 KiB

1
public/globe.svg Normal file
View File

@ -0,0 +1 @@
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><g clip-path="url(#a)"><path fill-rule="evenodd" clip-rule="evenodd" d="M10.27 14.1a6.5 6.5 0 0 0 3.67-3.45q-1.24.21-2.7.34-.31 1.83-.97 3.1M8 16A8 8 0 1 0 8 0a8 8 0 0 0 0 16m.48-1.52a7 7 0 0 1-.96 0H7.5a4 4 0 0 1-.84-1.32q-.38-.89-.63-2.08a40 40 0 0 0 3.92 0q-.25 1.2-.63 2.08a4 4 0 0 1-.84 1.31zm2.94-4.76q1.66-.15 2.95-.43a7 7 0 0 0 0-2.58q-1.3-.27-2.95-.43a18 18 0 0 1 0 3.44m-1.27-3.54a17 17 0 0 1 0 3.64 39 39 0 0 1-4.3 0 17 17 0 0 1 0-3.64 39 39 0 0 1 4.3 0m1.1-1.17q1.45.13 2.69.34a6.5 6.5 0 0 0-3.67-3.44q.65 1.26.98 3.1M8.48 1.5l.01.02q.41.37.84 1.31.38.89.63 2.08a40 40 0 0 0-3.92 0q.25-1.2.63-2.08a4 4 0 0 1 .85-1.32 7 7 0 0 1 .96 0m-2.75.4a6.5 6.5 0 0 0-3.67 3.44 29 29 0 0 1 2.7-.34q.31-1.83.97-3.1M4.58 6.28q-1.66.16-2.95.43a7 7 0 0 0 0 2.58q1.3.27 2.95.43a18 18 0 0 1 0-3.44m.17 4.71q-1.45-.12-2.69-.34a6.5 6.5 0 0 0 3.67 3.44q-.65-1.27-.98-3.1" fill="#666"/></g><defs><clipPath id="a"><path fill="#fff" d="M0 0h16v16H0z"/></clipPath></defs></svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

BIN
public/group.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

BIN
public/mmm.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

BIN
public/mo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

1
public/next.svg Normal file
View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 394 80"><path fill="#000" d="M262 0h68.5v12.7h-27.2v66.6h-13.6V12.7H262V0ZM149 0v12.7H94v20.4h44.3v12.6H94v21h55v12.6H80.5V0h68.7zm34.3 0h-17.8l63.8 79.4h17.9l-32-39.7 32-39.6h-17.9l-23 28.6-23-28.6zm18.3 56.7-9-11-27.1 33.7h17.8l18.3-22.7z"/><path fill="#000" d="M81 79.3 17 0H0v79.3h13.6V17l50.2 62.3H81Zm252.6-.4c-1 0-1.8-.4-2.5-1s-1.1-1.6-1.1-2.6.3-1.8 1-2.5 1.6-1 2.6-1 1.8.3 2.5 1a3.4 3.4 0 0 1 .6 4.3 3.7 3.7 0 0 1-3 1.8zm23.2-33.5h6v23.3c0 2.1-.4 4-1.3 5.5a9.1 9.1 0 0 1-3.8 3.5c-1.6.8-3.5 1.3-5.7 1.3-2 0-3.7-.4-5.3-1s-2.8-1.8-3.7-3.2c-.9-1.3-1.4-3-1.4-5h6c.1.8.3 1.6.7 2.2s1 1.2 1.6 1.5c.7.4 1.5.5 2.4.5 1 0 1.8-.2 2.4-.6a4 4 0 0 0 1.6-1.8c.3-.8.5-1.8.5-3V45.5zm30.9 9.1a4.4 4.4 0 0 0-2-3.3 7.5 7.5 0 0 0-4.3-1.1c-1.3 0-2.4.2-3.3.5-.9.4-1.6 1-2 1.6a3.5 3.5 0 0 0-.3 4c.3.5.7.9 1.3 1.2l1.8 1 2 .5 3.2.8c1.3.3 2.5.7 3.7 1.2a13 13 0 0 1 3.2 1.8 8.1 8.1 0 0 1 3 6.5c0 2-.5 3.7-1.5 5.1a10 10 0 0 1-4.4 3.5c-1.8.8-4.1 1.2-6.8 1.2-2.6 0-4.9-.4-6.8-1.2-2-.8-3.4-2-4.5-3.5a10 10 0 0 1-1.7-5.6h6a5 5 0 0 0 3.5 4.6c1 .4 2.2.6 3.4.6 1.3 0 2.5-.2 3.5-.6 1-.4 1.8-1 2.4-1.7a4 4 0 0 0 .8-2.4c0-.9-.2-1.6-.7-2.2a11 11 0 0 0-2.1-1.4l-3.2-1-3.8-1c-2.8-.7-5-1.7-6.6-3.2a7.2 7.2 0 0 1-2.4-5.7 8 8 0 0 1 1.7-5 10 10 0 0 1 4.3-3.5c2-.8 4-1.2 6.4-1.2 2.3 0 4.4.4 6.2 1.2 1.8.8 3.2 2 4.3 3.4 1 1.4 1.5 3 1.5 5h-5.8z"/></svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
public/s.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 147 KiB

BIN
public/ss.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

BIN
public/sss.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

BIN
public/st.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

BIN
public/sy.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

BIN
public/tit.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

1
public/vercel.svg Normal file
View File

@ -0,0 +1 @@
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1155 1000"><path d="m577.3 0 577.4 1000H0z" fill="#fff"/></svg>

After

Width:  |  Height:  |  Size: 128 B

1
public/window.svg Normal file
View File

@ -0,0 +1 @@
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path fill-rule="evenodd" clip-rule="evenodd" d="M1.5 2.5h13v10a1 1 0 0 1-1 1h-11a1 1 0 0 1-1-1zM0 1h16v11.5a2.5 2.5 0 0 1-2.5 2.5h-11A2.5 2.5 0 0 1 0 12.5zm3.75 4.5a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5M7 4.75a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0m1.75.75a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5" fill="#666"/></svg>

After

Width:  |  Height:  |  Size: 385 B

17
tailwind.config.mjs Normal file
View File

@ -0,0 +1,17 @@
/** @type {import('tailwindcss').Config} */
export default {
content: [
"./pages/**/*.{js,ts,jsx,tsx,mdx}",
"./components/**/*.{js,ts,jsx,tsx,mdx}",
"./app/**/*.{js,ts,jsx,tsx,mdx}",
],
theme: {
extend: {
colors: {
background: "var(--background)",
foreground: "var(--foreground)",
},
},
},
plugins: [],
};