Update padding in Parallax component for improved layout consistency
Some checks failed
Deploy / deploy (push) Has been cancelled

This commit is contained in:
bilalgursen
2026-07-30 03:54:31 +03:00
parent dc6d894a37
commit 2c542e7756
22 changed files with 274 additions and 133 deletions

View File

@@ -0,0 +1,33 @@
"use client";
import { useEffect } from "react";
let hasPlayed = false;
const consoleMessage = [
"%cبِسْمِ اللَّهِ الرَّحْمٰنِ الرَّحِيمِ",
"",
"وَالْعَصْرِۙ اِنَّ الْاِنْسَانَ لَف۪ي خُسْرٍۙ",
"اِلَّا الَّذ۪ينَ اٰمَنُوا وَعَمِلُوا الصَّالِحَاتِ",
"وَتَوَاصَوْا بِالْحَقِّ وَتَوَاصَوْا بِالصَّبْرِ",
"",
"Rahmân ve Rahîm olan Allahın adıyla.",
"",
"Asra yemîn olsun ki,",
"İnsan gerçekten ziyândadır.",
"Ancak iman edip sâlih ameller yapanlar, birbirlerine hakkı tavsiye",
"edenler ve birbirlerine sabretmeyi öğütleyenler müstesnâ!",
].join("\n");
export function ConsoleAsr() {
useEffect(() => {
if (hasPlayed) return;
hasPlayed = true;
window.setTimeout(() => {
console.log(consoleMessage, "font-size:16px");
}, 250);
}, []);
return null;
}

View File

@@ -200,7 +200,10 @@ export function DevPanel() {
</button>
</div>
<div className="flex flex-col gap-4 overflow-y-auto p-4 text-sm">
<div
data-lenis-prevent
className="flex flex-col gap-4 overflow-y-auto p-4 text-sm"
>
{/* Oturum */}
<section>
<p className="text-[11px] font-semibold uppercase tracking-wide text-slate-400">

View File

@@ -0,0 +1,26 @@
"use client";
import { Button } from "@/components/ui/button";
export function HeroFocusButton() {
function handleClick() {
const input = document.getElementById("siralama");
if (input instanceof HTMLInputElement) {
input.focus({ preventScroll: true });
}
window.scrollTo({ top: 0, behavior: "smooth" });
}
return (
<Button
type="button"
size="lg"
onClick={handleClick}
className="mt-8 h-12 cursor-pointer bg-orange-500 px-8 text-white transition-colors duration-200 hover:bg-orange-600"
>
Ücretsiz dene
</Button>
);
}

View File

@@ -132,7 +132,7 @@ export function HeroForm() {
// flex-1 yalnızca yatay dizilimde (sm+): mobilde form flex-col olduğu
// için flex-1 inputun yüksekliğini eziyordu. Mobilde geniş padding
// + büyük yazı; sm ve üzeri eski görünüm.
className="h-12 bg-background px-5 text-lg sm:flex-1 sm:px-2.5 sm:text-base"
className="h-14 bg-background px-6 py-3 text-lg sm:h-12 sm:flex-1 sm:px-2.5 sm:py-1 sm:text-base"
/>
<Button
type="submit"

View File

@@ -206,6 +206,7 @@ function CekmeceSheet() {
layout="position"
layoutScroll
as="ol"
data-lenis-prevent
className="min-h-0 flex-1 space-y-2 overflow-x-hidden overflow-y-auto px-4 py-4"
>
<AnimatePresence initial={false}>

View File

@@ -0,0 +1,46 @@
"use client";
import { usePathname } from "next/navigation";
import { PixelCorner } from "@/components/pixel-decor";
const pixelClass = "size-10 [&_rect]:[fill-opacity:0.55]";
/**
* Ana sayfanın kendi zengin piksel kompozisyonunu tekrar etmeden, iç
* sayfalara ortak bir piksel çerçevesi taşır. Katman içeriklerin üstünde
* kaldığı için sayfaların opak zeminlerinde de görünür; kenarlara
* yerleştiğinden etkileşimleri ve okunabilirliği engellemez.
*/
export function PagePixelLayer() {
const pathname = usePathname();
if (pathname === "/") return null;
return (
<div
aria-hidden
className="pointer-events-none fixed inset-0 z-30 overflow-hidden print:hidden"
>
<PixelCorner
className={`absolute -left-3 top-28 -rotate-90 ${pixelClass}`}
/>
<PixelCorner
className={`absolute -right-3 top-28 ${pixelClass}`}
/>
<PixelCorner
className={`absolute -left-4 top-[46%] -rotate-90 text-orange-500 max-sm:hidden ${pixelClass}`}
/>
<PixelCorner
className={`absolute -right-4 top-[58%] rotate-90 max-sm:hidden ${pixelClass}`}
/>
<PixelCorner
className={`absolute -bottom-3 left-6 rotate-180 ${pixelClass}`}
/>
<PixelCorner
className={`absolute -bottom-3 right-6 rotate-90 text-orange-500 ${pixelClass}`}
/>
</div>
);
}

View File

@@ -35,24 +35,27 @@ export function ScrollFlow({
const reduceMotion = useReducedMotion();
const { scrollY } = useScroll();
const velocity = useVelocity(scrollY);
// Ham hız titrek olur; yay ile yumuşatınca bükülme salınıp yerine oturur
const smoothVelocity = useSpring(velocity, {
damping: 50,
stiffness: 420,
mass: 0.6,
// Önce hızı kesintisiz bir hedef açıya dönüştür, sonra doğrudan görünen
// açıyı yumuşat. Böylece eşik/clamp kaynaklı ani hız değişimleri yaya girmez.
const targetSkew = useTransform(velocity, (v) => {
const RESPONSE = 1800;
return Math.tanh(v / RESPONSE) * maxSkew;
});
// Ölü bölge: yavaş/ufak kaydırmalarda bükülme tamamen 0 kalır — transform
// hiç değişmediği için compositor'a kare başı iş çıkmaz. Eşik üstünde
// kareyle (ease-in) yükselir, 0,01°'lik adımlara yuvarlanır ki yayın
// mikro-salınımları her karede katmanı kirletmesin.
const skewY = useTransform(smoothVelocity, (v) => {
const DEADZONE = 500; // px/sn — bunun altı "normal gezinme" sayılır
const FULL = 2600; // px/sn — bu hızda maxSkew'e ulaşılır
const mag = Math.abs(v);
if (mag < DEADZONE) return 0;
const t = Math.min(1, (mag - DEADZONE) / (FULL - DEADZONE));
const s = t * t * maxSkew * Math.sign(v);
return Math.round(s * 100) / 100;
const smoothSkew = useSpring(targetSkew, {
stiffness: 240,
damping: 26,
mass: 0.7,
restDelta: 0.005,
restSpeed: 0.01,
});
// Yuvarlama görsel basamaklanma üretir. Tam hassasiyetle çiz; yalnızca açı
// algılanamayacak kadar küçüldüğünde transform'u kaldırarak dev sayfa
// katmanının GPU belleğinde boşuna tutulmasını önle.
const transform = useTransform(smoothSkew, (v) => {
if (Math.abs(v) < 0.01) return "none";
return `skewY(${v}deg)`;
});
if (reduceMotion) {
@@ -61,12 +64,7 @@ export function ScrollFlow({
return (
<ReactLenis root options={{ lerp: 0.09, anchors: true }}>
{/* willChange: bükülme 0'a döndüğünde dev katman GPU'dan düşüp
bir sonraki tekerlekte yeniden rasterize edilmesin */}
<motion.div
className={className}
style={{ skewY, willChange: "transform" }}
>
<motion.div className={className} style={{ transform }}>
{children}
</motion.div>
</ReactLenis>

View File

@@ -26,6 +26,7 @@ function ChatContainerRoot({
return (
<StickToBottom
className={cn("flex overflow-y-auto", className)}
data-lenis-prevent
resize="smooth"
initial="instant"
role="log"

View File

@@ -60,6 +60,7 @@ function DialogContent({
<DialogOverlay />
<DialogPrimitive.Content
data-slot="dialog-content"
data-lenis-prevent
className={cn(
"fixed top-1/2 left-1/2 z-50 grid w-full max-w-[calc(100%-2rem)] -translate-x-1/2 -translate-y-1/2 gap-4 rounded-xl bg-popover p-4 text-sm text-popover-foreground ring-1 ring-foreground/10 duration-100 outline-none sm:max-w-sm data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95",
className

View File

@@ -68,6 +68,7 @@ function SelectContent({
<SelectPrimitive.Portal>
<SelectPrimitive.Content
data-slot="select-content"
data-lenis-prevent
data-align-trigger={position === "item-aligned"}
className={cn("relative z-50 max-h-(--radix-select-content-available-height) min-w-36 origin-(--radix-select-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-lg bg-popover text-popover-foreground shadow-md ring-1 ring-foreground/10 duration-100 data-[align-trigger=true]:animate-none data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95", position ==="popper"&&"data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1", className )}
position={position}

View File

@@ -0,0 +1,23 @@
"use client";
import { type ReactNode, useSyncExternalStore } from "react";
import { createPortal } from "react-dom";
const subscribe = () => () => {};
const getClientSnapshot = () => true;
const getServerSnapshot = () => false;
/**
* Viewport'a sabit kalması gereken öğeleri, transform uygulanan sayfa
* katmanının dışına taşır. Böylece üst katmandaki scroll skew animasyonu
* `position: fixed` koordinat sistemini değiştirmez.
*/
export function ViewportPortal({ children }: { children: ReactNode }) {
const mounted = useSyncExternalStore(
subscribe,
getClientSnapshot,
getServerSnapshot,
);
return mounted ? createPortal(children, document.body) : null;
}