This commit is contained in:
@@ -24,6 +24,8 @@ export default function ConnectPage() {
|
|||||||
width={128}
|
width={128}
|
||||||
height={128}
|
height={128}
|
||||||
className="rounded-full border shadow-sm"
|
className="rounded-full border shadow-sm"
|
||||||
|
sizes="128px"
|
||||||
|
priority
|
||||||
/>
|
/>
|
||||||
</BlurFade>
|
</BlurFade>
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ export default function Page() {
|
|||||||
<div className="flex flex-col items-center gap-y-2">
|
<div className="flex flex-col items-center gap-y-2">
|
||||||
<BlurFade delay={BLUR_FADE_DELAY}>
|
<BlurFade delay={BLUR_FADE_DELAY}>
|
||||||
<Avatar className="size-28 border">
|
<Avatar className="size-28 border">
|
||||||
<AvatarImage alt={DATA.name} src={DATA.avatarUrl} />
|
<AvatarImage alt={DATA.name} src={DATA.avatarUrl} fetchPriority="high" />
|
||||||
<AvatarFallback>{DATA.initials}</AvatarFallback>
|
<AvatarFallback>{DATA.initials}</AvatarFallback>
|
||||||
</Avatar>
|
</Avatar>
|
||||||
</BlurFade>
|
</BlurFade>
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ export function ResearchCard({
|
|||||||
src={image}
|
src={image}
|
||||||
alt={title}
|
alt={title}
|
||||||
fill
|
fill
|
||||||
|
sizes="160px"
|
||||||
className="object-cover object-center"
|
className="object-cover object-center"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -69,8 +70,10 @@ export function ResearchCard({
|
|||||||
{venue && <span>•</span>}
|
{venue && <span>•</span>}
|
||||||
<time>{dates}</time>
|
<time>{dates}</time>
|
||||||
</div>
|
</div>
|
||||||
<div className="prose max-w-full text-pretty font-normal text-xs text-foreground dark:prose-invert">
|
<div className="prose max-w-full text-pretty font-sans text-xs text-muted-foreground dark:prose-invert">
|
||||||
<Markdown>{description}</Markdown>
|
<Markdown>
|
||||||
|
{description}
|
||||||
|
</Markdown>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
|
|||||||
@@ -52,6 +52,8 @@ export function Header() {
|
|||||||
width={40}
|
width={40}
|
||||||
height={40}
|
height={40}
|
||||||
className="rounded-full"
|
className="rounded-full"
|
||||||
|
sizes="40px"
|
||||||
|
priority
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ export function ResearchListItem({
|
|||||||
alt={title}
|
alt={title}
|
||||||
width={200}
|
width={200}
|
||||||
height={150}
|
height={150}
|
||||||
|
sizes="120px"
|
||||||
className="max-h-30 h-full w-full object-contain p-2"
|
className="max-h-30 h-full w-full object-contain p-2"
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -15,14 +15,7 @@ interface Props {
|
|||||||
description: string;
|
description: string;
|
||||||
dates: string;
|
dates: string;
|
||||||
tags: readonly string[];
|
tags: readonly string[];
|
||||||
link?: string;
|
|
||||||
image?: string;
|
image?: string;
|
||||||
video?: string;
|
|
||||||
links?: readonly {
|
|
||||||
icon: React.ReactNode;
|
|
||||||
type: string;
|
|
||||||
href: string;
|
|
||||||
}[];
|
|
||||||
className?: string;
|
className?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -32,7 +25,6 @@ export function ExperienceCard({
|
|||||||
description,
|
description,
|
||||||
dates,
|
dates,
|
||||||
image,
|
image,
|
||||||
links,
|
|
||||||
className,
|
className,
|
||||||
}: Props) {
|
}: Props) {
|
||||||
return (
|
return (
|
||||||
@@ -43,7 +35,6 @@ export function ExperienceCard({
|
|||||||
, className
|
, className
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{/* 3. The Card component now has its conflicting shadow removed. */}
|
|
||||||
<Card className="flex flex-row items-center p-4 shadow-none">
|
<Card className="flex flex-row items-center p-4 shadow-none">
|
||||||
<div className="flex-none flex-shrink-0 size-12">
|
<div className="flex-none flex-shrink-0 size-12">
|
||||||
<Avatar className="h-full w-full rounded-md bg-muted-background">
|
<Avatar className="h-full w-full rounded-md bg-muted-background">
|
||||||
@@ -52,6 +43,8 @@ export function ExperienceCard({
|
|||||||
src={image}
|
src={image}
|
||||||
alt={title}
|
alt={title}
|
||||||
className="object-contain"
|
className="object-contain"
|
||||||
|
fetchPriority="low"
|
||||||
|
sizes="48"
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<AvatarFallback>{title[0]}</AvatarFallback>
|
<AvatarFallback>{title[0]}</AvatarFallback>
|
||||||
@@ -63,19 +56,6 @@ export function ExperienceCard({
|
|||||||
<div className="flex items-center justify-between gap-x-2 text-base">
|
<div className="flex items-center justify-between gap-x-2 text-base">
|
||||||
<h3 className="inline-flex items-center justify-center gap-x-2 font-semibold leading-none text-xs sm:text-sm">
|
<h3 className="inline-flex items-center justify-center gap-x-2 font-semibold leading-none text-xs sm:text-sm">
|
||||||
{title}
|
{title}
|
||||||
{links && links.length > 0 && (
|
|
||||||
<span className="inline-flex gap-x-1">
|
|
||||||
{links.map((link, idx) => (
|
|
||||||
<Badge
|
|
||||||
variant="secondary"
|
|
||||||
className="align-middle text-xs"
|
|
||||||
key={idx}
|
|
||||||
>
|
|
||||||
{link.type}
|
|
||||||
</Badge>
|
|
||||||
))}
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
<ChevronRightIcon className="size-4 shrink-0 translate-x-0 transform opacity-0 transition-all duration-300 ease-out group-hover:translate-x-1 group-hover:opacity-100" />
|
<ChevronRightIcon className="size-4 shrink-0 translate-x-0 transform opacity-0 transition-all duration-300 ease-out group-hover:translate-x-1 group-hover:opacity-100" />
|
||||||
</h3>
|
</h3>
|
||||||
<div className="text-xs sm:text-sm tabular-nums text-muted-foreground text-right whitespace-nowrap">
|
<div className="text-xs sm:text-sm tabular-nums text-muted-foreground text-right whitespace-nowrap">
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ export const ModeToggle = React.forwardRef<
|
|||||||
size="icon"
|
size="icon"
|
||||||
className={className}
|
className={className}
|
||||||
ref={ref}
|
ref={ref}
|
||||||
|
aria-label="Toogle theme"
|
||||||
{...props}
|
{...props}
|
||||||
onClick={() => setTheme(theme === "light" ? "dark" : "light")}
|
onClick={() => setTheme(theme === "light" ? "dark" : "light")}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -15,9 +15,9 @@ import Link from "next/link";
|
|||||||
|
|
||||||
export default function Navbar() {
|
export default function Navbar() {
|
||||||
return (
|
return (
|
||||||
<div className="pointer-events-auto fixed inset-x-0 bottom-0 z-30 mx-auto mb-4 flex origin-bottom">
|
<div className="pointer-events-auto fixed inset-x-0 bottom-0 z-30 mx-auto mb-6 flex origin-bottom mt-0">
|
||||||
<div className="pointer-events-auto mx-auto max-w-max">
|
<div className="pointer-events-auto mx-auto max-w-max mt-0">
|
||||||
<Dock direction="middle" className="bg-background backdrop-blur-none border">
|
<Dock direction="middle" className=" shadow-lg bg-background border mt-0">
|
||||||
{DATA.navbar.map((item) => (
|
{DATA.navbar.map((item) => (
|
||||||
<DockIcon key={item.href}>
|
<DockIcon key={item.href}>
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
@@ -28,6 +28,7 @@ export default function Navbar() {
|
|||||||
buttonVariants({ variant: "ghost", size: "icon" }),
|
buttonVariants({ variant: "ghost", size: "icon" }),
|
||||||
"size-12",
|
"size-12",
|
||||||
)}
|
)}
|
||||||
|
aria-label={item.label}
|
||||||
>
|
>
|
||||||
<item.icon className="size-4" />
|
<item.icon className="size-4" />
|
||||||
</Link>
|
</Link>
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ export function ProjectCard({
|
|||||||
loop
|
loop
|
||||||
muted
|
muted
|
||||||
playsInline
|
playsInline
|
||||||
className="pointer-events-none mx-auto max-h-40 h-full object-cover object-top" // needed because random black line at bottom of video
|
className="pointer-events-none mx-auto max-h-40 h-full object-cover object-top"
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{image && (
|
{image && (
|
||||||
@@ -69,6 +69,7 @@ export function ProjectCard({
|
|||||||
alt={title}
|
alt={title}
|
||||||
width={500}
|
width={500}
|
||||||
height={300}
|
height={300}
|
||||||
|
sizes="240"
|
||||||
className="m-auto h-full max-h-40 min-h-40 max-w-60 overflow-hidden object-scale-down object-center place-content-center"
|
className="m-auto h-full max-h-40 min-h-40 max-w-60 overflow-hidden object-scale-down object-center place-content-center"
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ export const ResumeCard = ({
|
|||||||
src={logoUrl}
|
src={logoUrl}
|
||||||
alt={altText}
|
alt={altText}
|
||||||
className="object-contain"
|
className="object-contain"
|
||||||
|
fetchPriority="high"
|
||||||
/>
|
/>
|
||||||
<AvatarFallback>{altText[0]}</AvatarFallback>
|
<AvatarFallback>{altText[0]}</AvatarFallback>
|
||||||
</Avatar>
|
</Avatar>
|
||||||
|
|||||||
14
package.json
14
package.json
@@ -19,10 +19,10 @@
|
|||||||
"class-variance-authority": "^0.7.1",
|
"class-variance-authority": "^0.7.1",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"gray-matter": "^4.0.3",
|
"gray-matter": "^4.0.3",
|
||||||
"lucide-react": "^0.543.0",
|
"lucide-react": "^0.544.0",
|
||||||
"mdx-bundler": "^10.1.1",
|
"mdx-bundler": "^10.1.1",
|
||||||
"motion": "^12.23.12",
|
"motion": "^12.23.14",
|
||||||
"next": "15.5.2",
|
"next": "15.5.3",
|
||||||
"next-themes": "^0.4.6",
|
"next-themes": "^0.4.6",
|
||||||
"react": "19.1.1",
|
"react": "19.1.1",
|
||||||
"react-dom": "19.1.1",
|
"react-dom": "19.1.1",
|
||||||
@@ -44,17 +44,17 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/eslintrc": "^3.3.1",
|
"@eslint/eslintrc": "^3.3.1",
|
||||||
"@tailwindcss/postcss": "^4.1.13",
|
"@tailwindcss/postcss": "^4.1.13",
|
||||||
"@types/node": "^24.3.1",
|
"@types/node": "^24.5.2",
|
||||||
"@types/react": "^19.1.12",
|
"@types/react": "^19.1.13",
|
||||||
"@types/react-dom": "^19.1.9",
|
"@types/react-dom": "^19.1.9",
|
||||||
"eslint": "^9.35.0",
|
"eslint": "^9.35.0",
|
||||||
"eslint-config-next": "15.5.2",
|
"eslint-config-next": "15.5.3",
|
||||||
"tailwindcss": "^4.1.13",
|
"tailwindcss": "^4.1.13",
|
||||||
"tw-animate-css": "^1.3.8",
|
"tw-animate-css": "^1.3.8",
|
||||||
"typescript": "^5.9.2"
|
"typescript": "^5.9.2"
|
||||||
},
|
},
|
||||||
"pnpm": {
|
"pnpm": {
|
||||||
"trustedDependencies": [
|
"onlyBuiltDependencies": [
|
||||||
"@tailwindcss/oxide",
|
"@tailwindcss/oxide",
|
||||||
"esbuild",
|
"esbuild",
|
||||||
"sharp",
|
"sharp",
|
||||||
|
|||||||
806
pnpm-lock.yaml
generated
806
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user