Skip to content

Commit

Permalink
feat: add talks component
Browse files Browse the repository at this point in the history
  • Loading branch information
oerts committed Dec 23, 2024
1 parent 2182574 commit 6966831
Show file tree
Hide file tree
Showing 16 changed files with 255 additions and 47 deletions.
26 changes: 26 additions & 0 deletions app/components/about.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import Image from "next/image";

export default function About() {
return (
<section className="mb-16 lg:relative">
<h1 className="text-2xl tracking-widest max-lg:mb-8 lg:absolute lg:right-full lg:mr-6">
About
</h1>
<p className="mb-4">
Hi, I'm Oz, a UI Developer with a passion for building user-friendly
interfaces. I enjoy working with TypeScript, React, and Next.js, and
have spent the last 3 years building reusable UI components at{" "}
<a
target="_blank"
href="https://atolye15.com"
className="underline items-center gap-1 inline-flex align-baseline"
>
<Image src="/a15.svg" alt="Atolye15 logo" width={14} height={14} />
Atolye15
</a>
. Outside of coding, I enjoy writing and am committed to continuous
learning.
</p>
</section>
);
}
20 changes: 20 additions & 0 deletions app/components/contact.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
export default function Contact() {
return (
<div className="mb-8 lg:relative">
<h2 className="text-2xl max-lg:mb-8 lg:absolute lg:right-full lg:mr-6">
Contact
</h2>
<p className="mt-2 mb-4 text-neutral-600 dark:text-neutral-400">
Feel free to reach out to me via email. I'm always open to interesting
conversations and opportunities.
</p>
<div className="mt-4">
<div className="inline-block font-mono bg-stone-50 dark:bg-stone-800 px-3 py-2 rounded">
<span>hey</span>
<span className="select-none text-neutral-400 px-1">[at]</span>
<span>ertas.dev</span>
</div>
</div>
</div>
);
}
2 changes: 1 addition & 1 deletion app/components/footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ function ArrowIcon() {

export default function Footer() {
return (
<footer className="mb-4 flex justify-between items-center border-t border-red-400 mt-4 pt-4">
<footer className="mb-4 flex justify-between items-center border-t border-stone-400 mt-4 pt-4">
<ul className="font-sm flex flex-col space-x-0 space-y-2 text-neutral-600 md:flex-row md:space-x-4 md:space-y-0 dark:text-neutral-300">
<li>
<a
Expand Down
31 changes: 16 additions & 15 deletions app/components/nav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,26 +8,27 @@ const navItems = {
"/blog": {
name: "blog",
},
"/projects": {
name: "projects",
},
"/contact": {
name: "contact",
},
};

export function Navbar() {
return (
<aside className="-ml-[8px] mb-16 tracking-tight">
<div className="lg:sticky lg:top-20 flex items-center justify-between">
<div className="flex items-center gap-4">
<Image
src="/logo.svg"
alt="two half circles separated by a gap forming o and z"
width="40"
height="40"
/>
</div>
<div className="flex items-center justify-between">
<Link href="/" className="group relative">
<div className="bg-stone-50 dark:bg-stone-900 pr-4">
<div className="rounded-full w-[40px] h-[40px] group-hover:bg-brand-100 transition-colors duration-500 flex items-center justify-center">
<Image
src="/logo.svg"
alt="two half circles separated by a gap forming o and z"
width="40"
height="40"
/>
</div>
</div>
<span className="absolute -z-10 text-xl font-semibold left-full ml-2 top-1/2 -translate-y-1/2 -translate-x-full opacity-0 transition-all duration-300 group-hover:opacity-100 group-hover:translate-x-0">
ertas.dev
</span>
</Link>
<nav
className="flex flex-row items-start relative px-0 pb-0 fade md:overflow-auto scroll-pr-6 md:relative"
id="nav"
Expand Down
16 changes: 8 additions & 8 deletions app/components/posts.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import Link from 'next/link'
import { formatDate, getBlogPosts } from 'app/blog/utils'
import Link from "next/link";
import { formatDate, getBlogPosts } from "app/blog/utils";

export function BlogPosts() {
let allBlogs = getBlogPosts()
let allBlogs = getBlogPosts();

return (
<div>
Expand All @@ -11,26 +11,26 @@ export function BlogPosts() {
if (
new Date(a.metadata.publishedAt) > new Date(b.metadata.publishedAt)
) {
return -1
return -1;
}
return 1
return 1;
})
.map((post) => (
<Link
key={post.slug}
className="flex flex-col space-y-1 mb-4"
className="group flex flex-col space-y-1 mb-4"
href={`/blog/${post.slug}`}
>
<div className="w-full flex flex-col md:flex-row space-x-0 md:space-x-2">
<p className="text-neutral-600 dark:text-neutral-400 w-[100px] tabular-nums">
{formatDate(post.metadata.publishedAt, false)}
</p>
<p className="text-neutral-900 dark:text-neutral-100 tracking-tight">
<p className="text-neutral-900 dark:text-neutral-100 group-hover:text-brand-300 tracking-tight">
{post.metadata.title}
</p>
</div>
</Link>
))}
</div>
)
);
}
37 changes: 37 additions & 0 deletions app/components/projects.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import Image from "next/image";
import { TiltCard } from "./tilt-card";

const projects = [
{
title: "Bettermark",
url: "https://bettermark.app",
description:
"My most recent side project. A modern bookmark manager that helps prevent link rot by taking snapshots of the pages you save. It's cross-platform by default since bookmark saving is done by prefixing your URL with the apps url.",
},
{
title: "tomatotomato",
url: "https://tomatotomato.fly.dev",
description:
"One of my first ever projects. A simple recipe manager I built for my wife. She is still the only user. It was an experiment to learn how to use Remix. It has a lot of room for improvement but I don't think that's happening any time soon. (My wife's pretty sad about it.)",
},
];

export default function Projects() {
return (
<div className="mb-16 lg:relative">
<h2 className="text-2xl max-lg:mb-8 lg:absolute lg:right-full lg:mr-6">
Projects
</h2>
<div className="grid gap-6 mt-4">
{projects.map((project) => (
<TiltCard
key={project.title}
title={project.title}
description={project.description}
link={project.url}
/>
))}
</div>
</div>
);
}
37 changes: 37 additions & 0 deletions app/components/talks.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { TiltCard } from "./tilt-card";

const talks = [
{
title: "Navigating Redesigns",
occasion: "BBT",
date: "2024",
description:
"A talk about the challenges of redesigning a component library that has been around for a long time.",
link: "https://bursa.dev/event-detail/bbt-connect-atolye15-e0c52b3a",
},
];

export default function Talks() {
return (
<div className="mb-16 lg:relative">
<h2 className="text-2xl max-lg:mb-8 lg:absolute lg:right-full lg:mr-6">
Talks
</h2>
<div className="grid gap-6 mt-4">
{talks.map((talk) => (
<TiltCard
key={talk.title}
title={talk.title}
description={talk.description}
link={talk.link}
metadata={
<p className="text-sm text-neutral-600">
{talk.occasion} · {talk.date}
</p>
}
/>
))}
</div>
</div>
);
}
59 changes: 59 additions & 0 deletions app/components/tilt-card.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
"use client";

import { useEffect, useRef } from "react";
import VanillaTilt from "vanilla-tilt";

type TiltCardProps = {
title: string;
description: string;
link: string;
metadata?: React.ReactNode;
};

export function TiltCard({
title,
description,
link,
metadata,
}: TiltCardProps) {
const tiltRef = useRef<HTMLAnchorElement>(null);

useEffect(() => {
const element = tiltRef.current;
if (!element) return;

VanillaTilt.init(element, {
max: 5,
speed: 750,
glare: true,
"max-glare": 0.25,
scale: 1.02,
});

return () => {
if (element) {
// @ts-ignore - vanilla-tilt adds this method to the element
element.vanillaTilt.destroy();
}
};
}, []);

return (
<a
ref={tiltRef}
href={link}
target="_blank"
className="group block p-4 border-l border-stone-400 hover:border-brand-400 hover:bg-stone-100 dark:hover:bg-stone-800 transition-all duration-200"
>
<div className="flex items-center gap-2 mb-2">
<div>
<h3 className="font-semibold text-lg transition-all duration-200">
{title}
</h3>
{metadata && metadata}
</div>
</div>
<p className="text-neutral-600 dark:text-neutral-400">{description}</p>
</a>
);
}
14 changes: 14 additions & 0 deletions app/global.css
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
@import "tailwindcss";

@theme {
--color-brand-50: #fffaeb;
--color-brand-100: #fff0c6;
--color-brand-200: #ffdf88;
--color-brand-300: #ffc53d; /* Primary */
--color-brand-400: #ffb320;
--color-brand-500: #f98f07;
--color-brand-600: #dd6902;
--color-brand-700: #b74806;
--color-brand-800: #94360c;
--color-brand-900: #7a2e0d;
--color-brand-950: #461602;
}

::selection {
background-color: #47a3f3;
color: #fefefe;
Expand Down
4 changes: 2 additions & 2 deletions app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,12 @@ export default function RootLayout({
<html
lang="en"
className={cx(
"text-stone-900 bg-white dark:text-white dark:bg-stone-900",
"text-stone-900 bg-stone-50 dark:text-stone-100 dark:bg-stone-900",
outfit.className,
spaceMono.className,
)}
>
<body className="antialiased max-w-prose mx-4 lg:mx-auto">
<body className="antialiased max-w-prose mx-auto">
<main className="h-full min-w-0 pt-6 flex flex-col px-2 md:px-0 min-h-screen">
<Navbar />
{children}
Expand Down
2 changes: 1 addition & 1 deletion app/og/route.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export function GET(request: Request) {

return new ImageResponse(
(
<div tw="flex flex-col w-full h-full items-center justify-center bg-white">
<div tw="flex flex-col w-full h-full items-center justify-center bg-stone-50">
<div tw="flex flex-col md:flex-row w-full py-12 px-4 md:items-center justify-between p-8">
<h2 tw="flex flex-col text-4xl font-bold tracking-tight text-left">
{title}
Expand Down
27 changes: 10 additions & 17 deletions app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,15 @@
import { BlogPosts } from "app/components/posts";
import Projects from "./components/projects";
import Talks from "./components/talks";
import Contact from "./components/contact";
import About from "./components/about";

export default function Page() {
return (
<section className="grow">
<h1 className="mb-8 text-3xl font-semibold tracking-tighter">Oz Ertas</h1>
<p className="mb-4">
Hi, I'm Oz, a UI Developer with a passion for building user-friendly
interfaces. I enjoy working with TypeScript, React, and Next.js, and
have spent the last 3 years building reusable UI components at{" "}
<a target="_blank" href="https://atolye15.com" className="underline">
Atolye15
</a>
. Outside of coding, I enjoy writing and am committed to continuous
learning.
</p>
<div className="my-8">
<BlogPosts />
</div>
</section>
<>
<About />
<Projects />
<Talks />
<Contact />
</>
);
}
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"react-dom": "19.0.0",
"sugar-high": "^0.7.5",
"tailwindcss": "4.0.0-alpha.13",
"typescript": "5.7.2"
"typescript": "5.7.2",
"vanilla-tilt": "^1.8.1"
}
}
8 changes: 8 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 6966831

Please sign in to comment.