مسار التنقّل (Breadcrumb)
يعرض مكوّن مسار التنقّل مكان الصفحة الحالية في موقعك على شكل سلسلة من الروابط، ويعيد القارئ إلى أي مستوى أعلى بنقرة واحدة. تركّبه من أجزاء، فيضم عدد الخطوات الذي تحتاجه الصفحة، ويتبع اتجاه القراءة فيها.
التثبيت
npx @smicolon/fasla-ui@latest add breadcrumbقبل إضافة أي مكوّن، شغّل الأمر init مرة واحدة في مشروعك. التفاصيل في صفحة التثبيت.
معاينة
الأنماط (variant)
في Figma أربعة أنماط. يرسم المكوّن BreadcrumbSeparator سهمًا ما لم تمرّر إليه أيقونة، فالأيقونة SlashIcon تعطيك الفاصل المخصص. أما نمطا الشارة فتركيبان: شارة Soft أو Outline من المكوّن Badge داخل كل خطوة.
الأيقونات
أضف أيقونة قبل التسمية بالخاصية icon في المكوّن BreadcrumbLink أو BreadcrumbPage. يضبط المكوّن حجمها على 14px ويترك 4px بينها وبين التسمية، فمرّر الأيقونة دون حجم خاص بها. وفي نمطي الشارة، مرّر الأيقونة إلى المكوّن Badge بخاصيته icon، وهو يضبط حجمها ومسافتها. الأيقونات زخرفية، فيتخطاها قارئ الشاشة.
مسار مختصر
إذا طال المسار، فأبقِ الخطوة الأولى وآخر خطوتين، وضع المكوّن BreadcrumbEllipsis مكان الخطوات التي بينهما. يبقى الترتيب نفسه في الاتجاهين. ولكي يصل القارئ إلى الخطوات المخفية، اجعل النقاط الثلاث العنصرَ المُشغِّل لقائمة منسدلة DropdownMenu تعرض تلك الخطوات روابطَ، كما في هذين المثالين: اضغط على النقاط الثلاث لفتح القائمة. أما النقاط الثلاث وحدها فتدل على موضع الخطوات المحذوفة فحسب.
إتاحة الوصول (accessibility)
- المكوّن
Breadcrumbمنطقة تنقّل في الصفحة. سمّها بلغة الصفحة بالخاصيةaria-labelكما تفعل الأمثلة هنا، وإلا فاسمهاBreadcrumb. والخطوات قائمة مرتبة، فيعلن قارئ الشاشة عددها. - يحمل المكوّن
BreadcrumbPageالسمةaria-current="page"، وهو نص عادي، لا رابط إلى الصفحة التي يقرؤها القارئ. - الفواصل والأيقونات مخفية عن قارئ الشاشة. أما النقاط الثلاث فيقرؤها «المزيد»، أو «More» حين تكون أقرب قيمة لـ
langهي الإنجليزية. - حين تكون النقاط الثلاث العنصرَ المُشغِّل لقائمة، فهي زر. سمّها بالخاصية
aria-labelكما تفعل الأمثلة هنا، ليعلن قارئ الشاشة ما تحويه القائمة. يفتح مفتاح Enter أو مفتاح المسافة أو السهم السفلي القائمة، وتنتقل مفاتيح الأسهم بين الخطوات، ويفتح مفتاح Enter الرابط، ويغلق مفتاح Escape القائمة ويعيد التركيز إلى النقاط الثلاث. - تُظهر الروابط، والنقاط الثلاث حين تفتح قائمة، حلقة التركيز حين تنتقل إليها بلوحة المفاتيح.
- يتبع المسار السمة
dirفي الصفحة: في العربية تبدأ الخطوات من بداية السطر، وينقلب السهم معها. ويأتي ارتفاع السطر العربي الأطول من سلّم الخطوط، دون أي إعداد منك.
الخصائص (props)
Breadcrumb
| الخاصية | النوع | الافتراضي | الوصف |
|---|---|---|---|
aria-label | string | "Breadcrumb" | اسم منطقة التنقّل لقارئ الشاشة، بلغة الصفحة. |
children | ReactNode | لا يوجد | المكوّن BreadcrumbList. |
className | string | لا يوجد | أصناف إضافية للعنصر nav. |
BreadcrumbList
| الخاصية | النوع | الافتراضي | الوصف |
|---|---|---|---|
children | ReactNode | لا يوجد | الخطوات والفواصل، بترتيب القراءة. |
className | string | لا يوجد | أصناف إضافية للعنصر ol. |
BreadcrumbItem
| الخاصية | النوع | الافتراضي | الوصف |
|---|---|---|---|
children | ReactNode | لا يوجد | خطوة واحدة: رابط أو الصفحة الحالية أو النقاط الثلاث. |
className | string | لا يوجد | أصناف إضافية للعنصر li. |
BreadcrumbLink
| الخاصية | النوع | الافتراضي | الوصف |
|---|---|---|---|
href | string | لا يوجد | وجهة الخطوة. ويقبل الرابط كل سمات العنصر a الأخرى أيضًا. |
asChild | boolean | false | يجعل العنصر الذي بداخله، مثل المكوّن Link في Next.js، هو الرابط. |
icon | ReactNode | لا يوجد | أيقونة قبل التسمية، بحجم 14px. |
children | ReactNode | لا يوجد | تسمية الخطوة. |
className | string | لا يوجد | أصناف إضافية للرابط. |
BreadcrumbPage
| الخاصية | النوع | الافتراضي | الوصف |
|---|---|---|---|
icon | ReactNode | لا يوجد | أيقونة قبل التسمية، بحجم 14px. |
children | ReactNode | لا يوجد | اسم الصفحة الحالية. |
className | string | لا يوجد | أصناف إضافية للصفحة الحالية. |
BreadcrumbSeparator
| الخاصية | النوع | الافتراضي | الوصف |
|---|---|---|---|
children | ReactNode | لا يوجد | أيقونة تحلّ محل السهم، مثل SlashIcon. |
className | string | لا يوجد | أصناف إضافية للفاصل. |
BreadcrumbEllipsis
| الخاصية | النوع | الافتراضي | الوصف |
|---|---|---|---|
className | string | لا يوجد | أصناف إضافية للنقاط الثلاث. نص قارئ الشاشة مضمَّن فيها. |
الاستخدام
مسار أساسي
import {
Breadcrumb,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbPage,
BreadcrumbSeparator,
} from "@/components/ui/breadcrumb"
export function DocumentBreadcrumb() {
return (
<Breadcrumb aria-label="مسار التنقّل">
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink href="/">الرئيسية</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbLink href="/projects">
المشاريع
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbLink href="/docs">
المستندات
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbPage>إضافة مستند</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
)
}مسار مختصر
import { HouseIcon } from "lucide-react"
import {
Breadcrumb,
BreadcrumbEllipsis,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbPage,
BreadcrumbSeparator,
} from "@/components/ui/breadcrumb"
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"
const TRIGGER = [
"-m-[5px] inline-flex size-6 cursor-pointer items-center",
"justify-center rounded-[var(--radius-sm)] transition-colors",
"hover:bg-accent data-[popup-open]:bg-accent",
"focus-visible:outline focus-visible:outline-2",
"focus-visible:outline-ring motion-reduce:transition-none",
].join(" ")
export function CollapsedBreadcrumb() {
return (
<Breadcrumb aria-label="مسار التنقّل">
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink href="/" icon={<HouseIcon />}>
الرئيسية
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<DropdownMenu>
<DropdownMenuTrigger
aria-label="الخطوات المخفية"
className={TRIGGER}
>
<BreadcrumbEllipsis />
</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuItem render={<a href="/projects" />}>
المشاريع
</DropdownMenuItem>
<DropdownMenuItem render={<a href="/projects/website" />}>
الموقع الإلكتروني
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbLink href="/docs">المستندات</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbPage>إضافة مستند</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
)
}فاصل مخصص
import { SlashIcon } from "lucide-react"
import {
Breadcrumb,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbPage,
BreadcrumbSeparator,
} from "@/components/ui/breadcrumb"
export function SlashBreadcrumb() {
return (
<Breadcrumb aria-label="مسار التنقّل">
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink href="/">الرئيسية</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator>
<SlashIcon />
</BreadcrumbSeparator>
<BreadcrumbItem>
<BreadcrumbPage>إضافة مستند</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
)
}مع رابط Next.js
import Link from "next/link"
import {
Breadcrumb,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbPage,
BreadcrumbSeparator,
} from "@/components/ui/breadcrumb"
export function ProjectBreadcrumb() {
return (
<Breadcrumb aria-label="مسار التنقّل">
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink asChild>
<Link href="/projects">المشاريع</Link>
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbPage>المستندات</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
)
}مع الشارات
import { SlashIcon } from "lucide-react"
import { Badge } from "@/components/ui/badge"
import {
Breadcrumb,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbPage,
BreadcrumbSeparator,
} from "@/components/ui/breadcrumb"
const DIMMED = [
"rounded-full opacity-60",
"hover:opacity-100 focus-visible:opacity-100",
].join(" ")
export function DepartmentBreadcrumb() {
return (
<Breadcrumb aria-label="مسار التنقّل">
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink href="/marketing" className={DIMMED}>
<Badge variant="soft" size="md">
التسويق
</Badge>
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator>
<SlashIcon />
</BreadcrumbSeparator>
<BreadcrumbItem>
<BreadcrumbPage>
<Badge variant="soft" size="md">
التسويق الإلكتروني
</Badge>
</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
)
}