تنبيه (Alert)
صندوق رسالة يُعلم المستخدم بخبر جديد، أو يرشده، أو يؤكد له اكتمال مهمة، أو ينبّهه إلى أمر يحتاج إلى انتباهه، أو يبلغه بخطأ. يأتي بخمسة أنماط وثلاثة أنواع كما في ملف التصميم، ومعه زر إجراء وزر إغلاق عند الحاجة.
التثبيت
npx @smicolon/fasla-ui@latest add alertقبل إضافة أي مكوّن، شغّل الأمر init مرة واحدة في مشروعك. التفاصيل في صفحة التثبيت.
التنبيه مبني على مكوّن زر، فإضافته تضيف معه العنصر button من السجل.
معاينة
الأنماط (variant)
تحدد الخاصية variant موضوع الرسالة: النمط default للأخبار، والنمط info للإرشاد، والنمط success لمهمة اكتملت، والنمط warning لأمر يحتاج إلى انتباه قريب، والنمط destructive للأخطاء. ولكل نمط أيقونة خاصة به إلى جانب لونه، فلا يعتمد المعنى على اللون وحده.
defaultinfosuccesswarningdestructiveالأنواع
تحدد الخاصية type مدى بروز التنبيه. النوع outline هو الافتراضي، وهو بطاقة لها حافة بعرض بكسل واحد بلون النمط. ويضع النوع soft فوق البطاقة طبقة من لون النمط بنسبة 10%. أما النوع solid فيملأ التنبيه باللون، وهو الأكثر بروزًا، فخصّصه للرسائل التي يجب ألا تفوت المستخدم. ويتبع زر الإجراء نوع التنبيه: زر بحدود في النوع outline، وزر مصمت في النوع soft، وزر ثانوي في النوع solid.
outlinesoftsolidالأيقونة والصورة الرمزية
يعرض كل نمط أيقونته الخاصة بحجم 16 بكسل، في منتصف السطر الأول من العنوان: علامة معلومات في دائرة للنمط default والنمط info، وعلامة صح للنمط success، ومثلث للنمط warning، وعلامة تعجب في دائرة للنمط destructive. ولتغيير الأيقونة مرّر أيقونة أخرى إلى الخاصية icon، أو مرّر صورة رمزية لرسالة من شخص، أو أعطِ الخاصية icon القيمة false لإخفائها. وتظهر الصورة الرمزية بحجم 32 بكسل في أعلى التنبيه.
زر الإجراء وزر الإغلاق
المكوّن AlertAction زر بالحجم xs ارتفاعه 26 بكسل، ويقبل كل خصائص الزر، فتجعله الخاصية asChild رابطًا. أما المكوّن AlertClose فزر أيقونة شفاف فيه علامة × بحجم 16 بكسل. ويقع الزران في نهاية السطر الأول، زر الإجراء أولًا، وبينهما 12 بكسل.
النص الطويل
يلتف العنوان والوصف داخل عمودهما. وتبقى الأيقونة في منتصف السطر الأول من العنوان، ويبقى زر الإجراء وزر الإغلاق في الأعلى. ويتسع المكوّن AlertDescription لأكثر من جملة: فقرات، أو قائمة، أو رابط.
تنتقل المشاريع والأعضاء والملفات كما هي. وتبقى الروابط المشتركة التي أنشأتها قبل الانتقال صالحة 30 يومًا، ثم تطلب من زائريها تسجيل الدخول.
اقرأ القائمة الكاملة للتغييرات قبل الانتقال، وأخبر فريقك بالروابط التي يجب استبدالها.
الإغلاق
يُخفي الضغط على المكوّن AlertClose التنبيه، ويستدعي onOpenChange(false). ولإظهار التنبيه مرة أخرى، أو لتذكّر أن المستخدم أغلقه، تحكّم فيه بالخاصية open. ولإبقائه ظاهرًا، استدعِ event.preventDefault() داخل الدالة onClick في زر الإغلاق.
إتاحة الوصول (accessibility)
- يتبع الدور النمط. فللنمط
destructiveالدورrole="alert"، لأن الخطأ يحتاج إلى انتباه فوري، فيقطع قارئ الشاشة ما يقرؤه ليعلنه. ولبقية الأنماط الدورrole="status"، فيعلنه قارئ الشاشة بعد أن ينهي الجملة الحالية، لأن الخبر والإرشاد واكتمال المهمة والتحذير تحتمل هذا الانتظار. ولاختيار دور آخر استخدم الخاصيةrole، مثلrole="note"لرسالة تظهر مع الصفحة منذ تحميلها. - يعلن قارئ الشاشة التنبيه عند ظهوره. لذلك اعرض التنبيه لحظة وقوع الحدث، واجعل العنوان والوصف قصيرين، لأن قارئ الشاشة يقرؤهما معًا.
- الأيقونة للزينة، وهي مخفية عن التقنيات المساعدة، فالعنوان يوضح موضوع الرسالة.
- اسم زر الإغلاق «إغلاق»، ويصبح بالإنجليزية حين تكون أقرب قيمة للسمة
langهي الإنجليزية. ولتوضيح ما يغلقه الزر، استخدم الخاصيةlabel. - إذا أُغلق التنبيه والتركيز داخله، فانقل التركيز في الدالة
onOpenChangeإلى عنصر مناسب، مثل العنصر الذي أدّى إلى ظهور الرسالة. وإلا فسيبدأ التنقّل بلوحة المفاتيح من أول الصفحة. - في وضع التباين العالي على نظام ويندوز يحتفظ التنبيه بحدود بلون نص النظام، فتبقى حافته ظاهرة حين يُلغى لون خلفيته.
- يتبع الاتجاه السمة
dirفي الصفحة، ولا توجد له خاصية. ففي الصفحات العربية تبدأ الأيقونة الصفّ وينتهي بزر الإغلاق، فينعكس ترتيب الأجزاء كله، ويظهر النص بالخط العربي على سطر أطول.
الخصائص (props)
Alert
| الخاصية | النوع | الافتراضي | الوصف |
|---|---|---|---|
variant | "default" | "info" | "success" | "warning" | "destructive" | "default" | موضوع الرسالة. يحدد الأيقونة واللون والدور الافتراضي. |
type | "outline" | "solid" | "soft" | "outline" | مدى بروز التنبيه: بطاقة بحافة، أو طبقة لون خفيفة، أو لون مصمت. |
icon | boolean | ReactNode | true | أيقونة النمط افتراضيًا. القيمة false تخفيها، وأي عنصر آخر، مثل أيقونة أو صورة رمزية، يحل محلها. |
open | boolean | لا يوجد | تحدد ظهور التنبيه. استخدمها لتتحكم فيه بنفسك. |
defaultOpen | boolean | true | تحدد ظهور التنبيه في البداية، حين لا تتحكم فيه بنفسك. |
onOpenChange | (open: boolean) => void | لا يوجد | تُستدعى بالقيمة false عند الضغط على زر الإغلاق. |
role | string | لا يوجد | الدور alert للنمط destructive، والدور status لبقية الأنماط، ما لم تمرّر دورًا آخر. |
children | ReactNode | لا يوجد | أجزاء التنبيه بهذا الترتيب: AlertTitle، AlertDescription، AlertAction، AlertClose. |
className | string | لا يوجد | أصناف إضافية للتنبيه. ويملأ التنبيه عرض حاويته. |
AlertTitle
| الخاصية | النوع | الافتراضي | الوصف |
|---|---|---|---|
children | ReactNode | لا يوجد | العنوان: سطر واحد قصير يوضح ما حدث. |
className | string | لا يوجد | أصناف إضافية للعنوان. |
AlertDescription
| الخاصية | النوع | الافتراضي | الوصف |
|---|---|---|---|
children | ReactNode | لا يوجد | تفاصيل إضافية: جملة، أو فقرات، أو قائمة، أو رابط. |
className | string | لا يوجد | أصناف إضافية للوصف. |
AlertAction
| الخاصية | النوع | الافتراضي | الوصف |
|---|---|---|---|
variant | "default" | "outline" | "ghost" | "soft" | "link" | لا يوجد | نوع الزر. يتبع نوع التنبيه ما لم تحدده. |
tone | "primary" | "secondary" | "destructive" | لا يوجد | اللون الدلالي للزر. يتبع نوع التنبيه ما لم تحدده. |
size | "xs" | "sm" | "md" | "lg" | "xs" | حجم الزر. |
asChild | boolean | false | تجعل العنصر الابن الوحيد زرَّ الإجراء بمظهر الزر نفسه، مثل رابط. |
onClick | (event) => void | لا يوجد | تُستدعى عند الضغط على زر الإجراء. |
children | ReactNode | لا يوجد | التسمية: فعل يصف ما سيحدث بعد الضغط. |
className | string | لا يوجد | أصناف إضافية لزر الإجراء. ويقبل الزر كل خصائص مكوّن زر الأخرى أيضًا. |
AlertClose
| الخاصية | النوع | الافتراضي | الوصف |
|---|---|---|---|
label | string | لا يوجد | اسم الزر لقارئ الشاشة. وهو افتراضيًا «إغلاق» بلغة الصفحة. |
onClick | (event) => void | لا يوجد | تُستدعى قبل إغلاق التنبيه. ولإبقائه ظاهرًا استدعِ event.preventDefault(). |
children | ReactNode | لا يوجد | أيقونة أخرى بدل العلامة ×. |
className | string | لا يوجد | أصناف إضافية لزر الإغلاق. |
الاستخدام
رسالة
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert"
export function MaintenanceNotice() {
return (
<Alert variant="info">
<AlertTitle>صيانة مجدولة الليلة</AlertTitle>
<AlertDescription>تتوقف لوحة التحكم عن العمل من الساعة 22:00 إلى 23:00.</AlertDescription>
</Alert>
)
}مع زر إجراء وزر إغلاق
import {
Alert,
AlertAction,
AlertClose,
AlertDescription,
AlertTitle,
} from "@/components/ui/alert"
export function SaveError({ onRetry }: { onRetry: () => void }) {
return (
<Alert variant="destructive" type="soft">
<AlertTitle>تعذّر حفظ التغييرات</AlertTitle>
<AlertDescription>انقطع الاتصال بالخادم. تحقّق من اتصالك ثم حاول مرة أخرى.</AlertDescription>
<AlertAction onClick={onRetry}>إعادة المحاولة</AlertAction>
<AlertClose />
</Alert>
)
}إظهار تنبيه مغلق مرة أخرى
"use client"
import { useState } from "react"
import { Alert, AlertClose, AlertDescription, AlertTitle } from "@/components/ui/alert"
import { Button } from "@/components/ui/button"
export function InboxNotice() {
const [open, setOpen] = useState(true)
if (!open) {
return (
<Button variant="outline" size="sm" onClick={() => setOpen(true)}>
أظهره مرة أخرى
</Button>
)
}
return (
<Alert open={open} onOpenChange={setOpen}>
<AlertTitle>رسالة جديدة</AlertTitle>
<AlertDescription>لديك 12 رسالة غير مقروءة في صندوق الوارد.</AlertDescription>
<AlertClose />
</Alert>
)
}رسالة من شخص
import { Alert, AlertAction, AlertDescription, AlertTitle } from "@/components/ui/alert"
import { Avatar } from "@/components/ui/avatar"
export function ReplyNotice() {
return (
<Alert icon={<Avatar src="/avatars/layla.png" name="" radius="rounded" />}>
<AlertTitle>ردّت ليلى حداد</AlertTitle>
<AlertDescription>«التصميم الجديد يعمل جيدًا. لننشره يوم الاثنين.»</AlertDescription>
<AlertAction asChild>
<a href="/messages/42">ردّ</a>
</AlertAction>
</Alert>
)
}