# النموذج

> كيف تجتمع حقول كنز في نموذج: أقسام بعنوان وسبب قصير، وحقول بترتيب القراءة، وشريط إجراءات واحد واضح، ورسائل خطأ تقول كيف يُصلح الخطأ. لا مكتبة نماذج مدمجة: يعمل مع حالتك الخاصة أو مع react-hook-form وZod.

الصفحة: https://ritla.app/ar/ui/form

## التثبيت

يُفتح التثبيت من السجل قريبًا، وهذه هي الأوامر التي ستشغّلها حينها.

```bash
npx ritla add form
```

أو بأداة shadcn:

```bash
npx shadcn@latest add @ritla/form
```

الاعتماديات: `@base-ui/react`، `@phosphor-icons/react`

## الاستخدام

```tsx
import { Form, FormActions, FormErrorSummary, FormSection } from "@/components/ui/form";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";

<Form onSubmit={save}>
  <FormSection title="Personal details" description="We use these on receipts and transfers.">
    <FormErrorSummary errors={summary} focusKey={submitCount} />
    <Input id="email" label="Email" required type="email" error={errors.email} />
    <FormActions status="Saved 2 minutes ago">
      <Button variant="outline" size="md">Cancel</Button>
      <Button size="md" type="submit">Save changes</Button>
    </FormActions>
  </FormSection>
</Form>
```

## أمثلة

### مكدّس، مع أخطاء

`layout="stacked"` للجوال والنوافذ والأعمدة الضيقة، و`align="full-width"` يضع «حفظ» فوق «إلغاء» بعرض كامل. بعد حفظ فشل، الملخص في الأعلى وكل حقل يعرض خطأه في مكانه. `FormOptional` يكتب «(اختياري)» بعد تسمية الحقل؛ علّم الحقول الاختيارية القليلة لا المطلوبة الكثيرة.

معاينة حيّة: https://ritla.app/_kanz/preview/arabic/form-stacked

### مع react-hook-form وZod

لفرق تستخدمهما أصلًا. كنز لا يضيف أيًا منهما: ثبّتهما بنفسك (`npm install react-hook-form zod @hookform/resolvers`). `register` يعطي كل حقل اسمه ومرجعه ومعالجاته، ورسائل المخطط تذهب إلى `error` وإلى الملخص، و`submitCount` يعيد التركيز إلى الملخص عند كل حفظ، و`shouldFocusError: false` يترك التركيز للملخص.

معاينة حيّة: https://ritla.app/_kanz/preview/arabic/form-react-hook-form

## مرجع الخصائص

### `Form`

| الخاصية | النوع | الافتراضي | الوصف |
| --- | --- | --- | --- |
| `onSubmit` | `(event) => void` | لا يوجد | عند الإرسال. تحقّق من كل الحقول هنا، واعرض الملخص إن وُجدت أخطاء. |
| `noValidate` | `boolean` | `true` | يطفئ فقاعات الخطأ في المتصفح، فتظهر الأخطاء في حقول كنز وفي الملخص. |

### `FormSection`

| الخاصية | النوع | الافتراضي | الوصف |
| --- | --- | --- | --- |
| `title` | `ReactNode` | لا يوجد | عنوان القسم («البيانات الشخصية»). القسم `<section>` باسم عنوانه. |
| `description` | `ReactNode` | لا يوجد | السبب القصير تحت العنوان: لماذا تطلب هذه البيانات. |
| `layout` | `"auto" \| "two-column" \| "stacked"` | `"auto"` | خاصية Layout: عمودان للإعدادات على سطح المكتب (السبب في جهة والحقول في الأخرى)، أو مكدّس. `auto` مكدّس تحت نقطة التوقف lg. |

### `FormRow / FormOptional`

| الخاصية | النوع | الافتراضي | الوصف |
| --- | --- | --- | --- |
| `children (FormRow)` | `ReactNode` | لا يوجد | حقلان متجاوران حين تتسع المساحة (الاسم الأول واسم العائلة)، ومكدّسان على الجوال. |
| `FormOptional` | `component` | لا يوجد | يكتب «(اختياري)» بلغة الصفحة بعد تسمية الحقل. |

### `FormErrorSummary`

| الخاصية | النوع | الافتراضي | الوصف |
| --- | --- | --- | --- |
| `errors` | `{ id, label, message }[]` | لا يوجد | حقل لكل خطأ، بترتيب النموذج. `id` معرّف عنصر الحقل، فينقل الرابط التركيز إليه. لا يظهر شيء والقائمة فارغة. |
| `title` | `ReactNode` | لا يوجد | العنوان. الافتراضي «صحّح الحقول التالية:» بالعربية و"Fix 2 things before you save" بالإنجليزية، بالعدد بأرقام الصفحة. |
| `focusKey` | `unknown` | لا يوجد | يأخذ التركيز كلما تغيّر: مرّر عدد مرات الإرسال، فيصل كل إرسال فاشل إلى الملخص، ولا يُسحب التركيز من حقل أثناء إصلاحه. |
| `autoFocus` | `boolean` | `true` | يأخذ التركيز حين يظهر. |

### `FormActions`

| الخاصية | النوع | الافتراضي | الوصف |
| --- | --- | --- | --- |
| `children` | `ReactNode` | لا يوجد | الأزرار بترتيب القراءة: «إلغاء» (Outline) ثم «حفظ» (Filled، الزر الممتلئ الوحيد). |
| `status` | `ReactNode` | لا يوجد | حالة الحفظ في بداية الشريط («تم الحفظ قبل دقيقتين»)، تُعلَن دون مقاطعة (`aria-live="polite"`) حين تتغير. |
| `align` | `"auto" \| "end" \| "full-width"` | `"auto"` | خاصية Align: الحفظ في النهاية على سطح المكتب، أو «حفظ» فوق «إلغاء» بعرض كامل على الجوال. `auto` بعرض كامل تحت نقطة التوقف sm. |

## إمكانية الوصول

لوحة المفاتيح (المفاتيح مكتوبة للاتجاه من اليسار إلى اليمين، ويتبادل السهمان في الاتجاه من اليمين إلى اليسار):

- `Tab`: عبر الحقول بترتيب القراءة، ثم «إلغاء» و«حفظ».
- `Enter`: في حقل نصي يرسل النموذج؛ على رابط في الملخص ينقل التركيز إلى حقله.

ARIA:

- الملخص `role="alert"` ويأخذ التركيز بعد إرسال فاشل، فيصل إليه المستخدم بلوحة المفاتيح وقارئ الشاشة مباشرة؛ كل سطر فيه رابط إلى حقله.
- تحقّق من الحقل حين يغادره المستخدم، لا أثناء الكتابة؛ ويختفي الخطأ فور صحة القيمة.
- كل حقل بتسمية ظاهرة. النجمة زخرفة: `required` على الحقل هو ما يُعلَن «مطلوب».
- رسالة الخطأ تسمّي الحقل والإصلاح («أدخل عنوانًا مثل name@example.com»)، لا «غير صالح» وحدها.

## ملاحظات العربية والاتجاه

ينعكس:

- في العمودين: العنوان والسبب على اليمين والحقول على اليسار.
- شريط الإجراءات: «حفظ» في نهاية السطر (اليسار) و«إلغاء» بجانبه، وحالة الحفظ على اليمين.
- الملخص: أيقونة التحذير على اليمين والنص بعدها.

لا ينعكس:

- البريد الإلكتروني ورقم الهاتف والآيبان تبقى من اليسار إلى اليمين، معزولة داخل الصفحة العربية.
- أيقونة التحذير لا تنعكس.

الأرقام: العدد في عنوان الملخص الافتراضي يتبع `numerals`، وكذلك أي رقم تكتبه في الرسائل عبر `formatNumber`.

الخط العربي: عنوان القسم `body-18` بوزن Semibold والسبب `label-14`؛ الأسطر العربية أطول، فلا ارتفاعات ثابتة على النص.

النص ثنائي الاتجاه: سطر الملخص `dir="auto"`: رسالة إنجليزية من الخادم في صفحة عربية تبقى صحيحة الترتيب.
