some edit

This commit is contained in:
2026-08-13 20:38:45 +03:30
parent 1cea5b78cb
commit 031e0cc413
24 changed files with 462 additions and 330 deletions
+34 -29
View File
@@ -220,56 +220,61 @@ const Feature199 = ({ className }: Feature199Props) => {
const handleScroll = () => { const handleScroll = () => {
const container = containerRef.current; const container = containerRef.current;
if (!container) return; if (!container) return;
const items = container.getElementsByClassName("feature-item");
const containerMiddle = window.innerHeight * 0.6;
let closestItem: number | null = null; const rect = container.getBoundingClientRect();
let closestDistance = Infinity; const listHeight = container.offsetHeight;
const viewportHeight = window.innerHeight;
const scrollRange = Math.max(listHeight - viewportHeight * 0.45, 1);
const passed = Math.min(Math.max(-rect.top + viewportHeight * 0.2, 0), scrollRange);
const progress = passed / scrollRange;
const steppedIndex = Math.round(progress * (FEATURES.length - 1));
const nextIndex = Math.min(Math.max(steppedIndex, 0), FEATURES.length - 1);
Array.from(items).forEach((item, index) => { setActiveFeature((prev) => (prev === nextIndex ? prev : nextIndex));
const rect = item.getBoundingClientRect();
const distance = Math.abs(rect.top + rect.height / 2 - containerMiddle);
if (distance < closestDistance) {
closestDistance = distance;
closestItem = index;
}
});
if (closestItem !== null) {
setActiveFeature(closestItem);
}
}; };
window.addEventListener("scroll", handleScroll); handleScroll();
window.addEventListener("scroll", handleScroll, { passive: true });
return () => window.removeEventListener("scroll", handleScroll); return () => window.removeEventListener("scroll", handleScroll);
}, [isMobile]); }, [isMobile]);
return ( return (
<section dir="rtl" lang="fa" className={cn("py-32", className)}> <section
<div className="container"> dir="rtl"
<h2 className="mb-10 text-xl font-bold text-balance md:text-2xll lg:mb-20 lg:text-2xll"> lang="fa"
className={cn("min-w-0 overflow-x-hidden py-16 sm:py-24 lg:py-32", className)}
>
<div className="container min-w-0">
<h2 className="mb-8 text-xl font-bold text-balance sm:mb-10 sm:text-2xl lg:mb-20 lg:text-3xl">
هر سرنخ را تا قرارداد دنبال کنید هر سرنخ را تا قرارداد دنبال کنید
</h2> </h2>
<div className="relative gap-6 pb-72 md:grid md:grid-cols-5 md:pb-0"> <div className="relative min-w-0 gap-6 pb-64 sm:pb-60 lg:grid lg:grid-cols-5 lg:pb-0">
<div className="col-span-3 pb-4 text-start" ref={containerRef}> <div
className="col-span-3 min-w-0 pb-4 text-start"
ref={containerRef}
>
<Separator /> <Separator />
{FEATURES.map((feature, index) => ( {FEATURES.map((feature, index) => (
<React.Fragment key={feature.id}> <React.Fragment key={feature.id}>
<div <div
className="feature-item py-3" className="feature-item py-2.5 sm:py-3"
onMouseEnter={() => !isMobile && setActiveFeature(index)} onMouseEnter={() => !isMobile && setActiveFeature(index)}
> >
<div className="flex items-center gap-7 md:gap-16 lg:gap-28"> <div
className={cn(
"flex min-w-0 items-center gap-3 rounded-lg px-2 py-2 transition-colors sm:gap-5 sm:px-0 sm:py-0 lg:gap-16 xl:gap-28",
activeFeature === index && "bg-muted/40 sm:bg-transparent",
)}
>
<span <span
className={cn( className={cn(
"invisible size-2.5 shrink-0 rounded-full bg-primary md:size-3", "invisible size-2 shrink-0 rounded-full bg-primary sm:size-2.5 lg:size-3",
activeFeature === index && "visible", activeFeature === index && "visible",
)} )}
/> />
<p <p
className={cn( className={cn(
"text-[clamp(1.65rem,3vw,2.15rem)] font-bold text-muted-foreground", "min-w-0 wrap-break-word text-base font-bold text-muted-foreground sm:text-lg md:text-xl lg:text-2xl xl:text-3xl",
activeFeature === index && "text-primary", activeFeature === index && "text-primary",
)} )}
> >
@@ -281,11 +286,11 @@ const Feature199 = ({ className }: Feature199Props) => {
</React.Fragment> </React.Fragment>
))} ))}
</div> </div>
<div className="sticky bottom-3 start-3 col-span-2 h-72 w-fit border md:top-20 md:h-fit"> <div className="fixed inset-x-3 bottom-3 z-20 mx-auto max-w-md border bg-background shadow-md md:sticky md:top-20 md:bottom-auto md:inset-x-auto md:col-span-2 md:mx-0 md:max-w-none md:h-fit md:w-fit md:shadow-none">
<img <img
src={FEATURES[activeFeature].image} src={FEATURES[activeFeature].image}
alt={FEATURES[activeFeature].imageAlt} alt={FEATURES[activeFeature].imageAlt}
className="h-72 md:h-auto" className="h-44 w-full object-cover sm:h-52 md:h-72 md:w-auto md:object-fill"
/> />
</div> </div>
</div> </div>
+7 -14
View File
@@ -153,7 +153,6 @@ const Feature216 = ({ className }: Feature216Props) => {
const [buttonPosition, setButtonPosition] = useState<number>(0); const [buttonPosition, setButtonPosition] = useState<number>(0);
// Rightmost tab in RTL (`justify-start`) is the first item. // Rightmost tab in RTL (`justify-start`) is the first item.
const [tabValue, setTabValue] = useState<TabValue>(TAB_ITEMS[0].value); const [tabValue, setTabValue] = useState<TabValue>(TAB_ITEMS[0].value);
const triggerRefs = useRef<HTMLButtonElement[]>([]);
const imageRef = useRef<HTMLDivElement | null>(null); const imageRef = useRef<HTMLDivElement | null>(null);
const updateBottom = () => { const updateBottom = () => {
@@ -178,10 +177,6 @@ const Feature216 = ({ className }: Feature216Props) => {
}; };
const handleTabNavigation = (direction: "next" | "prev") => { const handleTabNavigation = (direction: "next" | "prev") => {
triggerRefs.current.forEach((ref) => {
ref.classList.add("grayscale-[1]", "opacity-[0.2]");
});
const currentIndex = getCurrentTabIndex(); const currentIndex = getCurrentTabIndex();
if (currentIndex === -1) return; if (currentIndex === -1) return;
@@ -207,21 +202,19 @@ const Feature216 = ({ className }: Feature216Props) => {
<h2 className="mb-10 text-center text-3xl font-light text-balance md:text-xl"> <h2 className="mb-10 text-center text-3xl font-light text-balance md:text-xl">
شاخص‌های کلیدی را یکجا ببینید شاخص‌های کلیدی را یکجا ببینید
</h2> </h2>
<Tabs value={tabValue} onValueChange={onValueChange} className="w-full"> <Tabs
dir="rtl"
value={tabValue}
onValueChange={onValueChange}
className="w-full"
>
<TabsList className="hidden !h-auto w-full !justify-start items-end gap-12 bg-transparent pb-10 xl:flex"> <TabsList className="hidden !h-auto w-full !justify-start items-end gap-12 bg-transparent pb-10 xl:flex">
{TAB_ITEMS.map((trigger, index) => { {TAB_ITEMS.map((trigger, index) => {
const Icon = trigger.icon; const Icon = trigger.icon;
return ( return (
<TabsTrigger <TabsTrigger
ref={(el) => { className="flex !h-auto !flex-none shrink-0 flex-col items-center gap-5 !border-none !bg-transparent p-0 opacity-[0.2] !shadow-none grayscale hover:!bg-transparent hover:opacity-50 hover:grayscale-0 data-[state=active]:!bg-transparent data-[state=active]:opacity-100 data-[state=active]:!shadow-none data-[state=active]:grayscale-0 dark:!bg-transparent dark:data-[state=active]:!bg-transparent"
if (el) {
triggerRefs.current[index] = el;
} else {
delete triggerRefs.current[index];
}
}}
className="flex !h-auto flex-col items-center gap-5 !border-none !bg-transparent p-0 opacity-[0.2] !shadow-none grayscale-[1] hover:!bg-transparent hover:opacity-[0.5] hover:grayscale-[0] data-[state=active]:!bg-transparent data-[state=active]:opacity-100 data-[state=active]:!shadow-none data-[state=active]:grayscale-0 dark:!bg-transparent dark:data-[state=active]:!bg-transparent"
key={trigger.id} key={trigger.id}
value={trigger.value} value={trigger.value}
data-index={index} data-index={index}
+11 -13
View File
@@ -1,6 +1,5 @@
import { ArrowRight } from "lucide-react"; import { ArrowRight } from "lucide-react";
import { AspectRatio } from "@/components/ui/aspect-ratio";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
@@ -32,13 +31,13 @@ const Feature220 = ({ className }: Feature220Props) => {
dir="rtl" dir="rtl"
lang="fa" lang="fa"
className={cn( className={cn(
"bg-muted bg-[url('/block-media/shadcnblocks/block/patterns/dot-pattern-2.svg')] bg-[length:3.125rem_3.125rem] bg-repeat py-20", "flex min-h-full w-full min-w-0 flex-col justify-center bg-muted bg-[url('/block-media/shadcnblocks/block/patterns/dot-pattern-2.svg')] bg-[length:3.125rem_3.125rem] bg-repeat py-12 sm:py-16 lg:py-20",
className, className,
)} )}
> >
<div className="container flex flex-wrap-reverse gap-12 lg:grid lg:grid-cols-[1fr_1.5fr] lg:gap-[7.5rem]"> <div className="container flex min-w-0 flex-col gap-8 px-4 sm:gap-10 sm:px-6 md:gap-12 lg:grid lg:grid-cols-[1fr_1.5fr] lg:gap-[7.5rem] lg:px-0">
<div className="flex flex-col justify-between gap-20"> <div className="order-2 flex min-w-0 flex-col justify-between gap-10 sm:gap-14 md:gap-16 lg:order-1 lg:gap-20 lg:ps-12">
<div className="mt-10 flex flex-col gap-5 text-start"> <div className="flex flex-col gap-5 text-start md:mt-8 lg:mt-10">
<h2 className="text-xl leading-none font-semibold tracking-tight text-balance md:text-2xll"> <h2 className="text-xl leading-none font-semibold tracking-tight text-balance md:text-2xll">
از خرید تا فروش در یک سیستم از خرید تا فروش در یک سیستم
</h2> </h2>
@@ -53,7 +52,7 @@ const Feature220 = ({ className }: Feature220Props) => {
</div> </div>
</div> </div>
<div> <div>
<div className="group flex w-full max-w-[30rem] flex-col gap-10 rounded-[.5rem] bg-background p-5 text-start transition-shadow hover:shadow-[0_0_2px_theme('colors.gray.300')]"> <div className="group flex w-full max-w-full flex-col gap-10 rounded-[.5rem] bg-background p-5 text-start transition-shadow hover:shadow-[0_0_2px_theme('colors.gray.300')] sm:max-w-[30rem]">
<div className="flex w-full flex-col gap-8 sm:flex-row"> <div className="flex w-full flex-col gap-8 sm:flex-row">
{STATS.map((item) => ( {STATS.map((item) => (
<div className="flex flex-col gap-1" key={item.id}> <div className="flex flex-col gap-1" key={item.id}>
@@ -67,21 +66,20 @@ const Feature220 = ({ className }: Feature220Props) => {
</div> </div>
</div> </div>
</div> </div>
<div className="w-full max-w-[46.5rem]"> <div className="order-1 w-full min-w-0 max-w-full pt-6 sm:pt-8 md:pt-8 lg:order-2 lg:max-w-[46.5rem] lg:pe-12 lg:pt-10">
<AspectRatio <div className="aspect-video max-h-80 overflow-hidden rounded-2xl sm:max-h-96 md:aspect-[4/3] md:max-h-none lg:aspect-[712/815]">
ratio={0.873239437}
className="overflow-hidden rounded-2xl"
>
<video <video
src="/block-media/shadcnblocks/block/video-8.mp4" src="https://deifkwefumgah.cloudfront.net/shadcnblocks/block/video-8.mp4"
className="block size-full object-cover object-center" className="block size-full object-cover object-center"
loop loop
autoPlay autoPlay
muted muted
playsInline
preload="metadata"
controls={false} controls={false}
aria-label="عملیات سازمان را یکپارچه کنید" aria-label="عملیات سازمان را یکپارچه کنید"
/> />
</AspectRatio> </div>
</div> </div>
</div> </div>
</section> </section>
+22 -14
View File
@@ -33,44 +33,52 @@ const Feature220a = ({ className }: Feature220aProps) => {
dir="rtl" dir="rtl"
lang="fa" lang="fa"
className={cn( className={cn(
"bg-muted bg-[url('/block-media/shadcnblocks/block/patterns/dot-pattern-2.svg')] bg-[length:3.125rem_3.125rem] bg-repeat py-24", "flex min-h-full w-full min-w-0 flex-col justify-center overflow-x-hidden bg-muted bg-[url('/block-media/shadcnblocks/block/patterns/dot-pattern-2.svg')] bg-[length:3.125rem_3.125rem] bg-repeat py-12 sm:py-16 lg:py-24",
className, className,
)} )}
> >
<div className="container max-w-5xl"> <div className="container min-w-0 max-w-5xl px-4 sm:px-6">
<div className="mb-16 text-center"> <div className="mb-10 min-w-0 text-center sm:mb-16">
<Badge variant="secondary" className="mb-6 px-4 py-2"> <Badge variant="secondary" className="mb-6 px-4 py-2">
هر تیم داشبورد خودش را داشته باشد هر تیم داشبورد خودش را داشته باشد
</Badge> </Badge>
<h2 className="leading-tighter mb-6 text-2xll font-semibold tracking-tight text-balance lg:text-2xll"> <h2 className="leading-tighter mb-6 text-balance text-xl font-semibold tracking-tight sm:text-2xll lg:text-2xll">
روندها را زودتر از رقبا ببینید روندها را زودتر از رقبا ببینید
<span className="block text-primary">گزارش‌هایی که مدیران واقعاً استفاده می‌کنند</span> <span className="block text-primary">
گزارش‌هایی که مدیران واقعاً استفاده می‌کنند
</span>
</h2> </h2>
<p className="mx-auto mb-8 max-w-3xl text-xl leading-relaxed font-medium text-pretty text-muted-foreground"> <p className="mx-auto mb-8 max-w-3xl text-base leading-relaxed font-medium text-pretty text-muted-foreground sm:text-xl">
داشبوردهای تعاملی به تیم‌ها اجازه می‌دهد سؤال جدید بپرسند بدون اینکه هر بار به تیم داده وابسته باشند. داشبوردهای تعاملی به تیم‌ها اجازه می‌دهد سؤال جدید بپرسند بدون اینکه
هر بار به تیم داده وابسته باشند.
</p> </p>
<Button size="lg" className="gap-2 px-8 py-6 text-lg"> <Button
size="lg"
className="h-auto max-w-full gap-2 px-6 py-4 text-base whitespace-normal sm:px-8 sm:py-6 sm:text-lg"
>
گزارش سفارشی را بدون SQL بسازید و سریع منتشر کنید. گزارش سفارشی را بدون SQL بسازید و سریع منتشر کنید.
<ArrowRight className="size-4 rtl:rotate-180" /> <ArrowRight className="size-4 shrink-0 rtl:rotate-180" />
</Button> </Button>
</div> </div>
<div className="mb-16"> <div className="mb-10 min-w-0 sm:mb-16">
<AspectRatio ratio={16 / 9} className="overflow-hidden rounded-3xl"> <AspectRatio ratio={16 / 9} className="overflow-hidden rounded-2xl sm:rounded-3xl">
<video <video
src="/block-media/shadcnblocks/block/video-8.mp4" src="https://deifkwefumgah.cloudfront.net/shadcnblocks/block/video-8.mp4"
className="block size-full object-cover object-center" className="block size-full object-cover object-center"
loop loop
autoPlay autoPlay
muted muted
playsInline
preload="metadata"
controls={false} controls={false}
aria-label="تصمیم استراتژیک را داده‌محور کنید" aria-label="تصمیم استراتژیک را داده‌محور کنید"
/> />
</AspectRatio> </AspectRatio>
</div> </div>
<div className="rounded-2xl bg-card p-8"> <div className="min-w-0 rounded-2xl bg-card p-4 sm:p-8">
<div className="grid grid-cols-1 gap-8 sm:grid-cols-3"> <div className="grid min-w-0 grid-cols-1 gap-6 sm:grid-cols-3 sm:gap-8">
{STATS.map((item) => ( {STATS.map((item) => (
<div className="text-center" key={item.id}> <div className="text-center" key={item.id}>
<div className="mb-2 text-xl font-bold text-primary"> <div className="mb-2 text-xl font-bold text-primary">
+8 -4
View File
@@ -32,11 +32,11 @@ const Feature220b = ({ className }: Feature220bProps) => {
dir="rtl" dir="rtl"
lang="fa" lang="fa"
className={cn( className={cn(
"bg-muted bg-[url('/block-media/shadcnblocks/block/patterns/dot-pattern-2.svg')] bg-[length:3.125rem_3.125rem] bg-repeat py-20", "flex min-h-full w-full min-w-0 flex-col justify-center overflow-x-hidden bg-muted bg-[url('/block-media/shadcnblocks/block/patterns/dot-pattern-2.svg')] bg-[length:3.125rem_3.125rem] bg-repeat py-12 sm:py-16 lg:py-20",
className, className,
)} )}
> >
<div className="container"> <div className="container min-w-0 px-4 sm:px-6">
<div className="mb-20 flex flex-wrap justify-center gap-12"> <div className="mb-20 flex flex-wrap justify-center gap-12">
{STATS.map((item) => ( {STATS.map((item) => (
<div key={item.id} className="min-w-48 text-center"> <div key={item.id} className="min-w-48 text-center">
@@ -57,11 +57,13 @@ const Feature220b = ({ className }: Feature220bProps) => {
className="overflow-hidden rounded-2xl" className="overflow-hidden rounded-2xl"
> >
<video <video
src="/block-media/shadcnblocks/block/video-8.mp4" src="https://deifkwefumgah.cloudfront.net/shadcnblocks/block/video-8.mp4"
className="block size-full object-cover object-center" className="block size-full object-cover object-center"
loop loop
autoPlay autoPlay
muted muted
playsInline
preload="metadata"
controls={false} controls={false}
aria-label="هر سرنخ را تا قرارداد دنبال کنید" aria-label="هر سرنخ را تا قرارداد دنبال کنید"
/> />
@@ -73,7 +75,9 @@ const Feature220b = ({ className }: Feature220bProps) => {
فروش تیم‌تان را یکجا مدیریت کنید فروش تیم‌تان را یکجا مدیریت کنید
</h2> </h2>
<p className="text-lg leading-[1.4] font-medium text-pretty text-muted-foreground md:text-xl"> <p className="text-lg leading-[1.4] font-medium text-pretty text-muted-foreground md:text-xl">
تمام تعاملات، سرنخ‌ها و قراردادها در یک فضای کاری متمرکز جمع می‌شود. تیم فروش بدون جابجایی بین ابزارها، سریع‌تر پیش‌بینی می‌کند و معاملات بیشتری می‌بندد. تمام تعاملات، سرنخ‌ها و قراردادها در یک فضای کاری متمرکز جمع
می‌شود. تیم فروش بدون جابجایی بین ابزارها، سریع‌تر پیش‌بینی می‌کند
و معاملات بیشتری می‌بندد.
</p> </p>
<div className="pt-4"> <div className="pt-4">
<Button size="lg" className="gap-2 px-8 py-6 text-lg"> <Button size="lg" className="gap-2 px-8 py-6 text-lg">
+16 -15
View File
@@ -64,41 +64,42 @@ const Feature221 = ({ className }: Feature221Props) => {
dir="rtl" dir="rtl"
lang="fa" lang="fa"
className={cn( className={cn(
"bg-muted bg-[url('/block-media/shadcnblocks/block/patterns/dot-pattern-2.svg')] bg-[length:3.125rem_3.125rem] bg-repeat py-32", "w-full min-w-0 bg-muted bg-[url('/block-media/shadcnblocks/block/patterns/dot-pattern-2.svg')] bg-size-[3.125rem_3.125rem] bg-repeat py-32",
className, className,
)} )}
> >
<div className="container"> <div className="container px-4 sm:px-6 lg:px-8">
<div className="flex w-full flex-col items-start justify-between gap-4 pb-16 lg:flex-row lg:items-end"> <div className="flex w-full flex-col items-start justify-between gap-4 pb-16 lg:flex-row lg:items-end">
<div className="flex w-full max-w-lg flex-1 flex-col items-start gap-5 text-start"> <div className="flex w-full max-w-lg flex-1 flex-col items-start gap-5 text-start">
<h2 className="text-[2rem] leading-none font-bold tracking-tight text-balance md:text-[2.75rem] lg:text-2xll"> <h2 className="text-[2rem] leading-none font-bold tracking-tight text-balance md:text-[2.75rem]">
پیش‌بینی درآمد را دقیق‌تر کنید پیش‌بینی درآمد را دقیق‌تر کنید
</h2> </h2>
<p className="w-full max-w-[30rem] text-[1.15rem] leading-normal font-medium text-pretty text-muted-foreground sm:text-xl"> <p className="w-full max-w-[30rem] text-[1.15rem] leading-normal font-medium text-pretty text-muted-foreground sm:text-xl">
با یادآورهای هوشمند و اولویت‌بندی سرنخ، زمان تیم روی معاملات با احتمال بیشتر صرف می‌شود و چرخه فروش کوتاه‌تر می‌شود. با یادآورهای هوشمند و اولویت‌بندی سرنخ، زمان تیم روی معاملات با
احتمال بیشتر صرف می‌شود و چرخه فروش کوتاه‌تر می‌شود.
</p> </p>
</div> </div>
<div> <div className="w-full lg:w-auto lg:shrink-0">
<Button className="gap-2 rounded-full"> <Button className="h-10 w-full gap-2 rounded-full px-4 lg:w-auto">
چرخه فروش را از سرنخ تا قرارداد در یک مسیر مشخص پیش ببرید. مدیران می‌توانند گلوگاه‌ها را ببینند و تیم‌ها با اولویت درست روی معاملات ارزشمند تمرکز کنند. شروع کنید
<ArrowRight className="size-4 rtl:rotate-180" /> <ArrowRight className="size-4 shrink-0 rtl:rotate-180" />
</Button> </Button>
</div> </div>
</div> </div>
<div className="grid w-full grid-cols-1 grid-rows-[auto] gap-10 md:grid-cols-2"> <div className="grid w-full grid-cols-1 gap-10 md:grid-cols-2">
{FEATURES.map((feature) => ( {FEATURES.map((feature) => (
<Card <Card
key={feature.id} key={feature.id}
className="flex w-full flex-col justify-between gap-10 rounded-lg border bg-background p-5" className="flex w-full min-w-0 flex-col justify-between gap-10 rounded-lg border bg-background p-5"
> >
<CardHeader className="flex w-full flex-col justify-between gap-4 p-0 lg:flex-row lg:items-center"> <CardHeader className="flex w-full min-w-0 flex-row items-center justify-between gap-4 p-0">
<CardTitle className="flex w-fit items-center justify-start gap-2.5"> <CardTitle className="min-w-0 flex-1">
<h3 className="text-[1.75rem] leading-none font-bold tracking-tight text-balance"> <h3 className="text-[1.75rem] leading-none font-bold tracking-tight text-balance">
{feature.title} {feature.title}
</h3> </h3>
</CardTitle> </CardTitle>
<Badge className="bg-muted"> <Badge className="shrink-0 bg-muted px-2 py-0.5 text-xs text-foreground">
<p className="text-sm text-foreground">الگوهای موفق فروش را در کل سازمان تکرار کنید. داده لحظه‌ای نشان می‌دهد کدام مرحله بیشترین افت تبدیل را دارد.</p> ویژگی
</Badge> </Badge>
</CardHeader> </CardHeader>
<CardContent className="p-0 text-start"> <CardContent className="p-0 text-start">
@@ -106,7 +107,7 @@ const Feature221 = ({ className }: Feature221Props) => {
{feature.description} {feature.description}
</p> </p>
</CardContent> </CardContent>
<CardFooter className="flex w-full items-end justify-between gap-5 p-0 lg:flex-row"> <CardFooter className="flex w-full items-end justify-between gap-5 border-0 bg-transparent p-0 pb-5">
<div className="flex-1"> <div className="flex-1">
<Button size="sm" className="rounded-full"> <Button size="sm" className="rounded-full">
<a <a
+4 -4
View File
@@ -118,7 +118,7 @@ const Card = ({ link, background, title, imageAlt, stats }: CardData) => {
href={link} href={link}
aria-label={title} aria-label={title}
style={{ backgroundImage: `url(${background})` }} style={{ backgroundImage: `url(${background})` }}
className="before:content-[] relative min-h-auto w-full overflow-hidden rounded-lg bg-black/80 bg-cover bg-center bg-no-repeat p-5 transition-all duration-300 before:absolute before:start-0 before:top-0 before:z-10 before:block before:size-full before:bg-black/50 before:transition-all before:duration-300 hover:before:bg-black/30 sm:aspect-square md:aspect-auto md:min-h-120 md:max-w-120" className="before:content-[] relative min-h-auto w-full overflow-hidden rounded-lg bg-black/80 bg-cover bg-center bg-no-repeat p-5 transition-all duration-300 before:absolute before:start-0 before:top-0 before:z-10 before:block before:size-full before:bg-black/50 before:transition-all before:duration-300 hover:before:bg-black/30 sm:aspect-square md:aspect-auto md:min-h-120"
> >
<span className="sr-only">{imageAlt}</span> <span className="sr-only">{imageAlt}</span>
<div className="relative z-20 flex size-full flex-col justify-between gap-20 text-start md:gap-16"> <div className="relative z-20 flex size-full flex-col justify-between gap-20 text-start md:gap-16">
@@ -150,9 +150,9 @@ interface Feature222Props {
const Feature222 = ({ className }: Feature222Props) => { const Feature222 = ({ className }: Feature222Props) => {
return ( return (
<section dir="rtl" lang="fa" className={cn("py-32", className)}> <section dir="rtl" lang="fa" className={cn("w-full min-w-0 py-32", className)}>
<div className="container"> <div className="w-full px-4 sm:px-6 lg:px-8">
<div className="grid gap-5 md:grid-cols-2 lg:grid-cols-3"> <div className="grid w-full grid-cols-1 gap-5 md:grid-cols-2 lg:grid-cols-3">
{LIST.map((item) => ( {LIST.map((item) => (
<Card key={item.id} {...item} /> <Card key={item.id} {...item} />
))} ))}
+24 -21
View File
@@ -120,10 +120,14 @@ const Feature224 = ({ className }: Feature224Props) => {
}; };
return ( return (
<section dir="rtl" lang="fa" className={cn("py-32", className)}> <section
<div className="container"> dir="rtl"
<div className="flex w-full flex-col items-center justify-center gap-4"> lang="fa"
<h2 className="mx-auto max-w-87.5 text-center text-xl leading-none font-medium text-balance md:max-w-112.5 md:text-2xll lg:max-w-140 lg:text-2xll"> className={cn("w-full min-w-0 overflow-x-hidden py-12 sm:py-20 lg:py-32", className)}
>
<div className="container min-w-0 px-4 sm:px-6">
<div className="flex w-full min-w-0 flex-col items-center justify-center gap-4">
<h2 className="mx-auto max-w-full text-center text-xl leading-none font-medium text-balance md:max-w-112.5 md:text-2xll lg:max-w-140 lg:text-2xll">
فرایندها را استاندارد و سریع کنید فرایندها را استاندارد و سریع کنید
</h2> </h2>
</div> </div>
@@ -132,27 +136,27 @@ const Feature224 = ({ className }: Feature224Props) => {
align: "start", align: "start",
direction: "rtl", direction: "rtl",
}} }}
className="w-full" className="w-full min-w-0 max-w-full"
setApi={setApi} setApi={setApi}
> >
<CarouselContent className="-ms-8 pt-20"> <CarouselContent className="pt-12 sm:pt-20">
{FEATURES.map((card) => ( {FEATURES.map((card) => (
<CarouselItem <CarouselItem
key={card.id} key={card.id}
className="ps-8 md:basis-1/2 lg:basis-1/3" className="min-w-0 basis-[85%] sm:basis-1/2 lg:basis-1/3"
> >
<div className="p-1"> <div className="min-w-0 p-1">
<Card className="border-0 py-0 shadow-none dark:bg-background"> <Card className="min-w-0 border-0 py-0 shadow-none dark:bg-background">
<CardContent className="flex flex-col p-0"> <CardContent className="flex min-w-0 flex-col p-0">
<div <div
style={{ backgroundImage: `url("${card.background}")` }} style={{ backgroundImage: `url("${card.background}")` }}
className="relative flex aspect-[0.935802469] w-full flex-col items-center justify-between overflow-hidden rounded-2xl bg-cover bg-center bg-no-repeat p-7" className="relative flex aspect-[0.935802469] w-full min-w-0 flex-col items-center justify-between overflow-hidden rounded-2xl bg-cover bg-center bg-no-repeat p-4 sm:p-7"
role="img" role="img"
aria-label={card.imageAlt} aria-label={card.imageAlt}
> >
<div className="flex size-full flex-1" /> <div className="flex size-full flex-1" />
<div className="h-12 w-full"> <div className="h-12 w-full min-w-0">
<div className="mx-auto mb-8 flex w-full max-w-60 items-center gap-4 rounded-full bg-primary px-3 py-2.5 shadow-xl dark:bg-background"> <div className="mx-auto mb-6 flex w-full max-w-full min-w-0 items-center gap-3 rounded-full bg-primary px-3 py-2.5 shadow-xl sm:mb-8 sm:max-w-60 sm:gap-4 dark:bg-background">
<div className="shrink-0"> <div className="shrink-0">
<div className="flex -space-x-2 rtl:space-x-reverse"> <div className="flex -space-x-2 rtl:space-x-reverse">
<div className="flex size-7 rounded-full border border-black bg-background dark:bg-primary"> <div className="flex size-7 rounded-full border border-black bg-background dark:bg-primary">
@@ -163,14 +167,14 @@ const Feature224 = ({ className }: Feature224Props) => {
</div> </div>
</div> </div>
</div> </div>
<div className="text-sm font-medium text-white"> <div className="min-w-0 text-sm font-medium text-white">
{card.label} {card.label}
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div className="flex w-full flex-col gap-1 pt-6 text-start"> <div className="flex w-full min-w-0 flex-col gap-1 pt-6 text-start">
<h3 className="text-xl font-medium text-balance text-foreground"> <h3 className="text-lg font-medium text-balance text-foreground sm:text-xl">
{card.title} {card.title}
</h3> </h3>
<p className="text-sm text-pretty text-muted-foreground"> <p className="text-sm text-pretty text-muted-foreground">
@@ -182,12 +186,11 @@ const Feature224 = ({ className }: Feature224Props) => {
</div> </div>
</CarouselItem> </CarouselItem>
))} ))}
</CarouselContent> </CarouselContent> <div className="mt-8 hidden items-center justify-center gap-4 md:flex">
<div className="mt-8 hidden items-center justify-center gap-4 md:flex"> <CarouselPrevious className="static size-12 translate-y-0 rtl:rotate-180" />
<CarouselPrevious className="static size-12 translate-y-0" /> <CarouselNext className="static size-12 translate-y-0 rtl:rotate-180" />
<CarouselNext className="static size-12 translate-y-0" />
</div> </div>
<div className="mt-6 flex w-full items-center gap-2 md:hidden"> <div className="mt-6 flex w-full min-w-0 items-center gap-2 md:hidden">
{Array.from({ length: FEATURES.length }).map((_, i) => ( {Array.from({ length: FEATURES.length }).map((_, i) => (
<button <button
type="button" type="button"
+12 -7
View File
@@ -114,7 +114,7 @@ const Feature225 = ({ className }: Feature225Props) => {
className={cn("w-full bg-background py-12 md:py-24 lg:py-32", className)} className={cn("w-full bg-background py-12 md:py-24 lg:py-32", className)}
> >
<div className="container px-4 md:px-6"> <div className="container px-4 md:px-6">
<div className="flex flex-col items-center justify-center space-y-4 text-center"> <div className="flex w-full flex-col items-start space-y-4 text-right">
<h2 className="text-3xl font-bold tracking-tighter text-balance sm:text-xl md:text-2xll"> <h2 className="text-3xl font-bold tracking-tighter text-balance sm:text-xl md:text-2xll">
داده پراکنده را به تصمیم تبدیل کنید داده پراکنده را به تصمیم تبدیل کنید
</h2> </h2>
@@ -125,10 +125,11 @@ const Feature225 = ({ className }: Feature225Props) => {
<div className="mt-16"> <div className="mt-16">
<Tabs <Tabs
dir="rtl"
defaultValue={FEATURES[0].id} defaultValue={FEATURES[0].id}
value={activeTab} value={activeTab}
onValueChange={setActiveTab} onValueChange={setActiveTab}
className="w-full" className="w-full min-w-0"
> >
<div className="grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-4"> <div className="grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-4">
{FEATURES.map((feature) => ( {FEATURES.map((feature) => (
@@ -141,8 +142,8 @@ const Feature225 = ({ className }: Feature225Props) => {
onClick={() => setActiveTab(feature.id)} onClick={() => setActiveTab(feature.id)}
> >
<CardContent className="p-6"> <CardContent className="p-6">
<div className="flex flex-col items-start space-y-2 text-start"> <div className="flex w-full flex-col items-start space-y-2 text-right">
<div className="flex items-center gap-2"> <div className="flex w-full items-center justify-start gap-2">
<div className="flex size-10 shrink-0 items-center justify-center rounded-full bg-primary/10"> <div className="flex size-10 shrink-0 items-center justify-center rounded-full bg-primary/10">
{feature.icon} {feature.icon}
</div> </div>
@@ -150,7 +151,7 @@ const Feature225 = ({ className }: Feature225Props) => {
{feature.title} {feature.title}
</h3> </h3>
</div> </div>
<p className="text-sm text-pretty text-muted-foreground"> <p className="w-full text-sm text-pretty text-muted-foreground">
{feature.description} {feature.description}
</p> </p>
</div> </div>
@@ -184,8 +185,12 @@ const Feature225 = ({ className }: Feature225Props) => {
className="size-full object-cover" className="size-full object-cover"
/> />
) : ( ) : (
<div className="flex size-full items-center justify-center bg-muted"> <div className="flex size-full items-center justify-center bg-muted p-6">
<p className="text-muted-foreground">داده فروش، بازاریابی و پشتیبانی در داشبوردهای یکپارچه جمع می‌شود. مدیران بدون انتظار گزارش دستی، وضعیت واقعی کسب‌وکار را می‌بینند.</p> <p className="text-right text-pretty text-muted-foreground">
داده فروش، بازاریابی و پشتیبانی در داشبوردهای یکپارچه جمع
می‌شود. مدیران بدون انتظار گزارش دستی، وضعیت واقعی
کسب‌وکار را می‌بینند.
</p>
</div> </div>
)} )}
</div> </div>
+22 -15
View File
@@ -10,19 +10,26 @@ interface Feature228Props {
const Feature228 = ({ className }: Feature228Props) => { const Feature228 = ({ className }: Feature228Props) => {
return ( return (
<section dir="rtl" lang="fa" className={cn("bg-muted/50 py-32", className)}> <section
<div className="container"> dir="rtl"
<div className="grid grid-cols-1 items-center gap-10 lg:grid-cols-2 lg:gap-0"> lang="fa"
<div className="text-start lg:pe-16"> className={cn(
<h2 className="mb-5 text-2xll text-balance md:text-2xll md:leading-20"> "w-full min-w-0 overflow-x-hidden bg-muted/50 py-16 md:py-24 lg:py-32",
className,
)}
>
<div className="container px-4 sm:px-6 lg:px-8">
<div className="grid w-full min-w-0 grid-cols-1 items-center gap-10 lg:grid-cols-2 lg:gap-12 xl:gap-16">
<div className="min-w-0 text-start lg:pe-16">
<h2 className="mb-5 text-xl leading-tight font-semibold text-balance md:text-2xll md:leading-20">
با هوش مصنوعی سریع‌تر تصمیم بگیرید با هوش مصنوعی سریع‌تر تصمیم بگیرید
<br /> <br />
کارهای تکراری را به AI بسپارید کارهای تکراری را به AI بسپارید
</h2> </h2>
<p className="text-lg text-pretty text-muted-foreground"> <p className="text-base text-pretty text-muted-foreground md:text-lg">
مدل‌های هوشمند الگوهای پنهان در داده فروش و پشتیبانی را پیدا می‌کنند. تیم‌ها با پیشنهادهای عملی، سریع‌تر اقدام می‌کنند. مدل‌های هوشمند الگوهای پنهان در داده فروش و پشتیبانی را پیدا می‌کنند. تیم‌ها با پیشنهادهای عملی، سریع‌تر اقدام می‌کنند.
</p> </p>
<div className="mt-12 grid gap-8 sm:grid-cols-2 sm:gap-10"> <div className="mt-8 grid gap-6 sm:mt-12 sm:grid-cols-2 sm:gap-8 md:gap-10">
<div> <div>
<span className="mb-4 grid size-12 place-items-center rounded-lg bg-muted-foreground/10"> <span className="mb-4 grid size-12 place-items-center rounded-lg bg-muted-foreground/10">
<Lightbulb /> <Lightbulb />
@@ -81,27 +88,27 @@ const Feature228 = ({ className }: Feature228Props) => {
</div> </div>
</div> </div>
</div> </div>
<div className="flex h-full flex-col gap-6 sm:max-h-[440px] sm:flex-row xl:max-h-[550px]"> <div className="flex w-full min-w-0 flex-col gap-6 md:max-h-[440px] md:flex-row xl:max-h-[550px]">
<div className="flex flex-col gap-6"> <div className="flex min-w-0 flex-1 flex-col gap-6">
<img <img
src="/block-media/shadcnblocks/block/placeholder-2.svg" src="/block-media/shadcnblocks/block/placeholder-2.svg"
alt="تحلیل با AI" alt="تحلیل با AI"
className="aspect-video rounded-2xl border border-border object-cover" className="aspect-video w-full rounded-2xl border border-border object-cover"
/> />
<img <img
src="/block-media/shadcnblocks/block/placeholder-3.svg" src="/block-media/shadcnblocks/block/placeholder-3.svg"
alt="دستیار هوش مصنوعی" alt="دستیار هوش مصنوعی"
className="ms-auto aspect-video flex-1 rounded-2xl border border-border object-cover sm:aspect-auto sm:w-2/3" className="aspect-video w-full rounded-2xl border border-border object-cover md:ms-auto md:aspect-auto md:w-2/3"
/> />
</div> </div>
<div className="min-h-[580px] rounded-4xl border border-border p-2 sm:min-h-0 sm:max-w-56 sm:shrink-0 xl:max-w-72"> <div className="mx-auto aspect-[9/16] w-full max-w-72 rounded-4xl border border-border p-2 md:mx-0 md:aspect-auto md:max-w-56 md:shrink-0 xl:max-w-72">
<div className="flex h-full flex-col rounded-3xl border border-border bg-background px-1.5 pt-3 pb-1.5"> <div className="flex h-full flex-col rounded-3xl border border-border bg-background px-1.5 pt-3 pb-1.5">
<div className="mx-auto mb-3 h-4 w-16 rounded-full bg-muted-foreground/15 xl:h-5 xl:w-20" /> <div className="mx-auto mb-3 h-4 w-16 shrink-0 rounded-full bg-muted-foreground/15 xl:h-5 xl:w-20" />
<div className="flex-1"> <div className="min-h-0 flex-1">
<img <img
src="/block-media/shadcnblocks/block/placeholder-1.svg" src="/block-media/shadcnblocks/block/placeholder-1.svg"
alt="پیشنهادهای هوشمند" alt="پیشنهادهای هوشمند"
className="h-full rounded-2xl object-cover" className="size-full rounded-2xl object-cover"
/> />
</div> </div>
</div> </div>
+20 -13
View File
@@ -12,27 +12,34 @@ interface Feature234Props {
const Feature234 = ({ className }: Feature234Props) => { const Feature234 = ({ className }: Feature234Props) => {
return ( return (
<section dir="rtl" lang="fa" className={cn("bg-background py-32", className)}> <section
<div className="container flex flex-col items-center"> dir="rtl"
<h1 className="font-inter mx-auto max-w-4xl text-center text-[70px] leading-[65px] font-semibold tracking-tighter text-balance lg:text-[85px] lg:leading-[86px]"> lang="fa"
className={cn(
"w-full min-w-0 overflow-x-hidden bg-background py-12 sm:py-20 lg:py-32",
className,
)}
>
<div className="container flex min-w-0 flex-col items-center px-4 sm:px-6">
<h1 className="font-inter mx-auto max-w-full text-center text-3xl leading-tight font-semibold tracking-tighter text-balance sm:text-5xl md:text-6xl lg:max-w-4xl lg:text-[85px] lg:leading-[86px]">
عملیات سازمان را یکپارچه کنید عملیات سازمان را یکپارچه کنید
</h1> </h1>
<CardsContainer /> <CardsContainer />
<p className="font-inter mx-auto max-w-xl text-center text-lg font-medium text-pretty text-black"> <p className="font-inter mx-auto max-w-xl text-center text-base font-medium text-pretty text-black sm:text-lg">
گزارش‌های یکپارچه نشان می‌دهد کدام بخش بیشترین تأثیر را روی سودآوری دارد. گزارش‌های یکپارچه نشان می‌دهد کدام بخش بیشترین تأثیر را روی سودآوری دارد.
</p> </p>
<div className="mt-10 flex items-center gap-2"> <div className="mt-8 flex w-full max-w-full flex-wrap items-center justify-center gap-2 sm:mt-10">
<Button <Button
asChild asChild
variant="default" variant="default"
className="block h-fit w-fit rounded-full px-6 py-2 text-sm leading-loose" className="block h-auto max-w-full rounded-full px-5 py-2 text-sm leading-loose whitespace-normal"
> >
<a href="#">از خرید تا فروش در یک سیستم</a> <a href="#">از خرید تا فروش در یک سیستم</a>
</Button> </Button>
<Button <Button
asChild asChild
variant="secondary" variant="secondary"
className="block h-fit w-fit rounded-full px-6 py-2 text-sm leading-loose" className="block h-auto max-w-full rounded-full px-5 py-2 text-sm leading-loose whitespace-normal"
> >
<a href="#">یکپارچگی</a> <a href="#">یکپارچگی</a>
</Button> </Button>
@@ -108,20 +115,20 @@ const CardsContainer = () => {
const [hoveredIndex, setHoveredIndex] = useState<number | null>(null); const [hoveredIndex, setHoveredIndex] = useState<number | null>(null);
return ( return (
<div className="my-16 ms-[50px] flex items-center justify-center lg:ms-0"> <div className="my-10 flex w-full max-w-full items-center justify-center overflow-hidden sm:my-14 lg:my-16">
{CARDS.map((card, index) => { {CARDS.map((card, index) => {
const yOffset = Math.pow(Math.abs(index - 3), 1.2) * 12; const yOffset = Math.pow(Math.abs(index - 3), 1.2) * 12;
const isHovered = hoveredIndex === index; const isHovered = hoveredIndex === index;
const visibilityClasses = const visibilityClasses =
(index === 0 || index === 1 || index === 5 || index === 6 (index === 0 || index === 1 || index === 5 || index === 6
? " hidden sm:hidden " ? "hidden sm:hidden "
: "") + : "") +
(index === 0 || index === 6 ? "md:hidden " : "md:block ") + (index === 0 || index === 6 ? "md:hidden " : "md:block ") +
"lg:block"; "lg:block";
return ( return (
<motion.div <motion.div
className={visibilityClasses} className={cn("shrink-0", visibilityClasses)}
key={card.id} key={card.id}
onMouseEnter={() => setHoveredIndex(index)} onMouseEnter={() => setHoveredIndex(index)}
onMouseLeave={() => setHoveredIndex(null)} onMouseLeave={() => setHoveredIndex(null)}
@@ -134,14 +141,14 @@ const CardsContainer = () => {
> >
<div <div
className={cn( className={cn(
"relative h-[176px] w-[177px] overflow-hidden rounded-3xl border", "relative h-28 w-28 overflow-hidden rounded-2xl border sm:h-36 sm:w-36 sm:rounded-3xl lg:h-[176px] lg:w-[177px]",
index !== 0 && "-ms-7 sm:-ms-9 lg:-ms-[50px]",
card.isDark card.isDark
? "mb-14 border-[#8b8b8b] bg-black shadow-2xl" ? "mb-8 border-[#8b8b8b] bg-black shadow-2xl sm:mb-14"
: "border-[#cecece] bg-[#f5f5f5] shadow-lg", : "border-[#cecece] bg-[#f5f5f5] shadow-lg",
)} )}
style={{ style={{
transform: `rotate(${card.rotate}deg)`, transform: `rotate(${card.rotate}deg)`,
marginInlineStart: index === 0 ? "0px" : "-50px",
}} }}
> >
<img <img
+41 -22
View File
@@ -14,44 +14,63 @@ interface Feature236Props {
const Feature236 = ({ className }: Feature236Props) => { const Feature236 = ({ className }: Feature236Props) => {
return ( return (
<section dir="rtl" lang="fa" className={cn("bg-background py-32", className)}> <section
<div className="container flex flex-col items-center gap-10 md:gap-0"> dir="rtl"
lang="fa"
className={cn(
"w-full min-w-0 overflow-x-hidden bg-background py-12 sm:py-20 lg:py-32",
className,
)}
>
<div className="container flex min-w-0 flex-col items-center gap-8 px-4 sm:gap-10 sm:px-6 md:gap-0">
<Button <Button
variant="outline" variant="outline"
className="flex items-center justify-center gap-5 rounded-full px-5! py-5 text-sm font-medium text-muted-foreground" className="h-auto max-w-full gap-3 rounded-full px-4 py-4 text-sm font-medium whitespace-normal text-muted-foreground sm:gap-5 sm:px-5 sm:py-5"
> >
<Group /> <Group className="size-4 shrink-0 sm:size-5" />
تمام تعاملات، سرنخ‌ها و قراردادها در یک فضای کاری متمرکز جمع می‌شود. تیم فروش بدون جابجایی بین ابزارها، سریع‌تر پیش‌بینی می‌کند و معاملات بیشتری می‌بندد. <span className="text-pretty">
<ArrowUpRight className="rtl:rotate-180" /> تمام تعاملات، سرنخ‌ها و قراردادها در یک فضای کاری متمرکز جمع می‌شود.
تیم فروش بدون جابجایی بین ابزارها، سریع‌تر پیش‌بینی می‌کند و معاملات
بیشتری می‌بندد.
</span>
<ArrowUpRight className="size-4 shrink-0 rtl:rotate-180" />
</Button> </Button>
<BracketedBorder> <BracketedBorder>
<div className="mb-7 flex items-center justify-center gap-5 tracking-tight"> <div className="mb-5 flex w-full min-w-0 max-w-2xl items-center justify-center gap-3 px-2 tracking-tight sm:mb-7 sm:gap-5 sm:px-4">
<div className="relative flex items-center justify-center"> <div className="relative flex shrink-0 items-center justify-center">
<span className="absolute inline-block size-2 rounded-full bg-green-300" /> <span className="absolute inline-block size-2 rounded-full bg-green-300" />
<span className="absolute inline-block size-3 animate-ping rounded-full bg-green-300" /> <span className="absolute inline-block size-3 animate-ping rounded-full bg-green-300" />
</div> </div>
<p>از اولین تماس تا تمدید قرارداد، هر مرحله فروش قابل ردیابی است. گزارش‌های لحظه‌ای به مدیران کمک می‌کند گلوگاه‌ها را قبل از از دست دادن درآمد شناسایی کنند.</p> <p className="min-w-0 text-pretty text-sm text-muted-foreground sm:text-base">
از اولین تماس تا تمدید قرارداد، هر مرحله فروش قابل ردیابی است.
گزارش‌های لحظه‌ای به مدیران کمک می‌کند گلوگاه‌ها را قبل از از دست
دادن درآمد شناسایی کنند.
</p>
</div> </div>
<h1 className="max-w-xl px-4 text-center text-2xll font-semibold tracking-tighter text-balance text-foreground md:text-[90px] md:leading-22"> <h1 className="max-w-full px-2 text-center text-3xl font-semibold tracking-tighter text-balance text-foreground sm:px-4 sm:text-4xl md:max-w-3xl md:text-5xl md:leading-tight lg:text-6xl xl:text-7xl">
هر سرنخ را تا قرارداد دنبال کنید هر سرنخ را تا قرارداد دنبال کنید
</h1> </h1>
</BracketedBorder> </BracketedBorder>
<h2 className="text-3xl font-medium tracking-tighter text-foreground">
<h2 className="max-w-full px-2 text-center text-2xl font-medium tracking-tighter text-balance text-foreground sm:text-3xl">
فروش تیم‌تان را یکجا مدیریت کنید فروش تیم‌تان را یکجا مدیریت کنید
</h2> </h2>
<p className="max-w-2xl px-10 text-center text-pretty text-muted-foreground sm:mt-5 lg:text-xl"> <p className="max-w-2xl px-2 text-center text-pretty text-muted-foreground sm:mt-5 sm:px-6 lg:text-xl">
پروفایل یکپارچه مشتری، تاریخچه تماس و وضعیت معامله را همزمان نشان می‌دهد. تیم‌ها با دید مشترک، هماهنگ‌تر پیش می‌روند و نرخ تبدیل بالاتر می‌رود. پروفایل یکپارچه مشتری، تاریخچه تماس و وضعیت معامله را همزمان نشان
می‌دهد. تیم‌ها با دید مشترک، هماهنگ‌تر پیش می‌روند و نرخ تبدیل بالاتر
می‌رود.
</p> </p>
<div className="flex flex-col gap-4 sm:mt-8 md:flex-row"> <div className="flex w-full min-w-0 max-w-2xl flex-col gap-4 sm:mt-8 md:flex-row md:justify-center">
<Button className="h-11 w-full rounded-xl sm:w-auto"> <Button className="h-auto min-h-11 w-full rounded-xl px-4 py-2 whitespace-normal sm:w-auto">
روابط مشتری را در یک نگاه ببینید روابط مشتری را در یک نگاه ببینید
</Button> </Button>
<Button <Button
variant="outline" variant="outline"
className="h-11 w-full gap-2 rounded-xl sm:w-auto" className="h-auto min-h-11 w-full gap-2 rounded-xl px-4 py-2 whitespace-normal sm:w-auto"
> >
پایپ‌لاین فروش را شفاف کنید پایپ‌لاین فروش را شفاف کنید
<ArrowRight className="size-4 rtl:rotate-180" /> <ArrowRight className="size-4 shrink-0 rtl:rotate-180" />
</Button> </Button>
</div> </div>
</div> </div>
@@ -61,12 +80,12 @@ const Feature236 = ({ className }: Feature236Props) => {
const BracketedBorder = ({ children }: { children: ReactNode }) => ( const BracketedBorder = ({ children }: { children: ReactNode }) => (
<motion.div <motion.div
initial={{ width: 0, opacity: 0 }} initial={{ opacity: 0, scaleX: 0.85 }}
className="relative flex flex-col items-center justify-center sm:my-10 md:h-[500px] md:overflow-hidden" className="relative flex w-full min-w-0 max-w-full flex-col items-center justify-center overflow-hidden sm:my-10 md:min-h-[500px]"
whileInView={{ width: "65vw", opacity: 1 }} whileInView={{ opacity: 1, scaleX: 1 }}
viewport={{ once: true }} viewport={{ once: true }}
transition={{ transition={{
width: { scaleX: {
type: "spring", type: "spring",
stiffness: 50, stiffness: 50,
damping: 20, damping: 20,
@@ -86,7 +105,7 @@ const BracketedBorder = ({ children }: { children: ReactNode }) => (
<Vector className="absolute start-1 bottom-1" /> <Vector className="absolute start-1 bottom-1" />
<Vector className="absolute end-1 bottom-1 -rotate-90" /> <Vector className="absolute end-1 bottom-1 -rotate-90" />
</div> </div>
<div className="flex h-full w-screen flex-col items-center justify-center"> <div className="flex w-full min-w-0 max-w-4xl flex-col items-center justify-center px-4 py-8 md:max-w-[65vw] md:py-12">
{children} {children}
</div> </div>
</motion.div> </motion.div>
+50 -34
View File
@@ -7,45 +7,53 @@ import { cn } from "@/lib/utils";
const Feature239 = () => { const Feature239 = () => {
return ( return (
<section dir="rtl" lang="fa" className="bg-background py-32"> <section
<div className="relative container flex flex-col items-center px-0! lg:pt-8"> dir="rtl"
<DottedDiv> lang="fa"
<div className="grid lg:grid-cols-2"> className="w-full min-w-0 overflow-x-hidden bg-background py-12 sm:py-20 lg:py-32"
<div className="flex w-full flex-col gap-8 px-10 py-20 text-start md:px-14"> >
<div className="relative container flex min-w-0 flex-col items-center px-4 sm:px-6 lg:px-8 lg:pt-8">
<DottedDiv className="w-full min-w-0">
<div className="grid min-w-0 lg:grid-cols-2">
<div className="flex w-full min-w-0 flex-col gap-6 px-2 py-10 text-start sm:gap-8 sm:px-6 sm:py-14 md:px-10 md:py-20 lg:px-14">
<Badge <Badge
variant="outline" variant="outline"
className="flex w-fit cursor-pointer items-center gap-4 rounded-full px-6 py-2 transition-all ease-in-out hover:gap-6" className="flex h-auto w-full max-w-full cursor-pointer items-start gap-3 rounded-full px-4 py-3 whitespace-normal transition-all ease-in-out hover:gap-4 sm:w-fit sm:items-center sm:px-6 sm:py-2"
> >
<span className="text-sm font-medium tracking-tight text-muted-foreground"> <span className="min-w-0 text-sm font-medium tracking-tight text-pretty text-muted-foreground">
قوانین ساده تعریف کنید تا وظایف تکراری بدون دخالت دست انجام شود. تیم روی تصمیم‌های مهم تمرکز می‌کند و سرعت اجرا بالاتر می‌رود. قوانین ساده تعریف کنید تا وظایف تکراری بدون دخالت دست انجام
شود. تیم روی تصمیم‌های مهم تمرکز می‌کند و سرعت اجرا بالاتر
می‌رود.
</span> </span>
<ChevronRight className="size-4! rtl:rotate-180" /> <ChevronRight className="size-4 shrink-0 rtl:rotate-180" />
</Badge> </Badge>
<h1 className="text-2xll font-semibold tracking-tighter text-balance md:text-2xll"> <h1 className="text-2xl font-semibold tracking-tighter text-balance text-foreground sm:text-3xl md:text-2xll">
فرایندها را استاندارد و سریع کنید فرایندها را استاندارد و سریع کنید
<br /> <br />
اتوماسیون را در کل سازمان یکپارچه کنید اتوماسیون را در کل سازمان یکپارچه کنید
<br /> <br />
خطای انسانی را در کارهای روزمره کم کنید خطای انسانی را در کارهای روزمره کم کنید
</h1> </h1>
<p className="tracking-tight text-pretty text-muted-foreground md:text-xl"> <p className="tracking-tight text-pretty text-muted-foreground sm:text-lg md:text-xl">
فرایندهای بین‌تیمی را در یک بوم بصری طراحی کنید. هر مرحله قابل ردیابی است و گلوگاه‌ها قبل از تأخیر جدی مشخص می‌شوند. فرایندهای بین‌تیمی را در یک بوم بصری طراحی کنید. هر مرحله قابل
ردیابی است و گلوگاه‌ها قبل از تأخیر جدی مشخص می‌شوند.
</p> </p>
<div className="flex w-full gap-2"> <div className="flex w-full flex-wrap gap-2">
<Button className="text-md h-12 w-fit rounded-full bg-primary px-10 text-primary-foreground"> <Button className="text-md h-12 w-fit rounded-full bg-primary px-8 text-primary-foreground sm:px-10">
شروع کنید شروع کنید
</Button> </Button>
<Button <Button
variant="outline" variant="outline"
className="text-md h-12 w-12 rounded-full transition-all ease-in-out hover:rotate-45" className="text-md h-12 w-12 shrink-0 rounded-full transition-all ease-in-out hover:rotate-45"
> >
<ArrowUpRight className="rtl:rotate-180" /> <ArrowUpRight className="rtl:rotate-180" />
</Button> </Button>
</div> </div>
</div> </div>
<DottedDiv className="group size-full place-self-end p-4 lg:w-4/6">
<div className="relative size-full bg-muted/50 p-4 transition-all ease-in-out group-hover:bg-muted"> <DottedDiv className="group min-w-0 place-self-end p-2 sm:p-4 lg:w-4/6">
<div className="relative size-full overflow-hidden rounded-3xl"> <div className="relative min-h-80 w-full bg-muted/50 p-3 transition-all ease-in-out group-hover:bg-muted sm:min-h-96 sm:p-4">
<div className="relative size-full min-h-72 overflow-hidden rounded-2xl sm:min-h-80 sm:rounded-3xl">
<img <img
src="/block-media/shadcnblocks/block/photos/simone-hutsch-5oYbG-sEImY-unsplash.jpg" src="/block-media/shadcnblocks/block/photos/simone-hutsch-5oYbG-sEImY-unsplash.jpg"
alt="سازنده گردش‌کار" alt="سازنده گردش‌کار"
@@ -54,32 +62,40 @@ const Feature239 = () => {
<div className="absolute inset-0 bg-linear-to-t from-black/70 to-transparent" /> <div className="absolute inset-0 bg-linear-to-t from-black/70 to-transparent" />
</div> </div>
<div className="absolute top-4 -ms-4 flex size-full flex-col items-center justify-between p-10"> <div className="absolute inset-0 flex flex-col items-center justify-between p-4 sm:p-6 lg:p-10">
<p className="flex w-full items-center text-xl tracking-tighter text-background"> <p className="flex w-full min-w-0 flex-col gap-2 text-sm tracking-tighter text-pretty text-background sm:flex-row sm:items-center sm:text-base lg:text-xl">
با اتصال ابزارهای موجود، داده بین سیستم‌ها خودکار جریان پیدا می‌کند و نیاز به کپی دستی از بین می‌رود. <span className="min-w-0">
<span className="mx-2 h-2.5 w-px bg-background" /> با اتصال ابزارهای موجود، داده بین سیستم‌ها خودکار جریان
قوانین ساده تعریف کنید تا وظایف تکراری بدون دخالت دست انجام شود. تیم روی تصمیم‌های مهم تمرکز می‌کند و سرعت اجرا بالاتر می‌رود. پیدا می‌کند و نیاز به کپی دستی از بین می‌رود.
</span>
<span className="hidden h-2.5 w-px shrink-0 bg-background sm:block" />
<span className="min-w-0">
قوانین ساده تعریف کنید تا وظایف تکراری بدون دخالت دست
انجام شود.
</span>
</p> </p>
<div className="flex flex-col items-center justify-center"> <div className="flex flex-col items-center justify-center px-2">
<h2 className="text-center text-2xll font-semibold tracking-tight text-balance text-background"> <h2 className="text-center text-xl font-semibold tracking-tight text-balance text-background sm:text-2xl lg:text-2xll">
کارهای تکراری را خودکار کنید کارهای تکراری را خودکار کنید
<br /> <br />
گردش‌کار تیم را بدون کد بسازید گردش‌کار تیم را بدون کد بسازید
</h2> </h2>
<div className="mt-2 h-1 w-6 rounded-full bg-background" /> <div className="mt-2 h-1 w-6 rounded-full bg-background" />
<p className="mt-10 max-w-sm px-2 text-center text-lg leading-5 font-light tracking-tighter text-pretty text-background/80"> <p className="mt-6 max-w-sm text-center text-sm leading-5 font-light tracking-tighter text-pretty text-background/80 sm:mt-10 sm:text-lg">
فرایندهای بین‌تیمی را در یک بوم بصری طراحی کنید. هر مرحله قابل ردیابی است و گلوگاه‌ها قبل از تأخیر جدی مشخص می‌شوند. فرایندهای بین‌تیمی را در یک بوم بصری طراحی کنید. هر مرحله
قابل ردیابی است و گلوگاه‌ها قبل از تأخیر جدی مشخص
می‌شوند.
</p> </p>
</div> </div>
<a <a
href="#" href="#"
className="group mb-6 flex cursor-pointer flex-col items-center justify-center text-background" className="group mb-2 flex cursor-pointer flex-col items-center justify-center text-background sm:mb-6"
> >
<ChevronUp <ChevronUp
size={30} size={30}
className="transition-all ease-in-out group-hover:-translate-y-2" className="transition-all ease-in-out group-hover:-translate-y-2"
/> />
<p className="text-xl tracking-tight text-background"> <p className="text-base tracking-tight text-background sm:text-xl">
مشاهده همه مشاهده همه
</p> </p>
</a> </a>
@@ -102,11 +118,11 @@ const DottedDiv = ({
children: React.ReactNode; children: React.ReactNode;
className?: string; className?: string;
}) => ( }) => (
<div className={cn("relative", className)}> <div className={cn("relative min-w-0 overflow-hidden", className)}>
<div className="absolute top-4 -start-25 h-px w-[115%] bg-muted" /> <div className="absolute top-4 start-4 end-4 h-px bg-muted lg:end-auto lg:w-[115%] lg:-start-25" />
<div className="absolute bottom-4 -start-25 h-px w-[115%] bg-muted" /> <div className="absolute bottom-4 start-4 end-4 h-px bg-muted lg:end-auto lg:w-[115%] lg:-start-25" />
<div className="absolute -top-25 start-4 h-[130%] w-px bg-muted" /> <div className="absolute start-4 top-4 bottom-4 w-px bg-muted lg:top-auto lg:bottom-auto lg:h-[130%] lg:-top-25" />
<div className="absolute -top-25 end-4 h-[130%] w-px bg-muted" /> <div className="absolute end-4 top-4 bottom-4 w-px bg-muted lg:top-auto lg:bottom-auto lg:h-[130%] lg:-top-25" />
<div className="absolute start-[12.5px] top-[12.5px] z-10 size-2 rounded-full bg-foreground" /> <div className="absolute start-[12.5px] top-[12.5px] z-10 size-2 rounded-full bg-foreground" />
<div className="absolute end-[12.5px] top-[12.5px] z-10 size-2 rounded-full bg-foreground" /> <div className="absolute end-[12.5px] top-[12.5px] z-10 size-2 rounded-full bg-foreground" />
<div className="absolute start-[12.5px] bottom-[12.5px] z-10 size-2 rounded-full bg-foreground" /> <div className="absolute start-[12.5px] bottom-[12.5px] z-10 size-2 rounded-full bg-foreground" />
+3 -3
View File
@@ -133,9 +133,9 @@ const Feature240 = () => {
))} ))}
</CarouselContent> </CarouselContent>
<div className="mt-5 flex justify-end gap-3"> <div className="mt-5 flex justify-start gap-3">
<CarouselPrevious className="static size-12" /> <CarouselPrevious className="static size-12 translate-y-0 rtl:rotate-180" />
<CarouselNext variant="default" className="static size-12" /> <CarouselNext variant="default" className="static size-12 translate-y-0 rtl:rotate-180" />
</div> </div>
</Carousel> </Carousel>
</div> </div>
+5 -26
View File
@@ -1,6 +1,6 @@
"use client"; "use client";
import { ChevronLeft, ChevronRight, Plus } from "lucide-react"; import { ChevronRight, Plus } from "lucide-react";
import React from "react"; import React from "react";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
@@ -9,6 +9,8 @@ import {
Carousel, Carousel,
CarouselContent, CarouselContent,
CarouselItem, CarouselItem,
CarouselNext,
CarouselPrevious,
} from "@/components/ui/carousel"; } from "@/components/ui/carousel";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
@@ -149,32 +151,9 @@ const Feature242 = ({ className }: Feature242Props) => {
</span> </span>
</div> </div>
{/*
Embla RTL: scrollNext/scrollPrev are index-based, so default
ChevronLeft→prev / ChevronRight→next feels reversed visually.
Match arrow direction to movement by swapping handlers.
*/}
<div className="relative z-10 flex gap-2"> <div className="relative z-10 flex gap-2">
<Button <CarouselPrevious className="static size-10 translate-y-0 rtl:rotate-180" />
type="button" <CarouselNext className="static size-10 translate-y-0 rtl:rotate-180" />
variant="outline"
size="icon"
className="size-10 rounded-full"
onClick={() => api?.scrollNext()}
aria-label="اسلاید بعدی"
>
<ChevronLeft className="size-4" />
</Button>
<Button
type="button"
variant="default"
size="icon"
className="size-10 rounded-full"
onClick={() => api?.scrollPrev()}
aria-label="اسلاید قبلی"
>
<ChevronRight className="size-4" />
</Button>
</div> </div>
</div> </div>
</Carousel> </Carousel>
+3 -3
View File
@@ -93,11 +93,11 @@ const Feature244 = () => {
</CarouselItem> </CarouselItem>
))} ))}
</CarouselContent> </CarouselContent>
<div className="my-3 flex justify-end gap-3 pe-5"> <div className="my-3 flex justify-start gap-3 ps-4 sm:ps-5">
<CarouselPrevious className="static m-0 size-12 translate-y-0 p-0" /> <CarouselPrevious className="static m-0 size-12 translate-y-0 p-0 rtl:rotate-180" />
<CarouselNext <CarouselNext
variant="default" variant="default"
className="static size-12 translate-y-0" className="static size-12 translate-y-0 rtl:rotate-180"
/> />
</div> </div>
</Carousel> </Carousel>
+15 -11
View File
@@ -7,7 +7,7 @@ import { Card, CardContent } from "@/components/ui/card";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
const handwrittenTextClasses = const handwrittenTextClasses =
"flex gap-3 font-handwriting text-xs tracking-tight md:text-xl"; "flex min-w-0 items-center gap-2 font-handwriting text-xs tracking-tight xl:gap-3 xl:text-xl";
const FEATURES = [ const FEATURES = [
{ id: "dark-mode", label: "ترافیک ارگانیک" }, { id: "dark-mode", label: "ترافیک ارگانیک" },
@@ -97,9 +97,13 @@ interface Feature245Props {
const Feature245 = ({ className }: Feature245Props) => { const Feature245 = ({ className }: Feature245Props) => {
return ( return (
<section dir="rtl" lang="fa" className={cn("bg-background", className)}> <section
<div className="relative container flex flex-col items-center overflow-hidden py-32"> dir="rtl"
<div className="mx-auto max-w-3xl text-center"> lang="fa"
className={cn("relative w-full min-w-0 overflow-hidden bg-background", className)}
>
<div className="relative container flex min-w-0 flex-col items-center overflow-hidden py-16 md:py-24 lg:py-32">
<div className="mx-auto w-full min-w-0 max-w-3xl px-4 text-center">
<h1 className="text-2xll font-semibold tracking-tighter text-balance text-foreground md:text-2xll"> <h1 className="text-2xll font-semibold tracking-tighter text-balance text-foreground md:text-2xll">
رتبه کلمات کلیدی را پیگیری کنید رتبه کلمات کلیدی را پیگیری کنید
</h1> </h1>
@@ -107,8 +111,8 @@ const Feature245 = ({ className }: Feature245Props) => {
تحلیل فنی، محتوا و رقبا در یک ابزار جمع می‌شود. تیم محتوا می‌داند روی کدام صفحه و کلمه باید تمرکز کند. تحلیل فنی، محتوا و رقبا در یک ابزار جمع می‌شود. تیم محتوا می‌داند روی کدام صفحه و کلمه باید تمرکز کند.
</p> </p>
</div> </div>
<div className="relative z-10 mx-auto mt-12 min-h-full max-w-3xl md:w-1/2"> <div className="relative z-10 mx-auto mt-12 w-full min-w-0 max-w-3xl px-4 lg:w-1/2 lg:px-0">
<div className="absolute -start-52 z-10 hidden h-full flex-col items-end justify-between md:flex lg:-start-62"> <div className="absolute -start-40 z-10 hidden h-full flex-col items-end justify-between xl:flex xl:-start-52 2xl:-start-62">
{[0, 1, 2, 3].map((i) => ( {[0, 1, 2, 3].map((i) => (
<motion.div <motion.div
key={FEATURES[i].id} key={FEATURES[i].id}
@@ -129,7 +133,7 @@ const Feature245 = ({ className }: Feature245Props) => {
</motion.div> </motion.div>
))} ))}
</div> </div>
<div className="absolute -end-58 z-10 hidden h-full flex-col justify-between md:flex lg:-end-64"> <div className="absolute -end-40 z-10 hidden h-full flex-col justify-between xl:flex xl:-end-52 2xl:-end-64">
{[4, 5, 6, 7].map((i) => ( {[4, 5, 6, 7].map((i) => (
<motion.div <motion.div
key={FEATURES[i].id} key={FEATURES[i].id}
@@ -152,12 +156,12 @@ const Feature245 = ({ className }: Feature245Props) => {
</div> </div>
<motion.div <motion.div
initial={{ opacity: 0, y: 200 }} initial={{ opacity: 0, y: 40 }}
animate={{ opacity: 100, y: 0 }} animate={{ opacity: 1, y: 0 }}
transition={{ ease: [0.33, 1, 0.68, 1], duration: 0.8 }} transition={{ ease: [0.33, 1, 0.68, 1], duration: 0.8 }}
className="relative z-0" className="relative z-0 w-full min-w-0"
> >
<Card className="group h-130 w-full rounded-4xl border border-border bg-background p-2 shadow-none lg:p-3"> <Card className="group aspect-[4/3] h-auto max-h-80 w-full rounded-4xl border border-border bg-background p-2 shadow-none sm:max-h-96 xl:h-130 xl:max-h-none xl:aspect-auto lg:p-3">
<CardContent className="size-full rounded-3xl border-2 border-background bg-muted"> <CardContent className="size-full rounded-3xl border-2 border-background bg-muted">
<img <img
src="/block-media/shadcnblocks/block/placeholder-1.svg" src="/block-media/shadcnblocks/block/placeholder-1.svg"
+14 -10
View File
@@ -24,10 +24,14 @@ const Feature251 = ({ className }: Feature251Props) => {
const div6Ref = useRef<HTMLDivElement>(null); const div6Ref = useRef<HTMLDivElement>(null);
const div7Ref = useRef<HTMLDivElement>(null); const div7Ref = useRef<HTMLDivElement>(null);
return ( return (
<section dir="rtl" lang="fa" className={cn("py-32", className)}> <section
<div className="container"> dir="rtl"
<div className="mx-auto flex max-w-5xl flex-wrap items-center justify-center gap-5"> lang="fa"
<Card className="relative h-96 w-166 rounded-3xl border"> className={cn("relative w-full min-w-0 overflow-hidden py-16 md:py-24 lg:py-32", className)}
>
<div className="container min-w-0 px-4 sm:px-6">
<div className="mx-auto flex w-full min-w-0 max-w-5xl flex-wrap items-center justify-center gap-5">
<Card className="relative h-96 w-full min-w-0 overflow-hidden rounded-3xl border md:w-166">
<CardHeader className="text-start"> <CardHeader className="text-start">
<h3 className="text-xl font-semibold tracking-tight text-balance"> <h3 className="text-xl font-semibold tracking-tight text-balance">
تریگر رویداد تریگر رویداد
@@ -36,7 +40,7 @@ const Feature251 = ({ className }: Feature251Props) => {
شرط هوشمند شرط هوشمند
</p> </p>
</CardHeader> </CardHeader>
<CardContent ref={containerRef1} className="relative ms-5"> <CardContent ref={containerRef1} className="relative ms-2 overflow-hidden sm:ms-5">
<IconCard <IconCard
ref={div1Ref as React.RefObject<HTMLDivElement>} ref={div1Ref as React.RefObject<HTMLDivElement>}
src="/block-media/shadcnblocks/block/logos/google-icon.svg" src="/block-media/shadcnblocks/block/logos/google-icon.svg"
@@ -47,7 +51,7 @@ const Feature251 = ({ className }: Feature251Props) => {
ref={div2Ref as React.RefObject<HTMLDivElement>} ref={div2Ref as React.RefObject<HTMLDivElement>}
src="/block-media/shadcnblocks/block/logos/figma-icon.svg" src="/block-media/shadcnblocks/block/logos/figma-icon.svg"
imageAlt="نمای اتوماسیون فرایند" imageAlt="نمای اتوماسیون فرایند"
className="translate-x-32 rtl:-translate-x-32" className="translate-x-12 rtl:-translate-x-12 sm:translate-x-20 sm:rtl:-translate-x-20 md:translate-x-32 md:rtl:-translate-x-32"
/> />
<IconCard <IconCard
ref={div3Ref as React.RefObject<HTMLDivElement>} ref={div3Ref as React.RefObject<HTMLDivElement>}
@@ -59,7 +63,7 @@ const Feature251 = ({ className }: Feature251Props) => {
ref={div5Ref as React.RefObject<HTMLDivElement>} ref={div5Ref as React.RefObject<HTMLDivElement>}
src="/block-media/shadcnblocks/block/block-1.svg" src="/block-media/shadcnblocks/block/block-1.svg"
imageAlt="سازنده گردش‌کار" imageAlt="سازنده گردش‌کار"
className="absolute end-12 top-1/2 -translate-y-1/2" className="absolute end-4 top-1/2 -translate-y-1/2 sm:end-8 md:end-12"
/> />
<div <div
ref={div4Ref as React.RefObject<HTMLDivElement>} ref={div4Ref as React.RefObject<HTMLDivElement>}
@@ -94,7 +98,7 @@ const Feature251 = ({ className }: Feature251Props) => {
</CardContent> </CardContent>
</Card> </Card>
<Card className="h-96 w-full rounded-3xl border md:w-83"> <Card className="h-96 w-full min-w-0 overflow-hidden rounded-3xl border md:w-83">
<CardHeader className="text-start"> <CardHeader className="text-start">
<h3 className="text-xl font-semibold tracking-tight text-balance"> <h3 className="text-xl font-semibold tracking-tight text-balance">
اعلان خودکار اعلان خودکار
@@ -132,7 +136,7 @@ const Feature251 = ({ className }: Feature251Props) => {
</CardContent> </CardContent>
</Card> </Card>
<Card className="relative flex h-96 w-full flex-col rounded-3xl border md:w-[330px]"> <Card className="relative flex h-96 w-full min-w-0 flex-col overflow-hidden rounded-3xl border md:w-[330px]">
<CardContent> <CardContent>
<img <img
src="/block-media/shadcnblocks/block/block-1.svg" src="/block-media/shadcnblocks/block/block-1.svg"
@@ -149,7 +153,7 @@ const Feature251 = ({ className }: Feature251Props) => {
</p> </p>
</CardHeader> </CardHeader>
</Card> </Card>
<Card className="relative flex h-96 w-166 flex-col overflow-hidden rounded-3xl border"> <Card className="relative flex h-96 w-full min-w-0 flex-col overflow-hidden rounded-3xl border md:w-166">
<CardHeader className="relative z-10 shrink-0 text-start"> <CardHeader className="relative z-10 shrink-0 text-start">
<h3 className="text-xl font-semibold tracking-tight text-balance"> <h3 className="text-xl font-semibold tracking-tight text-balance">
اتصال ابزار اتصال ابزار
+26 -17
View File
@@ -72,12 +72,19 @@ const Feature313 = ({
const isMobile = useIsMobile(); const isMobile = useIsMobile();
return ( return (
<section dir="rtl" lang="fa" className={cn("bg-muted py-24", className)}> <section
<div className="container flex flex-col gap-2"> dir="rtl"
<div className="grid grid-cols-1 gap-1 lg:grid-cols-4"> lang="fa"
className={cn("relative w-full min-w-0 overflow-hidden bg-muted py-16 md:py-24", className)}
>
<div className="container flex min-w-0 flex-col gap-2 px-4 sm:px-6">
<div className="grid w-full min-w-0 grid-cols-1 gap-1 lg:grid-cols-4">
{cards.map((card, index) => ( {cards.map((card, index) => (
<Card key={card.id} className="border-none p-10 text-start shadow-none"> <Card
<div className="flex items-center justify-between gap-2"> key={card.id}
className="min-w-0 overflow-hidden border-none p-5 text-start shadow-none sm:p-8 lg:p-10"
>
<div className="flex min-w-0 items-center justify-between gap-2">
<div className="flex gap-1"> <div className="flex gap-1">
{cards.map((_, circleIndex) => ( {cards.map((_, circleIndex) => (
<div <div
@@ -90,7 +97,7 @@ const Feature313 = ({
{(index + 1).toLocaleString("fa-IR").padStart(2, "۰")} {(index + 1).toLocaleString("fa-IR").padStart(2, "۰")}
</div> </div>
</div> </div>
<div className="flex flex-col gap-4 md:flex-row md:justify-between"> <div className="flex min-w-0 flex-col gap-4 md:flex-row md:justify-between">
<div className="aspect-square size-12 shrink-0"> <div className="aspect-square size-12 shrink-0">
<img <img
src={card.image} src={card.image}
@@ -99,7 +106,7 @@ const Feature313 = ({
/> />
</div> </div>
<div className="min-w-0 flex-1"> <div className="min-w-0 flex-1">
<h3 className="text-md leading-tight font-medium text-pretty"> <h3 className="text-md leading-tight font-medium text-balance break-words">
{card.title} {card.title}
</h3> </h3>
</div> </div>
@@ -111,7 +118,7 @@ const Feature313 = ({
<Dialog> <Dialog>
<DialogTrigger asChild> <DialogTrigger asChild>
<motion.div <motion.div
className="group relative aspect-video min-h-72 cursor-pointer overflow-hidden rounded-lg" className="group relative aspect-video w-full min-w-0 min-h-48 cursor-pointer overflow-hidden rounded-lg sm:min-h-72"
whileHover="hover" whileHover="hover"
initial="initial" initial="initial"
> >
@@ -126,10 +133,10 @@ const Feature313 = ({
<motion.img <motion.img
src={imageSrc} src={imageSrc}
alt={imageAlt} alt={imageAlt}
className="h-full w-full rounded-lg object-cover" className="h-full w-full max-w-full rounded-lg object-cover"
variants={{ variants={{
initial: { scale: 1 }, initial: { scale: 1 },
hover: { scale: 1.1 }, hover: isMobile ? { scale: 1 } : { scale: 1.1 },
}} }}
transition={{ duration: 0.3, ease: "easeOut" }} transition={{ duration: 0.3, ease: "easeOut" }}
/> />
@@ -148,7 +155,7 @@ const Feature313 = ({
initial: { x: 0, scale: 1 }, initial: { x: 0, scale: 1 },
hover: { hover: {
x: isMobile ? 0 : "-75%", x: isMobile ? 0 : "-75%",
scale: 1.2, scale: isMobile ? 1 : 1.2,
}, },
}} }}
transition={{ duration: 0.3, ease: "easeOut" }} transition={{ duration: 0.3, ease: "easeOut" }}
@@ -163,18 +170,20 @@ const Feature313 = ({
</motion.div> </motion.div>
<motion.div <motion.div
className="text-center md:text-start" className="min-w-0 text-center md:text-start"
variants={{ variants={{
initial: { opacity: 1 }, initial: { opacity: 1 },
hover: { opacity: 0, transform: "-translate-y-3" }, hover: isMobile
? { opacity: 1 }
: { opacity: 0, transform: "-translate-y-3" },
}} }}
transition={{ duration: 0.3, ease: "easeOut" }} transition={{ duration: 0.3, ease: "easeOut" }}
> >
<div className="px-4 py-2"> <div className="px-2 py-2 sm:px-4">
<p className="text-lg font-bold text-secondary"> <p className="text-base font-bold text-balance break-words text-secondary sm:text-lg">
{videoCaption} {videoCaption}
</p> </p>
<p className="text-lg font-medium text-muted-foreground"> <p className="text-base font-medium text-balance break-words text-muted-foreground sm:text-lg">
{videoSecondaryCaption} {videoSecondaryCaption}
</p> </p>
</div> </div>
@@ -183,7 +192,7 @@ const Feature313 = ({
</div> </div>
</motion.div> </motion.div>
</DialogTrigger> </DialogTrigger>
<DialogContent className="w-full border-none bg-black p-0 md:max-w-6xl md:p-1"> <DialogContent className="w-[calc(100%-2rem)] max-w-[calc(100%-2rem)] border-none bg-black p-0 sm:w-full md:max-w-6xl md:p-1">
<DialogTitle className="sr-only">{videoCaption}</DialogTitle> <DialogTitle className="sr-only">{videoCaption}</DialogTitle>
<DialogDescription className="sr-only"> <DialogDescription className="sr-only">
{videoSecondaryCaption} {videoCaption} {videoSecondaryCaption} {videoCaption}
+36 -5
View File
@@ -8,7 +8,7 @@ import {
useScroll, useScroll,
useTransform, useTransform,
} from "framer-motion"; } from "framer-motion";
import React, { useRef, useState } from "react"; import React, { useLayoutEffect, useRef, useState } from "react";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
@@ -228,11 +228,31 @@ const Feature322 = ({
testimonial = DEFAULT_TESTIMONIAL, testimonial = DEFAULT_TESTIMONIAL,
}: Feature322Props) => { }: Feature322Props) => {
const scrollRef = useRef<HTMLElement>(null); const scrollRef = useRef<HTMLElement>(null);
const [stageHeight, setStageHeight] = useState(0);
const { scrollYProgress } = useScroll({ const { scrollYProgress } = useScroll({
container: scrollRef, container: scrollRef,
}); });
const [activeIndex, setActiveIndex] = useState(0); const [activeIndex, setActiveIndex] = useState(0);
useLayoutEffect(() => {
const scrollContainer = scrollRef.current;
if (!scrollContainer) return;
const updateStageHeight = () => {
setStageHeight(scrollContainer.clientHeight);
};
updateStageHeight();
const observer = new ResizeObserver(updateStageHeight);
observer.observe(scrollContainer);
return () => observer.disconnect();
}, []);
const scrollSegmentCount = Math.max(features.length - 1, 1);
const scrollSpacerHeight =
stageHeight > 0 ? stageHeight * scrollSegmentCount : undefined;
useMotionValueEvent(scrollYProgress, "change", (latest) => { useMotionValueEvent(scrollYProgress, "change", (latest) => {
const nextIndex = getActiveFeatureIndex(latest, features.length); const nextIndex = getActiveFeatureIndex(latest, features.length);
setActiveIndex((prev) => (prev === nextIndex ? prev : nextIndex)); setActiveIndex((prev) => (prev === nextIndex ? prev : nextIndex));
@@ -246,14 +266,21 @@ const Feature322 = ({
dir="rtl" dir="rtl"
lang="fa" lang="fa"
className={cn( className={cn(
"relative h-svh w-full min-w-[20rem] max-w-full overflow-x-clip overflow-y-auto sm:min-w-[36rem] lg:min-w-[64rem]", "relative h-svh max-h-full min-h-[28rem] w-full min-w-[20rem] max-w-full overflow-x-clip overflow-y-auto overscroll-contain sm:min-w-[36rem] lg:min-h-[32rem] lg:min-w-[64rem]",
className, className,
)} )}
> >
<div className="container min-w-0 w-full max-w-full"> <div className="container min-w-0 w-full max-w-full">
{/* Desktop: sticky stage + scroll spacer */} {/* Desktop: sticky stage + scroll spacer */}
<div className="relative hidden lg:block"> <div className="relative hidden lg:block">
<div className="sticky top-0 flex h-svh w-full min-w-0 flex-col items-center justify-center"> <div
className="sticky top-0 z-10 flex w-full min-w-0 flex-col items-center justify-center"
style={
stageHeight > 0
? { height: stageHeight }
: { minHeight: "28rem" }
}
>
<div className="relative w-full min-w-0 max-w-full"> <div className="relative w-full min-w-0 max-w-full">
<AnimatePresence mode="wait" initial={false}> <AnimatePresence mode="wait" initial={false}>
{activeFeature ? ( {activeFeature ? (
@@ -279,8 +306,12 @@ const Feature322 = ({
</div> </div>
<div <div
style={{ height: `${Math.max(features.length, 1) * 75}vh` }} style={
className="pointer-events-none w-full" scrollSpacerHeight
? { height: scrollSpacerHeight }
: { height: `${scrollSegmentCount * 75}vh` }
}
className="pointer-events-none w-full shrink-0"
aria-hidden aria-hidden
/> />
</div> </div>
+1 -1
View File
@@ -70,7 +70,7 @@ const Feature52 = ({ className }: Feature52Props) => {
return ( return (
<section dir="rtl" lang="fa" className={cn("py-32", className)}> <section dir="rtl" lang="fa" className={cn("py-32", className)}>
<div className="container"> <div className="container">
<Tabs defaultValue="feature-1"> <Tabs defaultValue="feature-1" dir="rtl">
<TabsList className="flex h-auto w-full flex-wrap items-stretch justify-between gap-2 bg-background p-0 group-data-horizontal/tabs:h-auto"> <TabsList className="flex h-auto w-full flex-wrap items-stretch justify-between gap-2 bg-background p-0 group-data-horizontal/tabs:h-auto">
{tabs.map((tab, index) => ( {tabs.map((tab, index) => (
<TabsTrigger <TabsTrigger
+2 -2
View File
@@ -1,5 +1,5 @@
import { import {
ArrowRight, ArrowLeft,
Blocks, Blocks,
MessagesSquare, MessagesSquare,
MoveRight, MoveRight,
@@ -26,7 +26,7 @@ const Hero26 = ({ className }: Hero26Props) => {
<Badge className="rounded-full">نسخه جدید</Badge> <Badge className="rounded-full">نسخه جدید</Badge>
معرفی Collaboration 2.0 معرفی Collaboration 2.0
<span className="flex size-7 items-center justify-center rounded-full bg-muted"> <span className="flex size-7 items-center justify-center rounded-full bg-muted">
<ArrowRight className="w-4" /> <ArrowLeft className="w-4" />
</span> </span>
</a> </a>
<h1 className="mx-auto mt-4 mb-3 max-w-3xl text-xl font-semibold text-balance lg:mb-7 lg:text-2xll"> <h1 className="mx-auto mt-4 mb-3 max-w-3xl text-xl font-semibold text-balance lg:mb-7 lg:text-2xll">
+77 -41
View File
@@ -8,21 +8,33 @@ import {
Share2, Share2,
Sparkles, Sparkles,
Video, Video,
type LucideIcon,
} from "lucide-react"; } from "lucide-react";
import { Marquee } from "@/components/ui/marquee"; import {
Marquee,
MarqueeContent,
MarqueeFade,
MarqueeItem,
} from "@/components/kibo-ui/marquee";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
const integrations = [ const integrations: {
name: string;
description: string;
icon: LucideIcon;
}[] = [
{ {
name: "ذخیره‌سازی", name: "ذخیره‌سازی",
description: "فایل‌های ویدیویی خود را به‌صورت امن در فضای ذخیره‌سازی دلخواه مدیریت کنید.", description:
"فایل‌های ویدیویی خود را به‌صورت امن در فضای ذخیره‌سازی دلخواه مدیریت کنید.",
icon: Cloud, icon: Cloud,
}, },
{ {
name: "هوش مصنوعی", name: "هوش مصنوعی",
description: "با کمک هوش مصنوعی، تولید محتوای ویدیویی و تصویری را سرعت دهید.", description:
"با کمک هوش مصنوعی، تولید محتوای ویدیویی و تصویری را سرعت دهید.",
icon: Sparkles, icon: Sparkles,
}, },
{ {
@@ -37,7 +49,8 @@ const integrations = [
}, },
{ {
name: "شبکه‌های اجتماعی", name: "شبکه‌های اجتماعی",
description: "ویدیوهای خود را تنها با چند کلیک در شبکه‌های اجتماعی منتشر کنید.", description:
"ویدیوهای خود را تنها با چند کلیک در شبکه‌های اجتماعی منتشر کنید.",
icon: Share2, icon: Share2,
}, },
{ {
@@ -47,6 +60,27 @@ const integrations = [
}, },
]; ];
function IntegrationCard({
name,
description,
icon: Icon,
}: (typeof integrations)[number]) {
return (
<div
dir="rtl"
className="flex h-28 w-72 shrink-0 gap-2 rounded-lg border border-border p-4 text-right dark:bg-muted"
>
<Icon className="mt-0.5 size-4 shrink-0" />
<div className="flex min-w-0 flex-1 flex-col gap-2">
<p className="text-sm font-medium">{name}</p>
<p className="line-clamp-3 text-sm text-muted-foreground">
{description}
</p>
</div>
</div>
);
}
interface Hero40Props { interface Hero40Props {
className?: string; className?: string;
} }
@@ -59,10 +93,11 @@ const Hero40 = ({ className }: Hero40Props) => {
<div className="flex flex-col gap-6"> <div className="flex flex-col gap-6">
<h1 className="text-2xll font-bold"> <h1 className="text-2xll font-bold">
همه ابزارهای موردنیاز خود را یکپارچه کنید همه ابزارهای موردنیاز خود را یکپارچه کنید
</h1> </h1>
<p className="text-lg text-muted-foreground"> <p className="text-lg text-muted-foreground">
تمام سرویس‌ها و ابزارهای کاری خود را به یکدیگر متصل کنید و فرایند تولید و انتشار محتوا را ساده‌تر کنید. تمام سرویس‌ها و ابزارهای کاری خود را به یکدیگر متصل کنید و فرایند
</p> تولید و انتشار محتوا را ساده‌تر کنید.
</p>
<div className="flex gap-4"> <div className="flex gap-4">
<Button variant="outline" size="lg"> <Button variant="outline" size="lg">
<span>مشاهده دمو</span> <span>مشاهده دمو</span>
@@ -100,41 +135,42 @@ const Hero40 = ({ className }: Hero40Props) => {
alt="تصویر نمونه" alt="تصویر نمونه"
className="aspect-video w-full rounded-lg border border-border object-cover" className="aspect-video w-full rounded-lg border border-border object-cover"
/> />
<div className="relative flex w-full flex-col items-center justify-center overflow-hidden"> <div
<Marquee className="[--duration:30s]"> dir="rtl"
{integrations.map((integration) => ( className="relative flex w-full flex-col items-center justify-center gap-4 overflow-hidden"
<div >
key={integration.name} <Marquee className="w-full">
className="flex max-w-72 gap-2 rounded-lg border border-border p-4 dark:bg-muted" <MarqueeContent
> direction="right"
<integration.icon className="mt-0.5 size-4 shrink-0" /> speed={40}
<div className="flex flex-col gap-2"> loop={0}
<p className="text-sm">{integration.name}</p> autoFill
<p className="text-sm text-muted-foreground"> pauseOnHover={false}
{integration.description} >
</p> {integrations.map((integration) => (
</div> <MarqueeItem key={`fwd-${integration.name}`}>
</div> <IntegrationCard {...integration} />
))} </MarqueeItem>
))}
</MarqueeContent>
</Marquee> </Marquee>
<Marquee reverse className="[--duration:30s]"> <Marquee className="w-full">
{integrations.map((integration) => ( <MarqueeContent
<div direction="right"
key={integration.name} speed={40}
className="flex max-w-72 gap-2 rounded-lg border border-border p-4 dark:bg-muted" loop={0}
> autoFill
<integration.icon className="mt-0.5 size-4 shrink-0" /> pauseOnHover={false}
<div className="flex flex-col gap-2"> >
<p className="text-sm">{integration.name}</p> {integrations.map((integration) => (
<p className="text-sm text-muted-foreground"> <MarqueeItem key={`rev-${integration.name}`}>
{integration.description} <IntegrationCard {...integration} />
</p> </MarqueeItem>
</div> ))}
</div> </MarqueeContent>
))}
</Marquee> </Marquee>
<div className="pointer-events-none absolute inset-y-0 left-0 w-1/4 bg-gradient-to-r from-background"></div> <MarqueeFade side="left" />
<div className="pointer-events-none absolute inset-y-0 right-0 w-1/4 bg-gradient-to-l from-background"></div> <MarqueeFade side="right" />
</div> </div>
</div> </div>
</div> </div>
+9 -6
View File
@@ -1,3 +1,5 @@
"use client";
import { ArrowLeft } from "lucide-react"; import { ArrowLeft } from "lucide-react";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
@@ -91,19 +93,20 @@ const Testimonial31 = ({
</Button> </Button>
</div> </div>
<div className="relative mt-8 -mr-[max(3rem,calc((100vw-80rem)/2+3rem))] md:mt-12 lg:mt-20"> <div className="relative mt-8 -ml-[max(3rem,calc((100vw-80rem)/2+3rem))] md:mt-12 lg:mt-20">
<Carousel <Carousel
opts={{ opts={{
align: "start", align: "start",
loop: true, loop: true,
direction: "rtl",
}} }}
className="w-full" className="w-full"
> >
<CarouselContent> <CarouselContent className="-mr-4 ml-0">
{testimonials.map((testimonial, index) => ( {testimonials.map((testimonial, index) => (
<CarouselItem <CarouselItem
key={index} key={index}
className="basis-4/5 sm:basis-3/5 md:basis-2/5 lg:basis-[28%] xl:basis-[28%] 2xl:basis-1/4" className="basis-4/5 pl-0 pr-4 sm:basis-3/5 md:basis-2/5 lg:basis-[28%] xl:basis-[28%] 2xl:basis-1/4"
> >
<Card className="h-full overflow-hidden border-none bg-muted !pt-0"> <Card className="h-full overflow-hidden border-none bg-muted !pt-0">
<CardContent className="flex h-full flex-col p-0"> <CardContent className="flex h-full flex-col p-0">
@@ -132,9 +135,9 @@ const Testimonial31 = ({
</CarouselItem> </CarouselItem>
))} ))}
</CarouselContent> </CarouselContent>
<div className="mt-8 flex gap-3"> <div className="mt-8 flex justify-start gap-3">
<CarouselPrevious className="static size-14 translate-x-0 translate-y-0 bg-muted transition-colors hover:bg-muted/80 [&>svg]:size-6 lg:[&>svg]:size-8" /> <CarouselPrevious className="static size-14 translate-x-0 translate-y-0 bg-muted transition-colors hover:bg-muted/80 rtl:rotate-180 [&>svg]:size-6 lg:[&>svg]:size-8" />
<CarouselNext className="static size-14 translate-x-0 translate-y-0 bg-muted transition-colors hover:bg-muted/80 [&>svg]:size-6 lg:[&>svg]:size-8" /> <CarouselNext className="static size-14 translate-x-0 translate-y-0 bg-muted transition-colors hover:bg-muted/80 rtl:rotate-180 [&>svg]:size-6 lg:[&>svg]:size-8" />
</div> </div>
</Carousel> </Carousel>
</div> </div>