chore(projects): add projects, customize Card
This commit is contained in:
@@ -2,10 +2,10 @@ import Footer from '@/components/Footer'
|
||||
import Header from '@/components/Header'
|
||||
import SectionContainer from '@/components/SectionContainer'
|
||||
import siteMetadata from '@/data/siteMetadata'
|
||||
import { Analytics } from '@vercel/analytics/react'
|
||||
import 'css/tailwind.css'
|
||||
import { Metadata } from 'next'
|
||||
import { JetBrains_Mono } from 'next/font/google'
|
||||
import { Analytics } from '@vercel/analytics/react'
|
||||
import { SearchConfig, SearchProvider } from 'pliny/search'
|
||||
import 'pliny/search/algolia.css'
|
||||
import 'react-grid-layout/css/styles.css'
|
||||
|
||||
@@ -22,6 +22,7 @@ export default function Projects() {
|
||||
description={d.description}
|
||||
imgSrc={d.imgSrc}
|
||||
href={d.href}
|
||||
tags={d.tags}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
||||
@@ -1,7 +1,17 @@
|
||||
import { Badge } from '@/components/shadcn/badge'
|
||||
|
||||
import Image from './Image'
|
||||
import Link from './Link'
|
||||
|
||||
const Card = ({ title, description, imgSrc, href }) => (
|
||||
type CardProps = {
|
||||
title: string
|
||||
description: string
|
||||
imgSrc: string
|
||||
href: string
|
||||
tags?: string[]
|
||||
}
|
||||
|
||||
const Card = ({ title, description, imgSrc, href, tags = [] }: CardProps) => (
|
||||
<div className="md max-w-[544px] p-4 md:w-1/2">
|
||||
<div className={`${imgSrc && 'h-full'} overflow-hidden rounded-md border border-border`}>
|
||||
{imgSrc &&
|
||||
@@ -10,22 +20,22 @@ const Card = ({ title, description, imgSrc, href }) => (
|
||||
<Image
|
||||
alt={title}
|
||||
src={imgSrc}
|
||||
className="object-cover object-center md:h-36 lg:h-48"
|
||||
className="object-fit object-center"
|
||||
width={544}
|
||||
height={306}
|
||||
height={286}
|
||||
/>
|
||||
</Link>
|
||||
) : (
|
||||
<Image
|
||||
alt={title}
|
||||
src={imgSrc}
|
||||
className="object-cover object-center md:h-36 lg:h-48"
|
||||
className="object-fit object-center"
|
||||
width={544}
|
||||
height={306}
|
||||
height={286}
|
||||
/>
|
||||
))}
|
||||
<div className="p-6">
|
||||
<h2 className="mb-3 text-2xl font-bold leading-8 tracking-tight">
|
||||
<h2 className="mb-2 text-2xl font-bold leading-8 tracking-tight">
|
||||
{href ? (
|
||||
<Link href={href} aria-label={`Link to ${title}`}>
|
||||
{title}
|
||||
@@ -34,6 +44,17 @@ const Card = ({ title, description, imgSrc, href }) => (
|
||||
title
|
||||
)}
|
||||
</h2>
|
||||
<div className="mb-3 flex flex-wrap">
|
||||
{tags.map((tag, index) => (
|
||||
<Badge
|
||||
key={tag}
|
||||
className="mr-2 mb-2"
|
||||
variant={index === 0 ? 'default' : 'outline'}
|
||||
>
|
||||
{tag}
|
||||
</Badge>
|
||||
))}
|
||||
</div>
|
||||
<p className="prose prose-sm mb-3 max-w-none text-muted-foreground">
|
||||
{description}
|
||||
</p>
|
||||
|
||||
@@ -20,7 +20,9 @@ const SearchButton = () => {
|
||||
<kbd className="flex items-center justify-center !w-6 !h-6 border border-border rounded-md">
|
||||
<Command size={12} />
|
||||
</kbd>
|
||||
<kbd className="flex items-center justify-center !w-6 !h-6 p-1 border border-border rounded-md">K</kbd>
|
||||
<kbd className="flex items-center justify-center !w-6 !h-6 p-1 border border-border rounded-md">
|
||||
K
|
||||
</kbd>
|
||||
</span>
|
||||
</>
|
||||
)
|
||||
|
||||
33
components/shadcn/badge.tsx
Normal file
33
components/shadcn/badge.tsx
Normal file
@@ -0,0 +1,33 @@
|
||||
import { cn } from '@/scripts/utils/tailwind-helpers'
|
||||
import { type VariantProps, cva } from 'class-variance-authority'
|
||||
import * as React from 'react'
|
||||
|
||||
const badgeVariants = cva(
|
||||
'inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2',
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
default:
|
||||
'border-transparent bg-primary text-primary-foreground hover:bg-primary/80',
|
||||
secondary:
|
||||
'border-transparent bg-tertiary text-tertiary-foreground hover:bg-secondary/80',
|
||||
destructive:
|
||||
'border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80',
|
||||
outline: 'text-foreground',
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
variant: 'default',
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
export interface BadgeProps
|
||||
extends React.HTMLAttributes<HTMLDivElement>,
|
||||
VariantProps<typeof badgeVariants> {}
|
||||
|
||||
function Badge({ className, variant, ...props }: BadgeProps) {
|
||||
return <div className={cn(badgeVariants({ variant }), className)} {...props} />
|
||||
}
|
||||
|
||||
export { Badge, badgeVariants }
|
||||
@@ -1,11 +1,36 @@
|
||||
const projectsData = [
|
||||
{
|
||||
title: 'enscribe.dev',
|
||||
tags: ['Web Development', 'Next.js', 'TypeScript', 'Tailwind'],
|
||||
description:
|
||||
'Built with Next.js, TypeScript, Tailwind CSS, and deployed through Vercel, this bleeding-edge website is both an information security blog and a personal website for my cybersecurity shenanigans and web development ramblings.',
|
||||
imgSrc: '/static/images/twitter-card.png',
|
||||
href: 'https://github.com/jktrn/enscribe.dev/',
|
||||
},
|
||||
{
|
||||
title: 'Azusawa’s Gacha World',
|
||||
tags: ['Game Development', 'Unity', 'C#', 'Reverse Engineering', 'CTF'],
|
||||
description:
|
||||
'A fully functional gacha system themed around the popular mobile rhythm game “Project Sekai”, this Unity game was designed to be a reverse-engineering/game-hacking challenge for the SekaiCTF 2023 capture-the-flag competition.',
|
||||
imgSrc: '/static/images/sekaictf-2023/banner-no-text.png',
|
||||
href: 'https://github.com/jktrn/azusawas-gacha-world',
|
||||
},
|
||||
{
|
||||
title: 'Screenshot Impact',
|
||||
tags: ['Web Development', 'Next.js', 'Python', 'BeautifulSoup', 'Selenium'],
|
||||
description:
|
||||
'A WIP Next.js webapp which facilitates calculating, theorycrafting, and optimizing character builds in Genshin Impact. Includes a fleshed-out public API for data scraped from Honey Impact!',
|
||||
imgSrc: '/static/images/misc/screenshot-impact.png',
|
||||
href: 'https://github.com/jktrn/screenshot-impact',
|
||||
},
|
||||
{
|
||||
title: 'next.wanderer.moe',
|
||||
tags: ['Web Development', 'Next.js', 'TypeScript', 'Tailwind'],
|
||||
description:
|
||||
'Currently contributing frontend work for wanderer.moe, a centralized database of over 10,000 game assets and references——soon to support authentication and user-generated content!',
|
||||
imgSrc: '/static/images/misc/wanderer-moe.png',
|
||||
href: 'https://github.com/wanderer-moe/site/tree/next',
|
||||
},
|
||||
]
|
||||
|
||||
export default projectsData
|
||||
|
||||
BIN
public/static/images/misc/screenshot-impact.png
Normal file
BIN
public/static/images/misc/screenshot-impact.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 256 KiB |
BIN
public/static/images/misc/wanderer-moe.png
Normal file
BIN
public/static/images/misc/wanderer-moe.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 183 KiB |
BIN
public/static/images/sekaictf-2023/banner-no-text.png
Normal file
BIN
public/static/images/sekaictf-2023/banner-no-text.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 316 KiB |
Reference in New Issue
Block a user