v2 #10

Merged
bilal merged 34 commits from v2 into main 2026-10-11 01:38:50 +03:00
2 changed files with 32 additions and 15 deletions
Showing only changes of commit f08a26a022 - Show all commits

View File

@@ -334,16 +334,13 @@ export function TextShimmerLoader({
lg: "text-base", lg: "text-base",
} }
// prompt-kit'in özgün gradyanı `--muted-foreground/--foreground` token'ı ve
// projede tanımsız bir `shimmer` keyframe'i kullanıyordu (hareket etmiyordu).
// Sitenin tek parıltı kaynağı shadcn `shimmer` utility'sidir (currentColor
// üstünden; liste-uretici.tsx ve tercih-degisti-modali.tsx ile aynı), renk
// çağıranın `text-slate-*` sınıfından gelir, karanlık mod token'dan döner.
return ( return (
<div <div className={cn("shimmer font-medium", textSizes[size], className)}>
className={cn(
"bg-[linear-gradient(to_right,var(--muted-foreground)_40%,var(--foreground)_60%,var(--muted-foreground)_80%)]",
"bg-size-[200%_auto] bg-clip-text font-medium text-transparent",
"animate-[shimmer_4s_infinite_linear]",
textSizes[size],
className
)}
>
{text} {text}
</div> </div>
) )

View File

@@ -54,7 +54,7 @@ import {
TooltipProvider, TooltipProvider,
TooltipTrigger, TooltipTrigger,
} from "@/components/ui/tooltip"; } from "@/components/ui/tooltip";
import { DotsLoader } from "@/components/ui/loader"; import { DotsLoader, TextShimmerLoader } from "@/components/ui/loader";
import { Skeleton } from "@/components/ui/skeleton"; import { Skeleton } from "@/components/ui/skeleton";
import { olay } from "@/lib/analitik"; import { olay } from "@/lib/analitik";
import type { ProfilAlani } from "@/lib/danisman-profil"; import type { ProfilAlani } from "@/lib/danisman-profil";
@@ -283,9 +283,10 @@ export function DanismanBaslik() {
/** Danışman mesajlarının avatarı — KolayTercih markası. `canli` iken (cevap /** Danışman mesajlarının avatarı — KolayTercih markası. `canli` iken (cevap
* beklenirken/yazılırken) panel başlığındaki DanışmanlaKonuş işareti gibi * beklenirken/yazılırken) panel başlığındaki DanışmanlaKonuş işareti gibi
* yerinde nabız atar: danışmanın "düşündüğü" avatardan okunur. `aracta` iken * yerinde nabız atar: danışmanın "düşündüğü" avatardan okunur. `aracta` iken
* (danışman veriye bakıyor, "…bakıyorum" hapı dönüyor) kareler sırayla * (danışman veriye bakıyor, "…bakıyorum" hapı dönüyor) kareler site
* birbirinin yerine yürür; araç bitince nabza döner. Her geçişte ve cevap * başlığındaki logoyla aynı "rota" koreografisini oynar (her kare sıradakinin
* bitince kareler yumuşakça yerine oturur. * yerine süzülür; site-header.tsx, animasyonlu-mark.tsx); araç bitince nabza
* döner. Her geçişte ve cevap bitince kareler yumuşakça yerine oturur.
* `renk="turuncu"`: panel başlığındaki DanışmanlaKonuş işaretinin rengi — * `renk="turuncu"`: panel başlığındaki DanışmanlaKonuş işaretinin rengi —
* yalnız "Danışman uyarısı" balonunda (durağan; hareket "düşünüyor" demek). */ * yalnız "Danışman uyarısı" balonunda (durağan; hareket "düşünüyor" demek). */
export function DanismanAvatar({ export function DanismanAvatar({
@@ -304,7 +305,7 @@ export function DanismanAvatar({
> >
<AnimasyonluMark <AnimasyonluMark
oynat={canli} oynat={canli}
varyant={canli && aracta ? "zincir" : "nabiz"} varyant={canli && aracta ? "rota" : "nabiz"}
renk={renk} renk={renk}
className="size-5" className="size-5"
/> />
@@ -989,6 +990,16 @@ export function SohbetClient({
const piller = aracPilleri(m); const piller = aracPilleri(m);
// Soru formu balonun altında (sohbet-anketi.tsx) // Soru formu balonun altında (sohbet-anketi.tsx)
const anket = mesajinAnketi(m); const anket = mesajinAnketi(m);
// soru_sor aracı hap çizmez (arac-pilleri.tsx HAPSIZ_ARACLAR);
// sorular üretilirken (parça henüz output-available değil)
// formun yerinde shimmer satırı durur, form gelince kalkar.
const soruHazirlaniyor = m.parts.some(
(p) =>
p.type === "tool-soru_sor" &&
"state" in p &&
p.state !== "output-available" &&
p.state !== "output-error",
);
return ( return (
<Message <Message
key={cevapAnahtari(gorunenMesajlar, i)} key={cevapAnahtari(gorunenMesajlar, i)}
@@ -1012,9 +1023,18 @@ export function SohbetClient({
> >
{baglantilariIsaretle(metin)} {baglantilariIsaretle(metin)}
</MessageContent> </MessageContent>
) : ( ) : soruHazirlaniyor ? null : (
<CevapIskeleti /> <CevapIskeleti />
)} )}
{soruHazirlaniyor ? (
<div role="status" aria-live="polite">
<TextShimmerLoader
text="Soruları hazırlıyorum…"
size="sm"
className="px-0.5 text-slate-600"
/>
</div>
) : null}
{anket ? ( {anket ? (
<SohbetAnketi <SohbetAnketi
anket={anket} anket={anket}