Ders 01 / 25
Düğmeler
Düğme belirtiminin altı bölümü, yerel ögenin getirdiği davranışlar, basılı kalma durumunun bildirimi, klavye sözleşmesi ve tıklanabilir alanın hedef boyutu ölçütleriyle denetimi.
İçindekiler
Bileşen kataloğu kuruldu, adlandırma sözleşmesi yazıldı, sürümleme ve katkı süreci işliyor. Katalogdaki her kayıt bir ad, bir olgunluk düzeyi ve bir kullanım rehberi taşıyor. Ancak bir bileşenin katalogda bulunması, onun ne yaptığının yazılı olduğu anlamına gelmez: “birincil düğme” kaydı düğmenin nasıl göründüğünü söyler, klavyeden nasıl çalıştırıldığını, erişilebilirlik ağacında hangi adla ve hangi durumla göründüğünü söylemez.
Bu kurs o eksik yarıyı yazar. Her ders bir bileşeni belirtim olarak ele alır ve altı soruyu aynı sırayla yanıtlar. Kütüphane katalog arayüzü — arama alanı, süzgeç seçimleri, sonuç tablosu, kayıt ayrıntısı ve ödünç alma formu — bütün derslerin ortak örneğidir. İlk bileşen düğmedir, çünkü kalan bileşenlerin çoğu onu içerir.
Belirtimin Altı Bölümü
Bir bileşen belirtimi şu sırayla yazılır: bileşenin çözdüğü sorun ve ne zaman kullanılmayacağı; yerel karşılığın ne olduğu; rol, ad ve durumun nereden hesaplandığı; klavye sözleşmesi; ölçülebilir kısıtlar; sık yapılan hata ve nasıl saptandığı.
Sıra keyfi değildir. İlk iki bölüm yanıtlanmadan üçüncüsüne geçilirse, yerel bir öge yerine anlamsız bir kapsayıcı seçilmiş olur ve kalan dört bölüm o yanlışın üzerine yazılır. Frontend Kalitesi kursundaki birinci kural bu yüzden belirtimin de ikinci maddesidir: gereken anlamı taşıyan yerel bir öge varsa ARIA kullanılmaz.
Düğmenin İşi
Düğme, sayfada bir eylem başlatan denetimdir: aramayı çalıştırmak, süzgeçleri temizlemek, bir kaydı ödünç alma listesine eklemek, formu göndermek. Ortak özellikleri, çalıştırıldığında adres çubuğundaki adresin değişmemesidir.
Düğme kullanılmayacağı yer de aynı ölçütle belirlenir: kullanıcı başka bir kaynağa gidiyorsa bileşen düğme değil bağlantıdır. Katalogda bir kayda tıklamak kayıt ayrıntısı sayfasını açar; bu bir eylem değil, bir gezinmedir. Ayrımın tam kuralı ve ihlalinin nasıl saptandığı bu konunun son dersindedir.
Yerel Öge Önce
Karşılık button ögesidir ve type özniteliği üç değer alır. submit değeri ögeyi
form gönderimine bağlar ve bir form içinde öznitelik yazılmadığında geçerli olan
değerdir; button değeri hiçbir varsayılan eylem taşımaz, davranışı yalnızca bağlanan
kod belirler; reset değeri alanları başlangıç değerlerine döndürür.
Bu ayrımın atlanması somut bir kırılma üretir: ödünç alma formunun içine konan “Süzgeci
temizle” düğmesine type="button" yazılmadığında düğme formu gönderir. Kullanıcı bir
alanı temizlemek isterken kaydı ödünç almış olur.
Yerel öge, rolün yanında beş şey daha getirir: odaklanabilirlik, giriş ve boşluk tuşlarıyla
çalıştırılabilirlik, devre dışı durumunun ağaca bildirimi, form gönderimiyle ilişki ve
gönderici olarak gönderim listesine kendi ad–değer çiftini eklemesi. Bunların hiçbiri
div ögesine rol yazılarak gelmez.
Rol, Ad ve Durum
Rol örtük olarak button ögesinden gelir; ayrıca bildirilmez.
Ad, düğmenin içeriğinden hesaplanır. Metin taşıyan düğmelerde bu kendiliğinden çalışır. Yalnız simge taşıyan düğmelerde — sonuç tablosundaki işaretleme ve ödünç alma düğmelerinde — simgenin alternatif metni boşsa düğme adsız kalır. Katalog belirtiminde kural şudur: simge düğmelerinin adı, simgeye değil düğmeye yazılır; simge her koşulda sunumsaldır.
İki durum bildirimi düğmeye aittir. Birincisi devre dışı olmaktır: disabled özniteliği
hem ağaca bildirir hem ögeyi odak dışına çıkarır. aria-disabled="true" yalnızca bildirir,
öge odak alır ve tıklanabilir kalır; bu, kullanıcının düğmeyi bulup neden çalışmadığını
okuyabilmesi istendiğinde seçilir ve tıklamanın kod tarafında yok sayılması gerekir.
İkincisi basılı kalma durumudur (aria-pressed): iki durumlu bir düğmenin açık mı
kapalı mı olduğunu bildirir. Katalogda “Yalnız rafta olanlar” süzgeci böyle bir düğmedir.
Bu durum, Arayüz Tasarımının Temelleri kursunda tanımlanan geçici basılı etkileşim
durumundan ayrıdır: biri tuş bırakılınca biter, diğeri kullanıcı yeniden basana kadar
sürer. Görsel tasarımın ikisini ayrı kanallarda kodlaması gerekir.
Klavye Sözleşmesi
| Tuş | Davranış |
|---|---|
Tab |
Odağı düğmeye getirir; her düğme kendi başına bir sekme durağıdır. |
Shift+Tab |
Önceki sekme durağına döner. |
Enter |
Düğmeyi çalıştırır; tuşa basıldığı anda tetiklenir. |
Boşluk |
Düğmeyi çalıştırır; tuş bırakıldığında tetiklenir. |
İki tuşun tetiklenme anı arasındaki fark yerel ögede kendiliğinden vardır ve elle yazılan bir düğmede yeniden üretilmesi gerekir. Boşluk tuşunun bırakılışta tetiklenmesi, kullanıcıya tuşu basılı tutup düğmeden vazgeçme olanağı verir; giriş tuşunun basılışta tetiklenmesi ise form gönderiminin beklenen davranışıdır.
Odak, düğme çalıştırıldıktan sonra düğmede kalır. Düğme sayfadan kaldırılıyorsa — “Süzgeci temizle” düğmesi süzgeç kalmadığında gizleniyorsa — odağın nereye gideceği belirtilmek zorundadır; belirtilmezse odak belgenin köküne düşer.
Tıklanabilir Alan Ölçülür
Düğmenin görsel boyutu bir tasarım tercihi değil, ölçütlere bağlı bir kısıttır. 2.5.8 Hedef Boyutu (En Az) ölçütü her hedefin en az 24×24 CSS pikseli olmasını ister ve beş istisna tanır; bunların en çok işe yarayanı aralık istisnasıdır: küçük kalan bir hedefin merkezine yerleştirilen 24 piksel çaplı daire, başka bir hedefe ya da başka bir küçük hedefin dairesine değmiyorsa ölçüt karşılanır. 2.5.5 Hedef Boyutu (Gelişmiş) ölçütü aynı ölçüyü 44 piksele çıkarır.
// hedef.mjs — dugme hedef boyutunun 2.5.8 ve 2.5.5 olcutlerine gore denetimi // Katalog arac cubugu ve sonuc tablosu satiri: CSS pikseli cinsinden kutular. // x,y sol ust kose; w,h genislik ve yukseklik. const ARAYUZ = [ { ad: "button#ara", x: 16, y: 16, w: 88, h: 44 }, { ad: "button#suzgecleri-sil", x: 112, y: 16, w: 140, h: 44 }, { ad: "button#gorunum-liste", x: 600, y: 26, w: 24, h: 24 }, { ad: "button#gorunum-izgara", x: 628, y: 26, w: 24, h: 24 }, { ad: "a#kayit[K-118]", x: 60, y: 80, w: 220, h: 20 }, { ad: "button#isaretle[K-118]", x: 700, y: 80, w: 20, h: 20 }, { ad: "button#odunc[K-118]", x: 720, y: 80, w: 20, h: 20 }, ]; const EN_KUCUK = 24; // 2.5.8 Hedef Boyutu (En Az), AA const GELISMIS = 44; // 2.5.5 Hedef Boyutu (Gelismis), AAA const merkez = (t) => [t.x + t.w / 2, t.y + t.h / 2]; // 24 px capli daire ile bir kutunun kesisip kesismedigi function daireKutuKesisir(t, k) { const [cx, cy] = merkez(t); const yx = Math.max(k.x, Math.min(cx, k.x + k.w)); const yy = Math.max(k.y, Math.min(cy, k.y + k.h)); return Math.hypot(cx - yx, cy - yy) < EN_KUCUK / 2; } // Iki 24 px capli dairenin kesismesi: merkezler arasi uzaklik < 24 function daireDaireKesisir(a, b) { const [ax, ay] = merkez(a); const [bx, by] = merkez(b); return Math.hypot(ax - bx, ay - by) < EN_KUCUK; } const kucuk = (t) => Math.min(t.w, t.h) < EN_KUCUK; // Aralik istisnasi: kucuk hedefin dairesi baska bir hedefe ya da // baska bir kucuk hedefin dairesine degmemeli. function aralikIstisnasi(t, hepsi) { const carpisan = []; for (const b of hepsi) { if (b === t) continue; const carpti = kucuk(b) ? daireDaireKesisir(t, b) : daireKutuKesisir(t, b); if (carpti) carpisan.push(b.ad); } return carpisan; } function denetle(baslik, arayuz) { console.log(baslik); console.log("hedef olcu en kucuk kenar 2.5.8 2.5.5 aralik istisnasi"); for (const t of arayuz) { const kenar = Math.min(t.w, t.h); const carpisan = kucuk(t) ? aralikIstisnasi(t, arayuz) : []; const gecer258 = !kucuk(t) || carpisan.length === 0; const gecer255 = Math.min(t.w, t.h) >= GELISMIS; const not = !kucuk(t) ? "gerekmiyor" : carpisan.length === 0 ? "uygulandi" : "carpisan: " + carpisan.join(", "); console.log( t.ad.padEnd(24) + `${t.w}x${t.h}`.padEnd(9) + String(kenar).padStart(14) + (gecer258 ? " gecti" : " KALDI").padEnd(8) + (gecer255 ? " gecti" : " KALDI").padEnd(8) + " " + not, ); } const kalan = arayuz.filter((t) => kucuk(t) && aralikIstisnasi(t, arayuz).length > 0); console.log(`2.5.8 ihlali: ${kalan.length} hedef`); } denetle("mevcut arac cubugu ve satir denetimleri:", ARAYUZ); // Duzeltme: satir ici denetimler 24x24'e cikarilir ve aralari 8 px acilir. const DUZELTILMIS = ARAYUZ.map((t) => { if (t.ad === "button#isaretle[K-118]") return { ...t, w: 24, h: 24, x: 696, y: 78 }; if (t.ad === "button#odunc[K-118]") return { ...t, w: 24, h: 24, x: 728, y: 78 }; return t; }); console.log(""); denetle("satir ici denetimler 24x24, aralik 8 px:", DUZELTILMIS); // Hedefi buyutmeden cozmek: kutu ayni kalir, aralik acilir. const YALNIZ_ARALIK = ARAYUZ.map((t) => t.ad === "button#odunc[K-118]" ? { ...t, x: 726 } : t, ); console.log(""); denetle("kutular 20x20 kaldi, yalniz aralik 6 px acildi:", YALNIZ_ARALIK);
mevcut arac cubugu ve satir denetimleri: hedef olcu en kucuk kenar 2.5.8 2.5.5 aralik istisnasi button#ara 88x44 44 gecti gecti gerekmiyor button#suzgecleri-sil 140x44 44 gecti gecti gerekmiyor button#gorunum-liste 24x24 24 gecti KALDI gerekmiyor button#gorunum-izgara 24x24 24 gecti KALDI gerekmiyor a#kayit[K-118] 220x20 20 gecti KALDI uygulandi button#isaretle[K-118] 20x20 20 KALDI KALDI carpisan: button#odunc[K-118] button#odunc[K-118] 20x20 20 KALDI KALDI carpisan: button#isaretle[K-118] 2.5.8 ihlali: 2 hedef satir ici denetimler 24x24, aralik 8 px: hedef olcu en kucuk kenar 2.5.8 2.5.5 aralik istisnasi button#ara 88x44 44 gecti gecti gerekmiyor button#suzgecleri-sil 140x44 44 gecti gecti gerekmiyor button#gorunum-liste 24x24 24 gecti KALDI gerekmiyor button#gorunum-izgara 24x24 24 gecti KALDI gerekmiyor a#kayit[K-118] 220x20 20 gecti KALDI uygulandi button#isaretle[K-118] 24x24 24 gecti KALDI gerekmiyor button#odunc[K-118] 24x24 24 gecti KALDI gerekmiyor 2.5.8 ihlali: 0 hedef kutular 20x20 kaldi, yalniz aralik 6 px acildi: hedef olcu en kucuk kenar 2.5.8 2.5.5 aralik istisnasi button#ara 88x44 44 gecti gecti gerekmiyor button#suzgecleri-sil 140x44 44 gecti gecti gerekmiyor button#gorunum-liste 24x24 24 gecti KALDI gerekmiyor button#gorunum-izgara 24x24 24 gecti KALDI gerekmiyor a#kayit[K-118] 220x20 20 gecti KALDI uygulandi button#isaretle[K-118] 20x20 20 gecti KALDI uygulandi button#odunc[K-118] 20x20 20 gecti KALDI uygulandi 2.5.8 ihlali: 0 hedef
Üç koşum üç ayrı bilgi veriyor.
Birinci koşumda araç çubuğu ölçütü karşılıyor, sonuç tablosunun satır içi denetimleri karşılamıyor. İki düğmenin merkezleri arasındaki uzaklık 20 piksel; iki dairenin kesişmemesi için gereken 24. Kayıt bağlantısı da 20 piksel yüksekliğinde ama aralık istisnasını sağlıyor, çünkü çevresinde başka hedef yok.
İkinci koşum, doğrudan çözümü uyguluyor: kutular 24×24’e çıkarıldığında istisnaya hiç gerek kalmıyor. Üçüncü koşum ise ölçütün yanlış okunmasını düzeltiyor — kutuların büyütülmesi zorunlu değildir. Yalnızca aralığın 6 piksele çıkarılması, merkezleri 26 piksele taşıyarak ölçütü karşılatıyor. Yoğun bir sonuç tablosunda satır yüksekliğini korumak gerektiğinde kullanılabilecek yol budur.
2.5.5 sütunu bütün simge düğmelerinde “KALDI” gösteriyor. Bu bir ihlal değil: 44 piksel ölçüsü AAA düzeyindedir. Sütunun belirtimde bulunması, dokunmatik kullanım hedefleniyorsa hangi düğmelerin büyütülmesi gerektiğini önceden gösterir.
Hiyerarşi Davranış Farkı Değildir
Katalog araç çubuğunda üç görsel ağırlık kullanılır: dolgulu birincil düğme (“Ara”), çerçeveli ikincil düğme (“Süzgeçleri temizle”) ve dolgusuz düz düğme (görünüm değiştiriciler). Bu ayrım tümüyle görseldir; üçünün rolü, adı, klavye sözleşmesi ve hedef boyutu ölçütü aynıdır.
Belirtimde yazılması gereken tek kural, bir görünümde en çok bir birincil düğme bulunmasıdır. İki birincil düğme, görsel hiyerarşinin taşıdığı “önerilen eylem budur” bilgisini siler. Bu kural bir uygunluk ölçütünden gelmez; Arayüz Tasarımının Temelleri kursundaki karşıtlık ve vurgu kararının bileşen düzeyindeki karşılığıdır.
Sık Yapılan Hata
En sık üretilen üç kusur ve saptama yolları şunlardır.
Adsız simge düğmesi. Alternatif metni boş bir simge taşıyan düğme ağaçta adsız görünür. Saptaması araçsızdır: sayfadaki her düğmenin erişilebilir adı listelenir, boş olan aranır. Otomatik denetleyicilerin varlık kuralı bunu yakalar.
Görünen metinle adın ayrışması. Düğmenin üzerinde “Ödünç al” yazarken aria-label
bildirimi “Ekle” diyorsa, sesle arayüz kullanan kişinin söylediği ad hiçbir ögeye uymaz;
2.5.3 Ad Etikette ölçütü bunu yasaklar. Saptaması, görünen metnin erişilebilir adın içinde
geçip geçmediğinin denetlenmesidir.
Devre dışı düğmenin gerekçesiz kalması. Rafta olmayan bir kayıt için ödünç alma
düğmesi disabled yazılarak kapatıldığında düğme odak dışına çıkar ve kullanıcı nedeni
okuyamaz. Saptaması bir klavye turudur: sekme tuşuyla gezilen sayfada bulunamayan ama
ekranda görünen her denetim bu durumdadır. Belirtimin kararı, nedenin okunması gerekiyorsa
düğmenin aria-disabled ile bildirilmesi ve nedenin aria-describedby ile bağlanmasıdır.
Özet
- Bileşen belirtimi altı bölümden oluşur: sorun ve kullanılmayacağı yer, yerel karşılık, rol–ad–durum, klavye sözleşmesi, ölçülebilir kısıtlar, sık yapılan hata ve saptaması.
- Düğme eylem başlatır; adres değişiyorsa bileşen düğme değildir.
typeözniteliği yazılmadığında form içindeki düğme gönderim düğmesi olur. - Ad düğme içeriğinden hesaplanır; simge düğmelerinde ad düğmeye yazılır.
disabledögeyi odak dışına çıkarır,aria-disabledyalnızca bildirir ve odakta bırakır. - Giriş tuşu basılışta, boşluk tuşu bırakılışta tetikler; elle yazılan bir düğmede bu fark yeniden üretilmelidir.
- 2.5.8 her hedeften 24×24 CSS pikseli ister; aralık istisnası, kutuyu büyütmeden merkezler arası uzaklığı 24 pikselin üstüne çıkararak da karşılanabilir.
- Birincil, ikincil ve düz düğme ayrımı yalnızca görseldir; bir görünümde en çok bir birincil düğme bulunur.
Sonraki Adım
Düğme, kullanıcıdan hiçbir şey almadan çalışan bir denetimdir: adı sabittir, değeri yoktur ve tek bildirdiği şey basılıp basılmadığıdır. Katalog arayüzünün asıl veri toplayan bileşeni ise arama alanıdır ve orada ad tek başına yetmez — alanın bir etiketi, bir biçim ipucu, bir yardım metni ve gerektiğinde bir hata iletisi vardır. Bunların dördü de ekranda alanın çevresinde durur, ancak erişilebilirlik ağacında birbirinden ayrı bildirimlerdir ve duyurulma sıraları farklıdır. Sonraki ders metin girdisini bu dört metnin düzeni üzerinden belirtir.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.