زر (Button)
ينفّذ مكوّن زر إجراءً، أو ينقل القارئ إلى مكان آخر. يأتي بخمسة أنماط وثلاثة ألوان دلالية وأربعة أحجام وشكلين للزوايا، كما في Figma، مع حالة تحميل.
التثبيت
npx @smicolon/fasla-ui@latest add buttonقبل إضافة أي مكوّن، شغّل الأمر init مرة واحدة في مشروعك. التفاصيل في صفحة التثبيت.
معاينة
الأنماط (variant)
تختار الخاصية variant نمط الزر. الأنماط default، secondary، destructive ممتلئة. وللنمط outline حدّ من الداخل، ولا يمتلئ النمط ghost إلا عند التمرير فوقه، ويضع النمط soft صبغة خفيفة فوق سطح البطاقة. أما النمط link فنص تحته خط في كل الحالات.
الألوان الدلالية
تختار الخاصية tone اللون داخل النمط: primary، secondary، destructive. لكل نمط لون افتراضي، فالنمط outline وحده محايد، وإذا أضفت إليه القيمة destructive صار زرًّا للإجراءات الخطرة.
defaultsoftoutlineghostlinkالأحجام
أربعة أحجام: ارتفاع الحجم xs هو 26px، والحجم sm هو 32px، والحجم md هو 36px، والحجم lg هو 40px. والأيقونة بحجم 16px في كل الأحجام. وللزر الذي فيه أيقونة فقط، استخدم أحجام الأيقونة في صفحة زر الأيقونة.
الزوايا
تجعل القيمة standard للخاصية radius الزوايا مستديرة بنصف قطر 8px، وتجعل القيمة rounded الزر على شكل كبسولة. وتتبع حلقة التركيز شكل الزر.
الحالات
التمرير والضغط والتركيز من لوحة المفاتيح حالات CSS حقيقية، لا خصائص: مرّر مؤشر الفأرة فوق زر، أو اضغطه، أو انتقل إليه بمفتاح Tab. تخفت الأزرار الممتلئة عند التمرير والضغط. أما الأنماط soft، outline، ghost فتزداد صبغتها، ويبقى الخط تحت الرابط ويخفت. ويظهر الزر المعطّل بنصف شفافيته في كل الأنماط.
متى تختار النمط link
النمطان هادئان، لكن معناهما مختلف. استخدم النمط ghost لإجراء في الصفحة نفسها، مثل إغلاق لوحة أو تعديل صف أو فتح قائمة. واستخدم النمط link للانتقال إلى مكان آخر، مثل «نسيت كلمة المرور؟» أو «اعرف المزيد» أو «عرض الكل»، واجعله رابطًا حقيقيًا بالخاصية asChild.
مع أيقونة
ضع الأيقونة قبل التسمية أو بعدها، كعنصر ابن. يجعلها الزر بحجم 16px وبلون التسمية. وتتبع الأيقونات اتجاه القراءة، فاقلب الأيقونة التي تشير إلى جهة، مثل السهم، بالصنف rtl:-scale-x-100.
حالة التحميل
تعرض الخاصية loading مؤشر تحميل دوّارًا وتعطّل الزر، ويقرأ قارئ الشاشة النص الذي في الخاصية loadingLabel. أما مع الخاصية asChild فيُعلَّم العنصر الابن مشغولًا بالسمة aria-busy ومعطّلًا فقط، فاعرض مؤشر التقدّم داخله بنفسك.
إتاحة الوصول (accessibility)
- يعرض المكوّن عنصر
buttonأصليًا، فيُضغط بمفتاح Enter أو بمفتاح المسافة. اختر قيمة الخاصيةtypeالتي يحتاجها النموذج، مثلsubmitأوbutton. - يرسم التركيز من لوحة المفاتيح حلقة بعرض 2px، على بعد 2px من الزر، باللون
ring. - مع الخاصية
asChildيطبّق الزر شكله على عنصره الابن الوحيد، مثل رابط. ويأخذ الابن المعطّل السمةaria-disabledبدل السمةdisabled. - أثناء التحميل يكون الزر معطّلًا، ويُعلن النص الذي في الخاصية
loadingLabelكرسالة حالة. - يتبع الاتجاه السمة
dirفي الصفحة، ولا توجد له خاصية. وتتبادل الأيقونات مع التسمية مكانيهما في الصفحات من اليمين إلى اليسار.
الخصائص (props)
| الخاصية | النوع | الافتراضي | الوصف |
|---|---|---|---|
tone | "primary" | "secondary" | "destructive" | لا يوجد | اللون داخل النمط. لكل نمط قيمة افتراضية. |
variant | "default" | "outline" | "ghost" | "soft" | "link" | "default" | نمط الزر: ممتلئ، أو بحدّ، أو شفاف، أو بصبغة خفيفة، أو رابط. |
size | "xs" | "sm" | "md" | "lg" | "icon-xs" | "icon-sm" | "icon-md" | "icon-lg" | "md" | ارتفاع الزر. أحجام icon لزر الأيقونة. |
radius | "standard" | "rounded" | "standard" | شكل الزوايا: مستديرة قليلًا، أو كبسولة. |
loading | boolean | false | يعرض مؤشر تحميل دوّارًا ويعطّل الزر. |
loadingLabel | string | "Loading" | النص الذي يقرؤه قارئ الشاشة أثناء التحميل. |
disabled | boolean | false | يعطّل الزر. |
asChild | boolean | false | يطبّق شكل الزر على عنصره الابن الوحيد، مثل رابط، بدل عرض زر. |
onClick | (event) => void | لا يوجد | تُستدعى عند الضغط على الزر. |
className | string | لا يوجد | أصناف إضافية للمكوّن. |
للتوافق مع shadcn/ui، ما زالت القيمتان secondary، destructive تعملان للخاصية variant، وهما النمط Solid بهذين اللونين. وما زالت القيمتان default، icon تعملان للخاصية size، وهما الحجمان md، icon-md.
الاستخدام
زر أساسي
import { Button } from "@/components/ui/button"
export function SaveButton() {
return <Button type="submit">حفظ التغييرات</Button>
}زر بحدّ للإجراءات الخطرة
import { Button } from "@/components/ui/button"
export function DeleteAccountButton() {
return (
<Button variant="outline" tone="destructive">
حذف الحساب
</Button>
)
}رابط إلى صفحة أخرى
import Link from "next/link"
import { Button } from "@/components/ui/button"
export function ForgotPasswordLink() {
return (
<Button variant="link" asChild>
<Link href="/forgot-password">نسيت كلمة المرور؟</Link>
</Button>
)
}مع أيقونة
import { UploadIcon } from "lucide-react"
import { Button } from "@/components/ui/button"
export function UploadButton() {
return (
<Button>
<UploadIcon aria-hidden="true" strokeWidth={1.5} />
رفع ملف
</Button>
)
}أثناء التحميل
import { Button } from "@/components/ui/button"
export function SavingButton() {
return (
<Button loading loadingLabel="جارٍ الحفظ">
جارٍ الحفظ…
</Button>
)
}