Çoklu seçim bileşeni oluşturma

Kullanıcı deneyimlerini sıralamak ve filtrelemek için duyarlı, uyarlanabilir, erişilebilir, çoklu seçim bileşeni oluşturmaya temel bir genel bakış.

Bu yayında, çoklu seçim bileşeni oluşturmanın bir yolu üzerine düşünmek istiyorum. Demoyu deneyin.

Tanıtım

Videoyu tercih ediyorsanız bu yayının YouTube sürümünü burada bulabilirsiniz:

Genel bakış

Kullanıcılara sıklıkla öğeler (bazen çok çok sayıda öğe) sunulur. Bu durumlarda, çok fazla seçenek olmasını önlemek için listeyi küçültecek bir yöntem sunmak iyi bir fikir olabilir. Bu blog yayınında, seçim sayısını azaltmanın bir yolu olarak filtreleme kullanıcı arayüzü ele alınmaktadır. Bunu, kullanıcıların seçebileceği veya seçimini kaldırabileceği öğe özellikleri sunarak, sonuçları azaltarak ve böylece seçim yükünü azaltarak yapar.

Etkileşimler

Amaç, tüm kullanıcılar ve bunların değişen giriş türleri için filtre seçenekleri arasında hızlı geçişe olanak tanımaktır. Bu, uyarlanabilir ve duyarlı bir bileşen çiftiyle teslim edilecektir. Masaüstü, klavye ve ekran okuyucular için onay kutularından oluşan geleneksel bir kenar çubuğu; dokunmatik kullanıcılar için bir <select multiple>.

Çoklu seçim öğesi bulunan mobil iOS ve Android ile mobil iOS ve Android&#39;in karşılaştırmasına göre, onay kutuları kenarlı bir kenar çubuğu olan masaüstü açık ve koyu renkli karşılaştırmalı ekran görüntüsü.

Masaüstü için değil, dokunma için yerleşik çoklu seçim özelliğini kullanma kararı iş tasarrufu sağlıyor ve iş yaratıyor. Ancak tüm duyarlı deneyimi tek bir bileşende oluşturmaktan daha az kod borcuyla uygun deneyimler sağladığına inanıyorum.

Dokunma

Dokunma bileşeni yerden tasarruf sağlar ve mobil cihazlarda kullanıcı etkileşimi doğruluğunun sağlanmasına yardımcı olur. Onay kutuları içeren kenar çubuğunu tümüyle <select> yerleşik bir yer paylaşımlı dokunma deneyimine daraltarak yerden tasarruf sağlar. Sistemin sağladığı geniş dokunmatik yer paylaşımı deneyimini göstererek giriş doğruluğuna yardımcı olur.

Android, iPhone ve iPad&#39;deki Chrome&#39;daki çoklu seçim öğesinin ekran görüntüsü önizlemesi. iPad&#39;de ve iPhone&#39;da çoklu seçim düğmesi açık ve her biri, ekran boyutuna göre optimize edilmiş benzersiz bir deneyime sahip.

Klavye ve oyun kumandası

Aşağıda, klavyeden <select multiple> öğesinin nasıl kullanılacağına ilişkin bir tanıtım yer almaktadır.

Bu yerleşik çoklu seçim özelliği, stil özellikleri ayarlanamaz ve yalnızca çok sayıda seçenek sunulmasına uygun olmayan kompakt bir düzende sunulur. O küçücük kutuda o kadar fazla seçeneği nasıl göremediğinizi anladınız mı? Boyutunu değiştirebilseniz de onay kutularından oluşan bir kenar çubuğu kadar kullanılabilir değildir.

Markup

Her iki bileşen de aynı <form> öğesinde yer alır. Bu formun sonuçları, ister onay kutuları ister çoklu seçim olsun, gözlemlenir ve tabloyu filtrelemek için kullanılır, ancak bir sunucuya da gönderilebilir.

<form>

</form>

Onay kutuları bileşeni

Onay kutusu grupları bir <fieldset> öğesi içine yerleştirilmeli ve bir <legend> verilmelidir. HTML bu şekilde yapılandırıldığında, ekran okuyucular ve FormData öğelerin ilişkisini otomatik olarak anlar.

<form>
  <fieldset>
    <legend>New</legend>
    … checkboxes …
  </fieldset>
</form>

Grup oluşturulduktan sonra, her filtre için bir <label> ve <input type="checkbox"> ekleyin. Benimkini bir <div> içine sarmayı seçtim. Böylece etiketler çok satırlı olduğunda CSS gap özelliği bunları eşit şekilde dağıtabilir ve hizalamayı koruyabilir.

<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>

Açıklamalar ve alan grubu öğeleri için bilgilendirici bir yer paylaşımı içeren ekran görüntüsünde renk ve öğe adı gösteriliyor.

<select multiple> bileşeni

<select> öğesinin nadir kullanılan bir özelliği de multiple şeklindedir. Özellik bir <select> öğesiyle kullanıldığında kullanıcının listeden birçok seçim yapmasına izin verilir. Etkileşimi bir radyo listesinden onay kutusu listesine dönüştürmeye benzer.

<form>
  <select multiple="true" title="Filter results by category">
    …
  </select>
</form>

Bir <select> içinde etiketlemek ve grup oluşturmak için <optgroup> öğesini kullanarak label özelliği ve değeri verin. Bu öğe ve özellik değeri, <fieldset> ve <legend> öğelerine benzer.

<form>
  <select multiple="true" title="Filter results by category">
    <optgroup label="New">
      …
    </optgroup>
  </select>
</form>

Şimdi filtre için <option> öğelerini ekleyin.

<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>

Çoklu seçim öğesinin masaüstünde oluşturulmuş ekran görüntüsü.

Yardımcı teknolojiler için bilgi sağlayan sayaçlarla girişi izleme

Bu kullanıcı deneyiminde durum rolü tekniği, ekran okuyucuları ve diğer yardımcı teknolojiler için filtrelerin kaydını izlemek ve tutmak için kullanılır. Bu özellik YouTube videosunda açıklanıyor. Entegrasyon, HTML ve role="status" özelliğiyle başlar.

<div role="status" class="sr-only" id="applied-filters"></div>

Bu öğe, içerikte yapılan değişiklikleri sesli okur. Kullanıcılar onay kutularıyla etkileşimde bulunurken içerikleri CSS sayaçları ile güncelleyebiliriz. Bunu yapmak için önce girişlerin ve durum öğesinin üst öğesinde adı olan bir sayaç oluşturmamız gerekir.

aside {
  counter-reset: filters;
}

Varsayılan olarak sayı 0 olur. Bu harikadır. Bu tasarımda varsayılan olarak :checked değeri yoktur.

Daha sonra, yeni oluşturulan sayacımızı artırmak için <aside> öğesinin :checked alt öğelerini hedefleyeceğiz. Kullanıcı, girişlerin durumunu değiştirdikçe filters sayacı buna göre ayarlanır.

aside :checked {
  counter-increment: filters;
}

CSS artık onay kutusu kullanıcı arayüzünün genel hesabını biliyor ve durum rolü öğesi boş ve değerleri bekliyor. CSS, kaydı bellekte tuttuğundan counter() işlevi, sözde öğe içeriklerindeki değere erişime izin verir:

aside #applied-filters::before {
  content: counter(filters) " filters ";
}

Durum rolü öğesinin HTML'si artık bir ekran okuyucuya "2 filtre" mesajını duyurdu. Bu iyi bir başlangıç, ama biz daha iyisini yapabiliriz. Örneğin, filtrelerin güncellediği sonuçların kaydını paylaşabiliriz. Bu işi JavaScript'ten yapacağız, çünkü sayaçların yapabildiklerinin dışında.

Etkin filtrelerin sayısını duyuran MacOS ekran okuyucusunun ekran görüntüsü.

Yuva heyecanı

Tüm mantığı tek bir bloka yerleştirebildiğim için sayaç algoritması, CSS Nesting-1 ile çok iyi bir fikirdi. Taşınabilir ve merkezi bir şekilde okuma ve güncelleme için kullanılabilir.

aside {
  counter-reset: filters;

  & :checked {
    counter-increment: filters;
  }

  & #applied-filters::before {
    content: counter(filters) " filters ";
  }
}

Düzenler

Bu bölümde, iki bileşen arasındaki düzenler açıklanmaktadır. Düzen stillerinin çoğu masaüstü onay kutusu bileşenine yöneliktir.

Form

Kullanıcıların okunabilirliğini ve taranabilirliğini optimize etmek için forma maksimum 30 karakter genişliği verilir. Bu genişlik temelde her filtre etiketi için bir optik çizgi genişliği ayarlanır. Form, alan kümeleri arasında boşluk bırakmak için ızgara düzenini ve gap özelliğini kullanır.

form {
  display: grid;
  gap: 2ch;
  max-inline-size: 30ch;
}

<select> öğesi

Hem etiket listesi hem de onay kutuları mobil cihazlarda çok fazla yer kaplar. Bu nedenle düzen, dokunma deneyimini değiştirmek için kullanıcının birincil işaretleme cihazını kontrol eder.

@media (pointer: coarse) {
  select[multiple] {
    display: block;
  }
}

coarse değeri, kullanıcının birincil giriş cihazını kullanarak ekranla yüksek hassasiyetle etkileşimde bulunamayacağını belirtir. Mobil cihazlarda, birincil etkileşim dokunma olduğundan işaretçi değeri genellikle coarse'dir. İşaretçi değeri, masaüstü cihazlarda fare veya başka bir yüksek hassasiyete sahip giriş cihazının bağlı olması yaygın olarak kullanıldığı için genellikle fine'dir.

Alan kümeleri

<legend> içeren <fieldset> öğesinin varsayılan stili ve düzeni benzersizdir:

Alan grubu ve gösterge için varsayılan stillerin ekran görüntüsü.

Normalde, alt öğelerimi boşluk bırakmak için gap özelliğini kullanırım ancak <legend> öğesinin benzersiz konumlandırılması, eşit aralıklı bir alt öğe grubu oluşturmayı zorlaştırır. gap yerine, bitişik olan eşdüzey seçici ve margin-block-start kullanılır.

fieldset {
  padding: 2ch;

  & > div + div {
    margin-block-start: 2ch;
  }
}

Bu işlem, <legend> alanının yalnızca <div> alt öğelerini hedefleyerek düzenlenmesini engeller.

Açıklamada değil, girişler arasındaki kenar boşluğunun gösterildiği ekran görüntüsü.

Filtre etiketi ve onay kutusu

<fieldset> öğesinin doğrudan alt öğesi olarak ve formun 30ch etiketinin maksimum genişliği dahilinde, etiket metni çok uzunsa kayabilir. Metni kaydırmak harika bir şey, ancak metin ile onay kutusu arasındaki yanlış hizalama değil. Flexbox, bunun için idealdir.

fieldset > div {
  display: flex;
  gap: 2ch;
  align-items: baseline;
}
Çok satırlı sarmalama senaryosunda onay işaretinin metnin ilk satırıyla nasıl hizalandığını gösteren ekran görüntüsü.
Bu Codepen ile daha fazla bilgi edinin

Animasyonlu ızgara

Düzen animasyonu, Isotope tarafından yapılır. Etkileşimli sıralama ve filtreleme için yüksek performanslı, güçlü bir eklenti.

JavaScript

JavaScript, düzgün animasyonlu, etkileşimli bir ızgaranın düzenlenmesine yardımcı olmanın yanı sıra birkaç pürüzlü kenarı parlatmak için de kullanılır.

Kullanıcı girişini normalleştirme

Bu tasarımda, giriş sağlamak için iki farklı yol içeren tek bir biçim vardır ve aynı şekilde serileştirme yapılmaz. Yine de bazı JavaScript'lerle verileri normalleştirebiliriz.

DevTools JavaScript konsolunun hedef olarak normalleştirilmiş veri sonuçlarını gösteren ekran görüntüsü.

<select> öğesinin veri yapısını gruplandırılmış onay kutuları yapısıyla hizalamayı seçtim. Bunu yapmak için <select> öğesine bir input etkinlik işleyici eklenir ve bu noktada selectedOptions eşlenir.

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
  }, [])
})

Artık formu güvenle gönderebilir ya da bu demoda Isotope'a neyi filtreleyeceğini öğretebilirsiniz.

Durum rolü öğesini tamamlama

Bu öğe yalnızca onay kutusu etkileşimine dayalı filtre sayısını hesaplıyor ve duyuruyor, ancak sonuçların sayısını ek olarak paylaşmanın ve <select> öğe seçeneklerinin de sayılmasını sağlamanın iyi bir fikir olduğunu düşündüm.

<select> öğe seçimi counter() bölümüne yansıtıldı

Veri normalleştirme bölümünde, girişte bir işleyici zaten oluşturuldu. Bu işlevin sonunda, seçilen filtrelerin sayısı ve bu filtreler için sonuçların sayısı bilinmektedir. Değerler, durum rolü öğesine bu şekilde geçirilebilir.

let statusRoleElement = document.querySelector('#applied-filters')
statusRoleElement.style.counterSet = selectData.length

Sonuçlar role="status" öğesine yansıtılır

:checked, seçilen filtre sayısını durum rolü öğesine geçirmek için yerleşik bir yol sağlar, ancak filtrelenmiş sonuç sayısını göremez. JavaScript, onay kutularıyla etkileşimi izleyebilir ve ızgarayı filtreledikten sonra <select> öğesinin yaptığı gibi textContent öğesini ekleyin.

document
  .querySelector('aside form')
  .addEventListener('input', e => {
    // isotope demo code
    let filterResults = IsotopeGrid.getFilteredItemElements().length
    document.querySelector('#applied-filters').textContent = `giving ${filterResults} results`
})

Bu çalışma tümüyle "2 filtre, 25 sonuç verir" duyurusunu tamamlar.

Sonuçları duyuran MacOS ekran okuyucusunun ekran görüntüsü.

Artık mükemmel yardımcı teknoloji deneyimimiz, kullanıcılarla ne şekilde etkileşimde bulunurlar olsunlar kullanıcılara sunulacak.

Sonuç

Nasıl yaptığımı artık bildiğine göre siz de nasıl yapardınız? 🙂

Yaklaşımlarımızı çeşitlendirelim ve web'de geliştirme yapmanın tüm yollarını öğrenelim. Bir demo oluşturun, bana tweet atın bağlantıları, aşağıdaki topluluk remiksleri bölümüne ekleyeceğim.

Topluluk remiksleri

Henüz burada görülecek bir şey yok.