نظرة عامة أساسية حول كيفية إنشاء مكوّن اختيار متعدّد متجاوب وقابل للتكيّف وسهل الاستخدام لتصنيف تجارب المستخدمين وفلترتها
في هذه المشاركة، أريد مشاركة أفكار حول طريقة إنشاء مكوّن اختيار متعدّد. جرِّب الإصدار التجريبي.
إذا كنت تفضّل الفيديو، يمكنك الاطّلاع على نسخة من هذه المشاركة على YouTube:
نظرة عامة
غالبًا ما يُعرض للمستخدمين عناصر، وأحيانًا كثير من العناصر، وفي هذه الحالات، قد يكون من الجيد توفير طريقة لتقليل القائمة لمنع التحميل الزائد للاختيار. تتناول مشاركة المدونة هذه واجهة مستخدم الفلترة كطريقة لتقليل الخيارات. ويتم ذلك من خلال عرض سمات السلع التي يمكن للمستخدمين اختيارها أو إلغاء اختيارها، ما يؤدي إلى تقليل النتائج وبالتالي تقليل عدد الخيارات المعروضة.
التفاعلات
والهدف من ذلك هو السماح بالتنقّل السريع في خيارات الفلترة لجميع المستخدمين و
أنواع الإدخال المختلفة. سيتم تقديم هذا مع زوج من المكونات
القابلين للتكيف والاستجابة. هو شريط جانبي تقليدي من مربّعات الاختيار لأجهزة الكمبيوتر المكتبي ولوحة المفاتيح
وبرامج قراءة الشاشة و<select
multiple>
لمستخدمي الأجهزة التي تعمل باللمس.
إنّ قرار استخدام ميزة "الاختيار المتعدّد" المضمّنة للأجهزة التي تعمل باللمس وليس لأجهزة الكمبيوتر المكتبي يوفر الجهد ويخلق العمل، ولكنّني أعتقد أنّه يقدّم تجارب مناسبة مع تقليل عبء الرموز البرمجية مقارنةً بإنشاء تجربة الاستجابة الكاملة في مكوّن واحد.
اللمس
يوفر مكوّن اللمس مساحة ويساعد في دقة تفاعل المستخدم على
الأجهزة الجوّالة. ويساعد ذلك في توفير المساحة من خلال تصغير شريط جانبي كامل من مربّعات الاختيار إلى تجربتَي لمس مدمجتَين في
<select>
. ويساعد ذلك في دقة الإدخال من خلال عرض
تجربة تراكب لمس كبيرة يوفرها النظام.
لوحة المفاتيح وجهاز التحكّم في الألعاب
في ما يلي عرض توضيحي لكيفية استخدام <select multiple>
من لوحة المفاتيح.
لا يمكن تصميم هذا التحديد المتعدد المدمج هذا ويتم تقديمه فقط في تخطيط مكثف غير مناسب لتقديم الكثير من الخيارات. هل ترى أنّه لا يمكنك الاطّلاع على مجموعة الخيارات الواسعة في هذا المربّع الصغير؟ بينما يمكنك تغيير حجمه، إلا أنه لا يزال غير قابل للاستخدام مثل الشريط الجانبي لمربعات الاختيار.
Markup
سيتم تضمين كلا المكوّنين في عنصر <form>
نفسه. سيتم رصد نتائج
هذا النموذج، سواء كانت مربّعات اختيار أو قائمة اختيار متعدّدة، واستخدامها لfiltrare الشبكة، ولكن يمكن أيضًا إرسالها إلى خادم.
<form>
</form>
مكوّن مربّعات الاختيار
يجب تضمين مجموعات مربّعات الاختيار في عنصر
<fieldset>
ومنحهم علامة
<legend>
.
عند تنظيم صفحات HTML بهذه الطريقة، سيفهم قارئ الشاشة وFormData تلقائيًا علاقة العناصر.
<form>
<fieldset>
<legend>New</legend>
… checkboxes …
</fieldset>
</form>
مع وضع التجميع، أضِف <label>
و<input type="checkbox">
لكل فلتر من الفلاتر. اخترتُ لفّ تصنيفاتي في <div>
حتى تتمكّن خاصية gap
في CSS
من توزيعها بالتساوي والحفاظ على المحاذاة عندما تكون التصنيفات متعددة الأسطر.
<form>
<fieldset>
<legend>New</legend>
<div>
<input type="checkbox" id="last 30 days" name="new" value="last 30 days">
<label for="last 30 days">Last 30 Days</label>
</div>
<div>
<input type="checkbox" id="last 6 months" name="new" value="last 6 months">
<label for="last 6 months">Last 6 Months</label>
</div>
</fieldset>
</form>
مكوّن <select multiple>
من الميزات التي نادرًا ما يتم استخدامها للعنصر <select>
هي
multiple
.
عند استخدام السمة مع عنصر <select>
، يُسمح للمستخدم بتحديد
العديد من القيم من القائمة. يشبه ذلك تغيير التفاعل من قائمة خيارات متناوبة
إلى قائمة مربّعات اختيار.
<form>
<select multiple="true" title="Filter results by category">
…
</select>
</form>
لتصنيف وإنشاء مجموعات داخل <select>
، استخدِم عنصر
<optgroup>
وامنحه السمة والسمة label
. يشبه هذا العنصر وقيمة السمة
عنصرَي <fieldset>
و<legend>
.
<form>
<select multiple="true" title="Filter results by category">
<optgroup label="New">
…
</optgroup>
</select>
</form>
أضِف الآن عناصر
<option>
للفلتر.
<form>
<select multiple="true" title="Filter results by category">
<optgroup label="New">
<option value="last 30 days">Last 30 Days</option>
<option value="last 6 months">Last 6 Months</option>
</optgroup>
</select>
</form>
تتبُّع الإدخال باستخدام العدّادات لإعلام التكنولوجيا المساعِدة
يتم استخدام تقنية حالة
دور
في تجربة المستخدم هذه لتتبُّع عدد
الفلاتر لبرامج قراءة الشاشة والتقنيات المساعِدة الأخرى والحفاظ عليه. يوضح مقطع فيديو
YouTube هذه الميزة. تبدأ عملية الدمج بـ HTML والسمة
role="status"
.
<div role="status" class="sr-only" id="applied-filters"></div>
سيقرأ هذا العنصر التغييرات التي تم إجراؤها على المحتوى بصوت عالٍ. يمكننا تعديل المحتوى باستخدام عدادات CSS عندما يتفاعل المستخدمون مع مربّعات الاختيار. لإجراء ذلك، نحتاج أولاً إلى إنشاء ملف شخصي يحتوي على اسم في عنصر رئيسي للعناصر inputs وstate.
aside {
counter-reset: filters;
}
سيكون العدد تلقائيًا 0
، وهو أمر رائع، لأنّه ليس هناك أي :checked
تلقائيًا في هذا التصميم.
بعد ذلك، لزيادة المعداد الذي تم إنشاؤه حديثًا، سنستهدف العناصر الفرعية لعنصر
<aside>
التي تكون :checked
. وعندما يغيّر المستخدم حالة الإدخالات،
سيتم احتساب عدد العناصر في filters
.
aside :checked {
counter-increment: filters;
}
يعلم CSS الآن بالعدد الإجمالي لواجهة مستخدم مربّع الاختيار ويكون عنصر دور الحالة
فارغًا في انتظار القيم. بما أنّ CSS تحافظ على الاحتساب في
الذاكرة، تسمح الدالة
counter()
بالوصول إلى القيمة من محتويات العنصر
الزائف:
aside #applied-filters::before {
content: counter(filters) " filters ";
}
سيعلِن الآن HTML لعنصر دور الحالة عن "فلترَين" لقارئ الشاشة. هذه بداية جيدة، ولكن يمكننا تحسينها، مثلاً من خلال مشاركة عدد النتائج التي عدّلت الفلاتر. سننفّذ هذا العمل من JavaScript، لأنّه خارج نطاق ما يمكن أن تُنفّذه العدّادات.
إثارة الدمج
كانت خوارزمية العدّادات رائعة مع CSS التداخل-1، لأنّني تمكّنت من وضع كل المنطق في كتلة واحدة. شعور بالسهولة في نقل البيانات وتعديلها
aside {
counter-reset: filters;
& :checked {
counter-increment: filters;
}
& #applied-filters::before {
content: counter(filters) " filters ";
}
}
التنسيقات
يوضّح هذا القسم التنسيقات بين المكوّنين. معظم أنماط التخطيط للمكون خانة الاختيار لسطح المكتب.
النموذج
لتحسين سهولة القراءة والاطّلاع على النموذج، يتم ضبط عرضه على 30 حرفًا بحد أقصى، ما يؤدي إلى ضبط عرض السطر البصري لكل تصنيف فلتر. يستخدم النموذج تنسيق الشبكة والسمة gap
لترك مسافة بين
حقول المجموعة.
form {
display: grid;
gap: 2ch;
max-inline-size: 30ch;
}
العنصر <select>
تستهلك قائمة التصنيفات مربّعات الاختيار مساحة كبيرة جدًا على الأجهزة الجوّالة. وبالتالي، يتحقق التنسيق من جهاز التأشير الأساسي للمستخدم لتغيير تجربة اللمس.
@media (pointer: coarse) {
select[multiple] {
display: block;
}
}
تشير القيمة coarse
إلى أنّ المستخدم لن يتمكّن من التفاعل مع
الشاشة بدقة عالية باستخدام جهاز الإدخال الأساسي. على
الأجهزة الجوّالة، غالبًا ما تكون قيمة المؤشر هي coarse
، لأنّ التفاعل الأساسي
يكون من خلال اللمس. على أجهزة الكمبيوتر المكتبي، تكون قيمة المؤشر غالبًا fine
لأنّه من الشائع اتصال ماوس أو جهاز إدخال آخر عالي الدقة.
المجموعات
يكون التنسيق التلقائي لـ <fieldset>
مع <legend>
فريدًا:
عادةً، سأستخدِم السمة gap
لإضافة مسافة بين العناصر الفرعية، ولكنّ الموضع الفريد
للعنصر <legend>
يجعل من الصعب إنشاء مجموعة متساوية المسافة
للعناصر الفرعية. بدلاً من gap
، يتم استخدام أداة اختيار الشقيق المجاور
وmargin-block-start
.
fieldset {
padding: 2ch;
& > div + div {
margin-block-start: 2ch;
}
}
يؤدي ذلك إلى عدم تعديل مساحة <legend>
من خلال استهداف
<div>
الأطفال فقط.
تصنيف الفلتر ومربّع الاختيار
بصفتها عنصرًا ثانويًا مباشرًا لعنصر <fieldset>
وضمن الحد الأقصى لعرض
30ch
النموذج، قد يتمّ التفاف نص التصنيف إذا كان طويلاً جدًا. إنّ لفّ النص أمر رائع، ولكن
عدم محاذاة النص مربّع الاختيار ليس كذلك. يعد Flexbox مثاليًا لهذا.
fieldset > div {
display: flex;
gap: 2ch;
align-items: baseline;
}
الشبكة المتحركة
يتم إنشاء الصورة المتحركة للتخطيط بواسطة Isotope. مكوّن إضافي فعال وفعّال للفلترة والترتيب التفاعليَين
JavaScript
بالإضافة إلى المساعدة في تنظيم شبكة تفاعلية متحركة وأنيقة، يتم استخدام JavaScript لتحسين بعض الجوانب.
تطبيع إدخال المستخدم
يحتوي هذا التصميم على نموذج واحد مع طريقتين مختلفتين لتقديم المدخلات، ولا يتسلسلان بالتسلسل نفسه. باستخدام بعض رموز JavaScript، يمكننا تسويتها.
اخترت مواءمة بنية بيانات عنصر <select>
مع بنية مربّعات الاختيار المُجمَّعة
. لإجراء ذلك، تتم إضافة أداة معالجة حدث input
إلى العنصر <select>
، وعندها يتم ربط
selectedOptions
بها.
document.querySelector('select').addEventListener('input', event => {
// make selectedOptions iterable then reduce a new array object
let selectData = Array.from(event.target.selectedOptions).reduce((data, opt) => {
// parent optgroup label and option value are added to the reduce aggregator
data.push([opt.parentElement.label.toLowerCase(), opt.value])
return data
}, [])
})
يمكنك الآن إرسال النموذج بأمان، أو في حالة هذا العرض التوضيحي، عليك إرشاد Isotope إلى ما يجب التصفية وفقًا له.
إنهاء عنصر دور الحالة
لا يحتسب العنصر عدد الفلاتر ويعلن عنه إلا استنادًا إلى تفاعل مربّع الاختيار، ولكنني أعتقد أنّه من المفيد أيضًا مشاركة عدد
النتائج والتأكّد من احتساب خيارات عنصر <select>
أيضًا.
اختيار عنصر <select>
يظهر في counter()
في قسم تطبيع البيانات، سبق أن تم إنشاء مستمع عند الإدخال. في نهاية هذه الدالة، يكون عدد الفلاتر التي تم اختيارها وعدد النتائج لهذه الفلاتر معروفًا. يمكن تمرير القيم إلى عنصر دور الحالة مثل هذا.
let statusRoleElement = document.querySelector('#applied-filters')
statusRoleElement.style.counterSet = selectData.length
تظهر النتائج في العنصر role="status"
يوفّر :checked
طريقة مضمّنة لنقل عدد الفلاتر المحدّدة إلى
عنصر دور الحالة، ولكنّه لا يقدّم إمكانية الوصول إلى العدد الذي تمّت فلترته من النتائج.
بإمكان JavaScript ملاحظة التفاعل مع مربّعات الاختيار، وبعد فلترة
الشبكة، أضِف textContent
كما فعل العنصر <select>
.
document
.querySelector('aside form')
.addEventListener('input', e => {
// isotope demo code
let filterResults = IsotopeGrid.getFilteredItemElements().length
document.querySelector('#applied-filters').textContent = `giving ${filterResults} results`
})
يكمل هذا العمل الإعلان "فلتران يقدّمان 25 نتيجة".
ستتوفّر الآن تجربة التكنولوجيا المساعِدة الممتازة لجميع المستخدمين، بغض النظر عن طريقة تفاعلهم معها.
الخاتمة
الآن بعد أن عرفت كيف فعلت ذلك، كيف يمكنك‽ 🙂
لننوّع أساليبنا ونتعرّف على جميع الطرق لإنشاء تطبيقات على الويب. أنشئ عرضًا توضيحيًا وأرسِل إلينا رابطًا على Twitter، وسنضيفه إلى قسم الريمكسات التي أنشأها المستخدمون أدناه.
الريمكسات التي أنشأها المستخدمون
ما مِن عناصر للاطّلاع عليها هنا حتى الآن.