Files
reui-blocks/blocks/feature270.tsx
T
2026-07-23 06:55:21 +03:30

269 lines
9.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"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;
interface Feature270Props {
className?: string;
}
const Feature270 = ({ className }: Feature270Props) => {
return (
<section
dir="rtl"
lang="fa"
className={cn(
"relative h-full w-full min-w-0 overflow-hidden py-32",
className,
)}
>
<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>
<p className="max-w-2xl text-pretty break-words opacity-50 md:mb-20">
قوانین ساده تعریف کنید تا وظایف تکراری بدون دخالت دست انجام شود. تیم روی تصمیم‌های مهم تمرکز می‌کند و سرعت اجرا بالاتر می‌رود.
</p>
</div>
<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"
className="w-full min-w-0 rounded-3xl bg-muted/70! p-4"
containerClassName="w-full min-w-0 max-w-full"
>
<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"
className="h-70 w-full max-w-full rounded-3xl object-cover group-hover/card:shadow-xl"
alt={feature.imageAlt}
/>
</div>
<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>
<h2 className="my-3 text-3xl leading-none font-semibold tracking-tighter text-balance break-words">
{feature.title}
</h2>
<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(
"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)",
}}
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,
}}
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"
>
<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 (
<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>
);
};