diff --git a/src/app/(app)/layout.tsx b/src/app/(app)/layout.tsx index fbf3556..2abaada 100644 --- a/src/app/(app)/layout.tsx +++ b/src/app/(app)/layout.tsx @@ -27,6 +27,7 @@ export default function RootLayout({ +
{children} diff --git a/src/app/(app)/page.tsx b/src/app/(app)/page.tsx index c3b5b41..765f530 100644 --- a/src/app/(app)/page.tsx +++ b/src/app/(app)/page.tsx @@ -10,34 +10,42 @@ const IndexPage = async () => { const home = await getHome(); return ( -
- Liam Pietralla -

Liam Pietralla

-
+
+
+ Liam Pietralla +
+

+ Liam Pietralla +

+

Enthusiastic Software Developer

& DevOps Engineer

- -
+ +
{home.mainLinks.map(link => ( ))}
-
+
{home.popoverLinks.map(link => ( ))}
- - + + me@liampietralla.com - +
); } -export default IndexPage; \ No newline at end of file +export default IndexPage; diff --git a/src/app/(app)/projects/page.tsx b/src/app/(app)/projects/page.tsx index d2ab3c3..6b0820c 100644 --- a/src/app/(app)/projects/page.tsx +++ b/src/app/(app)/projects/page.tsx @@ -1,9 +1,7 @@ import ProjectCard from "@/components/project-card"; -import Rule from "@/components/horizontal-rule"; import { getProjects } from "@/services/projects-service"; import Image from "next/image"; import Link from "next/link"; -import { Fragment } from "react"; import ProfileImage from "../../../../public/images/liam_pietralla.jpg"; @@ -11,25 +9,26 @@ const ProjectsPage = async () => { const projects = await getProjects(); return (
-
+
Liam Pietralla Liam Pietralla - +
-

Projects

-

A collection of interesting projects that I am working on currently or have worked on in the past.

-
+

Projects

+

+ A collection of interesting projects that I am working on currently or have worked on in the past. +

+
{projects.docs.map((project, index) => ( - +
- {index < projects.docs.length - 1 && } - +
))}
) } -export default ProjectsPage; \ No newline at end of file +export default ProjectsPage; diff --git a/src/app/globals.css b/src/app/globals.css index ff18ea2..d6753cc 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -3,11 +3,13 @@ :root { --background: #0a0a0a; --foreground: #ededed; + --accent: #7c9cff; } @theme inline { --color-background: var(--background); --color-foreground: var(--foreground); + --color-accent: var(--accent); --font-sans: var(--font-geist-sans); --font-mono: var(--font-geist-mono); } @@ -15,5 +17,120 @@ body { background: var(--background); color: var(--foreground); - font-family: Arial, Helvetica, sans-serif; -} \ No newline at end of file + font-family: var(--font-geist-sans), Arial, Helvetica, sans-serif; + overflow-x: hidden; +} + +.aurora { + position: fixed; + inset: 0; + z-index: -1; + overflow: hidden; + pointer-events: none; +} + +.aurora::before, +.aurora::after { + content: ""; + position: absolute; + width: 60vw; + height: 60vw; + border-radius: 9999px; + filter: blur(120px); + opacity: 0.22; + will-change: transform; +} + +.aurora::before { + top: -15%; + left: -10%; + background: radial-gradient(circle at center, var(--accent), transparent 70%); + animation: drift-1 18s ease-in-out infinite alternate; +} + +.aurora::after { + bottom: -20%; + right: -10%; + background: radial-gradient(circle at center, #b07cff, transparent 70%); + animation: drift-2 22s ease-in-out infinite alternate; +} + +@keyframes drift-1 { + 0% { transform: translate(0, 0) scale(1); } + 100% { transform: translate(15vw, 10vh) scale(1.15); } +} + +@keyframes drift-2 { + 0% { transform: translate(0, 0) scale(1); } + 100% { transform: translate(-12vw, -8vh) scale(1.2); } +} + +@keyframes fade-in-up { + from { opacity: 0; transform: translateY(16px); } + to { opacity: 1; transform: translateY(0); } +} + +.animate-fade-in-up { + opacity: 0; + animation: fade-in-up 0.7s cubic-bezier(0.22, 1, 0.36, 1) forwards; +} + +@keyframes fade-in { + from { opacity: 0; } + to { opacity: 1; } +} + +.animate-fade-in { + opacity: 0; + animation: fade-in 1.2s ease forwards; +} + +.glow-ring { + position: relative; +} + +.glow-ring::before { + content: ""; + position: absolute; + inset: -6px; + border-radius: 9999px; + background: conic-gradient(from 0deg, var(--accent), #b07cff, var(--accent)); + filter: blur(8px); + opacity: 0.55; + z-index: -1; + animation: spin-slow 8s linear infinite; +} + +@keyframes spin-slow { + from { transform: rotate(0deg); } + to { transform: rotate(360deg); } +} + +.glass { + background: rgba(255, 255, 255, 0.04); + backdrop-filter: blur(8px); + -webkit-backdrop-filter: blur(8px); + border: 1px solid rgba(255, 255, 255, 0.08); + transition: background 0.3s ease, border-color 0.3s ease, transform 0.3s ease, box-shadow 0.3s ease; +} + +.glass-hover:hover { + background: rgba(255, 255, 255, 0.08); + border-color: rgba(124, 156, 255, 0.4); + transform: translateY(-2px); + box-shadow: 0 8px 30px -10px rgba(124, 156, 255, 0.35); +} + +@media (prefers-reduced-motion: reduce) { + *, + .aurora::before, + .aurora::after, + .glow-ring::before { + animation: none !important; + } + .animate-fade-in-up, + .animate-fade-in { + opacity: 1; + animation: none !important; + } +} diff --git a/src/components/home-page-link.tsx b/src/components/home-page-link.tsx index a6613dd..777a605 100644 --- a/src/components/home-page-link.tsx +++ b/src/components/home-page-link.tsx @@ -15,42 +15,53 @@ const HomePageLink = ({ title, icon, url, isPopover }: HomePageLinkProps) => { const IconComponent = lucidIconMap[icon as IconName]; if (isPopover) { + const LinkContent = ( + + {icon && } + + ); + + const Popover = ( +
+ {title} +
+ ); + if (isRelative) { return (
- - {icon && } - -
- {title} -
+ {LinkContent} + {Popover}
) } else { return (
- - {icon && } - -
- {title} -
+ {LinkContent} + {Popover}
) } } else { + const Content = ( + <> + + {icon && } {title} + + + + ); + if (isRelative) { return ( - {icon && } {title} - + {Content} ) } else { return ( - {icon && } {title} - + {Content} ) } @@ -58,4 +69,4 @@ const HomePageLink = ({ title, icon, url, isPopover }: HomePageLinkProps) => { } -export default HomePageLink; \ No newline at end of file +export default HomePageLink; diff --git a/src/components/horizontal-rule.tsx b/src/components/horizontal-rule.tsx index c203e77..6c83abe 100644 --- a/src/components/horizontal-rule.tsx +++ b/src/components/horizontal-rule.tsx @@ -1,13 +1,15 @@ import { cn } from "@/lib/utils"; +import { CSSProperties } from "react"; interface RuleProps { className?: string; + style?: CSSProperties; } -const HorizontalRule = ({ className }: RuleProps) => { +const HorizontalRule = ({ className, style }: RuleProps) => { return ( -
+
) } -export default HorizontalRule; \ No newline at end of file +export default HorizontalRule; diff --git a/src/components/project-card.tsx b/src/components/project-card.tsx index 1e211e8..9144652 100644 --- a/src/components/project-card.tsx +++ b/src/components/project-card.tsx @@ -5,16 +5,16 @@ import { Project } from "@/payload-types"; const ProjectCard = (project: Project) => { return ( -
+

{project.title}

{project.featuredImage && typeof project.featuredImage === "object" && ( - {project.title} + {project.title} )}

{project.description}

-
+
{(project?.tags || []).map((tag) => ( - + {tag.tag} ))} @@ -24,20 +24,20 @@ const ProjectCard = (project: Project) => {
{project.viewLink && ( - - + + View Project - + )} {project.repositoryLink && ( - - + + View Source - + )}
@@ -45,4 +45,4 @@ const ProjectCard = (project: Project) => { ) } -export default ProjectCard; \ No newline at end of file +export default ProjectCard;