({
- x: hareketiAzalt ? 0 : gecisYonu > 0 ? "100%" : "-100%",
- opacity: 0,
- height: panelYuksekligi,
- position: "relative",
- }),
- center: {
- zIndex: 1,
- x: 0,
- opacity: 1,
- height: panelYuksekligi,
- },
- exit: (gecisYonu: number) => ({
- zIndex: 0,
- x: hareketiAzalt ? 0 : gecisYonu < 0 ? "100%" : "-100%",
- opacity: 0,
- position: "absolute",
- top: 0,
- left: 0,
- width: "100%",
- }),
- }}
- transition={
- hareketiAzalt
- ? // Azaltılmış harekette yalnızca kısa çapraz solma; height/x
- // varsayılan spring'e düşüp oynamasın diye açıkça sıfırlanır.
- {
- opacity: { duration: 0.12 },
- x: { duration: 0 },
- height: { duration: 0 },
- }
- : {
- x: { type: "spring", stiffness: 300, damping: 30 },
- height: { type: "spring", stiffness: 300, damping: 30 },
- opacity: { duration: 0.2 },
- }
- }
+ variants={adimGecisiVaryantlari({
+ hareketiAzalt: !!hareketiAzalt,
+ yukseklik: panelYuksekligi,
+ })}
+ transition={adimGecisi(!!hareketiAzalt)}
>
diff --git a/src/lib/adim-gecisi.ts b/src/lib/adim-gecisi.ts
new file mode 100644
index 0000000..7096570
--- /dev/null
+++ b/src/lib/adim-gecisi.ts
@@ -0,0 +1,65 @@
+// Adım adım ilerleyen panellerin ortak geçişi (DESIGN.md §6): sihirbazın
+// alan → il → öncelik adımları (sihirbaz-adimlar.tsx, TransitionPanel) ile
+// danışmanın soru formundaki sorular (sohbet-anketi.tsx) aynı yoldan gelir
+// gider — yeni adım ileri giderken sağdan, geri dönerken soldan kayar; boy
+// ölçülen yüksekliğe yayla uzar. Sabitler yalnız burada; iki yerde de bu iki
+// fonksiyon çağrılır, kopyası yazılmaz. Yay sekmesiz (stiffness 300 /
+// damping 30), opaklık 0,2 s. "Hareketi azalt"ta kayma ve boy yayı yok,
+// yalnız 0,12 s'lik çapraz solma.
+
+import type { Transition, Variants } from "motion/react";
+
+/**
+ * enter / center / exit varyantları; `custom` geçiş yönüdür (1 ileri, -1
+ * geri). Giren panel akışta (`relative`) durur, çıkan panel mutlak konuma
+ * alınır ki ikisi aynı anda üst üste kayabilsin. `yukseklik` ölçülen boy
+ * (ilk ölçümden önce "auto").
+ */
+export function adimGecisiVaryantlari({
+ hareketiAzalt,
+ yukseklik,
+}: {
+ hareketiAzalt: boolean;
+ yukseklik: number | "auto";
+}): Variants {
+ return {
+ enter: (gecisYonu: number) => ({
+ x: hareketiAzalt ? 0 : gecisYonu > 0 ? "100%" : "-100%",
+ opacity: 0,
+ height: yukseklik,
+ position: "relative",
+ }),
+ center: {
+ zIndex: 1,
+ x: 0,
+ opacity: 1,
+ height: yukseklik,
+ position: "relative",
+ },
+ exit: (gecisYonu: number) => ({
+ zIndex: 0,
+ x: hareketiAzalt ? 0 : gecisYonu < 0 ? "100%" : "-100%",
+ opacity: 0,
+ position: "absolute",
+ top: 0,
+ left: 0,
+ width: "100%",
+ }),
+ };
+}
+
+/** Geçişin zamanlaması; azaltılmış harekette x/height açıkça sıfırlanır ki
+ * varsayılan yaya düşüp oynamasın. */
+export function adimGecisi(hareketiAzalt: boolean): Transition {
+ return hareketiAzalt
+ ? {
+ opacity: { duration: 0.12 },
+ x: { duration: 0 },
+ height: { duration: 0 },
+ }
+ : {
+ x: { type: "spring", stiffness: 300, damping: 30 },
+ height: { type: "spring", stiffness: 300, damping: 30 },
+ opacity: { duration: 0.2 },
+ };
+}