diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..2ef2d71 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,4 @@ +{ + "trailingComma": "es5", + "tabWidth": 4 +} \ No newline at end of file diff --git a/README.md b/README.md index 81d71e2..5477ed8 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,6 @@ My personal portfolio website hosted [here](https://rainnny.club) ## TODO -- [ ] Mobile Responsiveness +- [x] Mobile Responsiveness - [ ] Discord Integration (Status, Activity, etc) -- [ ] Add Configuration +- [ ] Add Configuration \ No newline at end of file diff --git a/bun.lockb b/bun.lockb index e8be417..37b4446 100644 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/package.json b/package.json index 24195fe..68feea8 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "next-themes": "^0.3.0", "react": "^18", "react-dom": "^18", + "sharp": "^0.33.5", "tailwind-merge": "^2.5.2", "tailwindcss-animate": "^1.0.7" }, diff --git a/src/app/(pages)/layout.tsx b/src/app/(pages)/layout.tsx index f9255c4..f542699 100644 --- a/src/app/(pages)/layout.tsx +++ b/src/app/(pages)/layout.tsx @@ -11,33 +11,33 @@ const inter = Inter({ subsets: ["latin"] }); * The metadata for this app. */ export const metadata: Metadata = { - title: "RainnnyCLUB", - description: - "My name is Braydon and I am a self-taught software engineer living in Canada.", + title: "RainnnyCLUB", + description: + "My name is Braydon and I am a self-taught software engineer living in Canada.", }; export const viewport: Viewport = { - themeColor: "#5555FF", + themeColor: "#5555FF", }; /** * The primary layout for this app. */ const RootLayout = ({ - children, + children, }: Readonly<{ - children: React.ReactNode; + children: React.ReactNode; }>): ReactElement => ( - - - - {children} - - - + + + + {children} + + + ); export default RootLayout; diff --git a/src/app/(pages)/page.tsx b/src/app/(pages)/page.tsx index b327b78..0134554 100644 --- a/src/app/(pages)/page.tsx +++ b/src/app/(pages)/page.tsx @@ -3,17 +3,17 @@ import Navbar from "@/components/landing/navbar"; import { ReactElement } from "react"; const LandingPage = (): ReactElement => ( -
- -
- -
-
+
+ +
+ +
+
); export default LandingPage; diff --git a/src/app/globals.css b/src/app/globals.css index a36413a..ebac54f 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -3,69 +3,70 @@ @tailwind utilities; @layer base { - :root { - --background: 0 0% 100%; - --foreground: 240 10% 3.9%; - --card: 0 0% 100%; - --card-foreground: 240 10% 3.9%; - --popover: 0 0% 100%; - --popover-foreground: 240 10% 3.9%; - --primary: 240 5.9% 10%; - --primary-foreground: 0 0% 98%; - --secondary: 240 4.8% 95.9%; - --secondary-foreground: 240 5.9% 10%; - --muted: 240 4.8% 95.9%; - --muted-foreground: 240 3.8% 46.1%; - --accent: 240 4.8% 95.9%; - --accent-foreground: 240 5.9% 10%; - --destructive: 0 72.22% 50.59%; - --destructive-foreground: 0 0% 98%; - --border: 240 5.9% 90%; - --input: 240 5.9% 90%; - --ring: 240 5% 64.9%; - --radius: 0.5rem; + :root { + --background: 0 0% 100%; + --foreground: 240 10% 3.9%; + --card: 0 0% 100%; + --card-foreground: 240 10% 3.9%; + --popover: 0 0% 100%; + --popover-foreground: 240 10% 3.9%; + --primary: 240 5.9% 10%; + --primary-foreground: 0 0% 98%; + --secondary: 240 4.8% 95.9%; + --secondary-foreground: 240 5.9% 10%; + --muted: 240 4.8% 95.9%; + --muted-foreground: 240 3.8% 46.1%; + --accent: 240 4.8% 95.9%; + --accent-foreground: 240 5.9% 10%; + --destructive: 0 72.22% 50.59%; + --destructive-foreground: 0 0% 98%; + --border: 240 5.9% 90%; + --input: 240 5.9% 90%; + --ring: 240 5% 64.9%; + --radius: 0.5rem; - --chart-1: 12 76% 61%; - --chart-2: 173 58% 39%; - --chart-3: 197 37% 24%; - --chart-4: 43 74% 66%; - --chart-5: 27 87% 67%; - } + --chart-1: 12 76% 61%; + --chart-2: 173 58% 39%; + --chart-3: 197 37% 24%; + --chart-4: 43 74% 66%; + --chart-5: 27 87% 67%; + } - .dark { - --background: 0 0% 0%; - --foreground: 0 0% 98%; - --card: 240 10% 3.9%; - --card-foreground: 0 0% 98%; - --popover: 240 10% 3.9%; - --popover-foreground: 0 0% 98%; - --primary: 0 0% 98%; - --primary-foreground: 240 5.9% 10%; - --secondary: 240 3.7% 15.9%; - --secondary-foreground: 0 0% 98%; - --muted: 240 3.7% 15.9%; - --muted-foreground: 240 5% 64.9%; - --accent: 240 3.7% 15.9%; - --accent-foreground: 0 0% 98%; - --destructive: 0 62.8% 30.6%; - --destructive-foreground: 0 85.7% 97.3%; - --border: 240 3.7% 15.9%; - --input: 240 3.7% 15.9%; - --ring: 240 4.9% 83.9%; + .dark { + --background: 0 0% 0%; + --foreground: 0 0% 98%; + --card: 240 10% 3.9%; + --card-foreground: 0 0% 98%; + --popover: 240 10% 3.9%; + --popover-foreground: 0 0% 98%; + --primary: 0 0% 98%; + --primary-foreground: 240 5.9% 10%; + --secondary: 240 3.7% 15.9%; + --secondary-foreground: 0 0% 98%; + --muted: 240 3.7% 15.9%; + --muted-foreground: 240 5% 64.9%; + --accent: 240 3.7% 15.9%; + --accent-foreground: 0 0% 98%; + --destructive: 0 62.8% 30.6%; + --destructive-foreground: 0 85.7% 97.3%; + --border: 240 3.7% 15.9%; + --input: 240 3.7% 15.9%; + --ring: 240 4.9% 83.9%; - --chart-1: 220 70% 50%; - --chart-2: 160 60% 45%; - --chart-3: 30 80% 55%; - --chart-4: 280 65% 60%; - --chart-5: 340 75% 55%; - } + --chart-1: 220 70% 50%; + --chart-2: 160 60% 45%; + --chart-3: 30 80% 55%; + --chart-4: 280 65% 60%; + --chart-5: 340 75% 55%; + } } @layer base { - * { - @apply border-border; - } - body { - @apply bg-background text-foreground; - } + * { + @apply border-border; + } + + body { + @apply bg-background text-foreground; + } } diff --git a/src/components/landing/greeting.tsx b/src/components/landing/greeting.tsx index 4ec0381..9ed7e94 100644 --- a/src/components/landing/greeting.tsx +++ b/src/components/landing/greeting.tsx @@ -9,59 +9,59 @@ import { FlipWords } from "@/components/ui/flip-words"; import Navigation from "./navigation"; const Greeting = (): ReactElement => { - const now: Moment = moment(Date.now()); - return ( -
- - My Selfie (: - + const now: Moment = moment(Date.now()); + return ( +
+ + My Selfie (: + - -

- Hello, I'm - - Braydon - - - Waving Hand - -

-
+ +

+ Hello, I'm + + Braydon + + + Waving Hand + +

+
- - + - + ]} + /> + - - - -
- ); + + + +
+ ); }; export default Greeting; diff --git a/src/components/landing/nav-content/homelab.tsx b/src/components/landing/nav-content/homelab.tsx index 5256989..9a3eb80 100644 --- a/src/components/landing/nav-content/homelab.tsx +++ b/src/components/landing/nav-content/homelab.tsx @@ -1,32 +1,32 @@ import { ReactElement } from "react"; const HomelabContent = (): ReactElement => ( - + ); export default HomelabContent; diff --git a/src/components/landing/nav-content/my-work.tsx b/src/components/landing/nav-content/my-work.tsx index f12b9b5..b333550 100644 --- a/src/components/landing/nav-content/my-work.tsx +++ b/src/components/landing/nav-content/my-work.tsx @@ -1,7 +1,6 @@ "use client"; import { MagicCard } from "@/components/ui/magic-card"; -import { cn } from "@/lib/utils"; import moment, { Moment } from "moment"; import { useTheme } from "next-themes"; import { UseThemeProps } from "next-themes/dist/types"; @@ -9,102 +8,122 @@ import Link from "next/link"; import { ReactElement } from "react"; type Project = { - name: string; - link?: string | undefined; - previewContent: ReactElement; - startDate: Moment; - endDate?: Moment | undefined; + name: string; + link?: string | undefined; + previewContent: ReactElement; + startDate: Moment; + endDate?: Moment | undefined; }; const projects: Project[] = [ - { - name: "This Website!", - link: "https://github.com/Rainnny7/rainnny.club", - previewContent:
This website!
, - startDate: moment([2024, 7, 29]), - }, - { - name: "WildNetwork", - link: "https://discord.gg/WildPrison", - previewContent: ( -

- WildNetwork is a Minecraft server that contains multiple gamemodes, one - of which is Prison, which is the most popular. I first joined the server - as a Developer where I would work behind the scenes to create new - features, now I'm currently working as a System Administrator. -

- ), - startDate: moment([2020, 7, 1]), - }, - { - name: "Lucity", - link: "https://youtube.com/@iamLucid", - previewContent: ( -

- Lucity was a minigame network for the game Minecraft, and was owned by - the YouTuber iamLucid. When I worked at Lucity, I was the development - lead, I focused mainly on infrastructure, databases, and monitoring - systems. A few things that I have made - a dynamically managed server - system, proxy rotation via the TCPShield API, and an API that can - interact with the entire network from a normal Java app. -

- ), - startDate: moment([2020, 7, 1]), - endDate: moment([2022, 10, 30]), - }, - { - name: "Rainplex", - previewContent: ( -

- Rainplex was a remake of the once popular Minecraft server, Mineplex. - Rainplex initially came to light using the plugin, Skript where it just - contained a Hub. After some time, the entirety of the network was - re-coded in the Java programming from the ground up. Rainplex went - through numerous re-codes over the time it was active, however I have - since abandoned development due to lack of free time. -

- ), - startDate: moment([2018, 8, 1]), - endDate: moment([2021, 6, 11]), - }, - { - name: "Arcane Client", - link: "https://github.com/ArcaneClientNET", - previewContent: ( -

- Arcane is the all-in-one Minecraft mod pack. This client was built to be - similar to LunarClient for portfolio and experience sake. I have since - abandoned development due to lack of free time. -

- ), - startDate: moment([2021, 6, 1]), - endDate: moment([2021, 10, 1]), - }, + { + name: "This Website!", + link: "https://github.com/Rainnny7/rainnny.club", + previewContent:
This website!
, + startDate: moment([2024, 7, 29]), + }, + { + name: "WildNetwork", + link: "https://discord.gg/WildPrison", + previewContent: ( +

+ WildNetwork is a Minecraft server that contains multiple + gamemodes, one of which is Prison, which is the most popular. I + first joined the server as a Developer where I would work behind + the scenes to create new features, now I'm currently + working as a System Administrator. +

+ ), + startDate: moment([2020, 7, 1]), + }, + { + name: "Bonfire", + link: "https://bonfire.wtf", + previewContent: ( +

+ Bonfire is a platform similar to Discord that a friend and I are + working on together in our free time. Bonfire is perfect for + connecting with friends or building a global community. + Personalize your space to chat, and hang out. +

+ ), + startDate: moment([2024, 3, 30]), + }, + { + name: "Lucity", + link: "https://youtube.com/@iamLucid", + previewContent: ( +

+ Lucity was a minigame network for the game Minecraft, and was + owned by the YouTuber iamLucid. When I worked at Lucity, I was + the development lead, I focused mainly on infrastructure, + databases, and monitoring systems. A few things that I have made + - a dynamically managed server system, proxy rotation via the + TCPShield API, and an API that can interact with the entire + network from a normal Java app. +

+ ), + startDate: moment([2020, 7, 1]), + endDate: moment([2022, 10, 30]), + }, + { + name: "Rainplex", + previewContent: ( +

+ Rainplex was a remake of the once popular Minecraft server, + Mineplex. Rainplex initially came to light using the plugin, + Skript where it just contained a Hub. After some time, the + entirety of the network was re-coded in the Java programming + from the ground up. Rainplex went through numerous re-codes over + the time it was active, however I have since abandoned + development due to lack of free time. +

+ ), + startDate: moment([2018, 8, 1]), + endDate: moment([2021, 6, 11]), + }, + { + name: "Arcane Client", + link: "https://github.com/ArcaneClientNET", + previewContent: ( +

+ Arcane is the all-in-one Minecraft mod pack. This client was + built to be similar to LunarClient for portfolio and experience + sake. I have since abandoned development due to lack of free + time. +

+ ), + startDate: moment([2021, 6, 1]), + endDate: moment([2021, 10, 1]), + }, ]; const MyWork = (): ReactElement => { - const { theme }: UseThemeProps = useTheme(); - return ( -
- {projects.map((project, index) => ( - - -

- {project.name} -

+ const { theme }: UseThemeProps = useTheme(); + return ( +
+ {projects.map((project, index) => ( + + +

+ {project.name} +

- {/* Years Active */} -

- {project.startDate.format("MMM YYYY")} - {project.endDate && ` - ${project.endDate.format("MMM YYYY")}`} -

-
- - ))} -
- ); + {/* Years Active */} +

+ {project.startDate.format("MMM YYYY")} + {project.endDate && + ` - ${project.endDate.format("MMM YYYY")}`} +

+
+ + ))} +
+ ); }; export default MyWork; diff --git a/src/components/landing/nav-content/skills.tsx b/src/components/landing/nav-content/skills.tsx index 0aff409..99b9f86 100644 --- a/src/components/landing/nav-content/skills.tsx +++ b/src/components/landing/nav-content/skills.tsx @@ -1,145 +1,145 @@ import Image from "next/image"; import Link from "next/link"; import { ReactElement } from "react"; -import { - Tooltip, - TooltipContent, - TooltipTrigger, -} from "@/components/ui/tooltip"; import SimpleTooltip from "@/components/ui/simple-tooltip"; type Skill = { - name: string; - icon: string; - link: string; + name: string; + icon: string; + link: string; }; const skillset: Skill[] = [ - // Languages - { - name: "Java", - icon: "https://img.icons8.com/color/2x/java-coffee-cup-logo.png", - link: "https://www.java.com", - }, - { - name: "JavaScript", - icon: "https://img.icons8.com/fluent/2x/javascript.png", - link: "https://developer.mozilla.org/en-US/docs/Web/JavaScript", - }, - { - name: "CSS", - icon: "https://img.icons8.com/fluent/2x/css3.png", - link: "https://www.w3schools.com/css", - }, + // Languages + { + name: "Java", + icon: "https://img.icons8.com/color/2x/java-coffee-cup-logo.png", + link: "https://www.java.com", + }, + { + name: "JavaScript", + icon: "https://img.icons8.com/fluent/2x/javascript.png", + link: "https://developer.mozilla.org/en-US/docs/Web/JavaScript", + }, + { + name: "CSS", + icon: "https://img.icons8.com/fluent/2x/css3.png", + link: "https://www.w3schools.com/css", + }, - // Operating Systems - { - name: "Linux", - icon: "https://img.icons8.com/color/2x/linux.png", - link: "https://www.linux.org", - }, - { - name: "Bash", - icon: "https://img.icons8.com/color/2x/bash.png", - link: "https://www.gnu.org/software/bash", - }, + // Operating Systems + { + name: "Linux", + icon: "https://img.icons8.com/color/2x/linux.png", + link: "https://www.linux.org", + }, + { + name: "Bash", + icon: "https://img.icons8.com/color/2x/bash.png", + link: "https://www.gnu.org/software/bash", + }, - // Databases - { - name: "MariaDB", - icon: "https://img.icons8.com/fluent/2x/maria-db.png", - link: "https://mariadb.org", - }, - { - name: "MongoDB", - icon: "https://img.icons8.com/color/2x/mongodb.png", - link: "https://www.mongodb.com", - }, - { - name: "Redis", - icon: "https://img.icons8.com/color/2x/redis.png", - link: "https://redis.io", - }, + // Databases + { + name: "MariaDB", + icon: "https://img.icons8.com/fluent/2x/maria-db.png", + link: "https://mariadb.org", + }, + { + name: "MongoDB", + icon: "https://img.icons8.com/color/2x/mongodb.png", + link: "https://www.mongodb.com", + }, + { + name: "Redis", + icon: "https://img.icons8.com/color/2x/redis.png", + link: "https://redis.io", + }, - // Software - { - name: "Git", - icon: "https://img.icons8.com/color/2x/git.png", - link: "https://git-scm.com", - }, - { - name: "Docker", - icon: "https://img.icons8.com/fluent/2x/docker.png", - link: "https://www.docker.com", - }, - { - name: "Jenkins", - icon: "https://img.icons8.com/color/2x/jenkins.png", - link: "https://www.jenkins.io", - }, - { - name: "Figma", - icon: "https://img.icons8.com/fluent/2x/figma.png", - link: "https://www.figma.com", - }, - { - name: "Postman", - icon: "https://img.icons8.com/dusk/2x/postman-api.png", - link: "https://www.postman.com", - }, + // Software + { + name: "Git", + icon: "https://img.icons8.com/color/2x/git.png", + link: "https://git-scm.com", + }, + { + name: "Docker", + icon: "https://img.icons8.com/fluent/2x/docker.png", + link: "https://www.docker.com", + }, + { + name: "Jenkins", + icon: "https://img.icons8.com/color/2x/jenkins.png", + link: "https://www.jenkins.io", + }, + { + name: "Figma", + icon: "https://img.icons8.com/fluent/2x/figma.png", + link: "https://www.figma.com", + }, + { + name: "Postman", + icon: "https://img.icons8.com/dusk/2x/postman-api.png", + link: "https://www.postman.com", + }, - // Frameworks & Libraries - { - name: "Maven", - icon: "/maven.png", - link: "https://maven.apache.org", - }, - { - name: "NPM", - icon: "https://img.icons8.com/color/2x/npm.png", - link: "https://www.npmjs.com", - }, - { - name: "React", - icon: "https://img.icons8.com/dusk/2x/react.png", - link: "https://reactjs.org/", - }, - { - name: "NextJS", - icon: "https://img.icons8.com/color/2x/nextjs.png", - link: "https://nextjs.org/", - }, - { - name: "TailwindCSS", - icon: "https://img.icons8.com/color/2x/tailwindcss.png", - link: "https://tailwindcss.com", - }, - { - name: "Redux", - icon: "https://img.icons8.com/color/2x/redux.png", - link: "https://redux.js.org", - }, - { - name: "Nginx", - icon: "https://img.icons8.com/color/2x/nginx.png", - link: "https://www.nginx.com", - }, + // Frameworks & Libraries + { + name: "Maven", + icon: "/maven.png", + link: "https://maven.apache.org", + }, + { + name: "NPM", + icon: "https://img.icons8.com/color/2x/npm.png", + link: "https://www.npmjs.com", + }, + { + name: "React", + icon: "https://img.icons8.com/dusk/2x/react.png", + link: "https://reactjs.org/", + }, + { + name: "NextJS", + icon: "https://img.icons8.com/color/2x/nextjs.png", + link: "https://nextjs.org/", + }, + { + name: "TailwindCSS", + icon: "https://img.icons8.com/color/2x/tailwindcss.png", + link: "https://tailwindcss.com", + }, + { + name: "Redux", + icon: "https://img.icons8.com/color/2x/redux.png", + link: "https://redux.js.org", + }, + { + name: "Nginx", + icon: "https://img.icons8.com/color/2x/nginx.png", + link: "https://www.nginx.com", + }, ]; const Skills = (): ReactElement => ( -
- {skillset.map((skill, index) => ( - - - {`${skill.name} - - - ))} -
+
+ {skillset.map((skill, index) => ( + + + {`${skill.name} + + + ))} +
); export default Skills; diff --git a/src/components/landing/navbar.tsx b/src/components/landing/navbar.tsx index fa020b8..2abb658 100644 --- a/src/components/landing/navbar.tsx +++ b/src/components/landing/navbar.tsx @@ -2,114 +2,115 @@ import Image from "next/image"; import Link from "next/link"; import { ReactElement } from "react"; import { - NavigationMenu, - NavigationMenuContent, - NavigationMenuIndicator, - NavigationMenuItem, - NavigationMenuLink, - NavigationMenuList, - NavigationMenuTrigger, - NavigationMenuViewport, + NavigationMenu, + NavigationMenuContent, + NavigationMenuItem, + NavigationMenuLink, + NavigationMenuList, + NavigationMenuTrigger, + navigationMenuTriggerStyle, } from "@/components/ui/navigation-menu"; -import { navigationMenuTriggerStyle } from "@/components/ui/navigation-menu"; import { HeartIcon } from "@heroicons/react/24/solid"; import { cn } from "@/lib/utils"; import ThemeSwitcher from "./theme-switcher"; import { Button } from "@/components/ui/button"; -import { BookOpenIcon } from "@heroicons/react/24/outline"; -import { SignalIcon } from "@heroicons/react/24/outline"; +import { + BookOpenIcon, + CodeBracketIcon, + SignalIcon, +} from "@heroicons/react/24/outline"; import BlurFade from "@/components/ui/blur-fade"; -import { CodeBracketIcon } from "@heroicons/react/24/outline"; const Navbar = (): ReactElement => ( - - - + + + ); const Branding = (): ReactElement => ( - - My Selfie (: -

RainnnyCLUB

- + + My Selfie (: +

RainnnyCLUB

+ ); const Links = (): ReactElement => ( - - - {/* Useful Links */} - - Useful Links - - - - - - + + + {/* Useful Links */} + + Useful Links + + + + + + - {/* Donate */} - - - - Buy me a Coffee - - - - - - {/* Theme Switcher */} - - - - - + {/* Donate */} + + + + Buy me a Coffee + Donate + + + + + + ); const UsefulLinksContent = (): ReactElement => ( -
- {/* Git */} - - - +
+ {/* Git */} + + + - {/* Wiki */} - - - + {/* Wiki */} + + + - {/* Status Page */} - - - -
+ {/* Status Page */} + + + +
); export default Navbar; diff --git a/src/components/landing/navigation.tsx b/src/components/landing/navigation.tsx index c45c006..9d6f339 100644 --- a/src/components/landing/navigation.tsx +++ b/src/components/landing/navigation.tsx @@ -2,9 +2,11 @@ import { ReactElement, useState } from "react"; import { Button } from "@/components/ui/button"; -import { BriefcaseIcon } from "@heroicons/react/24/outline"; -import { WrenchIcon } from "@heroicons/react/24/outline"; -import { ServerStackIcon } from "@heroicons/react/24/outline"; +import { + BriefcaseIcon, + ServerStackIcon, + WrenchIcon, +} from "@heroicons/react/24/outline"; import { cn } from "@/lib/utils"; import BlurFade from "@/components/ui/blur-fade"; import HomelabContent from "./nav-content/homelab"; @@ -12,64 +14,66 @@ import Skills from "./nav-content/skills"; import MyWork from "./nav-content/my-work"; type Item = { - name: string; - icon: ReactElement; - content: ReactElement; + name: string; + icon: ReactElement; + content: ReactElement; }; const items: Item[] = [ - { - name: "My Work", - icon: , - content: , - }, - { - name: "Skills", - icon: , - content: , - }, - { - name: "Homelab", - icon: , - content: , - }, + { + name: "My Work", + icon: , + content: , + }, + { + name: "Skills", + icon: , + content: , + }, + { + name: "Homelab", + icon: , + content: , + }, ]; const Navigation = (): ReactElement => { - const [selected, setSelected] = useState(undefined); - return ( -
- {/* Selection Buttons */} -
- {items.map((item, index) => { - const active: boolean = selected === item; - return ( - - - - ); - })} -
+ const [selected, setSelected] = useState(undefined); + return ( +
+ {/* Selection Buttons */} +
+ {items.map((item, index) => { + const active: boolean = selected === item; + return ( + + + + ); + })} +
- {/* Selected Content */} - {selected && ( - -
{selected.content}
-
- )} -
- ); + {/* Selected Content */} + {selected && ( + +
{selected.content}
+
+ )} +
+ ); }; export default Navigation; diff --git a/src/components/landing/theme-switcher.tsx b/src/components/landing/theme-switcher.tsx index 73b626d..cfed50e 100644 --- a/src/components/landing/theme-switcher.tsx +++ b/src/components/landing/theme-switcher.tsx @@ -8,31 +8,31 @@ import { motion } from "framer-motion"; import { UseThemeProps } from "next-themes/dist/types"; const ThemeSwitcher = (): ReactElement => { - const { theme, setTheme }: UseThemeProps = useTheme(); - const isLight = theme === "light"; - return ( - - ); + const { theme, setTheme }: UseThemeProps = useTheme(); + const isLight = theme === "light"; + return ( + + ); }; export default ThemeSwitcher; diff --git a/src/components/theme-provider.tsx b/src/components/theme-provider.tsx index c527cde..6b5fce1 100644 --- a/src/components/theme-provider.tsx +++ b/src/components/theme-provider.tsx @@ -5,5 +5,5 @@ import { ThemeProvider as NextThemesProvider } from "next-themes"; import { type ThemeProviderProps } from "next-themes/dist/types"; export function ThemeProvider({ children, ...props }: ThemeProviderProps) { - return {children}; + return {children}; } diff --git a/src/components/ui/button.tsx b/src/components/ui/button.tsx index 0ba4277..cd7d5b9 100644 --- a/src/components/ui/button.tsx +++ b/src/components/ui/button.tsx @@ -1,56 +1,57 @@ -import * as React from "react" -import { Slot } from "@radix-ui/react-slot" -import { cva, type VariantProps } from "class-variance-authority" +import * as React from "react"; +import { Slot } from "@radix-ui/react-slot"; +import { cva, type VariantProps } from "class-variance-authority"; -import { cn } from "@/lib/utils" +import { cn } from "@/lib/utils"; const buttonVariants = cva( - "inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50", - { - variants: { - variant: { - default: "bg-primary text-primary-foreground hover:bg-primary/90", - destructive: - "bg-destructive text-destructive-foreground hover:bg-destructive/90", - outline: - "border border-input bg-background hover:bg-accent hover:text-accent-foreground", - secondary: - "bg-secondary text-secondary-foreground hover:bg-secondary/80", - ghost: "hover:bg-accent hover:text-accent-foreground", - link: "text-primary underline-offset-4 hover:underline", - }, - size: { - default: "h-10 px-4 py-2", - sm: "h-9 rounded-md px-3", - lg: "h-11 rounded-md px-8", - icon: "h-10 w-10", - }, - }, - defaultVariants: { - variant: "default", - size: "default", - }, - } -) + "inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50", + { + variants: { + variant: { + default: + "bg-primary text-primary-foreground hover:bg-primary/90", + destructive: + "bg-destructive text-destructive-foreground hover:bg-destructive/90", + outline: + "border border-input bg-background hover:bg-accent hover:text-accent-foreground", + secondary: + "bg-secondary text-secondary-foreground hover:bg-secondary/80", + ghost: "hover:bg-accent hover:text-accent-foreground", + link: "text-primary underline-offset-4 hover:underline", + }, + size: { + default: "h-10 px-4 py-2", + sm: "h-9 rounded-md px-3", + lg: "h-11 rounded-md px-8", + icon: "h-10 w-10", + }, + }, + defaultVariants: { + variant: "default", + size: "default", + }, + } +); export interface ButtonProps - extends React.ButtonHTMLAttributes, - VariantProps { - asChild?: boolean + extends React.ButtonHTMLAttributes, + VariantProps { + asChild?: boolean; } const Button = React.forwardRef( - ({ className, variant, size, asChild = false, ...props }, ref) => { - const Comp = asChild ? Slot : "button" - return ( - - ) - } -) -Button.displayName = "Button" + ({ className, variant, size, asChild = false, ...props }, ref) => { + const Comp = asChild ? Slot : "button"; + return ( + + ); + } +); +Button.displayName = "Button"; -export { Button, buttonVariants } +export { Button, buttonVariants }; diff --git a/src/components/ui/flip-words.tsx b/src/components/ui/flip-words.tsx index ec3fe0a..c974ebd 100644 --- a/src/components/ui/flip-words.tsx +++ b/src/components/ui/flip-words.tsx @@ -1,99 +1,107 @@ "use client"; -import React, { useCallback, useEffect, useRef, useState } from "react"; -import { AnimatePresence, motion, LayoutGroup } from "framer-motion"; +import React, { useCallback, useEffect, useState } from "react"; +import { AnimatePresence, motion } from "framer-motion"; import { cn } from "@/lib/utils"; export const FlipWords = ({ - words, - duration = 3000, - className, + words, + duration = 3000, + className, }: { - words: string[]; - duration?: number; - className?: string; + words: string[]; + duration?: number; + className?: string; }) => { - const [currentWord, setCurrentWord] = useState(words[0]); - const [isAnimating, setIsAnimating] = useState(false); + const [currentWord, setCurrentWord] = useState(words[0]); + const [isAnimating, setIsAnimating] = useState(false); - // thanks for the fix Julian - https://github.com/Julian-AT - const startAnimation = useCallback(() => { - const word = words[words.indexOf(currentWord) + 1] || words[0]; - setCurrentWord(word); - setIsAnimating(true); - }, [currentWord, words]); + // thanks for the fix Julian - https://github.com/Julian-AT + const startAnimation = useCallback(() => { + const word = words[words.indexOf(currentWord) + 1] || words[0]; + setCurrentWord(word); + setIsAnimating(true); + }, [currentWord, words]); - useEffect(() => { - if (!isAnimating) - setTimeout(() => { - startAnimation(); - }, duration); - }, [isAnimating, duration, startAnimation]); + useEffect(() => { + if (!isAnimating) + setTimeout(() => { + startAnimation(); + }, duration); + }, [isAnimating, duration, startAnimation]); - return ( - { - setIsAnimating(false); - }} - > - - {/* edit suggested by Sajal: https://x.com/DewanganSajal */} - {currentWord.split(" ").map((word, wordIndex) => ( - - {word.split("").map((letter, letterIndex) => ( - - {letter} - - ))} -   - - ))} - - - ); + return ( + { + setIsAnimating(false); + }} + > + + {/* edit suggested by Sajal: https://x.com/DewanganSajal */} + {currentWord.split(" ").map((word, wordIndex) => ( + + {word.split("").map((letter, letterIndex) => ( + + {letter} + + ))} +   + + ))} + + + ); }; diff --git a/src/components/ui/magic-card.tsx b/src/components/ui/magic-card.tsx index 4177af6..1651c77 100644 --- a/src/components/ui/magic-card.tsx +++ b/src/components/ui/magic-card.tsx @@ -6,59 +6,59 @@ import { motion, useMotionTemplate, useMotionValue } from "framer-motion"; import { cn } from "@/lib/utils"; export interface MagicCardProps extends React.HTMLAttributes { - gradientSize?: number; - gradientColor?: string; - gradientOpacity?: number; + gradientSize?: number; + gradientColor?: string; + gradientOpacity?: number; } export function MagicCard({ - children, - className, - gradientSize = 200, - gradientColor = "#262626", - gradientOpacity = 0.8, + children, + className, + gradientSize = 200, + gradientColor = "#262626", + gradientOpacity = 0.8, }: MagicCardProps) { - const mouseX = useMotionValue(-gradientSize); - const mouseY = useMotionValue(-gradientSize); + const mouseX = useMotionValue(-gradientSize); + const mouseY = useMotionValue(-gradientSize); - const handleMouseMove = useCallback( - (e: React.MouseEvent) => { - const { left, top } = e.currentTarget.getBoundingClientRect(); - mouseX.set(e.clientX - left); - mouseY.set(e.clientY - top); - }, - [mouseX, mouseY], - ); + const handleMouseMove = useCallback( + (e: React.MouseEvent) => { + const { left, top } = e.currentTarget.getBoundingClientRect(); + mouseX.set(e.clientX - left); + mouseY.set(e.clientY - top); + }, + [mouseX, mouseY] + ); - const handleMouseLeave = useCallback(() => { - mouseX.set(-gradientSize); - mouseY.set(-gradientSize); - }, [mouseX, mouseY, gradientSize]); + const handleMouseLeave = useCallback(() => { + mouseX.set(-gradientSize); + mouseY.set(-gradientSize); + }, [mouseX, mouseY, gradientSize]); - useEffect(() => { - mouseX.set(-gradientSize); - mouseY.set(-gradientSize); - }, [mouseX, mouseY, gradientSize]); + useEffect(() => { + mouseX.set(-gradientSize); + mouseY.set(-gradientSize); + }, [mouseX, mouseY, gradientSize]); - return ( -
-
{children}
- +
{children}
+ -
- ); + opacity: gradientOpacity, + }} + /> + + ); } diff --git a/src/components/ui/navigation-menu.tsx b/src/components/ui/navigation-menu.tsx index ede85e0..7b792b6 100644 --- a/src/components/ui/navigation-menu.tsx +++ b/src/components/ui/navigation-menu.tsx @@ -6,123 +6,123 @@ import { ChevronDown } from "lucide-react"; import { cn } from "@/lib/utils"; const NavigationMenu = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef + React.ElementRef, + React.ComponentPropsWithoutRef >(({ className, children, ...props }, ref) => ( - - {children} - - + + {children} + + )); NavigationMenu.displayName = NavigationMenuPrimitive.Root.displayName; const NavigationMenuList = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef + React.ElementRef, + React.ComponentPropsWithoutRef >(({ className, ...props }, ref) => ( - + )); NavigationMenuList.displayName = NavigationMenuPrimitive.List.displayName; const NavigationMenuItem = NavigationMenuPrimitive.Item; const navigationMenuTriggerStyle = cva( - "group inline-flex h-10 w-max items-center justify-center rounded-md bg-background px-4 py-2 text-sm font-medium cursor-default transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground focus:outline-none disabled:pointer-events-none disabled:opacity-50 data-[active]:bg-accent/50 data-[state=open]:bg-accent/50", + "group inline-flex h-10 w-max items-center justify-center rounded-md bg-background px-4 py-2 text-sm font-medium cursor-default transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground focus:outline-none disabled:pointer-events-none disabled:opacity-50 data-[active]:bg-accent/50 data-[state=open]:bg-accent/50" ); const NavigationMenuTrigger = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef + React.ElementRef, + React.ComponentPropsWithoutRef >(({ className, children, ...props }, ref) => ( - - {children}{" "} - + + {children}{" "} + )); NavigationMenuTrigger.displayName = NavigationMenuPrimitive.Trigger.displayName; const NavigationMenuContent = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef + React.ElementRef, + React.ComponentPropsWithoutRef >(({ className, ...props }, ref) => ( - + )); NavigationMenuContent.displayName = NavigationMenuPrimitive.Content.displayName; const NavigationMenuLink = NavigationMenuPrimitive.Link; const NavigationMenuViewport = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef + React.ElementRef, + React.ComponentPropsWithoutRef >(({ className, ...props }, ref) => ( -
- -
+
+ +
)); NavigationMenuViewport.displayName = - NavigationMenuPrimitive.Viewport.displayName; + NavigationMenuPrimitive.Viewport.displayName; const NavigationMenuIndicator = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef + React.ElementRef, + React.ComponentPropsWithoutRef >(({ className, ...props }, ref) => ( - -
- + +
+ )); NavigationMenuIndicator.displayName = - NavigationMenuPrimitive.Indicator.displayName; + NavigationMenuPrimitive.Indicator.displayName; export { - navigationMenuTriggerStyle, - NavigationMenu, - NavigationMenuList, - NavigationMenuItem, - NavigationMenuContent, - NavigationMenuTrigger, - NavigationMenuLink, - NavigationMenuIndicator, - NavigationMenuViewport, + navigationMenuTriggerStyle, + NavigationMenu, + NavigationMenuList, + NavigationMenuItem, + NavigationMenuContent, + NavigationMenuTrigger, + NavigationMenuLink, + NavigationMenuIndicator, + NavigationMenuViewport, }; diff --git a/src/components/ui/simple-tooltip.tsx b/src/components/ui/simple-tooltip.tsx index ce2be2e..5e0b07b 100644 --- a/src/components/ui/simple-tooltip.tsx +++ b/src/components/ui/simple-tooltip.tsx @@ -1,8 +1,8 @@ import { ReactElement, ReactNode } from "react"; import { - Tooltip, - TooltipContent, - TooltipTrigger, + Tooltip, + TooltipContent, + TooltipTrigger, } from "@/components/ui/tooltip"; import { SIDE_OPTIONS } from "@radix-ui/react-popper"; @@ -10,20 +10,20 @@ import { SIDE_OPTIONS } from "@radix-ui/react-popper"; * The props for a simple tooltip. */ type SimpleTooltipProps = { - /** - * The content to display in the tooltip. - */ - content: string | ReactElement; + /** + * The content to display in the tooltip. + */ + content: string | ReactElement; - /** - * The side to display the tooltip on. - */ - side?: (typeof SIDE_OPTIONS)[number]; + /** + * The side to display the tooltip on. + */ + side?: (typeof SIDE_OPTIONS)[number]; - /** - * The children to render in this tooltip. - */ - children: ReactNode; + /** + * The children to render in this tooltip. + */ + children: ReactNode; }; /** @@ -33,13 +33,13 @@ type SimpleTooltipProps = { * @return the tooltip jsx */ const SimpleTooltip = ({ - content, - side, - children, + content, + side, + children, }: SimpleTooltipProps): ReactElement => ( - - {children} - {content} - + + {children} + {content} + ); export default SimpleTooltip; diff --git a/src/components/ui/tooltip.tsx b/src/components/ui/tooltip.tsx index 30fc44d..0990b90 100644 --- a/src/components/ui/tooltip.tsx +++ b/src/components/ui/tooltip.tsx @@ -1,30 +1,30 @@ -"use client" +"use client"; -import * as React from "react" -import * as TooltipPrimitive from "@radix-ui/react-tooltip" +import * as React from "react"; +import * as TooltipPrimitive from "@radix-ui/react-tooltip"; -import { cn } from "@/lib/utils" +import { cn } from "@/lib/utils"; -const TooltipProvider = TooltipPrimitive.Provider +const TooltipProvider = TooltipPrimitive.Provider; -const Tooltip = TooltipPrimitive.Root +const Tooltip = TooltipPrimitive.Root; -const TooltipTrigger = TooltipPrimitive.Trigger +const TooltipTrigger = TooltipPrimitive.Trigger; const TooltipContent = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef + React.ElementRef, + React.ComponentPropsWithoutRef >(({ className, sideOffset = 4, ...props }, ref) => ( - -)) -TooltipContent.displayName = TooltipPrimitive.Content.displayName + +)); +TooltipContent.displayName = TooltipPrimitive.Content.displayName; -export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider } +export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider }; diff --git a/src/lib/utils.ts b/src/lib/utils.ts index d084cca..e644794 100644 --- a/src/lib/utils.ts +++ b/src/lib/utils.ts @@ -1,6 +1,6 @@ -import { type ClassValue, clsx } from "clsx" -import { twMerge } from "tailwind-merge" +import { type ClassValue, clsx } from "clsx"; +import { twMerge } from "tailwind-merge"; export function cn(...inputs: ClassValue[]) { - return twMerge(clsx(inputs)) + return twMerge(clsx(inputs)); } diff --git a/tailwind.config.ts b/tailwind.config.ts index 84287e8..e7d28ca 100644 --- a/tailwind.config.ts +++ b/tailwind.config.ts @@ -1,80 +1,83 @@ -import type { Config } from "tailwindcss" +import type {Config} from "tailwindcss" + +const defaultTheme = require('tailwindcss/defaultTheme') const config = { - darkMode: ["class"], - content: [ - './pages/**/*.{ts,tsx}', - './components/**/*.{ts,tsx}', - './app/**/*.{ts,tsx}', - './src/**/*.{ts,tsx}', - ], - prefix: "", - theme: { - container: { - center: true, - padding: "2rem", - screens: { - "2xl": "1400px", - }, + darkMode: ["class"], + content: [ + "./src/**/*.{ts,tsx}", + ], + prefix: "", + theme: { + screens: { + 'xs': '475px', + ...defaultTheme.screens, + }, + container: { + center: true, + padding: "2rem", + screens: { + "2xl": "1400px", + }, + }, + extend: { + colors: { + border: "hsl(var(--border))", + input: "hsl(var(--input))", + ring: "hsl(var(--ring))", + background: "hsl(var(--background))", + foreground: "hsl(var(--foreground))", + primary: { + DEFAULT: "hsl(var(--primary))", + foreground: "hsl(var(--primary-foreground))", + }, + secondary: { + DEFAULT: "hsl(var(--secondary))", + foreground: "hsl(var(--secondary-foreground))", + }, + destructive: { + DEFAULT: "hsl(var(--destructive))", + foreground: "hsl(var(--destructive-foreground))", + }, + muted: { + DEFAULT: "hsl(var(--muted))", + foreground: "hsl(var(--muted-foreground))", + }, + accent: { + DEFAULT: "hsl(var(--accent))", + foreground: "hsl(var(--accent-foreground))", + }, + popover: { + DEFAULT: "hsl(var(--popover))", + foreground: "hsl(var(--popover-foreground))", + }, + card: { + DEFAULT: "hsl(var(--card))", + foreground: "hsl(var(--card-foreground))", + }, + }, + borderRadius: { + lg: "var(--radius)", + md: "calc(var(--radius) - 2px)", + sm: "calc(var(--radius) - 4px)", + }, + keyframes: { + "accordion-down": { + from: {height: "0"}, + to: {height: "var(--radix-accordion-content-height)"}, + }, + "accordion-up": { + from: {height: "var(--radix-accordion-content-height)"}, + to: {height: "0"}, + }, + }, + animation: { + "accordion-down": "accordion-down 0.2s ease-out", + "accordion-up": "accordion-up 0.2s ease-out", + }, + }, }, - extend: { - colors: { - border: "hsl(var(--border))", - input: "hsl(var(--input))", - ring: "hsl(var(--ring))", - background: "hsl(var(--background))", - foreground: "hsl(var(--foreground))", - primary: { - DEFAULT: "hsl(var(--primary))", - foreground: "hsl(var(--primary-foreground))", - }, - secondary: { - DEFAULT: "hsl(var(--secondary))", - foreground: "hsl(var(--secondary-foreground))", - }, - destructive: { - DEFAULT: "hsl(var(--destructive))", - foreground: "hsl(var(--destructive-foreground))", - }, - muted: { - DEFAULT: "hsl(var(--muted))", - foreground: "hsl(var(--muted-foreground))", - }, - accent: { - DEFAULT: "hsl(var(--accent))", - foreground: "hsl(var(--accent-foreground))", - }, - popover: { - DEFAULT: "hsl(var(--popover))", - foreground: "hsl(var(--popover-foreground))", - }, - card: { - DEFAULT: "hsl(var(--card))", - foreground: "hsl(var(--card-foreground))", - }, - }, - borderRadius: { - lg: "var(--radius)", - md: "calc(var(--radius) - 2px)", - sm: "calc(var(--radius) - 4px)", - }, - keyframes: { - "accordion-down": { - from: { height: "0" }, - to: { height: "var(--radix-accordion-content-height)" }, - }, - "accordion-up": { - from: { height: "var(--radix-accordion-content-height)" }, - to: { height: "0" }, - }, - }, - animation: { - "accordion-down": "accordion-down 0.2s ease-out", - "accordion-up": "accordion-up 0.2s ease-out", - }, - }, - }, - plugins: [require("tailwindcss-animate")], + plugins: [require("tailwindcss-animate")], } satisfies Config export default config \ No newline at end of file