Skip to content

Commit

Permalink
Replace Swap component
Browse files Browse the repository at this point in the history
  • Loading branch information
josephdburdick committed Jun 12, 2024
1 parent 68cff23 commit d2a62d3
Show file tree
Hide file tree
Showing 12 changed files with 460 additions and 124 deletions.
Binary file modified bun.lockb
Binary file not shown.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
"@radix-ui/react-slot": "^1.0.2",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.1",
"embla-carousel-autoplay": "^8.1.5",
"embla-carousel-react": "^8.1.5",
"front-matter": "^4.0.2",
"lucide-react": "^0.390.0",
"marked": "^12.0.2",
Expand Down
47 changes: 33 additions & 14 deletions src/app/_content/About.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,24 @@
"use client"

import Icon from "@/components/global/Icon"
import ExternalLink from "@/components/global/ExternalLink"
import { useApi } from "@/components/providers/DataProvider"
import Image from "next/image"

export default function Footer() {
const { data } = useApi()
const profile = data.profile.attributes
const { width, height, src, alt } = profile.bg

const links = [
{
href: "https://github.com/josephdburdick/j0e",
children: "View Source Code",
},
{
href: "https://pagespeed.web.dev/analysis/https-j0e-me/3wq088el4g?form_factor=mobile",
children: "PageSpeed Insights",
},
]
return (
<div className="flex items-center bg-secondary">
<Image
Expand All @@ -20,22 +31,30 @@ export default function Footer() {

<div className="relative">
<div className="grid sm:grid-cols-2">
<div className="space-y-2 p-8 mix-blend-darken backdrop-blur-lg md:p-16 lg:p-24 xl:p-36">
<div className="space-y-2 rounded-3xl p-8 mix-blend-darken backdrop-blur-md md:p-16 lg:p-24 xl:p-36">
<div className="text-sm">About this site</div>
<p>
Data composed in front-matter format, front-end statically
generated with Next, server hosted with Github actions.
</p>
<p>
<a
className="inline-flex items-center gap-2"
href="https://github.com/josephdburdick/j0e"
>
<span className="underline">View Source Code</span>

<Icon.externalLink className="inline-block" />
</a>
Edited in{" "}
<ExternalLink href="https://neovim.io">Neovim</ExternalLink>,
composed in{" "}
<ExternalLink href="https://www.npmjs.com/package/front-matter">
Front Matter
</ExternalLink>
, statically generated with{" "}
<ExternalLink href="https://nextjs.org">Next.js</ExternalLink>,
server hosted with{" "}
<ExternalLink href="https://github.com/features/actions">
Github Actions
</ExternalLink>
.
</p>
<div className="flex flex-wrap gap-x-6 gap-y-2 pt-4">
{links.map((link, key) => (
<ExternalLink key={key} href={link.href} className="text-sm">
{link.children}
</ExternalLink>
))}
</div>
</div>
</div>
</div>
Expand Down
9 changes: 2 additions & 7 deletions src/app/_content/Intro.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
"use client"

import DarkModeToggle from "@/components/global/DarkModeToggle"
import HeaderAd from "@/components/global/HeaderAd"
import Icon from "@/components/global/Icon"
import LogoMarquee from "@/components/global/LogoMarquee"
import MainHeader from "@/components/global/MainHeader"
import MainNav from "@/components/global/MainNav"
import Swap from "@/components/global/Swap"
import WeatherComponent from "@/components/global/Weather"
import WorkAvailability from "@/components/global/WorkAvailability"
import { useApi } from "@/components/providers/DataProvider"
import { ContactLink } from "@/lib/types"
import { cn } from "@/lib/utils"
Expand Down Expand Up @@ -45,11 +44,7 @@ function Intro() {
)}
>
<MainHeader className="container z-10 py-4 md:py-8">
<Swap
firstComponent={<WorkAvailability />}
secondComponent={<WeatherComponent />}
/>
{/* <WorkAvailability reverse /> */}
<HeaderAd />
</MainHeader>
</div>

Expand Down
16 changes: 11 additions & 5 deletions src/components/global/DarkModeToggle.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"use client"

import { buttonVariants } from "@/components/ui/button"
import { Button, buttonVariants } from "@/components/ui/button"
import { cn } from "@/lib/utils"
import { useEffect, useState } from "react"

Expand All @@ -25,11 +25,17 @@ const DarkModeToggle = () => {
}, [darkMode])

return (
<button
className="group relative inline-flex items-center rounded-full bg-secondary focus:outline-none dark:bg-gray-800"
<Button
variant="secondary"
className="group relative inline-flex items-center rounded-full border-0 p-0 focus:outline-none"
onClick={() => setDarkMode(!darkMode)}
>
<div className="pointer-events-none absolute right-full z-0 mr-2 translate-x-1/4 whitespace-nowrap rounded-full bg-primary px-4 py-2 opacity-0 transition-all duration-300 group-hover:-translate-x-0 group-hover:opacity-100 group-active:opacity-100">
<div
className={cn(
buttonVariants({ variant: "default", size: "lg" }),
"pointer-events-none absolute right-full z-0 mr-2 translate-x-1/4 whitespace-nowrap rounded-full px-4 py-2 opacity-0 transition-all duration-300 group-hover:-translate-x-0 group-hover:opacity-100 group-active:opacity-100",
)}
>
Toggle theme
</div>
<div
Expand All @@ -44,7 +50,7 @@ const DarkModeToggle = () => {
<Icon.moon className="foreground text-foreground" />
)}
</div>
</button>
</Button>
)
}

Expand Down
23 changes: 23 additions & 0 deletions src/components/global/ExternalLink.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { cn } from "@/lib/utils"
import { PropsWithChildren } from "react"

import Icon from "./Icon"

type Props = PropsWithChildren & {
href: string;
className?: string;
};

export default function ExternalLink(props: Props) {
const { href, children, className = "" } = props
return (
<a
className={cn("inline-flex items-center gap-1 text-inherit", className)}
href={href}
>
<span className="underline">{children}</span>

<Icon.externalLink className="inline-block" size="16" />
</a>
)
}
103 changes: 103 additions & 0 deletions src/components/global/HeaderAd.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
"use client"

import { useApi } from "@/components/providers/DataProvider"
import {
Carousel,
CarouselContent,
CarouselItem,
} from "@/components/ui/carousel"
import { type CarouselApi } from "@/components/ui/carousel"
import { ContactLink } from "@/lib/types"
import { useEffect, useRef, useState } from "react"

import { Button } from "../ui/button"
import Icon from "./Icon"
import MainNav from "./MainNav"
import WorkAvailability from "./WorkAvailability"

export default function HeaderAd() {
const [api, setApi] = useState<CarouselApi | null>(null)
const { data } = useApi()
const links: ContactLink[] = Object.values(data.profile.attributes.links)

const intervalRef = useRef<number | null>(null)
const [isPaused, setIsPaused] = useState(false)

useEffect(() => {
const updateAutoplay = (currentSlide: number) => {
if (intervalRef.current !== null) {
clearInterval(intervalRef.current)
}

const delay = currentSlide === 0 ? 6000 : 2000

intervalRef.current = window.setInterval(() => {
if (api && !isPaused) {
api.scrollNext()
}
}, delay)
}
if (!api) {
return
}

const handleSelect = () => {
const currentSlide = api.selectedScrollSnap()
updateAutoplay(currentSlide)
}

api.on("select", handleSelect)
updateAutoplay(api.selectedScrollSnap())

return () => {
if (intervalRef.current !== null) {
clearInterval(intervalRef.current)
}
api.off("select", handleSelect)
}
}, [api, isPaused])

const handleMouseEnter = () => {
if (api?.selectedScrollSnap() === 0) {
setIsPaused(true)
}
}

const handleMouseLeave = () => {
if (api?.selectedScrollSnap() === 0) {
setIsPaused(false)
}
}

return (
<Carousel
setApi={setApi}
opts={{
loop: true,
align: "end",
}}
orientation="vertical"
className="w-full max-w-xs"
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
>
<CarouselContent className="h-12">
<CarouselItem className="flex justify-end pt-3">
<MainNav links={links} className="mr-auto">
<Button
variant="outline"
size="sm"
className="ml-auto mt-1 flex items-center gap-2"
>
<Icon.ellipsis />
<div>Menu</div>
</Button>
</MainNav>
</CarouselItem>
<CarouselItem>
<WorkAvailability />
</CarouselItem>
</CarouselContent>
</Carousel>
)
}
5 changes: 3 additions & 2 deletions src/components/global/MainHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export const MainHeader = forwardRef(
(props: Props, ref: ForwardedRef<HTMLElement>): ReactNode => {
const { className } = props
const { data } = useApi()
const { name } = data.profile
const { logo } = data.site.attributes

return (
Expand All @@ -31,9 +32,9 @@ export const MainHeader = forwardRef(
height={logo.height}
alt={logo.alt}
/>
<span className="sr-only">Joe Burdick</span>
<span className="sr-only">{name}</span>
</h1>
<div className="flex items-center gap-2 text-secondary">
<div className="flex items-center gap-2">
<div className="flex items-end justify-between gap-4 md:items-center">
{props.children}
</div>
Expand Down
29 changes: 19 additions & 10 deletions src/components/global/MainNav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,28 @@ import {
} from "@/components/ui/drawer"
import { ContactLink } from "@/lib/types"
import { cn } from "@/lib/utils"
import { PropsWithChildren } from "react"

import { Popover, PopoverContent, PopoverTrigger } from "../ui/popover"
import Icon from "./Icon"

type Props = {
type Props = PropsWithChildren & {
links: ContactLink[];
className?: string;
title?: string;
description?: string;
iconOnly?: boolean;
};

export default function MainNav(props: Props) {
const { iconOnly = false, links: linksProp = [], title, description } = props
const {
children = null,
iconOnly = false,
links: linksProp = [],
title,
description,
} = props
const hasText = title || description
const renderTrigger = (
<Button className="rounded-full" size="lg">
<span className="flex items-center gap-2">
Expand All @@ -40,7 +49,6 @@ export default function MainNav(props: Props) {
</span>
</Button>
)

const Nav = () => (
<nav>
<ul className="divide-y divide-gray-200 dark:divide-gray-700">
Expand Down Expand Up @@ -68,24 +76,25 @@ export default function MainNav(props: Props) {
</ul>
</nav>
)

return (
<>
<div className="hidden md:block">
<Popover>
<PopoverTrigger asChild>{renderTrigger}</PopoverTrigger>
<PopoverTrigger asChild>{children || renderTrigger}</PopoverTrigger>
<PopoverContent side="bottom" align="end" className="w-max space-y-8">
<div className="prose dark:prose-invert">
<h4>{title}</h4>
<p>{description}</p>
</div>
{hasText && (
<div className="prose dark:prose-invert">
<h4>{title}</h4>
<p>{description}</p>
</div>
)}
<Nav />
</PopoverContent>
</Popover>
</div>
<div className="visible w-full text-center md:hidden">
<Drawer>
<DrawerTrigger asChild>{renderTrigger}</DrawerTrigger>
<DrawerTrigger asChild>{children || renderTrigger}</DrawerTrigger>
<DrawerContent>
<div className="mx-auto w-full max-w-md">
<DrawerHeader>
Expand Down
Loading

0 comments on commit d2a62d3

Please sign in to comment.