حقل الإدخال الرقمي (Input Number)

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

التثبيت

bash
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"مكان الزرّين: خمسة تخطيطات.
valuenumber | nullلا يوجدالقيمة حين تتحكم بها. وتُستخدم مع onValueChange.
defaultValuenumberلا يوجدالقيمة عند العرض الأول.
onValueChange(value, details) => voidلا يوجدتُستدعى بالعدد الجديد، أو بالقيمة null عند إفراغ الحقل.
minnumberلا يوجدأدنى قيمة، ويتعطّل عندها زر الإنقاص.
maxnumberلا يوجدأعلى قيمة، ويتعطّل عندها زر الزيادة.
stepnumber | "any"1مقدار تغيّر القيمة مع كل ضغطة زر وكل مفتاح سهم.
formatIntl.NumberFormatOptionsلا يوجدخيارات Intl.NumberFormat، مثل عملة أو نسبة مئوية. وتبقى الأرقام لاتينية.
localeIntl.LocalesArgumentلا يوجداللغة والمنطقة اللتان تحددان الفواصل والرموز. والافتراضي إعدادات القارئ.
placeholderstringلا يوجدنص يظهر ما دام الحقل فارغًا.
labelReactNodeلا يوجدتسمية الحقل، ترتبط بحقل الإدخال تلقائيًا.
aria-labelstringلا يوجداسم حقل الإدخال لقارئ الشاشة حين لا توجد تسمية ظاهرة.
aria-labelledbystringلا يوجدمعرّف العنصر الذي يسمّي حقل الإدخال، بدل الخاصية label.
incrementLabelstringلا يوجداسم زر الزيادة. والافتراضي «زيادة» في الصفحات العربية.
decrementLabelstringلا يوجداسم زر الإنقاص. والافتراضي «إنقاص» في الصفحات العربية.
status"default" | "success""default"اختر القيمة success لتمييز قيمة اجتازت التحقق.
invalidbooleanfalseيجعل الحقل غير صالح، وللسمة aria-invalid الأثر نفسه.
disabledbooleanfalseيعطّل الحقل والزرّين، ويُظهر المجموعة كلها باهتة.
readOnlybooleanfalseيعرض القيمة ويمنع تغييرها.
requiredbooleanfalseيُرسل النموذج بعد إدخال قيمة فقط.
namestringلا يوجدالاسم الذي تُرسل به القيمة مع النموذج.
formstringلا يوجدمعرّف النموذج الذي تُرسل معه القيمة، حين يكون الحقل خارجه.
idstringلا يوجدمعرّف حقل الإدخال، لتربطه بعنصر label من عندك.
classNamestringلا يوجدأصناف CSS إضافية لمجموعة الحقل.

الاستخدام

حقل رقمي بسيط

tsx
import { InputNumber } from "@/components/ui/input-number"

export function QuantityField() {
  return <InputNumber name="quantity" label="الكمية" defaultValue={1} min={1} max={10} />
}

التحكّم بالقيمة مع حدّين

tsx
"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}
    />
  )
}

تنسيق العملة

tsx
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}
    />
  )
}