Update padding in Parallax component for improved layout consistency
Some checks failed
Deploy / deploy (push) Has been cancelled
Some checks failed
Deploy / deploy (push) Has been cancelled
This commit is contained in:
33
src/components/console-asr.tsx
Normal file
33
src/components/console-asr.tsx
Normal 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;
|
||||
}
|
||||
@@ -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">
|
||||
|
||||
26
src/components/hero-focus-button.tsx
Normal file
26
src/components/hero-focus-button.tsx
Normal 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>
|
||||
);
|
||||
}
|
||||
@@ -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"
|
||||
|
||||
@@ -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}>
|
||||
|
||||
46
src/components/page-pixel-layer.tsx
Normal file
46
src/components/page-pixel-layer.tsx
Normal 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>
|
||||
);
|
||||
}
|
||||
@@ -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>
|
||||
|
||||
@@ -26,6 +26,7 @@ function ChatContainerRoot({
|
||||
return (
|
||||
<StickToBottom
|
||||
className={cn("flex overflow-y-auto", className)}
|
||||
data-lenis-prevent
|
||||
resize="smooth"
|
||||
initial="instant"
|
||||
role="log"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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}
|
||||
|
||||
23
src/components/viewport-portal.tsx
Normal file
23
src/components/viewport-portal.tsx
Normal 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;
|
||||
}
|
||||
Reference in New Issue
Block a user