Files
reui-blocks/blocks/feature270.tsx
T

269 lines
9.3 KiB
TypeScript
Raw Normal View History

"use client";
import { motion } from "motion/react";
import React, { useState } from "react";
import { cn } from "@/lib/utils";
const FEATURES = [
{
id: "instant",
number: "۱",
title: "لاگ اجرا",
description:
"با هر رویداد مثل ثبت فرم یا تغییر وضعیت، اقدام بعدی را خودکار اجرا کنید.",
image: "/block-media/shadcnblocks/block/guri3/img11.jpeg",
imageAlt: "سازنده گردش‌کار",
imageOrder: "order-1",
contentOrder: "order-2",
},
{
id: "one-time",
number: "۲",
title: "قالب آماده",
description:
"مسیر متفاوت برای شرایط مختلف تعریف کنید و تصمیم‌گیری را سریع‌تر کنید.",
image: "/block-media/shadcnblocks/block/guri3/img12.jpeg",
imageAlt: "نمای اتوماسیون فرایند",
imageOrder: "order-2",
contentOrder: "order-1",
},
{
id: "developer",
number: "۰۳",
title: "اتصال ابزار",
description:
"تیم را در لحظه از تغییر وضعیت باخبر کنید تا هیچ موردی رها نشود.",
image: "/block-media/shadcnblocks/block/guri3/img14.jpeg",
imageAlt: "لاگ اجرای خودکار",
imageOrder: "order-1",
contentOrder: "order-2",
},
] as const;
2026-07-23 06:55:21 +03:30
interface Feature270Props {
className?: string;
}
const Feature270 = ({ className }: Feature270Props) => {
return (
<section
dir="rtl"
lang="fa"
2026-07-23 06:55:21 +03:30
className={cn(
"relative h-full w-full min-w-0 overflow-hidden py-32",
className,
)}
>
2026-07-23 06:55:21 +03:30
<div className="relative container min-w-0">
<div className="w-full min-w-0 space-y-5 text-start lg:w-3/5">
<h1 className="mb-6 w-full max-w-lg text-2xll font-semibold tracking-tighter text-balance lg:text-2xll">
فرایندها را استاندارد و سریع کنید
</h1>
2026-07-23 06:55:21 +03:30
<p className="max-w-2xl text-pretty break-words opacity-50 md:mb-20">
قوانین ساده تعریف کنید تا وظایف تکراری بدون دخالت دست انجام شود. تیم روی تصمیم‌های مهم تمرکز می‌کند و سرعت اجرا بالاتر می‌رود.
</p>
</div>
2026-07-23 06:55:21 +03:30
<div className="relative grid h-[95rem] min-w-0 items-center justify-between gap-3 md:h-[68rem] md:grid-cols-2 lg:h-[32rem] lg:grid-cols-3">
{FEATURES.map((feature) => (
<PinContainer
key={feature.id}
title="بیشتر بدانید"
href="https://www.ShadcnBlocks/blocks"
2026-07-23 06:55:21 +03:30
className="w-full min-w-0 rounded-3xl bg-muted/70! p-4"
containerClassName="w-full min-w-0 max-w-full"
>
2026-07-23 06:55:21 +03:30
<div className="flex min-w-0 flex-col text-start">
<div className={cn("min-w-0", feature.imageOrder)}>
<img
src={feature.image}
height="1000"
width="1000"
2026-07-23 06:55:21 +03:30
className="h-70 w-full max-w-full rounded-3xl object-cover group-hover/card:shadow-xl"
alt={feature.imageAlt}
/>
</div>
2026-07-23 06:55:21 +03:30
<div className={cn("mt-4 w-full min-w-0 p-3", feature.contentOrder)}>
<p className="leading-none tracking-tighter opacity-50">
{feature.number}
</p>
2026-07-23 06:55:21 +03:30
<h2 className="my-3 text-3xl leading-none font-semibold tracking-tighter text-balance break-words">
{feature.title}
</h2>
2026-07-23 06:55:21 +03:30
<p className="text-pretty break-words leading-5 opacity-50">
{feature.description}
</p>
</div>
</div>
</PinContainer>
))}
</div>
</div>
</section>
);
};
export { Feature270 };
// Below is the modified component from Aceternity UI
// Original source: npx shadcn@latest add https://ui.aceternity.com/registry/3d-pin.json
// Modified to follow our coding standards and design system
// We respect copyright and attribution to the original creators
export const PinContainer = ({
children,
title,
href,
className,
containerClassName,
}: {
children: React.ReactNode;
title?: string;
href?: string;
className?: string;
containerClassName?: string;
}) => {
const [transform, setTransform] = useState(
"translate(-50%,-50%) rotateX(0deg)",
);
const onMouseEnter = () => {
setTransform("translate(-50%,-50%) rotateX(40deg) scale(0.8)");
};
const onMouseLeave = () => {
setTransform("translate(-50%,-50%) rotateX(0deg) scale(1)");
};
return (
<a
className={cn(
2026-07-23 06:55:21 +03:30
"group/pin relative z-50 block w-full min-w-0 max-w-full cursor-pointer",
containerClassName,
)}
onMouseEnter={onMouseEnter}
onMouseLeave={onMouseLeave}
href={href || "/"}
>
<div
style={{
perspective: "1000px",
transform: "rotateX(70deg) translateZ(0deg)",
}}
2026-07-23 06:55:21 +03:30
className="absolute top-1/2 left-1/2 mt-4 ml-[0.09375rem] w-full max-w-full -translate-x-1/2 -translate-y-1/2"
>
<div
style={{
transform: transform,
}}
2026-07-23 06:55:21 +03:30
className="absolute top-1/2 left-1/2 flex w-full max-w-full items-start justify-start overflow-hidden rounded-2xl transition duration-700"
>
2026-07-23 06:55:21 +03:30
<div className={cn("relative z-50 min-w-0 w-full", className)}>
{children}
</div>
</div>
</div>
<PinPerspective title={title} />
</a>
);
};
export const PinPerspective = ({
title,
}: {
title?: string;
href?: string;
}) => {
return (
2026-07-23 06:55:21 +03:30
<motion.div className="pointer-events-none z-[60] flex h-80 w-full max-w-full items-center justify-center opacity-0 transition duration-500 group-hover/pin:opacity-100">
<div className="inset-0 -mt-7 h-full w-full min-w-0 flex-none overflow-hidden">
<div className="absolute inset-x-0 top-0 flex justify-center">
<span className="relative z-10 flex items-center gap-2 rounded-full bg-zinc-950 px-4 py-0.5 ring-1 ring-white/10">
<span className="relative z-20 inline-block py-0.5 text-xs font-bold text-white">
{title}
</span>
<span className="absolute -bottom-0 left-[1.125rem] h-px w-[calc(100%-2.25rem)] bg-gradient-to-r from-emerald-400/0 via-emerald-400/90 to-emerald-400/0 transition-opacity duration-500 group-hover/btn:opacity-40"></span>
</span>
</div>
<div
style={{
perspective: "1000px",
transform: "rotateX(70deg) translateZ(0)",
}}
className="absolute top-1/2 left-1/2 mt-4 ml-[0.09375rem] -translate-x-1/2 -translate-y-1/2"
>
<>
<motion.div
initial={{
opacity: 0,
scale: 0,
x: "-50%",
y: "-50%",
}}
animate={{
opacity: [0, 1, 0.5, 0],
scale: 1,
z: 0,
}}
transition={{
duration: 6,
repeat: Infinity,
delay: 0,
}}
className="absolute top-1/2 left-1/2 h-[11.25rem] w-[11.25rem] rounded-[50%] bg-sky-500/[0.08] shadow-[0_8px_16px_rgb(0_0_0/0.4)]"
></motion.div>
<motion.div
initial={{
opacity: 0,
scale: 0,
x: "-50%",
y: "-50%",
}}
animate={{
opacity: [0, 1, 0.5, 0],
scale: 1,
z: 0,
}}
transition={{
duration: 6,
repeat: Infinity,
delay: 2,
}}
className="absolute top-1/2 left-1/2 h-[11.25rem] w-[11.25rem] rounded-[50%] bg-sky-500/[0.08] shadow-[0_8px_16px_rgb(0_0_0/0.4)]"
></motion.div>
<motion.div
initial={{
opacity: 0,
scale: 0,
x: "-50%",
y: "-50%",
}}
animate={{
opacity: [0, 1, 0.5, 0],
scale: 1,
z: 0,
}}
transition={{
duration: 6,
repeat: Infinity,
delay: 4,
}}
className="absolute top-1/2 left-1/2 h-[11.25rem] w-[11.25rem] rounded-[50%] bg-sky-500/[0.08] shadow-[0_8px_16px_rgb(0_0_0/0.4)]"
></motion.div>
</>
</div>
<>
<motion.div className="absolute right-1/2 bottom-1/2 h-20 w-px translate-y-[14px] bg-gradient-to-b from-transparent to-cyan-500 blur-[2px] group-hover/pin:h-40" />
<motion.div className="absolute right-1/2 bottom-1/2 h-20 w-px translate-y-[14px] bg-gradient-to-b from-transparent to-cyan-500 group-hover/pin:h-40" />
<motion.div className="absolute right-1/2 bottom-1/2 z-40 h-[4px] w-[4px] translate-x-[1.5px] translate-y-[14px] rounded-full bg-cyan-600 blur-[3px]" />
<motion.div className="absolute right-1/2 bottom-1/2 z-40 h-[2px] w-[2px] translate-x-[0.5px] translate-y-[14px] rounded-full bg-cyan-300" />
</>
</div>
</motion.div>
);
};