perf(images): optimize cards and compact logo assets

This commit is contained in:
poyrazavsever
2026-08-31 20:08:04 +03:00
parent 340d504ac8
commit 9d5f347ffb
6 changed files with 70 additions and 21 deletions
+1 -1
View File
@@ -156,7 +156,7 @@ export function BlogContent({ data, section = "blog" }: BlogContentProps) {
readTime={post.readTime} readTime={post.readTime}
href={post.href} href={post.href}
className="rounded-sm border-border [&_h3]:line-clamp-2 [&_h3]:min-h-[2.5rem] [&_p]:line-clamp-3" className="rounded-sm border-border [&_h3]:line-clamp-2 [&_h3]:min-h-[2.5rem] [&_p]:line-clamp-3"
author={{ name: post.author, avatar: "/logo/logo.webp" }} author={{ name: post.author, avatar: "/logo/logo-96.webp" }}
/> />
</StaggerItem> </StaggerItem>
))} ))}
+2 -1
View File
@@ -43,7 +43,7 @@ export function HomeProjectsSection() {
<div className="relative overflow-hidden py-1"> <div className="relative overflow-hidden py-1">
<div className="flex w-max items-stretch gap-2"> <div className="flex w-max items-stretch gap-2">
{projects.map((project) => ( {projects.map((project, index) => (
<ProjectCardWithPopover <ProjectCardWithPopover
key={project.id} key={project.id}
image={project.image} image={project.image}
@@ -61,6 +61,7 @@ export function HomeProjectsSection() {
architectureLabel={tProjects("architecture")} architectureLabel={tProjects("architecture")}
triggerClassName="w-56 shrink-0 md:w-[calc((100vw-8rem)/4)] md:max-w-56" triggerClassName="w-56 shrink-0 md:w-[calc((100vw-8rem)/4)] md:max-w-56"
className="aspect-square rounded-sm border-border" className="aspect-square rounded-sm border-border"
priority={index === 0}
/> />
))} ))}
</div> </div>
+1 -1
View File
@@ -131,7 +131,7 @@ export function LinksContent({
<div className="flex flex-col gap-5 sm:flex-row sm:items-start sm:justify-between"> <div className="flex flex-col gap-5 sm:flex-row sm:items-start sm:justify-between">
<div className="flex min-w-0 items-start gap-4"> <div className="flex min-w-0 items-start gap-4">
<Avatar className="size-16 shrink-0 rounded-sm border border-border bg-background sm:size-20"> <Avatar className="size-16 shrink-0 rounded-sm border border-border bg-background sm:size-20">
<AvatarImage src="/logo/logo.webp" alt="Poyraz Avsever" /> <AvatarImage src="/logo/logo-96.webp" alt="Poyraz Avsever" />
<AvatarFallback className="rounded-sm bg-muted font-semibold"> <AvatarFallback className="rounded-sm bg-muted font-semibold">
PA PA
</AvatarFallback> </AvatarFallback>
+27 -8
View File
@@ -1,10 +1,10 @@
"use client"; "use client";
import { useEffect, useRef, useState } from "react"; import { useEffect, useRef, useState } from "react";
import Image from "next/image";
import { Icon } from "@iconify/react"; import { Icon } from "@iconify/react";
import { Badge, Typography } from "poyraz-ui/atoms"; import { Badge, Card, Typography } from "poyraz-ui/atoms";
import { import {
ImageCard,
Popover, Popover,
PopoverContent, PopoverContent,
PopoverTrigger, PopoverTrigger,
@@ -25,6 +25,7 @@ type ProjectCardWithPopoverProps = {
architectureLabel: string; architectureLabel: string;
className?: string; className?: string;
triggerClassName?: string; triggerClassName?: string;
priority?: boolean;
}; };
export function ProjectCardWithPopover({ export function ProjectCardWithPopover({
@@ -41,6 +42,7 @@ export function ProjectCardWithPopover({
architectureLabel, architectureLabel,
className, className,
triggerClassName, triggerClassName,
priority = false,
}: ProjectCardWithPopoverProps) { }: ProjectCardWithPopoverProps) {
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
const closeTimer = useRef<ReturnType<typeof setTimeout> | null>(null); const closeTimer = useRef<ReturnType<typeof setTimeout> | null>(null);
@@ -69,13 +71,30 @@ export function ProjectCardWithPopover({
}, []); }, []);
const card = ( const card = (
<ImageCard <Card
image={image} variant="interactive"
title={title} className={`group relative aspect-[4/3] overflow-hidden ${className ?? ""}`}
description={description} >
badge={badge} <Image
className={className} src={image}
alt=""
fill
sizes="(max-width: 767px) 224px, 224px"
preload={priority}
fetchPriority={priority ? "high" : "auto"}
className="object-cover transition-transform duration-500 ease-[var(--poyraz-motion-ease-out)] group-hover:scale-105"
/> />
<div className="absolute inset-0 bg-gradient-to-t from-overlay via-overlay/20 to-transparent transition-opacity group-hover:opacity-90" />
{badge ? (
<Badge className="absolute left-3 top-3 z-10">{badge}</Badge>
) : null}
<div className="absolute inset-x-0 bottom-0 z-10 p-4 text-primary-foreground">
<h3 className="font-semibold leading-tight">{title}</h3>
{description ? (
<p className="mt-1 line-clamp-2 text-xs opacity-80">{description}</p>
) : null}
</div>
</Card>
); );
const triggerClasses = `block ${triggerClassName ?? ""} text-inherit outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2`; const triggerClasses = `block ${triggerClassName ?? ""} text-inherit outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2`;
+37 -8
View File
@@ -1,5 +1,7 @@
import { TestimonialCard } from "poyraz-ui/molecules"; import Image from "next/image";
import { Card, CardContent } from "poyraz-ui/atoms";
import { StarRating } from "poyraz-ui/molecules";
import { REFERENCES } from "@/data/references"; import { REFERENCES } from "@/data/references";
import { useLocale } from "next-intl"; import { useLocale } from "next-intl";
import { getLocalizedValue } from "@/lib/locale"; import { getLocalizedValue } from "@/lib/locale";
@@ -27,14 +29,41 @@ export function ReferenceCards({
const quoteText = getLocalizedValue(item.quote, locale); const quoteText = getLocalizedValue(item.quote, locale);
const card = ( const card = (
<TestimonialCard <Card
quote={quoteText} className={`group flex h-full flex-col rounded-sm ${hoverClassName} ${cardClassName || "w-70 shrink-0"}`}
author={item.author} >
role={getLocalizedValue(item.role, locale)} <CardContent className="flex h-full flex-1 flex-col p-5">
avatar={item.avatar} <span className="font-secondary text-4xl leading-none text-primary">
rating={showRating ? item.rating : undefined}
className={`flex flex-col rounded-sm ${lineClamp ? "[&_blockquote]:line-clamp-4" : ""} ${hoverClassName} ${cardClassName || "w-70 shrink-0"}`} </span>
<blockquote
className={`mt-1 text-sm leading-relaxed text-secondary-foreground ${lineClamp ? "line-clamp-4" : ""}`}
>
{quoteText}
</blockquote>
{showRating && item.rating != null ? (
<StarRating rating={item.rating} className="mt-3" />
) : null}
<div className="mt-auto flex items-center gap-3 border-t border-border pt-4">
<Image
src={item.avatar}
alt=""
width={36}
height={36}
sizes="36px"
className="size-9 rounded-full object-cover"
/> />
<div className="min-w-0">
<div className="truncate text-sm font-semibold">
{item.author}
</div>
<div className="truncate text-xs text-muted-foreground">
{getLocalizedValue(item.role, locale)}
</div>
</div>
</div>
</CardContent>
</Card>
); );
const href = item.documentHref || item.profileHref; const href = item.documentHref || item.profileHref;
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB