animated index, chronark

This commit is contained in:
2024-12-26 16:14:56 -06:00
parent 9e11a7d455
commit 5a30a9a80a
2 changed files with 122 additions and 93 deletions

View File

@@ -1,4 +1,4 @@
import { readSingleton } from "@directus/sdk"; import { readItems, readSingleton } from "@directus/sdk";
import { GetStaticPropsResult, type NextPage } from "next"; import { GetStaticPropsResult, type NextPage } from "next";
import Head from "next/head"; import Head from "next/head";
import Link from "next/link"; import Link from "next/link";
@@ -6,9 +6,9 @@ import { useEffect } from "react";
import Balancer from "react-wrap-balancer"; import Balancer from "react-wrap-balancer";
import AppWrapper from "@/components/AppWrapper"; import AppWrapper from "@/components/AppWrapper";
import ItemCard from "@/components/ItemCard"; import ItemCard from "@/components/ItemCard";
import directus from "@/utils/directus"; import directus, { type Project } from "@/utils/directus";
import { useBreakpointValue } from "@/utils/helpers"; import { useBreakpointValue } from "@/utils/helpers";
import type { Project } from "@/utils/types"; import Dots from "@/components/Dots";
type IndexProps = { type IndexProps = {
tagline: string; tagline: string;
@@ -19,82 +19,12 @@ type IndexProps = {
export async function getStaticProps(): Promise< export async function getStaticProps(): Promise<
GetStaticPropsResult<IndexProps> GetStaticPropsResult<IndexProps>
> { > {
const metadata = await directus.request(readSingleton("metadata")); const [metadata, projects] = await Promise.all([directus.request(readSingleton("metadata")), directus.request(readItems("project"))]);
const resumeUrl = `${directus.url}assets/${metadata.resume}/${ const resumeUrl = `${directus.url}assets/${metadata.resume}/${
metadata.resumeFilename ?? "resume.pdf" metadata.resumeFilename ?? "resume.pdf"
}`; }`;
const projects: Project[] = [
{
title: "Portal",
banner: "/portal/banner.jpeg",
location: "/portal",
longDescription:
"An advanced membership & event management system for my university's premier computer science organization.",
shortDescription:
"Advanced membership & event management system for students",
links: [
{
icon: "github",
location: "https://github.com/acmutsa/Portal",
},
{
icon: "external",
location: "https://portal.acmutsa.org/",
},
],
},
{
title: "Phototag",
banner: "/phototag.png",
location: "/phototag",
longDescription: `Using Google's Vision API and supporting metadata formats on Windows, Phototag makes it easy to quickly add rich, descriptive tags to your photos, saving you time and effort.`,
shortDescription:
"Effortlessly add rich & descriptive tags to your photos with Phototag.",
links: [
{
icon: "github",
location: "https://github.com/Xevion/phototag",
},
],
},
{
title: "Paths",
banner: "/paths.png",
location: "/paths",
shortDescription:
"Discover the power of graph traversal algorithms with my interactive application.",
longDescription: `Discover the power of graph traversal algorithms with my interactive Unity application!
Easily generate and edit graphs, create mazes, and experiment with different algorithm configurations to find the most efficient path.`,
links: [
{
icon: "github",
location: "https://github.com/Xevion/Paths",
},
],
},
{
title: "Grain",
banner: "/grain/banner.jpeg",
bannerSettings: { quality: 100 },
location: "/grain",
shortDescription:
"An experimental React app to generate beautiful backgrounds with noise filters.",
longDescription:
"Quickly generate beautiful backgrounds with noise filters. Built with React, hosted on Vercel, and rendered using simple SVG noise filters (just HTML & CSS).",
links: [
{
icon: "external",
location: "https://grain.xevion.dev",
},
{
icon: "github",
location: "https://github.com/Xevion/grain",
},
],
},
];
return { return {
props: { props: {
tagline: metadata.tagline, tagline: metadata.tagline,
@@ -133,6 +63,7 @@ const Home: NextPage<IndexProps> = ({
</Head> </Head>
<AppWrapper hideNavigation={true} className="overflow-x-hidden"> <AppWrapper hideNavigation={true} className="overflow-x-hidden">
<div className="flex h-screen w-screen items-center justify-center overflow-hidden"> <div className="flex h-screen w-screen items-center justify-center overflow-hidden">
<Dots />
<div className="flex w-full flex-col items-center justify-start"> <div className="flex w-full flex-col items-center justify-start">
<nav className="animate-fade-in"> <nav className="animate-fade-in">
<ul className="flex items-center justify-center gap-4"> <ul className="flex items-center justify-center gap-4">
@@ -147,12 +78,21 @@ const Home: NextPage<IndexProps> = ({
))} ))}
</ul> </ul>
</nav> </nav>
<div className="sm:text-9x cursor-default select-none py-10 font-hanken text-6xl font-black uppercase tracking-widest min-[300px]:text-7xl min-[500px]:text-8xl lg:text-10xl"> <div className="hidden w-screen h-px animate-glow md:block animate-fade-left bg-gradient-to-r from-zinc-300/0 via-zinc-300/50 to-zinc-300/0" />
<h1 className="font-hanken select-none py-3.5 px-0.5 z-10 text-transparent duration-1000 bg-white cursor-default text-edge-outline animate-title font-display text-5xl sm:text-6xl md:text-9xl lg:text-10xl whitespace-nowrap bg-clip-text ">
XEVION
</h1>
<div className="hidden w-screen h-px animate-glow md:block animate-fade-right bg-gradient-to-r from-zinc-300/0 via-zinc-300/50 to-zinc-300/0" />
{/* <div className="sm:text-9x cursor-default select-none py-10 font-hanken text-6xl font-black uppercase tracking-widest min-[300px]:text-7xl min-[500px]:text-8xl lg:text-10xl">
Xevion Xevion
</div> </div> */}
<div className="max-w-screen-sm px-4 text-center text-base text-zinc-500 sm:text-sm"> <div className="max-w-screen-sm text-center text-sm sm:text-base animate-fade-in text-zinc-500">
<Balancer>{tagline}</Balancer> <Balancer>{tagline}</Balancer>
</div> </div>
{/* <div className="max-w-screen-sm px-4 text-center text-base text-zinc-500 sm:text-sm">
<Balancer>{tagline}</Balancer>
</div>
</div> */}
</div> </div>
</div> </div>
<div <div
@@ -161,15 +101,11 @@ const Home: NextPage<IndexProps> = ({
> >
<div className="mx-auto h-full w-full max-w-[95%] lg:max-w-[85%] xl:max-w-[70%]"> <div className="mx-auto h-full w-full max-w-[95%] lg:max-w-[85%] xl:max-w-[70%]">
<div className="m-1 flex h-full flex-col justify-start gap-y-1"> <div className="m-1 flex h-full flex-col justify-start gap-y-1">
{projects.map((project, index) => ( {projects.map((project) => {
<ItemCard return (<ItemCard key={project.id}
key={index} description={useLong ? project.description : project.shortDescription} banner={`${directus.url}assets/${project.bannerImage}`} title={project.name} location={`/${project.id}/`} />
{...project} );
description={ })}
useLong ? project.longDescription : project.shortDescription
}
/>
))}
</div> </div>
</div> </div>
</div> </div>

View File

@@ -1,9 +1,11 @@
const defaultTheme = require("tailwindcss/defaultTheme");
/** @type {import('tailwindcss').Config} */ /** @type {import('tailwindcss').Config} */
module.exports = { module.exports = {
content: ["./src/**/*.{js,ts,jsx,tsx}"], content: ["./src/**/*.{js,ts,jsx,tsx}"],
theme: { theme: {
extend: { extend: {
colors: { colors: {
zinc: { zinc: {
850: "#1D1D20", 850: "#1D1D20",
}, },
@@ -11,13 +13,104 @@ module.exports = {
fontSize: { fontSize: {
"10xl": "10rem", "10xl": "10rem",
}, },
fontFamily: { typography: {
DEFAULT: {
css: {
"code::before": {
content: '""',
},
"code::after": {
content: '""',
},
},
},
quoteless: {
css: {
"blockquote p:first-of-type::before": { content: "none" },
"blockquote p:first-of-type::after": { content: "none" },
},
},
},
fontFamily: {
inter: ['"Inter"', "sans-serif"], inter: ['"Inter"', "sans-serif"],
roboto: ['"Roboto"', "sans-serif"], roboto: ['"Roboto"', "sans-serif"],
mono: ['"Roboto Mono"', "monospace"], mono: ['"Roboto Mono"', "monospace"],
hanken: ['"Hanken Grotesk"', "sans-serif"], hanken: ['"Hanken Grotesk"', "sans-serif"],
}, // sans: ["var(--font-inter)", ...defaultTheme.fontFamily.sans],
}, // display: ["var(--font-calsans)"],
}, },
backgroundImage: {
"gradient-radial":
"radial-gradient(50% 50% at 50% 50%, var(--tw-gradient-stops))",
},
animation: {
bg: "bg 5s ease-in-out forwards",
"fade-in": "fade-in 3s ease-in-out forwards",
title: "title 3s ease-out forwards",
"fade-left": "fade-left 3s ease-in-out forwards",
"fade-right": "fade-right 3s ease-in-out forwards",
},
keyframes: {
"fade-in": {
"0%": {
opacity: "0%",
},
"75%": {
opacity: "0%",
},
"100%": {
opacity: "100%",
},
},
"fade-left": {
"0%": {
transform: "translateX(100%)",
opacity: "0%",
},
"30%": {
transform: "translateX(0%)",
opacity: "100%",
},
"100%": {
opacity: "0%",
},
},
"fade-right": {
"0%": {
transform: "translateX(-100%)",
opacity: "0%",
},
"30%": {
transform: "translateX(0%)",
opacity: "100%",
},
"100%": {
opacity: "0%",
},
},
title: {
"0%": {
"line-height": "0%",
"letter-spacing": "0.25em",
opacity: "0",
},
"25%": {
"line-height": "0%",
opacity: "0%",
},
"80%": {
opacity: "100%",
},
"100%": {
"line-height": "100%",
opacity: "100%",
},
},
},
},
},
plugins: [require("@tailwindcss/typography")], plugins: [require("@tailwindcss/typography")],
}; };