منتقي التاريخ (Date Picker)

حقل للتاريخ يفتح تقويمًا تحته. عنصره المُشغِّل هو نفسه في حقل الاختيار، فيصطف الاثنان في النموذج: الأحجام الأربعة نفسها، والتسمية والنص المساعد وحلقة التركيز. يحمل يومًا واحدًا أو مدة، ويعرضها بصيغة 20 يناير 2026 في الصفحة العربية، وبصيغة Jan 20, 2026 في الإنجليزية.

التثبيت

bash
npx @smicolon/fasla-ui@latest add date-picker

قبل إضافة أي مكوّن، شغّل الأمر init مرة واحدة في مشروعك. التفاصيل في صفحة التثبيت.

معاينة

تاريخ التوصيل
نوصل الطلبات بين 9 صباحًا و5 مساءً.

الأحجام

أربعة أحجام: ارتفاع الحجم xs هو 28px، والحجم sm هو 32px، والحجم md هو 36px، والحجم lg هو 40px، وهي ارتفاعات حقل الاختيار نفسها. ويتغير الارتفاع والمسافة بين الأيقونة والنص فقط، أما الحشو فهو 12px وأيقونة التقويم 16px في كل الأحجام.

الحالات

التركيز حالة حقيقية، لا خاصية: انتقل إلى الحقل بمفتاح Tab أو افتحه. يرسم العنصر المُشغِّل حلقة التركيز عند التركيز من لوحة المفاتيح، وطوال بقاء التقويم مفتوحًا. وتُظهر الخاصية disabled الحقل كله باهتًا بنصف شفافيته، مع التسمية والنص المساعد.

مفعّل
معطّل

المدة

تحمل القيمة mode="range" يومًا للبداية ويومًا للنهاية، بينهما شرطة. يبقى التقويم مفتوحًا بعد الضغطة الأولى، ويُغلق بعد اختيار الطرفين. واضبط الخاصية numberOfMonths على 2 ليُفتح بشهرين.

مدة الإقامة
تاريخا الوصول والمغادرة.

بجوار حقل الاختيار

تعمل التسمية والملاحظة في نهاية سطرها والنص المساعد كما في حقل الاختيار، والعنصر المُشغِّل هو عنصره نفسه، فيصطف منتقي التاريخ وحقل الاختيار جنبًا إلى جنب في كل الأحجام.

المدينة

اختياري

حيث نوصل طلبك.

تاريخ التوصيل
اختياري
نوصل الطلبات بين 9 صباحًا و5 مساءً.

التقويم

يُفتح التقويم تحت العنصر المُشغِّل بمسافة 4px، محاذيًا لحافته في البداية، وينتقل فوقه حين لا يتسع له المكان تحته. وينتقل التركيز إلى اليوم المختار، وإلا فإلى اليوم الحالي، فتعمل مفاتيح الأسهم فورًا. ويُغلق التقويم باختيار يوم أو بمفتاح Escape، ويعود التركيز إلى العنصر المُشغِّل.

في نموذج

امنح الحقل الخاصية name فيُرسل مع نموذجه: اليوم بصيغة 2026-01-20، والمدة بصيغة 2026-01-20/2026-02-09. ومرّر خصائص التقويم عبر calendarProps، مثل قائمتي الشهر والسنة لتاريخ الميلاد.

تاريخ الميلاد
نستخدم تاريخ ميلادك لحساب عمرك.

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

  • العنصر المُشغِّل عنصر button يفتح نافذة بالدور dialog. واسمه التسمية والقيمة معًا، فيقرأ قارئ الشاشة الاثنين، ويقرأ النص المساعد معهما.
  • يفتح مفتاح Enter أو مفتاح المسافة التقويم وينقل التركيز إلى اليوم المختار. ثم تعمل مفاتيح التقويم نفسها: الأسهم، ومفتاح Page Up، ومفتاح Page Down، ومفتاح Home، ومفتاح End. ويغلق مفتاح Escape التقويم ويعيد التركيز إلى العنصر المُشغِّل.
  • تسمّي الخاصية label العنصر المُشغِّل. وإذا لم تضع تسمية، فأضف السمة aria-label. والضغط على التسمية ينقل التركيز إلى العنصر المُشغِّل دون أن يفتح التقويم.
  • يتبع الاتجاه السمة dir في الصفحة، ولا توجد له خاصية. ويأخذ التقويم اتجاه الصفحة ولغتها وخطها من العنصر المُشغِّل، مع أنه يُعرض في نهاية العنصر body.

الخصائص (props)

DatePicker

الخاصيةالنوعالافتراضيالوصف
mode"single" | "range""single"يوم واحد، أو مدة من يوم إلى آخر.
valueDate | DateRange | nullلا يوجداليوم المختار، أو المدة مع القيمة mode="range". وتُستخدم مع onValueChange.
defaultValueDate | DateRange | nullلا يوجدالقيمة المختارة عند العرض الأول.
onValueChange(value) => voidلا يوجدتُستدعى باليوم الجديد، أو بالمدة عند اختيار كل طرف.
placeholderReactNodeلا يوجدنص يظهر قبل اختيار تاريخ. والافتراضي «اختر تاريخًا» في الصفحة العربية، وما يقابله بالإنجليزية في غيرها.
size"xs" | "sm" | "md" | "lg""md"ارتفاع الحقل: 28 أو 32 أو 36 أو 40px.
numberOfMonthsnumber1عدد الأشهر المتجاورة في التقويم.
calendarPropsCalendarPropsلا يوجدخصائص أخرى للتقويم: الأيام الموقوفة، والشهر المعروض، وقائمتا الشهر والسنة، والخاصية radius.
labelReactNodeلا يوجدتسمية الحقل، ترتبط بالعنصر المُشغِّل تلقائيًا.
aria-labelstringلا يوجدالاسم الذي يقرؤه قارئ الشاشة للعنصر المُشغِّل حين لا توجد تسمية ظاهرة.
aria-labelledbystringلا يوجدمعرّف عنصر يسمّي العنصر المُشغِّل بدل الخاصية label.
labelEndReactNodeلا يوجدملاحظة قصيرة في نهاية سطر التسمية، مثل «اختياري».
descriptionReactNodeلا يوجدنص مساعد تحت الحقل، يقرؤه قارئ الشاشة مع الحقل.
descriptionEndReactNodeلا يوجدملاحظة في نهاية سطر النص المساعد.
disabledbooleanfalseيعطّل الحقل ويُظهر المجموعة كلها باهتة.
namestringلا يوجدالاسم الذي تُرسل به القيمة مع النموذج.
formstringلا يوجدمعرّف النموذج الذي تُرسل معه القيمة، حين يكون الحقل خارجه.
idstringلا يوجدمعرّف العنصر المُشغِّل.
openbooleanلا يوجديفتح التقويم أو يغلقه حين تتحكم به.
defaultOpenbooleanfalseيفتح التقويم عند العرض الأول.
onOpenChange(open) => voidلا يوجدتُستدعى عند فتح التقويم أو إغلاقه.
collisionAvoidance{ side, align, fallbackAxisSide }لا يوجدكيف يتجنب التقويم حافة النافذة. ينتقل تلقائيًا فوق العنصر المُشغِّل حين لا يتسع له المكان تحته.
containerHTMLElementلا يوجدمكان عرض التقويم، والافتراضي العنصر body.
classNamestringلا يوجدأصناف CSS إضافية لمجموعة الحقل.

الاستخدام

يوم واحد

tsx
import { DatePicker } from "@/components/ui/date-picker"

export function DeliveryDate() {
  return (
    <DatePicker
      name="delivery"
      label="تاريخ التوصيل"
      description="نوصل الطلبات بين 9 صباحًا و5 مساءً."
      calendarProps={{ disabled: { before: new Date() } }}
    />
  )
}

مدة

tsx
"use client"

import * as React from "react"
import { DatePicker, type DateRange } from "@/components/ui/date-picker"

export function StayDates() {
  const [stay, setStay] = React.useState<DateRange | null>(null)
  return (
    <DatePicker
      mode="range"
      numberOfMonths={2}
      label="مدة الإقامة"
      value={stay}
      onValueChange={setStay}
    />
  )
}

في نموذج

tsx
import { Button } from "@/components/ui/button"
import { DatePicker } from "@/components/ui/date-picker"

export function BirthDateForm() {
  return (
    <form action="/profile" className="flex flex-col items-start gap-8">
      <DatePicker
        name="dob"
        label="تاريخ الميلاد"
        description="نستخدم تاريخ ميلادك لحساب عمرك."
        calendarProps={{
          captionLayout: "dropdown",
          startMonth: new Date(1926, 0),
          endMonth: new Date(),
        }}
      />
      <Button type="submit">إرسال</Button>
    </form>
  )
}