النماذج القابلة للوصول
إنشاء نماذج قابلة للاستخدام من قبل الجميع مع تجربة واضحة وموجهة
التسميات والارتباطات
مثال سيء
<!-- ❌ سيء: تسميات مفقودة -->
<form>
<h4>تسجيل الدخول</h4>
<!-- لا توجد تسمية مرتبطة -->
<input
type="email"
placeholder="بريدك الإلكتروني">
<!-- لا توجد تسمية مرتبطة، لا يوجد إكمال تلقائي -->
<input
type="password"
placeholder="كلمة المرور">
<!-- مربع اختيار غير مرتبط -->
<input type="checkbox">
<span>تذكرني</span>
<button type="submit">تسجيل الدخول</button>
</form>مثال جيد
<!-- ✅ جيد: تسميات صريحة ومرتبطة -->
<form>
<h4>تسجيل الدخول</h4>
<!-- تسمية مرتبطة عبر for/id -->
<label for="email-good">عنوان البريد الإلكتروني</label>
<input
type="email"
id="email-good"
placeholder="example@domain.com"
required
aria-describedby="email-help"
autocomplete="email">
<div id="email-help">
لن نشارك بريدك الإلكتروني أبدًا
</div>
<!-- تسمية مع تعليمات -->
<label for="password-good">كلمة المرور</label>
<input
type="password"
id="password-good"
required
aria-describedby="password-help"
autocomplete="current-password">
<div id="password-help">
8 أحرف على الأقل مع أحرف كبيرة وأرقام
</div>
<!-- مربع اختيار مرتبط بشكل صحيح -->
<input type="checkbox" id="remember-good">
<label for="remember-good">تذكرني</label>
<button type="submit">تسجيل الدخول</button>
</form>الشرح: يجب أن يكون لكل حقل نموذج تسمية صريحة مرتبطة بشكل صحيح. العناصر النائبة لا تحل محل التسميات.
التحقق من الصحة ورسائل الخطأ
مثال سيء
<!-- ❌ سيء: أخطاء لم يتم الإعلان عنها بشكل جيد -->
<form @submit.prevent="submitBadForm">
<h4>الاشتراك في النشرة الإخبارية</h4>
<!-- لا يوجد ارتباط تسمية-إدخال -->
<label>الاسم</label>
<input
type="text"
v-model="badForm.name"
:class="{ 'error': submitted && !badForm.name }">
<!-- خطأ مرئي فقط -->
<label>البريد الإلكتروني</label>
<input
type="email"
v-model="badForm.email"
:class="{ 'error': submitted && !isValidEmail(badForm.email) }">
<!-- لا توجد معلومات خطأ -->
<label>العمر</label>
<input
type="number"
v-model="badForm.age"
:class="{ 'error': submitted && badForm.age < 16 }">
<!-- رسالة خطأ عامة وغير مفيدة -->
<div v-if="submitted && badFormErrors.length">
❌ يرجى تصحيح الأخطاء
</div>
<button type="submit">اشترك</button>
</form>مثال جيد
<!-- ✅ جيد: أخطاء مرتبطة بوضوح -->
<form @submit.prevent="submitGoodForm" novalidate>
<h4>الاشتراك في النشرة الإخبارية</h4>
<!-- ملخص الأخطاء مع التنقل -->
<div
v-if="submitted && goodFormErrors.length"
role="alert"
aria-labelledby="error-summary-title">
<h5 id="error-summary-title">أخطاء يجب تصحيحها:</h5>
<ul>
<li v-for="error in goodFormErrors" :key="error.field">
<a :href="`#${error.field}-good-form`">
</a>
</li>
</ul>
</div>
<!-- حقل مع خطأ محدد مرتبط -->
<label for="name-good-form">الاسم الكامل *</label>
<input
type="text"
id="name-good-form"
v-model="goodForm.name"
required
aria-invalid="submitted && !goodForm.name"
aria-describedby="name-error">
<div
v-if="submitted && !goodForm.name"
id="name-error"
role="alert">
❌ الاسم مطلوب
</div>
<button type="submit">اشترك</button>
</form>الشرح: يجب الإعلان عن الأخطاء بوضوح، وربطها بالحقول ذات الصلة، وتوفير تعليمات دقيقة للتصحيح.
مجموعات الحقول مع aria-labelledby
مثال سيء
<!-- ❌ سيء: بنية غير منظمة -->
<form>
<h4>التفضيلات</h4>
<!-- عناصر مختلطة بدون منطق -->
<div>
<input type="radio" name="contact-bad"
id="email-contact-bad" value="email">
<label for="email-contact-bad">البريد الإلكتروني</label>
<input type="checkbox" id="newsletter-bad"
value="newsletter">
<label for="newsletter-bad">النشرة الإخبارية</label>
</div>
<div>
<input type="radio" name="contact-bad"
id="phone-contact-bad" value="phone">
<label for="phone-contact-bad">الهاتف</label>
<!-- حقل نصي بدون سياق -->
<input type="text" placeholder="الاسم">
</div>
<div>
<input type="checkbox" id="offers-bad" value="offers">
<label for="offers-bad">العروض</label>
<input type="radio" name="contact-bad"
id="sms-contact-bad" value="sms">
<label for="sms-contact-bad">الرسائل القصيرة</label>
</div>
<!-- اختيار بدون سياق -->
<select>
<option>اختر...</option>
<option>يومي</option>
<option>أسبوعي</option>
</select>
<button type="submit">موافق</button>
</form>مثال جيد
<!-- ✅ جيد: مجموعات منطقية مع aria-labelledby -->
<form>
<h4>تفضيلات الاتصال</h4>
<!-- قسم المعلومات الشخصية -->
<div role="group" aria-labelledby="personal-info-title">
<h5 id="personal-info-title">
المعلومات الشخصية
</h5>
<label for="name-good">الاسم الكامل *</label>
<input
type="text"
id="name-good"
name="name"
required
aria-required="true"
aria-describedby="name-desc">
<span id="name-desc">
اسمك الكامل كما سيظهر في اتصالاتنا
</span>
</div>
<!-- مجموعة أزرار الراديو -->
<div
role="radiogroup"
aria-labelledby="contact-method-title"
aria-required="true">
<h5 id="contact-method-title">
طريقة الاتصال المفضلة *
</h5>
<input
type="radio"
name="contact-good"
id="email-contact-good"
value="email"
required>
<label for="email-contact-good">البريد الإلكتروني</label>
<input
type="radio"
name="contact-good"
id="phone-contact-good"
value="phone"
required>
<label for="phone-contact-good">الهاتف</label>
</div>
<!-- مجموعة مربعات الاختيار -->
<div role="group" aria-labelledby="comm-types-title">
<h5 id="comm-types-title">أنواع الاتصالات</h5>
<p id="comm-types-desc">
اختر أنواع الاتصالات التي ترغب في تلقيها
</p>
<input
type="checkbox"
id="newsletter-good"
value="newsletter"
aria-describedby="comm-types-desc">
<label for="newsletter-good">النشرة الإخبارية</label>
</div>
<button type="submit">
حفظ التفضيلات
</button>
</form>الشرح: يجب ربط مجموعات الحقول ذات الصلة بعناوينها عبر aria-labelledby لإنشاء علاقات دلالية واضحة، خاصة لأزرار الراديو ومربعات الاختيار.
نموذج معقد مع التحقق في الوقت الفعلي
مثال سيء
<!-- ❌ سيء: تحقق متطفل -->
<form>
<h4>إنشاء حساب</h4>
<!-- تحقق فوري على كل ضغطة مفتاح -->
<label>اسم المستخدم</label>
<input
type="text"
v-model="complexBadForm.username"
@input="validateUsernameBad"
:class="{ 'error': usernameBadError }">
<!-- خطأ يظهر/يختفي باستمرار -->
<div v-if="usernameBadError">
</div>
<!-- لا يوجد ارتباط مع aria-describedby -->
<label>البريد الإلكتروني</label>
<input
type="email"
v-model="complexBadForm.email"
@input="validateEmailBad"
:class="{ 'error': emailBadError }">
<div v-if="emailBadError"></div>
<!-- رسائل خطأ قصيرة جدًا وغير مفيدة -->
<!-- لا يوجد إكمال تلقائي لمساعدة مديري كلمات المرور -->
<label>كلمة المرور</label>
<input
type="password"
v-model="complexBadForm.password"
@input="validatePasswordBad"
:class="{ 'error': passwordBadError }">
<div v-if="passwordBadError"></div>
<button type="submit">إنشاء حساب</button>
</form>مثال جيد
<!-- ✅ جيد: تحقق محترم مع ردود الفعل -->
<form>
<h4>إنشاء حساب</h4>
<!-- التحقق عند blur، وليس على input -->
<label for="username-complex">اسم المستخدم *</label>
<input
type="text"
id="username-complex"
v-model="complexGoodForm.username"
@blur="validateUsernameGood"
:class="{ error: usernameGoodError,
success: usernameGoodValid }"
aria-describedby="username-requirements username-feedback"
aria-invalid="!!usernameGoodError"
required>
<!-- تعليمات واضحة -->
<div id="username-requirements">
<h6>المتطلبات:</h6>
<ul>
<li :class="{ valid: complexGoodForm.username.length >= 3 }">
3 أحرف على الأقل
</li>
<li :class="{ valid: /^[a-zA-Z0-9_]+$/.test(username) }">
أحرف وأرقام وشرطة سفلية فقط
</li>
</ul>
</div>
<!-- ردود فعل يمكن الوصول إليها -->
<div
v-if="usernameGoodError"
id="username-feedback"
role="alert"
aria-live="polite">
❌
</div>
<div
v-else-if="usernameGoodValid"
id="username-feedback"
role="status"
aria-live="polite">
✅ اسم المستخدم متاح
</div>
<!-- مؤشر قوة كلمة المرور -->
<label for="password-complex">كلمة المرور *</label>
<input
type="password"
id="password-complex"
v-model="complexGoodForm.password"
@input="validatePasswordGood"
aria-describedby="password-strength"
autocomplete="new-password"
required>
<div id="password-strength">
<h6>قوة كلمة المرور:</h6>
<div class="strength-indicator">
<div
class="strength-bar"
:class="`strength-${passwordStrength}`"
:style="{ width: `${passwordStrength * 25}%` }">
</div>
</div>
</div>
<button type="submit" :disabled="!isFormValid">
إنشاء حساب
</button>
</form>الشرح: بالنسبة للنماذج المعقدة، يمكن أن يساعد التحقق في الوقت الفعلي، ولكن يجب تنفيذه بطريقة غير متطفلة ويمكن الوصول إليها.