شارة (Badge)

يعرض مكوّن شارة (Badge) تسمية قصيرة داخل السطر لحالة أو فئة أو معلومة، مع أيقونة أو صورة رمزية أو زر إغلاق عند الحاجة.

التثبيت

bash
npx @smicolon/fasla-ui@latest init
npx @smicolon/fasla-ui@latest add badge

معاينة

جديدمدفوعمميّز

الأنماط (variant)

تحدد الخاصية variant وزن الشارة البصري، وتحدد tone معناها. أبرز الأنماط (variant) هو Solid، ويضع Soft لونًا خفيفًا فوق سطح البطاقة فيبدو كما هو أينما وُضع، وأهدؤها Outline.

جديدمسودةقيد المراجعةمدفوعبانتظار الدفعمتأخر
جديدمسودةقيد المراجعةمدفوعبانتظار الدفعمتأخر
جديدمسودةقيد المراجعةمدفوعبانتظار الدفعمتأخر

تجعل radius="standard" زوايا الشارة صغيرة بدل الشكل الكبسولي.

جديدجديدجديدجديد

الأحجام

الارتفاعات حدود دنيا: للإنجليزية 20px أو 22px أو 26px. أما العربية فسطرها أطول، فتكبر الشارة إلى 24px أو 24px أو 28px بدل أن يُضغط النص.

مميّزمميّزمميّز

الحالات

مرّر onClose فتحصل الشارة على زر إغلاق حقيقي. انتقل إليه بمفتاح Tab لترى حلقة التركيز، وهي تحيط بالشارة كلها على بُعد 2px.

التصميمالهندسةالبحثالتسويق
مميّزليلىليلىمراجِعة

إتاحة الوصول (accessibility)

  • الشارة عنصر <span> بسيط. زر الإغلاق وحده تفاعلي، وهو عنصر <button> أصلي.
  • يُسمّى زر الإغلاق باسم التسمية: «إزالة القاهرة»، أو «Remove Cairo» حين تكون أقرب قيمة لـ lang هي الإنجليزية. ويتبع الاسم تغيير اللغة دون إعادة تحميل. مرّر closeLabel لسياق أوضح، مثل «إزالة عامل التصفية: القاهرة».
  • الأيقونة زخرفية ومخفية عن التقنيات المساعدة، أما الصورة الرمزية فلا. أعطِ مكوّن صورة رمزية (Avatar) قيمة name، أو مرّر name="" إذا كانت التسمية تذكر اسم الشخص.
  • لا تعتمد على اللون الدلالي (tone) وحده لنقل المعنى، بل اكتبه في التسمية.
  • تأخذ الشارة اتجاهها من السمة (attribute) dir، وليس من خاصية، فلا تختلف أبدًا عن اتجاه الصفحة.

الخصائص (props)

الخاصيةالنوعالافتراضيالوصف
childrenReactNodeلا يوجدنص التسمية.
variant"solid" | "soft" | "outline""solid"الوزن البصري.
tone"primary" | "secondary" | "info" | "success" | "warning" | "destructive""primary"المعنى، ويظهر لونًا.
size"sm" | "md" | "lg""sm"حجم الشارة.
radius"rounded" | "standard""rounded"شكل كبسولي أو زوايا صغيرة.
iconReactNodeلا يوجدأيقونة قبل التسمية.
avatarReactNodeلا يوجدصورة رمزية قبل التسمية.
onClose(event) => voidلا يوجديضيف زر إغلاق، وتُستدعى عند الضغط عليه.
closeLabelstringلا يوجداسم زر الإغلاق لقارئ الشاشة، ويتبع لغة الصفحة افتراضيًا.
classNamestringلا يوجدأصناف (class) إضافية للمكوّن.

الاستخدام

الأنماط والألوان الدلالية

tsx
import { Badge } from "@/components/ui/badge"

export function OrderBadges() {
  return (
    <div className="flex flex-wrap items-center gap-2">
      <Badge>جديد</Badge>
      <Badge variant="soft" tone="success">مدفوع</Badge>
      <Badge variant="outline" tone="destructive" size="md">متأخر</Badge>
    </div>
  )
}

الأيقونة والصورة الرمزية: تحدد الشارة حجمهما ولونهما

tsx
import { Star } from "lucide-react"
import { Badge } from "@/components/ui/badge"
import { Avatar } from "@/components/ui/avatar"

interface Reviewer {
  name: string
  // صورة الشخص من بياناتك. إن لم تتوفّر، تعرض الصورة الرمزية أيقونة المستخدم.
  photo?: string
}

const reviewer: Reviewer = { name: "ليلى" }

export function ReviewerBadges() {
  return (
    <div className="flex flex-wrap items-center gap-2">
      <Badge icon={<Star />}>مميّز</Badge>
      <Badge avatar={<Avatar size="12" radius="rounded" src={reviewer.photo} name="" />}>
        {reviewer.name}
      </Badge>
    </div>
  )
}

قابلة للإزالة

tsx
"use client"

import { useState } from "react"
import { Badge } from "@/components/ui/badge"

export function FilterBadges() {
  const [filters, setFilters] = useState(["التصميم", "الهندسة", "البحث"])
  const remove = (filter: string) => setFilters((current) => current.filter((f) => f !== filter))

  return (
    <div className="flex flex-wrap items-center gap-2">
      {filters.map((filter) => (
        <Badge
          key={filter}
          variant="soft"
          onClose={() => remove(filter)}
          closeLabel={`إزالة عامل التصفية: ${filter}`}
        >
          {filter}
        </Badge>
      ))}
    </div>
  )
}