نظرِ مشتریها، چرخان
پیشنمایش تمامصفحهبخشِ نظرِ مشتری در دو ردیفِ چرخان با جهتِ مخالف، کارتهای کوتاه با ستاره و عکسِ گوینده؛ با هاور میایستد.
۱. نصب کامپوننتها
این بلاک از ۴ آیتم دیگ استفاده میکند: avatarcontrol-sizeiconsmarquee
پکیجمنیجر پیشفرض Node.jsنصب سریع با لینک سخت و دیسک مشترکYarn نسخهٔ ۲ به بالا (Berry)رانتایم و پکیجمنیجر Bun
npx digdesign@latest add https://docs.digdesign.ir/r/avatar.json https://docs.digdesign.ir/r/control-size.json https://docs.digdesign.ir/r/icons.json https://docs.digdesign.ir/r/marquee.jsonpnpm dlx digdesign@latest add https://docs.digdesign.ir/r/avatar.json https://docs.digdesign.ir/r/control-size.json https://docs.digdesign.ir/r/icons.json https://docs.digdesign.ir/r/marquee.jsonyarn dlx digdesign@latest add https://docs.digdesign.ir/r/avatar.json https://docs.digdesign.ir/r/control-size.json https://docs.digdesign.ir/r/icons.json https://docs.digdesign.ir/r/marquee.jsonbunx --bun digdesign@latest add https://docs.digdesign.ir/r/avatar.json https://docs.digdesign.ir/r/control-size.json https://docs.digdesign.ir/r/icons.json https://docs.digdesign.ir/r/marquee.json۲. کد صفحه
کد را در app/<route>/page.tsx بگذارید و متنها، داده و هندلرها را با محصول خودتان عوض کنید.
testimonials-marquee.tsx
"use client"
import { Avatar } from "@/components/ui/avatar"
import { ControlSizeProvider } from "@/components/ui/control-size"
import { Marquee, MarqueeItem } from "@/components/ui/marquee"
import { StarIcon } from "@/components/icons"
import { stockImages, type StockImageName } from "@/lib/stock-images"
const QUOTES: { text: string; name: string; role: string; photo: StockImageName }[] = [
{ text: "فاکتورها را سه برابر سریعتر میفرستیم.", name: "سارا محمدی", role: "کافه رست", photo: "personWoman2" },
{ text: "اولین ابزاری که حسابدارمان دوستش دارد.", name: "امیر رضایی", role: "فروشگاهِ بوم", photo: "personMan1" },
{ text: "گزارشِ ماهانه دیگر دو روز طول نمیکشد.", name: "نگار احمدی", role: "حسابدارِ آزاد", photo: "personWoman3" },
{ text: "پشتیبانی واقعاً آدم است و زود جواب میدهد.", name: "علی کاظمی", role: "استودیو نقش", photo: "personMan2" },
{ text: "اتصال به بانک یعنی صفر ورودِ دستی.", name: "مهسا کریمی", role: "طراحِ مستقل", photo: "personWoman1" },
]
function QuoteCard({ quote }: { quote: (typeof QUOTES)[number] }) {
return (
<figure className="flex w-80 flex-col gap-4 rounded-xl border border-border bg-card p-5">
<span className="flex gap-0.5" aria-label="پنج ستاره">
{[0, 1, 2, 3, 4].map((star) => (
<StarIcon key={star} aria-hidden className="size-4 fill-[var(--dig-orange-400)] text-[var(--dig-orange-400)]" />
))}
</span>
<blockquote className="leading-7">{quote.text}</blockquote>
<figcaption className="flex items-center gap-3">
<Avatar size="sm" alt="" src={stockImages[quote.photo].src} />
<span className="flex flex-col">
<span className="text-sm font-semibold">{quote.name}</span>
<span className="text-xs text-muted-foreground">{quote.role}</span>
</span>
</figcaption>
</figure>
)
}
/**
* نظرِ مشتریها در دو ردیفِ چرخان با جهتِ مخالف؛ با هاور میایستد و لبهها محو میشوند.
* برای وقتی که نظرها کوتاه و زیادند و میخواهی حجمِ رضایت دیده شود، نه یک داستان.
*/
export default function TestimonialsMarqueeBlock() {
return (
<ControlSizeProvider size="xl" asChild>
<section aria-labelledby="tm-title" className="flex flex-col gap-12 py-24">
<div className="mx-auto flex max-w-2xl flex-col items-center gap-3 px-4 text-center">
<span className="text-sm font-semibold text-brand-secondary">نظرِ مشتریها</span>
<h2 id="tm-title" className="text-3xl leading-snug font-black text-balance sm:text-4xl">
هزاران کسبوکار هر روز با ما کار میکنند
</h2>
</div>
<div className="flex flex-col gap-4">
<Marquee fade pauseOnHover duration={45} gap={16} repeat={2}>
{QUOTES.map((quote) => (
<MarqueeItem key={quote.name}>
<QuoteCard quote={quote} />
</MarqueeItem>
))}
</Marquee>
<Marquee fade pauseOnHover direction="reverse" duration={50} gap={16} repeat={2}>
{[...QUOTES].reverse().map((quote) => (
<MarqueeItem key={quote.name}>
<QuoteCard quote={quote} />
</MarqueeItem>
))}
</Marquee>
</div>
</section>
</ControlSizeProvider>
)
}