حقل الإدخال الرقمي (Input Number)
يتيح لك مكوّن حقل الإدخال الرقمي أن تكتب عددًا، أو أن تغيّره بزرّين للإنقاص والزيادة. له ارتفاع حقل الإدخال وإطاره وحالاته نفسها، ويأتي بخمسة تخطيطات، ويُبقي القيمة بين حدّ أدنى وحدّ أعلى، ويعرض الأرقام بالصيغة اللاتينية في اللغتين.
التثبيت
npx @smicolon/fasla-ui@latest add input-numberقبل إضافة أي مكوّن، شغّل الأمر init مرة واحدة في مشروعك. التفاصيل في صفحة التثبيت.
معاينة
الأنماط (variant)
يأتي الحقل بخمسة تخطيطات تختارها بالخاصية variant. يضع التخطيط default زرَّي أيقونة بعد القيمة. ويرصّ التخطيط vertically-stacked زر الزيادة فوق زر الإنقاص في عمود ضيق، ويضع التخطيط horizontally-stacked الزرّين متجاورين بعد القيمة. أما التخطيط horizontally-stretched فيضع زر الإنقاص قبل القيمة وزر الزيادة بعدها. وفي هذه التخطيطات الثلاثة يفصل خط بعرض 1px بين كل زر والقيمة. والتخطيط mini بعرض 128px، ويناسب خلايا الجداول وأشرطة الأدوات. ارتفاع كل التخطيطات 36px، والقيمة في وسط الحقل.
الحالات
حالات هذا الحقل هي حالات حقل الإدخال نفسها. التركيز حالة حقيقية، لا خاصية: انتقل إلى الحقل بمفتاح Tab، أو اضغط أحد الزرّين. تلوّن القيمة status="success" الإطار والتسمية بلون success، وتلوّنهما الخاصية invalid بلون destructive، وتأخذ هالة التركيز اللون نفسه. وتعطّل الخاصية disabled الحقل والزرّين، وتُظهر الحقل كله باهتًا بنصف شفافيته.
الحدود والخطوة
تُبقي الخاصية min والخاصية max القيمة ضمن مداها. وعند بلوغ أحد الحدّين يتعطّل الزر المقابل له ويبقى في مكانه، فلا يتغير شكل الحقل. وتحدد الخاصية step مقدار تغيّر القيمة مع كل ضغطة زر وكل مفتاح سهم. واضغط مفتاح Shift مع السهم لتتغير القيمة بمقدار 10.
الأرقام والتنسيق
يعرض الحقل القيمة دائمًا بالأرقام اللاتينية من 0 إلى 9، في الصفحات العربية والإنجليزية. وإذا كتبت العدد بالأرقام العربية المشرقية، فإنه يقرؤه العدد نفسه. وتقبل الخاصية format خيارات Intl.NumberFormat لعرض عملة أو نسبة مئوية، وتحدد الخاصية locale الفواصل والرموز. وتحتفظ القيمة باتجاهها الخاص، فتبقى إشارة السالب قبل الأرقام في الصفحات العربية.
التسمية
تضع الخاصية label تسمية فوق الحقل وتربطها بحقل الإدخال. وإذا كان السياق يسمّي الحقل أصلًا، كما في صفّ جدول، فاترك التسمية واستخدم السمة aria-label بدلًا منها.
إتاحة الوصول (accessibility)
- القيمة حقل نصي يفتح لوحة مفاتيح رقمية على الهاتف. ويرسل حقل مخفي العدد مع النموذج باسم الخاصية
name. - يغيّر مفتاحا السهم للأعلى والأسفل القيمة بمقدار خطوة. ومع مفتاح Shift تتغير بمقدار 10. وينقلك مفتاح Home إلى قيمة الخاصية
min، ومفتاح End إلى قيمة الخاصيةmax، إذا حدّدتهما. - اسم الزرّين لقارئ الشاشة «زيادة» و«إنقاص»، واسماهما في الصفحات الإنجليزية Increase مع Decrease. ويمكنك تغيير الاسمين بالخاصية
incrementLabelوالخاصيةdecrementLabel. لا يصل مفتاح Tab إلى الزرّين، لأن مفاتيح الأسهم تؤدي عملهما من حقل الإدخال. وإذا أبقيت الضغط على زر، فإن القيمة تستمر في التغيّر. - تجنّب التخطيط
vertically-stackedعلى شاشات اللمس، لأن عرض زرّيه 23px وارتفاع كل منهما 17px، وهذا أصغر من الحد الأدنى لمساحة اللمس، وهو 24px. استخدم التخطيطhorizontally-stackedأو التخطيطhorizontally-stretchedبدلًا منه. - تسمّي الخاصية
labelحقل الإدخال. وإذا لم تضع تسمية ظاهرة، فأضف السمةaria-labelأو السمةaria-labelledby. - يتبع الاتجاه السمة
dirفي الصفحة، ولا توجد له خاصية. ويعتمد التخطيط على الخصائص المنطقية وحدها، فينتقل الزرّان والخطوط الفاصلة إلى الجهة الأخرى في الصفحات العربية، ويتبادل زر الإنقاص وزر الزيادة مكانيهما. ويبقى زر الزيادة في الأعلى في التخطيط العمودي.
الخصائص (props)
InputNumber
| الخاصية | النوع | الافتراضي | الوصف |
|---|---|---|---|
variant | "default" | "vertically-stacked" | "horizontally-stacked" | "horizontally-stretched" | "mini" | "default" | مكان الزرّين: خمسة تخطيطات. |
value | number | null | لا يوجد | القيمة حين تتحكم بها. وتُستخدم مع onValueChange. |
defaultValue | number | لا يوجد | القيمة عند العرض الأول. |
onValueChange | (value, details) => void | لا يوجد | تُستدعى بالعدد الجديد، أو بالقيمة null عند إفراغ الحقل. |
min | number | لا يوجد | أدنى قيمة، ويتعطّل عندها زر الإنقاص. |
max | number | لا يوجد | أعلى قيمة، ويتعطّل عندها زر الزيادة. |
step | number | "any" | 1 | مقدار تغيّر القيمة مع كل ضغطة زر وكل مفتاح سهم. |
format | Intl.NumberFormatOptions | لا يوجد | خيارات Intl.NumberFormat، مثل عملة أو نسبة مئوية. وتبقى الأرقام لاتينية. |
locale | Intl.LocalesArgument | لا يوجد | اللغة والمنطقة اللتان تحددان الفواصل والرموز. والافتراضي إعدادات القارئ. |
placeholder | string | لا يوجد | نص يظهر ما دام الحقل فارغًا. |
label | ReactNode | لا يوجد | تسمية الحقل، ترتبط بحقل الإدخال تلقائيًا. |
aria-label | string | لا يوجد | اسم حقل الإدخال لقارئ الشاشة حين لا توجد تسمية ظاهرة. |
aria-labelledby | string | لا يوجد | معرّف العنصر الذي يسمّي حقل الإدخال، بدل الخاصية label. |
incrementLabel | string | لا يوجد | اسم زر الزيادة. والافتراضي «زيادة» في الصفحات العربية. |
decrementLabel | string | لا يوجد | اسم زر الإنقاص. والافتراضي «إنقاص» في الصفحات العربية. |
status | "default" | "success" | "default" | اختر القيمة success لتمييز قيمة اجتازت التحقق. |
invalid | boolean | false | يجعل الحقل غير صالح، وللسمة aria-invalid الأثر نفسه. |
disabled | boolean | false | يعطّل الحقل والزرّين، ويُظهر المجموعة كلها باهتة. |
readOnly | boolean | false | يعرض القيمة ويمنع تغييرها. |
required | boolean | false | يُرسل النموذج بعد إدخال قيمة فقط. |
name | string | لا يوجد | الاسم الذي تُرسل به القيمة مع النموذج. |
form | string | لا يوجد | معرّف النموذج الذي تُرسل معه القيمة، حين يكون الحقل خارجه. |
id | string | لا يوجد | معرّف حقل الإدخال، لتربطه بعنصر label من عندك. |
className | string | لا يوجد | أصناف CSS إضافية لمجموعة الحقل. |
الاستخدام
حقل رقمي بسيط
import { InputNumber } from "@/components/ui/input-number"
export function QuantityField() {
return <InputNumber name="quantity" label="الكمية" defaultValue={1} min={1} max={10} />
}التحكّم بالقيمة مع حدّين
"use client"
import * as React from "react"
import { InputNumber } from "@/components/ui/input-number"
export function GuestsField() {
const [guests, setGuests] = React.useState<number | null>(2)
return (
<InputNumber
variant="horizontally-stretched"
label="عدد الضيوف"
value={guests}
onValueChange={setGuests}
min={1}
max={8}
/>
)
}تنسيق العملة
import { InputNumber } from "@/components/ui/input-number"
export function PriceField() {
return (
<InputNumber
name="price"
label="السعر"
format={{ style: "currency", currency: "SAR" }}
defaultValue={1250}
min={0}
step={50}
/>
)
}