İçeriğe geç
academia.sh

Ders 03 / 25

Seçim Denetimleri

Onay kutusu, seçenek düğmesi ve anahtarın çözdüğü ayrı sorunlar; grubun adlandırılması, karma durumun bildirimi ve iki farklı klavye sözleşmesinin sınanması.

İçindekiler

Metin girdisinde adın kaynağı alanın kendi etiketiydi. Ödünç alma formundaki “Bildirim yöntemi” bölümü ise üç ayrı denetimden oluşur — “E-posta”, “SMS”, “Bildirim yok” — ve kullanıcının yanıtladığı soru bu üç adın hiçbirinde yazmaz. Soru grubun kendisine aittir.

Bu ders üç seçim denetimini belirtir: onay kutusu, seçenek düğmesi ve anahtar. Üçünün görünümü birbirine yakındır, çözdükleri sorunlar ve klavye sözleşmeleri ise ayrıdır. Ayrımın yanlış kurulması, arayüzün klavyeyle çalışmayı sürdürdüğü ama beklenenden farklı davrandığı bir sonuç üretir.

Üç Denetim, Üç Ayrı Sorun

Onay kutusu bağımsız bir açık/kapalı seçimdir. Katalogun süzgeç panelinde “Yalnız rafta olanlar”, “Yalnız e-kitaplar” ve “Süreli yayınlar” birbirinden bağımsızdır; hiçbiri diğerini kapatmaz. Sıfır tanesi seçili olabilir, hepsi seçili olabilir.

Seçenek düğmesi birbirini dışlayan bir seçimdir ve her zaman bir grup içinde bulunur. Ödünç süresi 14, 21 ya da 28 gündür; biri seçildiğinde diğeri kapanır. Tek başına bir seçenek düğmesi anlamsızdır — kullanıcı onu seçtikten sonra seçimden vazgeçemez.

Anahtar açık/kapalı bir ayardır ve değiştirildiği anda etkili olur. Kullanıcı hesabındaki “İade hatırlatması gönder” ayarı böyledir: değiştirilir, kaydedilir, sayfada bir gönderim düğmesi beklemez.

Ayrım buradan çıkar: bir gönderim düğmesiyle onaylanacak bir form içinde anahtar kullanılmaz, onay kutusu kullanılır. Anahtarın verdiği söz “şimdi etkili oldu”dur; formun gönderilmesini bekleyen bir anahtar bu sözü tutmaz.

Yerel Öge Önce

Onay kutusunun ve seçenek düğmesinin yerel karşılıkları vardır: input ögesinin checkbox ve radio türleri. İkisi de rolü, işaretlilik durumunu, klavye sözleşmesini ve gönderim listesine katılmayı birlikte getirir. Seçenek düğmelerini bir gruba bağlayan şey name özniteliğinin aynı olmasıdır; grup, işaretlemedeki komşuluktan değil bu addan doğar.

Anahtarın yerel karşılığı yoktur. Karşılanma yolu, role="switch" bildirimi taşıyan bir düğmedir; durumu aria-checked ile yazılır. Onay kutusuna role="switch" yazmak da tanımlıdır ve o durumda ögenin yerel işaretlilik durumu ağaca anahtar durumu olarak geçer.

Grubun Adı

Grubun bir adı olmadığında kullanıcı üç seçeneği duyar, sorusunu duymaz. Yerel karşılık fieldset ve legend ögeleridir: fieldset ögesi ağaçta grup rolü üretir, legend ögesinin metni grubun adı olur.

<fieldset>
  <legend>Bildirim yöntemi</legend>
  <p><label><input type="radio" name="bildirim" value="eposta" checked> E-posta</label></p>
  <p><label><input type="radio" name="bildirim" value="sms"> SMS</label></p>
  <p><label><input type="radio" name="bildirim" value="yok"> Bildirim yok</label></p>
</fieldset>

<fieldset>
  <legend>Süzgeçler</legend>
  <p><label><input type="checkbox" name="raf" value="rafta"> Yalnız rafta olanlar</label></p>
  <p><label><input type="checkbox" name="tur" value="e-kitap"> Yalnız e-kitaplar</label></p>
</fieldset>

İki ayrıntı bağlayıcıdır. Birincisi, her denetimin kendi etiketinin label ögesiyle kurulmasıdır; etiketin denetimi içine alması (örtük bağ) for ve id çifti yazmadan aynı sonucu verir ve etiket metnini de tıklanabilir alana katar. İkincisi, seçenek düğmelerinin name değerinin aynı olmasıdır; farklı yazıldığında üç ayrı tek seçenekli grup oluşur ve kullanıcı üçünü birden seçebilir.

Grup ögesi kullanılamadığında karşılık role="group" ya da seçenek düğmeleri için role="radiogroup" bildirimidir; grubun adı aria-labelledby ile başlık ögesine bağlanır. Bu yol yalnız fieldset ögesinin düzen kısıtları sorun çıkardığında seçilir.

Rol, Ad ve Durum

Üç denetimin de adı kendi etiketinden gelir; grubun adı, denetimin adının yerine geçmez, onun bağlamı olur.

Durum bildirimi işaretliliktir. Yerel ögelerde checked özelliğinden ağaca geçer; elle kurulan bir denetimde aria-checked değeriyle yazılır ve her değişimde güncellenir.

Onay kutusunun üçüncü bir durumu vardır: karma durum (mixed). Süzgeç panelinde “Hepsini seç” kutusu, alt kutuların bir bölümü seçiliyken bu durumdadır. Yerel ögede karma durum bir öznitelikle değil, indeterminate özelliğiyle kurulur ve ağaca karma olarak bildirilir. Karma durum bir üçüncü seçenek değildir: kullanıcı ona tıkladığında denetim ya tümünü seçer ya tümünü bırakır, karmaya geri dönmez.

Anahtarda karma durum yoktur. Ayrıca anahtarın durumu metinle de bildirilir mi sorusu tasarım kararıdır: “Açık”/“Kapalı” metni denetimin adının parçası değildir, çünkü ad değişmez; durum yalnızca aria-checked üzerinden bildirilir ve metin bir ek gösterge olur.

İki Klavye Sözleşmesi

Seçenek grubu:

Tuş Davranış
Tab Odağı gruba getirir; grubun tamamı tek sekme durağıdır ve odak seçili düğmeye gelir.
Ok tuşları Odağı ve seçimi birlikte taşır; uçlarda başa döner.
Boşluk Odaktaki düğmeyi seçer.
Tab (grup içindeyken) Grubun tamamından çıkar, sonraki durağa geçer.

Onay kutusu ve anahtar:

Tuş Davranış
Tab Her denetim ayrı bir sekme durağıdır.
Boşluk Durumu değiştirir.
Ok tuşları Etkisizdir; odak ve seçim değişmez.

İki sözleşmenin farkı, seçenek grubunun dönen sekme durağı düzenini kullanmasıdır: grupta yalnızca bir öge sekme sırasındadır, kalanlarına ok tuşlarıyla ulaşılır. On beş seçenekli bir grup böylece on beş değil bir durak tutar. Onay kutuları bağımsız oldukları için bu düzeni kullanamaz; kullanıcı her birine ayrı ayrı ulaşmak zorundadır.

Aşağıdaki sınama iki sözleşmeyi durum makinesi olarak kurar ve tuş dizileriyle denetler.

// secim.test.mjs — secenek grubu ile onay kutusu grubunun klavye sozlesmesi
// Kosum: node --test secim.test.mjs
import { test } from "node:test";
import assert from "node:assert/strict";

const OGELER = ["E-posta", "SMS", "Bildirim yok"];
const ILERI = new Set(["ArrowDown", "ArrowRight"]);
const GERI = new Set(["ArrowUp", "ArrowLeft"]);

// odak: null ise odak grubun disinda
const secenek = (secili = null) => ({ tur: "secenek", ogeler: OGELER, secili, odak: null });
const onay = () => ({ tur: "onay", ogeler: OGELER, secili: new Set(), odak: null });

// Grubun kapladigi sekme duragi sayisi
function sekmeDuragi(d) {
  return d.tur === "secenek" ? 1 : d.ogeler.length;
}

function tus(d, t) {
  const n = d.ogeler.length;
  if (d.tur === "secenek") {
    if (d.odak === null) return t === "Tab" ? { ...d, odak: d.secili ?? 0 } : d;
    if (t === "Tab") return { ...d, odak: null };
    if (ILERI.has(t)) { const i = (d.odak + 1) % n; return { ...d, odak: i, secili: i }; }
    if (GERI.has(t)) { const i = (d.odak + n - 1) % n; return { ...d, odak: i, secili: i }; }
    if (t === "Space") return { ...d, secili: d.odak };
    return d;
  }
  if (d.odak === null) return t === "Tab" ? { ...d, odak: 0 } : d;
  if (t === "Tab") return d.odak === n - 1 ? { ...d, odak: null } : { ...d, odak: d.odak + 1 };
  if (t === "Space") {
    const s = new Set(d.secili);
    if (s.has(d.odak)) s.delete(d.odak); else s.add(d.odak);
    return { ...d, secili: s };
  }
  return d;   // ok tuslari onay kutusu grubunu etkilemez
}

const uygula = (d, dizi) => dizi.reduce(tus, d);

test("secenek grubu tek sekme duragi, onay kutulari ogesi kadar durak tutar", () => {
  assert.equal(sekmeDuragi(secenek()), 1);
  assert.equal(sekmeDuragi(onay()), 3);
});

test("gruba giriste odak secili ogeye gelir", () => {
  assert.equal(uygula(secenek(2), ["Tab"]).odak, 2);
});

test("hic secim yokken giriste odak ilk ogede olur ve secim yapilmaz", () => {
  const d = uygula(secenek(), ["Tab"]);
  assert.equal(d.odak, 0);
  assert.equal(d.secili, null);
});

test("ok tusu odagi ve secimi birlikte tasir, sonda basa doner", () => {
  const d = uygula(secenek(0), ["Tab", "ArrowDown", "ArrowDown", "ArrowDown"]);
  assert.equal(d.odak, 0);
  assert.equal(d.secili, 0);
  const g = uygula(secenek(0), ["Tab", "ArrowUp"]);
  assert.equal(g.secili, 2);
});

test("Tab grubun tamamindan tek basista cikar", () => {
  const d = uygula(secenek(1), ["Tab", "ArrowDown", "Tab"]);
  assert.equal(d.odak, null);
  assert.equal(d.secili, 2);
});

test("onay kutusunda ok tusu hicbir sey yapmaz", () => {
  const d = uygula(onay(), ["Tab", "ArrowDown", "ArrowRight"]);
  assert.equal(d.odak, 0);
  assert.equal(d.secili.size, 0);
});

test("onay kutulari birbirinden bagimsiz acilip kapanir", () => {
  const d = uygula(onay(), ["Tab", "Space", "Tab", "Tab", "Space"]);
  assert.deepEqual([...d.secili].sort(), [0, 2]);
  const k = uygula(d, ["Space"]);
  assert.deepEqual([...k.secili], [0]);
});

test("bosluk tusu secenek grubunda odaktaki ogeyi secer", () => {
  const d = uygula(secenek(0), ["Tab", "Space"]);
  assert.equal(d.secili, 0);
});
✔ secenek grubu tek sekme duragi, onay kutulari ogesi kadar durak tutar (0.361166ms)
✔ gruba giriste odak secili ogeye gelir (0.08225ms)
✔ hic secim yokken giriste odak ilk ogede olur ve secim yapilmaz (0.045375ms)
✔ ok tusu odagi ve secimi birlikte tasir, sonda basa doner (0.04925ms)
✔ Tab grubun tamamindan tek basista cikar (0.339708ms)
✔ onay kutusunda ok tusu hicbir sey yapmaz (0.072458ms)
✔ onay kutulari birbirinden bagimsiz acilip kapanir (0.360833ms)
✔ bosluk tusu secenek grubunda odaktaki ogeyi secer (0.046833ms)
ℹ tests 8
ℹ suites 0
ℹ pass 8
ℹ fail 0
ℹ cancelled 0
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 35.587

Parantez içindeki süreler ve toplam süre koşumdan koşuma değişir; sınamanın sonucu değişmez.

Üçüncü sınama sözleşmenin en çok atlanan yerini yakalıyor: hiçbir seçenek işaretli değilken gruba girildiğinde odak ilk ögeye gelir ama seçim yapılmaz. Odağın seçimi sürüklediği kural yalnızca ok tuşları için geçerlidir; giriş anı bunun dışındadır. Elle yazılan gruplarda bu ayrım gözden kaçtığında, kullanıcı sekme tuşuna bastığı için istemediği bir ödünç süresini seçmiş olur.

Beşinci sınama, dönen sekme durağının doğrudan sonucudur: grup içinde ok tuşuyla iki adım gidilmiş olsa da Tab tek basışta gruptan çıkar.

Ölçülebilir Kısıtlar

Hedef boyutu. Onay kutusunun görsel kutusu genelde 16 ile 20 piksel arasındadır ve tek başına 2.5.8 ölçütünü karşılamaz. Etiket metninin denetimle birlikte tıklanabilir olması — label ögesi bunu kendiliğinden sağlar — hedefi metnin genişliğine kadar büyütür. Süzgeç listesindeki kutuların dikey aralığı da 2.5.8’in aralık istisnasını sağlayacak kadar açılmalıdır.

1.4.11 Metin Dışı Kontrast. Kutunun ve düğmenin sınırı, sayfa yüzeyinden en az 3:1 ile ayrılmalıdır. Aynı ölçü işaretlilik göstergesi için de geçerlidir: işaret, kutunun içindeki dolgudan ayırt edilebilmelidir.

1.4.1 Rengin Tek Taşıyıcı Olmaması. İşaretli durum yalnızca dolgu rengiyle bildirilemez; bir onay imi, bir nokta ya da anahtarın kaydırılmış konumu ikinci kanaldır.

3.2.2 Girdide Bağlam Değişikliği. Bir onay kutusunun değiştirilmesi formu kendiliğinden göndermemeli ya da sayfayı değiştirmemelidir. Süzgeç panelinde bir kutu işaretlendiğinde sonuç tablosunun tazelenmesi kabul edilebilir bir davranıştır, çünkü bağlam değişmez; sayfa adresinin değişmesi ve odağın kaybolması kabul edilemez.

Sık Yapılan Hata

Onay kutusunun birbirini dışlayan seçim için kullanılması. Saptaması davranıştandır: kullanıcı ikinci kutuyu işaretlediğinde birincisi kendiliğinden kapanıyorsa, bileşen yanlış seçilmiştir. Kullanıcı için bu, kapanma nedeninin hiçbir yerde bildirilmemesi anlamına gelir.

Grubun adsız bırakılması. Saptaması bir varlık kuralıyla yapılır: seçenek düğmesi taşıyan her grubun bir adı olmalıdır. Ekranda grubun üstünde duran bir başlık metni, bir bağ kurulmadıkça ad değildir.

Anahtarın gönderim düğmesi bekleyen bir forma konması. Saptaması, anahtarın değiştirilmesinden sonra bir kaydetme adımı gerekip gerekmediğinin sorulmasıdır. Gerekiyorsa bileşen onay kutusuna çevrilir.

Karma durumun false olarak bildirilmesi. “Hepsini seç” kutusu, alt kutuların bir bölümü seçiliyken kapalı görünüyorsa kullanıcıya yanlış bilgi verilir. Saptaması, alt kutuların sayımıyla üst kutunun bildirilen durumunun karşılaştırılmasıdır.

Özet

  • Onay kutusu bağımsız açık/kapalı seçim, seçenek düğmesi birbirini dışlayan seçim, anahtar ise değiştirildiği anda etkili olan bir ayardır; gönderim bekleyen formda anahtar kullanılmaz.
  • Onay kutusunun ve seçenek düğmesinin yerel karşılığı vardır; anahtarın yoktur ve role="switch" ile kurulur. Seçenek grubunu name özniteliğinin aynılığı oluşturur.
  • Grubun adı fieldset ve legend ile verilir; grup adı denetimin adının yerine geçmez, bağlamı olur.
  • Seçenek grubu dönen sekme durağı kullanır: grup tek durak tutar, ok tuşları odağı ve seçimi birlikte taşır; onay kutuları ise ayrı duraklardır ve ok tuşlarına yanıt vermez.
  • Gruba ilk girişte hiçbir seçenek seçili değilse odak ilk ögeye gelir ama seçim yapılmaz; bu, elle yazılan gruplarda en çok atlanan kuraldır.
  • Karma durum bir üçüncü seçenek değil, alt seçimlerin özetidir; kullanıcı tıkladığında ya tümü seçilir ya tümü bırakılır.

Sonraki Adım

Seçenek grubu, seçenekler sayılabilir ve az sayıda olduğunda çalışır. Katalogun süzgeç panelinde “Konu” alanı ise iki yüz elli değer taşır ve hepsi ekranda gösterilemez. Bu, seçim işini kapalı bir listeye devretmeyi gerektirir: kullanıcı listeyi açar, gezinir, yazarak daraltır ve bir değer seçer. Sonraki ders bu bileşeni iki ayrı kalıp olarak belirtir — yerel seçim ögesi ile elle kurulan birleşik giriş alanı — ve ikincisinin neden en çok bildirim gerektiren kalıp olduğunu gösterir.

İlerlemeni kaydetmek ve not almak için Giriş yap

Notlarım

Not almak için giriş yapmalısın.

Aramak için yazmaya başlayın.

↑↓ Esc gezin · aç · kapat