کاستومایز
منوی بینهایتInfinite Menu
کرهای از کاشیهای تصویر که با کشیدن میچرخه، نزدیکترین کاشی رو روبهرو میآره و عنوان و توضیحش رو نشون میده — با پخشِ خودکار و چهار پریستِ شکلی.
وابستگیها
نوع تعامل
کره رو با نشانگر یا انگشت بچرخون؛ سرعتِ رهاکردن با لختی ادامه پیدا میکنه و نزدیکترین کاشی خودش رو روبهرو میآره. کلیک روی کاشیِ روبهرو فقط انتخابش میکنه؛ برای بازکردن/کنش باید `onItemClick` یا `link` بدی (وگرنه فلشِ کنش ساخته نمیشه). کلیدهای جهت کاشیِ همسایه رو میبرن و Enter همون انتخاب رو صدا میزنه؛ هاور/فوکوس پخشِ خودکار رو میایستونه.
پراپها
گزینههایی که میتونی به کامپوننت بدی؛ ستارهدارها اجباریاند.
itemsInfiniteMenuItem[]پیشفرض: []کاشیها؛ هر مورد `image` (اجباری)، `title`، `description` و `link` اختیاری دارد. دموی میزکار شش تصویرِ محلی با عنوان فارسی میدهد.
countnumberپیشفرض: 160تعداد کاشیهای کره؛ ۶ تا ۴۰۰ (بهصورتِ خودکار محدود میشه).
tileSizenumberپیشفرض: 0.63اندازهی هر کاشی نسبت به شعاعِ کره، ۰٫۲ تا ۱٫۲.
roundnessnumberپیشفرض: 0.2گردیِ گوشهی کاشیها، ۰ تا ۱.
zoomnumberپیشفرض: 1.65نزدیکیِ دوربین به کره؛ ۰٫۲ تا ۴.
pullBacknumberپیشفرض: 1چقدر کره هنگامِ کشیدن عقب برود، ۰ تا ۳.
نصب
۱. این آدرس رو یکبار توی components.json بذار تا shadcn مخزن فارسیفای رو بشناسه.
{
"registries": {
"@farsify": "https://farsify.ir/r/{name}.json"
}
}۲. بعد با دستورِ زیر کامپوننت رو نصب کن.
npx shadcn@latest add @farsify/infinite-menuپیشنیاز: Tailwind CSS v4 و صفحهٔ راستبهچپ dir="rtl".
نمونه
"use client";
import InfiniteMenu from "@/components/farsify/infinite-menu";
const photos = [
{
image: "/images/coast.jpg",
title: "ساحل",
description: "خطِ روشنِ افق و موجِ آرام.",
},
{
image: "/images/forest.jpg",
title: "جنگل",
description: "مه میانِ تنههای بلند.",
},
{
image: "/images/city.jpg",
title: "شهر",
description: "چراغها و پنجرههای روشن.",
},
];
export function Gallery() {
return (
<div style={{ height: 480, position: "relative" }}>
<InfiniteMenu items={photos} count={160} theme="dark" />
</div>
);
}
// بدونِ کنشِ بیرونی؛ فلش پنهان میماند و فقط عنوان/توضیح میآید
<InfiniteMenu items={photos} showInfo />
// برای ساختنِ فلشِ کنش، onItemClick یا link بدهید؛ وگرنه کلیک فقط میچرخاند
<InfiniteMenu items={photos} onItemClick={(item) => console.log(item)} />
// کارتِ سبکتر برای موبایل: کاشیهای درشتتر و تعدادِ کمتر
<InfiniteMenu items={photos} count={90} tileSize={0.9} dim={0.25} />نکتهها
- همهی تصاویر توی یه اطلس مینشینن و کاشیها با `drawElementsInstanced` توی یه فراخوانی کشیده میشن؛ نه وابستگیِ `three` لازمه نه یه draw call برای هر کاشی.
- توی RTL عنوان سمتِ راست (شروع) و توضیح سمتِ چپ (پایان) مینشینه؛ توی چیدمانِ باریک اطلاعات پایینراست و فلش پایینچپ میره و فلش هم افقی آینه میشه.
- فاصلهی حروف صفره؛ `letter-spacing` مثبت/منفیِ مرجع روی خطِ فارسی اتصالِ حروف رو خراب میکنه.
- اگه WebGL2 نباشه، بهجای بومِ خالی شبکهای از همون تصاویر نشون داده میشه؛ محتوا و عنوان از دست نمیرن.
- توی `prefers-reduced-motion` معرفی و چرخشِ خودکار خاموش میشه؛ کشیدنِ دستی و کلیدها کار میکنن.
- برای گالریِ سبکتر `count` رو کم و `tileSize` رو زیاد کن؛ برای کلاژِ ریزِ شلوغ برعکس.
مجوز
کد بعد از نصب مالِ خودته؛ هر تغییری خواستی بده و توی پروژهی خودت نگهش دار. برای پروژههای شخصی و تجاری آزاده، حتی اگه کدت بسته باشه. فقط اسم و لینک فارسیفای رو یه جا توی پروژه نگه دار.