feat: add pill variant to Tabs component and enhance ProgramTablosu with motion effects
All checks were successful
Deploy / deploy (push) Successful in 7m49s
All checks were successful
Deploy / deploy (push) Successful in 7m49s
Introduced a new "pill" variant for the Tabs component, allowing for a rounded, active tab style that aligns with the design of the "Giriş yap" button. Enhanced the ProgramTablosu component by integrating motion effects for active tab indicators, improving user experience with smooth transitions. Updated color handling for active states to ensure better visibility and consistency across the UI.
This commit is contained in:
@@ -7,6 +7,7 @@
|
||||
|
||||
import { useMemo, useState } from "react";
|
||||
import Link from "next/link";
|
||||
import { motion, useReducedMotion } from "motion/react";
|
||||
import {
|
||||
ChevronDown,
|
||||
Rocket,
|
||||
@@ -43,30 +44,31 @@ import { UniLogo } from "@/components/uni-logo";
|
||||
const DILIMLER: {
|
||||
key: DilimKey;
|
||||
etiket: string;
|
||||
aciklama: string;
|
||||
icon: typeof Rocket;
|
||||
renk: string;
|
||||
// Aktif hap koyu (slate-900) — ikon tonu okunurluk için bir kademe açılır
|
||||
renkAktif: string;
|
||||
}[] = [
|
||||
{
|
||||
key: "hayal",
|
||||
etiket: "Hayal",
|
||||
aciklama: "Tabanı sıralamanın üstünde — şansını denediğin satırlar.",
|
||||
icon: Rocket,
|
||||
renk: "text-red-500",
|
||||
renkAktif: "text-red-400",
|
||||
},
|
||||
{
|
||||
key: "dengeli",
|
||||
etiket: "Dengeli",
|
||||
aciklama: "Tabanı sıralamana denk — listenin bel kemiği.",
|
||||
icon: Scale,
|
||||
renk: "text-amber-500",
|
||||
renkAktif: "text-amber-400",
|
||||
},
|
||||
{
|
||||
key: "garanti",
|
||||
etiket: "Garanti",
|
||||
aciklama: "Tabanı belirgin şekilde altında — güvenli bölge.",
|
||||
icon: ShieldCheck,
|
||||
renk: "text-emerald-600",
|
||||
renkAktif: "text-emerald-400",
|
||||
},
|
||||
];
|
||||
|
||||
@@ -106,6 +108,7 @@ export function ProgramTablosu({
|
||||
const [aktifDilim, setAktifDilim] = useState<DilimKey>(() =>
|
||||
varsayilanDilim(sonuclar),
|
||||
);
|
||||
const hareketAzalt = useReducedMotion();
|
||||
// Sihirbaz seçimlerinden profil çerezine yazılıp SSR'da prop olarak gelen
|
||||
// filtreler — sayfalama isteklerinde ve veri anahtarında kullanılır.
|
||||
const iller = useMemo(() => filtreIller ?? [], [filtreIller]);
|
||||
@@ -180,17 +183,43 @@ export function ProgramTablosu({
|
||||
onValueChange={(v) => setAktifDilim(v as DilimKey)}
|
||||
>
|
||||
{/* Dilim sekmeleri tablonun hemen üstünde; puan türü burada değil,
|
||||
navbar'daki sıralama rozetinden değiştirilir. */}
|
||||
<TabsList>
|
||||
{DILIMLER.map((d) => (
|
||||
<TabsTrigger key={d.key} value={d.key} className="cursor-pointer">
|
||||
<d.icon className={`size-3.5 ${d.renk}`} aria-hidden />
|
||||
{d.etiket}
|
||||
<span className="text-xs tabular-nums text-slate-400">
|
||||
{sonuclar.toplam[d.key].toLocaleString("tr-TR")}
|
||||
</span>
|
||||
</TabsTrigger>
|
||||
))}
|
||||
navbar'daki sıralama rozetinden değiştirilir. Aktif hap, nav'daki
|
||||
"Giriş yap" butonuyla aynı dilde (koyu, rounded-full) ve layoutId
|
||||
ile sekmeler arasında kayarak taşınır. */}
|
||||
<TabsList variant="pill" className="self-center">
|
||||
{DILIMLER.map((d) => {
|
||||
const aktif = aktifDilim === d.key;
|
||||
return (
|
||||
<TabsTrigger
|
||||
key={d.key}
|
||||
value={d.key}
|
||||
className="relative cursor-pointer px-3 py-1.5 transition-colors duration-200 hover:bg-slate-100 sm:px-4 sm:py-2"
|
||||
>
|
||||
{aktif ? (
|
||||
<motion.span
|
||||
layoutId="dilim-aktif-hap"
|
||||
className="absolute inset-0 rounded-full bg-slate-900"
|
||||
transition={
|
||||
hareketAzalt
|
||||
? { duration: 0 }
|
||||
: { type: "spring", duration: 0.4, bounce: 0.15 }
|
||||
}
|
||||
aria-hidden
|
||||
/>
|
||||
) : null}
|
||||
<span className="relative z-10 inline-flex items-center gap-1.5">
|
||||
<d.icon
|
||||
className={`size-3.5 ${aktif ? d.renkAktif : d.renk}`}
|
||||
aria-hidden
|
||||
/>
|
||||
{d.etiket}
|
||||
<span className="text-xs tabular-nums text-slate-400">
|
||||
{sonuclar.toplam[d.key].toLocaleString("tr-TR")}
|
||||
</span>
|
||||
</span>
|
||||
</TabsTrigger>
|
||||
);
|
||||
})}
|
||||
</TabsList>
|
||||
|
||||
{DILIMLER.map((d) => {
|
||||
@@ -198,7 +227,6 @@ export function ProgramTablosu({
|
||||
const toplam = sonuclar.toplam[d.key];
|
||||
return (
|
||||
<TabsContent key={d.key} value={d.key}>
|
||||
<p className="mt-2 text-xs text-slate-500">{d.aciklama}</p>
|
||||
<div className="mt-3 overflow-hidden rounded-2xl border border-slate-200 bg-white">
|
||||
{satirlar.length === 0 ? (
|
||||
<p className="px-5 py-8 text-center text-sm text-slate-500">
|
||||
|
||||
Reference in New Issue
Block a user