حقل الاختيار (Select)
يتيح لك مكوّن حقل الاختيار أن تختار خيارًا واحدًا من قائمة، أو عدة خيارات. فيه تسمية ونص مساعد وأيقونة في بدايته كما في حقل الإدخال، ويعرض الخيارات المختارة شاراتٍ أو نصًا، بأربعة أحجام وشكلين للزوايا.
التثبيت
npx @smicolon/fasla-ui@latest add selectقبل إضافة أي مكوّن، شغّل الأمر init مرة واحدة في مشروعك. التفاصيل في صفحة التثبيت.
معاينة
حيث نوصل طلبك.
الأحجام
أربعة أحجام: ارتفاع الحجم xs هو 28px، والحجم sm هو 32px، والحجم md هو 36px، والحجم lg هو 40px، وهي ارتفاعات حقل الإدخال نفسها. وكما في حقل الإدخال، يتغير الارتفاع والمسافة بين الأيقونة والنص فقط، أما الحشو فهو 12px والأيقونة 16px في كل الأحجام. والنص بحجم 14px، أو 16px على الشاشات التي يقل عرضها عن 768px حتى لا يكبّر نظام iOS الصفحة.
الزوايا
تجعل القيمة standard للخاصية radius الزوايا مستديرة بنصف قطر 8px، وتجعل القيمة rounded الحقل على شكل كبسولة. وتتبع حلقة التركيز شكل الحقل، وتبقى زوايا القائمة 8px في الحالتين.
الحالات
التركيز حالة حقيقية، لا خاصية: انتقل إلى الحقل بمفتاح Tab أو افتحه. يرسم العنصر المُشغِّل حلقة التركيز عند التركيز من لوحة المفاتيح، وطوال بقاء قائمته مفتوحة. وتُظهر الخاصية disabled الحقل كله باهتًا بنصف شفافيته، مع التسمية والنص المساعد.
الاختيار المتعدد
تتيح الخاصية multiple اختيار عدة خيارات. تبقى القائمة مفتوحة أثناء الاختيار، وتظهر علامة الصح عند كل خيار مختار. ويعرض العنصر المُشغِّل الخيارات المختارة شاراتٍ، أو سطرًا واحدًا من النص مع القيمة text للخاصية display. تلتف الشارات إلى أسطر أخرى ويتسع الحقل لها. اضغط علامة × في الشارة لإزالتها.
معروضة شاراتٍ.
معروضة سطرًا واحدًا من النص.
التسميات والأيقونات
تعمل التسمية والملاحظة في نهاية سطرها والنص المساعد والأيقونة كما في حقل الإدخال، فيصطف الحقلان جنبًا إلى جنب في النموذج. ضع الأيقونة في الخاصية startIcon، ويضبط الحقل حجمها على حجمه.
اختياري
كما يظهر في بطاقة الهوية.
اختياري
نحتفظ بطلبك 3 أيام.
6 فروع
القائمة
تُفتح القائمة تحت العنصر المُشغِّل، على بعد 4px منه وبعرضه تمامًا. يتميّز الخيار حين يستقر عليه مؤشر الفأرة أو تنتقل إليه بمفاتيح الأسهم. وتدل علامة الصح في نهاية السطر على الخيار المختار، ومكانها محجوز دائمًا فلا يتحرك النص. وفي الصفحات من اليمين إلى اليسار تنتقل علامة الصح وسهم القائمة إلى الطرف الآخر.
الخيارات الطويلة
يلتف الخيار الأطول من عرض القائمة إلى أسطر أخرى داخلها. أما في العنصر المُشغِّل فيبقى الخيار المختار في سطر واحد وينتهي بنقاط.
إتاحة الوصول (accessibility)
- تمنح مكتبة Base UI العنصر المُشغِّل، وهو عنصر
button، الدورcombobox، وتجعل القائمة بالدورlistboxوفيها الخيارات. ويرسل حقل مخفي القيمة مع النموذج باسم الخاصيةname. - تُفتح القائمة بمفتاح Enter أو بمفتاح المسافة أو بمفاتيح الأسهم. تنتقل بين الخيارات بمفاتيح الأسهم أو بمفتاح Home أو بمفتاح End، وتقفز إلى خيار يطابق الحرف الذي تكتبه. ويختار مفتاح Enter الخيار، ويغلق مفتاح Escape القائمة ويعيد التركيز إلى العنصر المُشغِّل.
- تسمّي الخاصية
labelالعنصر المُشغِّل، ويُقرأ النص المساعد معه. وإذا لم تضع تسمية، فأضف السمةaria-label. والضغط على التسمية ينقل التركيز إلى العنصر المُشغِّل دون أن يفتح القائمة. - علامة × في الشارة لمؤشر الفأرة، ويتجاوزها قارئ الشاشة. ومن لوحة المفاتيح، افتح القائمة واختر الخيار مرة أخرى لإزالته.
- يتبع الاتجاه السمة
dirفي الصفحة، ولا توجد له خاصية. وتأخذ القائمة اتجاه الصفحة ولغتها وخطها من العنصر المُشغِّل، مع أنها تُعرض في نهاية العنصرbody.
الخصائص (props)
Select
| الخاصية | النوع | الافتراضي | الوصف |
|---|---|---|---|
items | SelectOption[] | لا يوجد | الخيارات بصيغة بيانات: value، label، ومعهما disabled عند الحاجة. |
children | ReactNode | لا يوجد | صفوف SelectItem بدل الخاصية items. |
placeholder | ReactNode | لا يوجد | نص يظهر قبل الاختيار. |
size | "xs" | "sm" | "md" | "lg" | "md" | ارتفاع الحقل: 28 أو 32 أو 36 أو 40px. |
radius | "standard" | "rounded" | "standard" | شكل الزوايا: بنصف قطر 8px، أو مستديرة بالكامل فيبدو الحقل كبسولة. |
multiple | boolean | false | يتيح اختيار أكثر من خيار. |
display | "badges" | "text" | "badges" | مع الخاصية multiple، يعرض الخيارات المختارة شاراتٍ أو سطرًا واحدًا من النص. |
value | string | string[] | null | لا يوجد | القيمة المختارة، أو القيم مع الخاصية multiple. وتُستخدم مع onValueChange. |
defaultValue | string | string[] | null | لا يوجد | القيمة المختارة عند العرض الأول. |
onValueChange | (value) => void | لا يوجد | تُستدعى بالقيمة الجديدة، وعند إزالة شارة أيضًا. |
label | ReactNode | لا يوجد | تسمية الحقل، ترتبط بالعنصر المُشغِّل تلقائيًا. |
aria-label | string | لا يوجد | الاسم الذي يقرؤه قارئ الشاشة للعنصر المُشغِّل حين لا توجد تسمية ظاهرة. |
aria-labelledby | string | لا يوجد | معرّف عنصر يسمّي العنصر المُشغِّل بدل الخاصية label. |
labelEnd | ReactNode | لا يوجد | ملاحظة قصيرة في نهاية سطر التسمية، مثل «اختياري». |
description | ReactNode | لا يوجد | نص مساعد تحت الحقل، يقرؤه قارئ الشاشة مع الحقل. |
descriptionEnd | ReactNode | لا يوجد | ملاحظة في نهاية سطر النص المساعد، مثل عدد. |
startIcon | ReactNode | لا يوجد | أيقونة في بداية العنصر المُشغِّل. |
disabled | boolean | false | يعطّل الحقل ويُظهر المجموعة كلها باهتة. |
readOnly | boolean | false | يعرض القيمة ويمنع تغييرها. |
required | boolean | false | يُرسل النموذج بعد اختيار قيمة فقط. |
name | string | لا يوجد | الاسم الذي تُرسل به القيمة مع النموذج. |
form | string | لا يوجد | معرّف النموذج الذي تُرسل معه القيمة، حين يكون الحقل خارجه. |
id | string | لا يوجد | معرّف العنصر المُشغِّل، لتربطه بعنصر label من عندك. |
open | boolean | لا يوجد | يفتح القائمة أو يغلقها حين تتحكم بها. |
defaultOpen | boolean | false | يفتح القائمة عند العرض الأول. |
onOpenChange | (open) => void | لا يوجد | تُستدعى عند فتح القائمة أو إغلاقها. |
modal | boolean | true | يمنع تمرير الصفحة والضغط خارج القائمة ما دامت مفتوحة. |
collisionAvoidance | { side, align, fallbackAxisSide } | لا يوجد | كيف تتجنب القائمة حافة النافذة. تنتقل تلقائيًا فوق العنصر المُشغِّل حين لا يتسع لها المكان تحته، وتبقيها القيمة { side: "none" } تحته. |
container | HTMLElement | لا يوجد | مكان عرض القائمة، والافتراضي العنصر body. |
className | string | لا يوجد | أصناف CSS إضافية لمجموعة الحقل. |
SelectItem
| الخاصية | النوع | الافتراضي | الوصف |
|---|---|---|---|
value | string | لا يوجد | القيمة التي يرسلها هذا الخيار. |
label | string | لا يوجد | نص للعنصر المُشغِّل والشارات والبحث بالكتابة، حين يعرض الصف أكثر من نص. |
disabled | boolean | false | يعرض الخيار ويمنع اختياره. |
children | ReactNode | لا يوجد | ما يعرضه الصف. |
الاستخدام
حقل الاختيار البسيط
import { MapPin } from "lucide-react"
import { Select } from "@/components/ui/select"
const cities = [
{ value: "riyadh", label: "الرياض" },
{ value: "jeddah", label: "جدة" },
{ value: "dammam", label: "الدمام" },
]
export function CityField() {
return (
<Select
name="city"
label="المدينة"
placeholder="اختر مدينة"
startIcon={<MapPin />}
items={cities}
/>
)
}اختيار متعدد مع التحكّم بالقيمة
"use client"
import * as React from "react"
import { Select } from "@/components/ui/select"
const cities = [
{ value: "riyadh", label: "الرياض" },
{ value: "jeddah", label: "جدة" },
{ value: "dammam", label: "الدمام" },
]
export function DeliveryCities() {
const [value, setValue] = React.useState<string[]>(["riyadh"])
return (
<Select
multiple
label="مدن التوصيل"
placeholder="اختر المدن"
items={cities}
value={value}
onValueChange={setValue}
/>
)
}مع صفوف SelectItem
import { Select, SelectItem } from "@/components/ui/select"
export function BranchField() {
return (
<Select label="فرع الاستلام" placeholder="اختر فرعًا">
<SelectItem value="olaya">فرع العليا</SelectItem>
<SelectItem value="malqa">فرع الملقا</SelectItem>
<SelectItem value="nakheel" disabled>
فرع النخيل
</SelectItem>
</Select>
)
}