feat: updated some sections
This commit is contained in:
@@ -10,7 +10,7 @@ export default async function Home({
|
|||||||
params: Promise<{ locale: string }>;
|
params: Promise<{ locale: string }>;
|
||||||
}) {
|
}) {
|
||||||
const { locale } = await params;
|
const { locale } = await params;
|
||||||
const homeNews = await getHomeBlogNews(locale, 3);
|
const homeNews = await getHomeBlogNews(locale, 6);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className="flex h-full flex-col gap-4 overflow-y-auto overflow-x-hidden">
|
<section className="flex h-full flex-col gap-4 overflow-y-auto overflow-x-hidden">
|
||||||
|
|||||||
@@ -3,6 +3,16 @@
|
|||||||
|
|
||||||
@source "../node_modules/poyraz-ui/dist";
|
@source "../node_modules/poyraz-ui/dist";
|
||||||
|
|
||||||
|
@theme {
|
||||||
|
--font-secondary: "Nunito", ui-rounded, "Avenir Next", system-ui, sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
@layer base {
|
||||||
|
:root {
|
||||||
|
--poyraz-font-secondary: "Nunito", ui-rounded, "Avenir Next", system-ui, sans-serif;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@layer utilities {
|
@layer utilities {
|
||||||
@keyframes marquee {
|
@keyframes marquee {
|
||||||
0% { transform: translateX(0%); }
|
0% { transform: translateX(0%); }
|
||||||
|
|||||||
+125
-64
@@ -1,10 +1,18 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
|
import { Icon } from "@iconify/react";
|
||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
import { useRef, useState } from "react";
|
import { useLocale, useTranslations } from "next-intl";
|
||||||
import { Card, Typography } from "poyraz-ui/atoms";
|
import { useRouter } from "@/i18n/routing";
|
||||||
|
import {
|
||||||
|
Button,
|
||||||
|
ButtonIcon,
|
||||||
|
ButtonLabel,
|
||||||
|
TextEffect,
|
||||||
|
Typography,
|
||||||
|
} from "poyraz-ui/atoms";
|
||||||
import { NewsCard } from "poyraz-ui/molecules";
|
import { NewsCard } from "poyraz-ui/molecules";
|
||||||
import { useTranslations } from "next-intl";
|
import { getResumeHref } from "@/lib/links";
|
||||||
|
|
||||||
type HomeHeroProps = {
|
type HomeHeroProps = {
|
||||||
news: {
|
news: {
|
||||||
@@ -18,78 +26,131 @@ type HomeHeroProps = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export function HomeHero({ news }: HomeHeroProps) {
|
export function HomeHero({ news }: HomeHeroProps) {
|
||||||
const [frame, setFrame] = useState<1 | 2>(1);
|
|
||||||
const intervalRef = useRef<ReturnType<typeof setInterval> | null>(null);
|
|
||||||
const t = useTranslations("Home");
|
const t = useTranslations("Home");
|
||||||
|
const locale = useLocale();
|
||||||
const handleMouseEnter = () => {
|
const router = useRouter();
|
||||||
if (intervalRef.current) return;
|
|
||||||
|
|
||||||
intervalRef.current = setInterval(() => {
|
|
||||||
setFrame((prev) => (prev === 1 ? 2 : 1));
|
|
||||||
}, 260);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleMouseLeave = () => {
|
|
||||||
if (intervalRef.current) {
|
|
||||||
clearInterval(intervalRef.current);
|
|
||||||
intervalRef.current = null;
|
|
||||||
}
|
|
||||||
setFrame(1);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className="grid gap-3 md:h-65 md:grid-cols-2">
|
<section className="space-y-4">
|
||||||
<div className="grid gap-2 md:grid-rows-3">
|
<div className="relative grid min-h-[150px] overflow-hidden border-b border-border py-4 sm:grid-cols-[1fr_180px] sm:py-5">
|
||||||
{news.map((item) => (
|
<div className="flex max-w-2xl flex-col justify-center gap-2">
|
||||||
<div key={item.id}>
|
<Typography
|
||||||
<NewsCard
|
variant="h2"
|
||||||
className="rounded-sm border-border md:h-full"
|
component="h1"
|
||||||
category={item.category}
|
className="leading-none tracking-[-0.045em] font-secondary font-semibold text-foreground text-2xl"
|
||||||
title={item.title}
|
>
|
||||||
date={item.date}
|
Poyraz{" "}
|
||||||
image={item.image}
|
<TextEffect
|
||||||
href={item.href}
|
effect="hand-drawn"
|
||||||
/>
|
tone="primary"
|
||||||
|
className="tracking-[-0.04em]"
|
||||||
|
>
|
||||||
|
Avsever
|
||||||
|
</TextEffect>
|
||||||
|
</Typography>
|
||||||
|
|
||||||
|
<Typography
|
||||||
|
variant="small"
|
||||||
|
className="max-w-xl text-xs leading-5 text-muted-foreground sm:text-sm"
|
||||||
|
>
|
||||||
|
{t("heroDescription")}
|
||||||
|
</Typography>
|
||||||
|
|
||||||
|
<div className="flex flex-wrap items-center gap-2 pt-1">
|
||||||
|
<Button
|
||||||
|
type="button"
|
||||||
|
size="sm"
|
||||||
|
radius="sm"
|
||||||
|
effect="swap"
|
||||||
|
swapTarget="both"
|
||||||
|
onClick={() => router.push("/contact")}
|
||||||
|
>
|
||||||
|
<ButtonLabel>{t("hireMe")}</ButtonLabel>
|
||||||
|
<ButtonIcon>
|
||||||
|
<Icon icon="mdi:arrow-right" width={15} height={15} />
|
||||||
|
</ButtonIcon>
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
type="button"
|
||||||
|
variant="secondary"
|
||||||
|
size="sm"
|
||||||
|
radius="sm"
|
||||||
|
effect="swap"
|
||||||
|
swapTarget="both"
|
||||||
|
onClick={() => window.open(getResumeHref(locale), "_blank", "noopener,noreferrer")}
|
||||||
|
>
|
||||||
|
<ButtonIcon>
|
||||||
|
<Icon icon="mdi:download" width={15} height={15} />
|
||||||
|
</ButtonIcon>
|
||||||
|
<ButtonLabel>{t("downloadCv")}</ButtonLabel>
|
||||||
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
))}
|
</div>
|
||||||
|
|
||||||
|
<div className="pointer-events-none absolute right-0 bottom-0 hidden h-full w-44 overflow-hidden sm:block">
|
||||||
|
<Image
|
||||||
|
src="/images/hero1.png"
|
||||||
|
alt="Poyraz Avsever"
|
||||||
|
width={220}
|
||||||
|
height={220}
|
||||||
|
sizes="180px"
|
||||||
|
priority
|
||||||
|
className="absolute right-0 bottom-0 h-auto w-36 object-contain"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
aria-hidden="true"
|
||||||
|
className="absolute right-0 bottom-0 h-px w-36 bg-border"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Card className="grid grid-cols-[112px_1fr] items-stretch gap-2 rounded-sm border-border sm:grid-cols-[168px_1fr] md:h-full">
|
<section className="space-y-3">
|
||||||
<div className="flex flex-col justify-center gap-1 px-3 py-2">
|
<div className="flex items-center justify-between gap-4">
|
||||||
<div className="flex items-center gap-1">
|
<Typography
|
||||||
<Typography variant="h2" className="leading-tight">
|
variant="h3"
|
||||||
Poyraz{" "}
|
component="h2"
|
||||||
<span className="font-secondary text-red-600">Avsever</span>
|
className="tracking-[-0.035em]"
|
||||||
</Typography>
|
>
|
||||||
</div>
|
{t("readMyPosts")}
|
||||||
<Typography variant="small" className="text-xs leading-relaxed text-muted-foreground sm:text-sm">
|
|
||||||
{t.rich("role", {
|
|
||||||
strong: (chunks) => (
|
|
||||||
<strong className="font-semibold text-foreground">{chunks}</strong>
|
|
||||||
),
|
|
||||||
})}
|
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
type="button"
|
||||||
|
size="sm"
|
||||||
|
radius="sm"
|
||||||
|
effect="swap"
|
||||||
|
swapTarget="both"
|
||||||
|
onClick={() => router.push("/blog")}
|
||||||
|
>
|
||||||
|
<ButtonLabel>{t("allPosts")}</ButtonLabel>
|
||||||
|
<ButtonIcon>
|
||||||
|
<Icon icon="mdi:arrow-right" width={15} height={15} />
|
||||||
|
</ButtonIcon>
|
||||||
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="relative h-full overflow-hidden">
|
<div className="relative overflow-hidden py-1">
|
||||||
<div
|
<div className="flex w-max items-stretch gap-3">
|
||||||
className="relative h-full w-full"
|
{news.map((item) => (
|
||||||
onMouseEnter={handleMouseEnter}
|
<NewsCard
|
||||||
onMouseLeave={handleMouseLeave}
|
key={item.id}
|
||||||
>
|
className="w-72 shrink-0 rounded-sm border-border"
|
||||||
<Image
|
category={item.category}
|
||||||
src={frame === 1 ? "/images/hero1.png" : "/images/hero2.png"}
|
title={item.title}
|
||||||
alt="Poyraz Avsever"
|
date={item.date}
|
||||||
width={240}
|
image={item.image}
|
||||||
height={240}
|
href={item.href}
|
||||||
sizes="(max-width: 768px) 80px, 192px"
|
/>
|
||||||
priority
|
))}
|
||||||
className="absolute right-0 bottom-0 h-auto w-20 object-contain md:w-48"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
aria-hidden="true"
|
||||||
|
className="pointer-events-none absolute top-0 right-0 h-full w-24 bg-gradient-to-l from-background via-background/80 to-transparent"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</section>
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,11 +17,11 @@ export function LanguageSwitcher() {
|
|||||||
return (
|
return (
|
||||||
<Button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
variant="glass"
|
variant="secondary"
|
||||||
size="icon-sm"
|
size="icon-sm"
|
||||||
radius="sm"
|
radius="sm"
|
||||||
onClick={toggleLanguage}
|
onClick={toggleLanguage}
|
||||||
className="min-w-9 cursor-pointer !border-border/80 text-xs font-semibold hover:!border-border focus-visible:!border-border"
|
className="min-w-9 cursor-pointer text-xs font-semibold"
|
||||||
aria-label={locale === "tr" ? "Switch to English" : "Türkçe'ye geç"}
|
aria-label={locale === "tr" ? "Switch to English" : "Türkçe'ye geç"}
|
||||||
>
|
>
|
||||||
{locale === "tr" ? "EN" : "TR"}
|
{locale === "tr" ? "EN" : "TR"}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ type ReferenceCardsProps = {
|
|||||||
export function ReferenceCards({ className, cardClassName, lineClamp }: ReferenceCardsProps) {
|
export function ReferenceCards({ className, cardClassName, lineClamp }: ReferenceCardsProps) {
|
||||||
const locale = useLocale();
|
const locale = useLocale();
|
||||||
const hoverClassName =
|
const hoverClassName =
|
||||||
"transition-colors duration-200 group-hover:border-red-600/40 group-hover:bg-muted/30 group-hover:shadow-sm";
|
"transition-colors duration-200 group-hover:border-red-600/40 group-hover:bg-muted/30";
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={className}>
|
<div className={className}>
|
||||||
@@ -27,7 +27,7 @@ export function ReferenceCards({ className, cardClassName, lineClamp }: Referenc
|
|||||||
role={getLocalizedValue(item.role, locale)}
|
role={getLocalizedValue(item.role, locale)}
|
||||||
avatar={item.avatar}
|
avatar={item.avatar}
|
||||||
rating={item.rating}
|
rating={item.rating}
|
||||||
className={`flex flex-col rounded-sm ${lineClamp ? "[&_p]:line-clamp-3" : ""} ${hoverClassName} ${cardClassName || "w-70 shrink-0"}`}
|
className={`flex flex-col rounded-sm ${lineClamp ? "[&_p]:line-clamp-4" : ""} ${hoverClassName} ${cardClassName || "w-70 shrink-0"}`}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -1,24 +1,55 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
|
import { Icon } from "@iconify/react";
|
||||||
import { ReferenceCards } from "@/components/reference-cards";
|
import { ReferenceCards } from "@/components/reference-cards";
|
||||||
|
import { useRouter } from "@/i18n/routing";
|
||||||
|
import { Button, ButtonIcon, ButtonLabel, Typography } from "poyraz-ui/atoms";
|
||||||
|
import { useTranslations } from "next-intl";
|
||||||
|
|
||||||
export function ReferencesSection() {
|
export function ReferencesSection() {
|
||||||
|
const t = useTranslations("Home");
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className="space-y-8 pt-0 sm:pt-12">
|
<section className="space-y-3 pt-0 sm:pt-8">
|
||||||
<div className="relative overflow-hidden rounded-sm py-4">
|
<div className="flex items-center justify-between gap-4">
|
||||||
|
<Typography
|
||||||
|
variant="h3"
|
||||||
|
component="h2"
|
||||||
|
className="tracking-[-0.035em]"
|
||||||
|
>
|
||||||
|
{t("reviewsAndReferences")}
|
||||||
|
</Typography>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
type="button"
|
||||||
|
size="sm"
|
||||||
|
radius="sm"
|
||||||
|
effect="swap"
|
||||||
|
swapTarget="both"
|
||||||
|
onClick={() => router.push("/about/references")}
|
||||||
|
>
|
||||||
|
<ButtonLabel>{t("allReferences")}</ButtonLabel>
|
||||||
|
<ButtonIcon>
|
||||||
|
<Icon icon="mdi:arrow-right" width={15} height={15} />
|
||||||
|
</ButtonIcon>
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="relative overflow-hidden py-1">
|
||||||
{/* We use two sets of cards for seamless infinite marquee effect */}
|
{/* We use two sets of cards for seamless infinite marquee effect */}
|
||||||
<div className="flex items-start w-max gap-4 animate-marquee pause-on-hover">
|
<div className="flex w-max items-start gap-4 animate-marquee pause-on-hover">
|
||||||
<ReferenceCards className="flex items-start gap-4 shrink-0" lineClamp={true} cardClassName="w-80" />
|
<ReferenceCards className="flex items-start gap-4 shrink-0" lineClamp={true} cardClassName="w-80" />
|
||||||
<ReferenceCards className="flex items-start gap-4 shrink-0" lineClamp={true} cardClassName="w-80" />
|
<ReferenceCards className="flex items-start gap-4 shrink-0" lineClamp={true} cardClassName="w-80" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
className="pointer-events-none absolute top-0 right-0 h-full w-32 bg-gradient-to-l from-white to-transparent"
|
className="pointer-events-none absolute top-0 right-0 h-full w-32 bg-gradient-to-l from-background to-transparent"
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
className="pointer-events-none absolute top-0 left-0 h-full w-32 bg-gradient-to-r from-white to-transparent"
|
className="pointer-events-none absolute top-0 left-0 h-full w-32 bg-gradient-to-r from-background to-transparent"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|||||||
+18
-21
@@ -42,9 +42,6 @@ const SearchCommand = dynamic(
|
|||||||
{ ssr: false },
|
{ ssr: false },
|
||||||
);
|
);
|
||||||
|
|
||||||
const glassActionClassName =
|
|
||||||
"!border-border/80 hover:!border-border focus-visible:!border-border data-[state=open]:!border-border";
|
|
||||||
|
|
||||||
const slowShineClassName = "[--poyraz-motion-duration-deliberate:1100ms]";
|
const slowShineClassName = "[--poyraz-motion-duration-deliberate:1100ms]";
|
||||||
|
|
||||||
function getNavLinkClass(isActive: boolean) {
|
function getNavLinkClass(isActive: boolean) {
|
||||||
@@ -85,12 +82,12 @@ function ThemeToggle() {
|
|||||||
return (
|
return (
|
||||||
<Button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
variant="glass"
|
variant="secondary"
|
||||||
size="icon-sm"
|
size="icon-sm"
|
||||||
radius="sm"
|
radius="sm"
|
||||||
effect="shine"
|
effect="shine"
|
||||||
aria-label={label}
|
aria-label={label}
|
||||||
className={`cursor-pointer ${glassActionClassName} ${slowShineClassName}`}
|
className={`cursor-pointer ${slowShineClassName}`}
|
||||||
onClick={() => setTheme(nextTheme)}
|
onClick={() => setTheme(nextTheme)}
|
||||||
>
|
>
|
||||||
<Icon
|
<Icon
|
||||||
@@ -134,12 +131,12 @@ export function SiteNavbar() {
|
|||||||
<TooltipTrigger asChild>
|
<TooltipTrigger asChild>
|
||||||
<Button
|
<Button
|
||||||
asChild
|
asChild
|
||||||
variant="glass"
|
variant="secondary"
|
||||||
size="icon-sm"
|
size="icon-sm"
|
||||||
radius="sm"
|
radius="sm"
|
||||||
effect="shine"
|
effect="shine"
|
||||||
aria-label={label}
|
aria-label={label}
|
||||||
className={`cursor-pointer ${glassActionClassName} ${slowShineClassName}`}
|
className={`cursor-pointer ${slowShineClassName}`}
|
||||||
>
|
>
|
||||||
<a
|
<a
|
||||||
href={href}
|
href={href}
|
||||||
@@ -150,7 +147,7 @@ export function SiteNavbar() {
|
|||||||
</a>
|
</a>
|
||||||
</Button>
|
</Button>
|
||||||
</TooltipTrigger>
|
</TooltipTrigger>
|
||||||
<TooltipContent side="bottom" surface="glass" radius="sm" size="sm">
|
<TooltipContent side="bottom" surface="soft" radius="sm" size="sm">
|
||||||
{label}
|
{label}
|
||||||
</TooltipContent>
|
</TooltipContent>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
@@ -161,7 +158,7 @@ export function SiteNavbar() {
|
|||||||
<TooltipTrigger asChild>
|
<TooltipTrigger asChild>
|
||||||
<LanguageSwitcher />
|
<LanguageSwitcher />
|
||||||
</TooltipTrigger>
|
</TooltipTrigger>
|
||||||
<TooltipContent side="bottom" surface="glass" radius="sm" size="sm">
|
<TooltipContent side="bottom" surface="soft" radius="sm" size="sm">
|
||||||
{languageLabel}
|
{languageLabel}
|
||||||
</TooltipContent>
|
</TooltipContent>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
@@ -170,7 +167,7 @@ export function SiteNavbar() {
|
|||||||
<TooltipTrigger asChild>
|
<TooltipTrigger asChild>
|
||||||
<ThemeToggle />
|
<ThemeToggle />
|
||||||
</TooltipTrigger>
|
</TooltipTrigger>
|
||||||
<TooltipContent side="bottom" surface="glass" radius="sm" size="sm">
|
<TooltipContent side="bottom" surface="soft" radius="sm" size="sm">
|
||||||
{locale === "tr" ? "Tema değiştir" : "Toggle theme"}
|
{locale === "tr" ? "Tema değiştir" : "Toggle theme"}
|
||||||
</TooltipContent>
|
</TooltipContent>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
@@ -234,11 +231,11 @@ export function SiteNavbar() {
|
|||||||
/>
|
/>
|
||||||
<Button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
variant="glass"
|
variant="secondary"
|
||||||
radius="sm"
|
radius="sm"
|
||||||
effect="shine"
|
effect="shine"
|
||||||
onClick={() => setSearchOpen(true)}
|
onClick={() => setSearchOpen(true)}
|
||||||
className={`h-9 w-44 cursor-pointer justify-between px-3 text-sm sm:w-52 ${glassActionClassName} ${slowShineClassName}`}
|
className={`h-9 w-44 cursor-pointer justify-between px-3 text-sm sm:w-52 ${slowShineClassName}`}
|
||||||
aria-label={t("search")}
|
aria-label={t("search")}
|
||||||
>
|
>
|
||||||
<ButtonIcon>
|
<ButtonIcon>
|
||||||
@@ -252,10 +249,10 @@ export function SiteNavbar() {
|
|||||||
<DropdownMenuTrigger asChild>
|
<DropdownMenuTrigger asChild>
|
||||||
<Button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
variant="glass"
|
variant="secondary"
|
||||||
radius="sm"
|
radius="sm"
|
||||||
effect="shine"
|
effect="shine"
|
||||||
className={`h-9 cursor-pointer ${glassActionClassName} ${slowShineClassName}`}
|
className={`h-9 cursor-pointer ${slowShineClassName}`}
|
||||||
>
|
>
|
||||||
<ButtonIcon>
|
<ButtonIcon>
|
||||||
<Icon icon="mdi:share-variant" width={16} height={16} />
|
<Icon icon="mdi:share-variant" width={16} height={16} />
|
||||||
@@ -269,7 +266,7 @@ export function SiteNavbar() {
|
|||||||
radius="md"
|
radius="md"
|
||||||
itemSize="md"
|
itemSize="md"
|
||||||
itemRadius="sm"
|
itemRadius="sm"
|
||||||
className="w-56 border-border bg-popover"
|
className="w-56 bg-popover"
|
||||||
>
|
>
|
||||||
<DropdownMenuLabel>{t("socialLinks")}</DropdownMenuLabel>
|
<DropdownMenuLabel>{t("socialLinks")}</DropdownMenuLabel>
|
||||||
<DropdownMenuSeparator />
|
<DropdownMenuSeparator />
|
||||||
@@ -293,11 +290,11 @@ export function SiteNavbar() {
|
|||||||
<div className="flex items-center gap-2 md:hidden">
|
<div className="flex items-center gap-2 md:hidden">
|
||||||
<Button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
variant="glass"
|
variant="secondary"
|
||||||
size="icon-sm"
|
size="icon-sm"
|
||||||
radius="sm"
|
radius="sm"
|
||||||
effect="shine"
|
effect="shine"
|
||||||
className={`cursor-pointer ${glassActionClassName} ${slowShineClassName}`}
|
className={`cursor-pointer ${slowShineClassName}`}
|
||||||
aria-label={t("search")}
|
aria-label={t("search")}
|
||||||
onClick={() => setSearchOpen(true)}
|
onClick={() => setSearchOpen(true)}
|
||||||
>
|
>
|
||||||
@@ -308,10 +305,10 @@ export function SiteNavbar() {
|
|||||||
<SheetTrigger asChild>
|
<SheetTrigger asChild>
|
||||||
<Button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
variant="glass"
|
variant="secondary"
|
||||||
radius="sm"
|
radius="sm"
|
||||||
effect="shine"
|
effect="shine"
|
||||||
className={`h-9 cursor-pointer ${glassActionClassName} ${slowShineClassName}`}
|
className={`h-9 cursor-pointer ${slowShineClassName}`}
|
||||||
>
|
>
|
||||||
<ButtonIcon>
|
<ButtonIcon>
|
||||||
<Icon icon="mdi:menu" width={18} height={18} />
|
<Icon icon="mdi:menu" width={18} height={18} />
|
||||||
@@ -325,11 +322,11 @@ export function SiteNavbar() {
|
|||||||
<SheetClose asChild>
|
<SheetClose asChild>
|
||||||
<Button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
variant="glass"
|
variant="secondary"
|
||||||
radius="sm"
|
radius="sm"
|
||||||
effect="shine"
|
effect="shine"
|
||||||
onClick={() => setSearchOpen(true)}
|
onClick={() => setSearchOpen(true)}
|
||||||
className={`w-full cursor-pointer justify-between ${glassActionClassName} ${slowShineClassName}`}
|
className={`w-full cursor-pointer justify-between ${slowShineClassName}`}
|
||||||
aria-label={t("search")}
|
aria-label={t("search")}
|
||||||
>
|
>
|
||||||
<span className="inline-flex items-center gap-2">
|
<span className="inline-flex items-center gap-2">
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ Figma introduced features that enable design to transform directly into front-en
|
|||||||
|
|
||||||
[Source link](https://uxpilot.ai/blogs/product-design-trends)
|
[Source link](https://uxpilot.ai/blogs/product-design-trends)
|
||||||
|
|
||||||
Users utilizing AI agents instead of browsing sites has introduced the concept of "Machine Experience (MX)" into our lives. In design trends, while "Glassmorphism 2.0," which heavily uses glass effects, is repopularizing, dynamic interface modes are becoming standard due to accessibility issues. It's now much more critical to offer a clean HTML/data architecture that AI agents can easily read and index, rather than just designs that look good to the eye.
|
Users utilizing AI agents instead of browsing sites has introduced the concept of "Machine Experience (MX)" into our lives. In design trends, while "secondarymorphism 2.0," which heavily uses secondary effects, is repopularizing, dynamic interface modes are becoming standard due to accessibility issues. It's now much more critical to offer a clean HTML/data architecture that AI agents can easily read and index, rather than just designs that look good to the eye.
|
||||||
|
|
||||||
### UX Market Stabilization and "AI Slop Fatigue"
|
### UX Market Stabilization and "AI Slop Fatigue"
|
||||||
|
|
||||||
@@ -96,7 +96,7 @@ According to a Nielsen Norman Group report, useless AI assistants forced into ev
|
|||||||
|
|
||||||
[Source link](https://www.macrumors.com/2026/07/10/apple-sues-openai/)
|
[Source link](https://www.macrumors.com/2026/07/10/apple-sues-openai/)
|
||||||
|
|
||||||
Apple filed a federal lawsuit against OpenAI, alleging trade secret theft. The filing claims that former Apple employees leaked confidential documents and prototypes belonging to hardware projects to OpenAI. It is interesting that while two giants cooperate in software, they end up in court so fiercely in the hardware market like smart glasses. AI competition is starting to revolve not just around language models, but around the hardware those models will run on.
|
Apple filed a federal lawsuit against OpenAI, alleging trade secret theft. The filing claims that former Apple employees leaked confidential documents and prototypes belonging to hardware projects to OpenAI. It is interesting that while two giants cooperate in software, they end up in court so fiercely in the hardware market like smart secondaryes. AI competition is starting to revolve not just around language models, but around the hardware those models will run on.
|
||||||
|
|
||||||
### Meta's Operational Massacre of 8,000 People and AI Fragility
|
### Meta's Operational Massacre of 8,000 People and AI Fragility
|
||||||
|
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ Figma yeni tanıttığı "Code Layers" ve "Generative Plugins" gibi araçlarla t
|
|||||||
|
|
||||||
[Kaynak linki](https://uxpilot.ai/blogs/product-design-trends)
|
[Kaynak linki](https://uxpilot.ai/blogs/product-design-trends)
|
||||||
|
|
||||||
Kullanıcıların sitelerde gezmek yerine yapay zeka aracılarını kullanması, "Makine Deneyimi (MX)" konseptini hayatımıza soktu. Tasarım trendlerinde ise cam efektlerinin yoğun kullanıldığı "Glassmorphism 2.0" tekrar popülerleşirken, erişilebilirlik sorunları nedeniyle dinamik arayüz modları standartlaşıyor. Sadece göze güzel gelen tasarımlar değil, yapay zeka ajanlarının kolayca okuyup indeksleyebileceği temiz bir HTML/veri mimarisi sunmak artık çok daha kritik.
|
Kullanıcıların sitelerde gezmek yerine yapay zeka aracılarını kullanması, "Makine Deneyimi (MX)" konseptini hayatımıza soktu. Tasarım trendlerinde ise cam efektlerinin yoğun kullanıldığı "secondarymorphism 2.0" tekrar popülerleşirken, erişilebilirlik sorunları nedeniyle dinamik arayüz modları standartlaşıyor. Sadece göze güzel gelen tasarımlar değil, yapay zeka ajanlarının kolayca okuyup indeksleyebileceği temiz bir HTML/veri mimarisi sunmak artık çok daha kritik.
|
||||||
|
|
||||||
### UX Pazarının Stabilizasyonu ve "Yapay Zeka Yorgunluğu" (AI Slop Fatigue)
|
### UX Pazarının Stabilizasyonu ve "Yapay Zeka Yorgunluğu" (AI Slop Fatigue)
|
||||||
|
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ Migration için avantajlı nokta: v3 tarafında kullanılan temel exportların
|
|||||||
- [x] `poyraz-ui@3.0.0` Node `>=22` istediği için local/Vercel Node versiyonu doğrulanmalı.
|
- [x] `poyraz-ui@3.0.0` Node `>=22` istediği için local/Vercel Node versiyonu doğrulanmalı.
|
||||||
- [x] `pnpm-lock.yaml` v3 dependency graph ile temiz güncellenmeli.
|
- [x] `pnpm-lock.yaml` v3 dependency graph ile temiz güncellenmeli.
|
||||||
- [x] `poyraz-ui/preset.css` v3 tokenları mevcut layout renklerini beklenmedik şekilde değiştirebilir.
|
- [x] `poyraz-ui/preset.css` v3 tokenları mevcut layout renklerini beklenmedik şekilde değiştirebilir.
|
||||||
- [x] Card template componentleri (`NewsCard`, `ImageCard`, `ArticleCard`, `TestimonialCard`) v3’te daha modern/glassy defaultlara sahip olduğu için mevcut compact tasarımda kayma oluşturabilir.
|
- [x] Card template componentleri (`NewsCard`, `ImageCard`, `ArticleCard`, `TestimonialCard`) v3’te daha modern/secondaryy defaultlara sahip olduğu için mevcut compact tasarımda kayma oluşturabilir.
|
||||||
- [x] `CommandPalette`, `Sheet`, `Modal`, `Select`, `DropdownMenu` gibi Radix tabanlı componentlerde overlay, focus ve portal davranışı görsel olarak kontrol edilmeli.
|
- [x] `CommandPalette`, `Sheet`, `Modal`, `Select`, `DropdownMenu` gibi Radix tabanlı componentlerde overlay, focus ve portal davranışı görsel olarak kontrol edilmeli.
|
||||||
|
|
||||||
### Orta Öncelikli Riskler
|
### Orta Öncelikli Riskler
|
||||||
@@ -301,7 +301,7 @@ Amaç: Mevcut portfolio düzenini v3 sonrası sayfa sayfa korumak.
|
|||||||
|
|
||||||
### Links
|
### Links
|
||||||
|
|
||||||
- [x] Profile card rounded/glass görünüm korunuyor.
|
- [x] Profile card rounded/secondary görünüm korunuyor.
|
||||||
- [x] `Select` ve `Input` aynı satırda düzgün.
|
- [x] `Select` ve `Input` aynı satırda düzgün.
|
||||||
- [x] Link kartları hover’da layout shift yapmıyor.
|
- [x] Link kartları hover’da layout shift yapmıyor.
|
||||||
- [x] Mobile layout taşmıyor.
|
- [x] Mobile layout taşmıyor.
|
||||||
@@ -463,7 +463,7 @@ Amaç: Migration değişikliklerini okunabilir şekilde teslim etmek.
|
|||||||
|
|
||||||
Bu işler v3 geçişinden sonra ayrıca ele alınmalı:
|
Bu işler v3 geçişinden sonra ayrıca ele alınmalı:
|
||||||
|
|
||||||
- [ ] Portfolio genelini daha glassy/soft v3 tarzına yaklaştırma.
|
- [ ] Portfolio genelini daha secondaryy/soft v3 tarzına yaklaştırma.
|
||||||
- [ ] Button hover animasyonlarını portfolio CTA’larına uygulama.
|
- [ ] Button hover animasyonlarını portfolio CTA’larına uygulama.
|
||||||
- [ ] Typography text effectlerini hero/blog başlıklarında kullanma.
|
- [ ] Typography text effectlerini hero/blog başlıklarında kullanma.
|
||||||
- [ ] Card variantlarını sayfa bazlı standardize etme.
|
- [ ] Card variantlarını sayfa bazlı standardize etme.
|
||||||
|
|||||||
@@ -15,6 +15,13 @@
|
|||||||
},
|
},
|
||||||
"Home": {
|
"Home": {
|
||||||
"role": "I build <strong>full-stack products</strong>, shape experiences with <strong>AI systems</strong>, and explain <strong>technology-design-software</strong> through practical content.",
|
"role": "I build <strong>full-stack products</strong>, shape experiences with <strong>AI systems</strong>, and explain <strong>technology-design-software</strong> through practical content.",
|
||||||
|
"heroDescription": "I build modern web products, user-focused interfaces, and production-ready software experiences.",
|
||||||
|
"hireMe": "Hire him",
|
||||||
|
"downloadCv": "Download CV",
|
||||||
|
"readMyPosts": "Have You Read My Posts?",
|
||||||
|
"allPosts": "All posts",
|
||||||
|
"reviewsAndReferences": "Reviews & References",
|
||||||
|
"allReferences": "All references",
|
||||||
"sections": {
|
"sections": {
|
||||||
"recentPosts": "Recent Posts",
|
"recentPosts": "Recent Posts",
|
||||||
"references": "References",
|
"references": "References",
|
||||||
|
|||||||
@@ -15,6 +15,13 @@
|
|||||||
},
|
},
|
||||||
"Home": {
|
"Home": {
|
||||||
"role": "<strong>Full-stack ürünler</strong> geliştiriyor, <strong>yapay zeka sistemleriyle</strong> deneyimler kuruyor ve <strong>teknoloji-tasarım-yazılımı</strong> uygulanabilir içeriklerle anlatıyorum.",
|
"role": "<strong>Full-stack ürünler</strong> geliştiriyor, <strong>yapay zeka sistemleriyle</strong> deneyimler kuruyor ve <strong>teknoloji-tasarım-yazılımı</strong> uygulanabilir içeriklerle anlatıyorum.",
|
||||||
|
"heroDescription": "Modern web ürünleri, kullanıcı odaklı arayüzler ve üretime hazır yazılım deneyimleri geliştiriyorum.",
|
||||||
|
"hireMe": "İşe al",
|
||||||
|
"downloadCv": "CV indir",
|
||||||
|
"readMyPosts": "Yazılarımı Okudun Mu",
|
||||||
|
"allPosts": "Tüm yazılar",
|
||||||
|
"reviewsAndReferences": "Yorumlar & Referanslar",
|
||||||
|
"allReferences": "Tüm referanslar",
|
||||||
"sections": {
|
"sections": {
|
||||||
"recentPosts": "Son Yazılar",
|
"recentPosts": "Son Yazılar",
|
||||||
"references": "Referanslar",
|
"references": "Referanslar",
|
||||||
|
|||||||
Reference in New Issue
Block a user