İçeriğe geç
academia.sh

Ders 06 / 19

Tasarım Belirteçleri

Belirteçlerin ilkel, anlamsal ve bileşen katmanlarına ayrılması, katmanlar arası başvuru kurallarının konması ve belirteç grafiğinin döngü, tanımsız başvuru, katman ihlali ile boşta kalan belirteç için çözümlenmesi.

İçindekiler

Sistemin kuruluş kararları tamamlandı: kapsam çizildi, ölçekler seçildi, tasarım dili denetlenebilir hâle geldi. Bu kararların hepsi şu ana kadar metin olarak duruyor. Bir arayüz metni okuyamaz; adlandırılmış değerler okur.

Tasarım belirteci (design token), bir tasarım kararının makine tarafından okunabilen adlandırılmış karşılığıdır. Tasarım Sistemi Nedir dersinde adlandırmanın değişiklik yeri sayısını 3.88 kat azalttığı hesaplanmıştı; bu ders o adların nasıl düzenleneceğini kurar. Sorun tek bir liste tutmak değildir — tek bir liste, bir süre sonra hangi adın hangi amaçla konduğu belirsizleşen bir sözlüğe döner. Belirteçler katmanlanır ve katmanlar arası başvurular kurala bağlanır.

Üç Katman, İki Kural

İlkel katman ham değerleri taşır: renk basamakları, ölçek adımları, boyut basamakları. İlkel belirteç bir sayıdır ya da bir renktir; bir amaç taşımaz. notr-500 bir gri tonudur ve nerede kullanılacağını söylemez.

Anlamsal katman bir işi adlandırır ve bir ilkel belirtece bağlar. kenarlik bir iştir; hangi gri olduğu ikinci sorudur. Renk Sistemi dersinde bu ayrım renkte kurulmuştu; belirteç mimarisi aynı ayrımı aralık, boyut ve yarıçap için de kurar.

Bileşen katmanı tek bir bileşenin ayar noktalarını açar ve bir anlamsal belirtece bağlar. dugme-zemin bir ayar noktasıdır. Özel Özellikler dersinde bileşenin dışarıya açtığı adlara biçem arayüzü deniyordu; bileşen belirteçleri o arayüzün sistem düzeyindeki karşılığıdır.

Katmanlar arasındaki başvurular iki kurala bağlıdır. İlkel katman hiçbir belirtece başvurmaz; yalnız değişmez değer taşır. Bileşen katmanı yalnız anlamsal katmana başvurur; ilkel katmana doğrudan başvurmak yasaktır. Anlamsal katman ilkel ya da başka bir anlamsal belirtece başvurabilir.

İkinci kuralın gerekçesi Renk Sistemi dersinde verilmişti: bir bileşen --notr-600 yazdığı anda sistem delinir, çünkü o bileşen artık rol yeniden atamasından ve tema değişiminden etkilenmez. Kural yazılı olduğunda ihlali denetlenebilir hâle gelir.

// belirtec.mjs — uc katmanli belirtec grafiginin cozumlenmesi ve denetimi

// Katman kurallari:
//   ilkel    -> yalniz degismez deger tasir, baska belirtece basvuramaz
//   anlamsal -> ilkel ya da anlamsal belirtece basvurur
//   bilesen  -> yalniz anlamsal belirtece basvurur
const IZIN = { ilkel: [], anlamsal: ["ilkel", "anlamsal"], bilesen: ["anlamsal"] };

const BELIRTECLER = {
  // --- ilkel katman ---
  "notr-000": { katman: "ilkel", deger: "#ffffff" },
  "notr-500": { katman: "ilkel", deger: "#757e8a" },
  "notr-600": { katman: "ilkel", deger: "#5e656e" },
  "notr-900": { katman: "ilkel", deger: "#212327" },
  "ana-100": { katman: "ilkel", deger: "#dee9f7" },
  "ana-600": { katman: "ilkel", deger: "#275ea5" },
  "ana-800": { katman: "ilkel", deger: "#15335b" },
  "adim-1": { katman: "ilkel", deger: "4px" },
  "adim-2": { katman: "ilkel", deger: "8px" },
  "adim-3": { katman: "ilkel", deger: "12px" },
  "adim-4": { katman: "ilkel", deger: "16px" },
  "adim-6": { katman: "ilkel", deger: "24px" },
  "basamak-0": { katman: "ilkel", deger: "16px" },
  "basamak-1": { katman: "ilkel", deger: "20px" },
  "yaricap-1": { katman: "ilkel", deger: "4px" },

  // --- anlamsal katman ---
  yuzey: { katman: "anlamsal", deger: "{notr-000}" },
  "metin-birincil": { katman: "anlamsal", deger: "{notr-900}" },
  "metin-ikincil": { katman: "anlamsal", deger: "{notr-600}" },
  kenarlik: { katman: "anlamsal", deger: "{notr-500}" },
  "eylem-ana": { katman: "anlamsal", deger: "{ana-600}" },
  "eylem-ana-uzeri": { katman: "anlamsal", deger: "{notr-000}" },
  "vurgu-soluk": { katman: "anlamsal", deger: "{ana-100}" },
  "vurgu-soluk-uzeri": { katman: "anlamsal", deger: "{ana-800}" },
  "aralik-grup-ici": { katman: "anlamsal", deger: "{adim-2}" },
  "aralik-blok-arasi": { katman: "anlamsal", deger: "{adim-4}" },
  "aralik-bolum-arasi": { katman: "anlamsal", deger: "{adim-6}" },
  "govde-boyutu": { katman: "anlamsal", deger: "{basamak-0}" },
  "baslik-boyutu": { katman: "anlamsal", deger: "{basamak-1}" },
  "yaricap-varsayilan": { katman: "anlamsal", deger: "{yaricap-1}" },
  "uyari-zemini": { katman: "anlamsal", deger: "{uyari-kenarligi}" },   // dongu
  "uyari-kenarligi": { katman: "anlamsal", deger: "{uyari-zemini}" },   // dongu
  "aralik-sikisik": { katman: "anlamsal", deger: "{adim-1}" },          // hicbir yerden basvurulmuyor

  // --- bilesen katmani ---
  "dugme-zemin": { katman: "bilesen", deger: "{eylem-ana}" },
  "dugme-metin": { katman: "bilesen", deger: "{eylem-ana-uzeri}" },
  "dugme-ic-bosluk-y": { katman: "bilesen", deger: "{aralik-grup-ici}" },
  "dugme-ic-bosluk-x": { katman: "bilesen", deger: "{aralik-blok-arasi}" },
  "dugme-yaricap": { katman: "bilesen", deger: "{yaricap-varsayilan}" },
  "kart-zemin": { katman: "bilesen", deger: "{yuzey}" },
  "kart-kenarlik": { katman: "bilesen", deger: "{notr-500}" },          // katman ihlali: ilkele dogrudan
  "kart-ic-bosluk": { katman: "bilesen", deger: "{aralik-blok-arasi}" },
  "kayit-baslik-boyutu": { katman: "bilesen", deger: "{baslik-boyutu}" },
  "kayit-ustveri-rengi": { katman: "bilesen", deger: "{metin-ucuncul}" }, // tanimsiz basvuru
  "etiket-zemin": { katman: "bilesen", deger: "{vurgu-soluk}" },
  "etiket-metin": { katman: "bilesen", deger: "{vurgu-soluk-uzeri}" },
};

const BASVURU = /^\{([\w-]+)\}$/;
const hedef = (ad) => {
  const m = BELIRTECLER[ad].deger.match(BASVURU);
  return m ? m[1] : null;
};

// --- cozumleme ----------------------------------------------------------------
function coz(ad) {
  const gorulen = new Set();
  let su = ad;
  const zincir = [ad];
  while (true) {
    if (!(su in BELIRTECLER)) return { deger: null, neden: `tanimsiz: ${su}`, zincir };
    if (gorulen.has(su)) return { deger: null, neden: "dongu", zincir };
    gorulen.add(su);
    const h = hedef(su);
    if (h === null) return { deger: BELIRTECLER[su].deger, neden: null, zincir };
    su = h;
    zincir.push(su);
  }
}

// --- denetimler ---------------------------------------------------------------
const kirik = [];
const katmanIhlali = [];
for (const ad of Object.keys(BELIRTECLER)) {
  const c = coz(ad);
  if (c.neden) kirik.push({ ad, ...c });
  const h = hedef(ad);
  if (h === null) continue;
  const kendi = BELIRTECLER[ad].katman;
  const hedefKatman = h in BELIRTECLER ? BELIRTECLER[h].katman : null;
  if (hedefKatman && !IZIN[kendi].includes(hedefKatman)) {
    katmanIhlali.push({ ad, kendi, h, hedefKatman });
  }
}

// Bilesen bicem dosyalarinda dogrudan okunan belirtecler. Her anlamsal belirtecin bir
// bilesen belirteci karsiligi olmak zorunda degildir; bilesen katmani yalniz ayar noktasi
// acilan yerlerde kurulur.
const DOGRUDAN_KULLANIM = new Set([
  "metin-birincil", "metin-ikincil", "kenarlik", "govde-boyutu", "aralik-bolum-arasi",
  "aralik-grup-ici", "yuzey",
]);

// Basvurulma sayisi: bir belirtece kac belirtecten basvuruluyor?
const gelen = Object.fromEntries(Object.keys(BELIRTECLER).map((a) => [a, 0]));
for (const ad of Object.keys(BELIRTECLER)) {
  const h = hedef(ad);
  if (h && h in gelen) gelen[h]++;
}
// Bilesen katmani yaprak sayilir; ilkel ve anlamsal katmanda gelen basvurusu olmayan
// belirtec bosta kalmistir.
const bosta = Object.keys(BELIRTECLER).filter(
  (a) => BELIRTECLER[a].katman !== "bilesen" && gelen[a] === 0 && !DOGRUDAN_KULLANIM.has(a)
);

const sayim = { ilkel: 0, anlamsal: 0, bilesen: 0 };
for (const a of Object.keys(BELIRTECLER)) sayim[BELIRTECLER[a].katman]++;
console.log("katman     belirtec sayisi");
for (const k of ["ilkel", "anlamsal", "bilesen"]) console.log(`${k.padEnd(10)} ${String(sayim[k]).padStart(15)}`);
console.log(`toplam     ${String(Object.keys(BELIRTECLER).length).padStart(15)}`);

console.log("\nbilesen belirteci        zincir                                              deger");
for (const ad of Object.keys(BELIRTECLER).filter((a) => BELIRTECLER[a].katman === "bilesen")) {
  const c = coz(ad);
  console.log(
    `${ad.padEnd(24)} ${c.zincir.join(" > ").padEnd(51)} ${c.deger === null ? "COZULEMEDI (" + c.neden + ")" : c.deger}`
  );
}

console.log("\ncozulemeyen belirtecler");
for (const k of kirik) console.log(`  ${k.ad.padEnd(24)} ${k.neden.padEnd(24)} zincir: ${k.zincir.join(" > ")}`);

console.log("\nkatman ihlalleri");
for (const i of katmanIhlali) {
  console.log(`  ${i.ad} (${i.kendi}) -> ${i.h} (${i.hedefKatman});  izin verilen: ${IZIN[i.kendi].join(", ")}`);
}

console.log("\nbosta kalan belirtecler (ne belirtecten ne bicem dosyasindan basvuru var)");
for (const a of bosta) console.log(`  ${a.padEnd(24)} katman: ${BELIRTECLER[a].katman}`);

// --- zincir uzunlugu dagilimi --------------------------------------------------
const uzunluk = {};
for (const ad of Object.keys(BELIRTECLER)) {
  const c = coz(ad);
  if (c.neden) continue;
  uzunluk[c.zincir.length] = (uzunluk[c.zincir.length] || 0) + 1;
}
console.log("\nzincir uzunlugu  belirtec sayisi");
for (const u of Object.keys(uzunluk).sort((a, b) => a - b)) {
  console.log(`${u.padStart(15)} ${String(uzunluk[u]).padStart(16)}`);
}

// --- katman gecisleri ----------------------------------------------------------
const gecis = {};
for (const ad of Object.keys(BELIRTECLER)) {
  const h = hedef(ad);
  if (!h || !(h in BELIRTECLER)) continue;
  const anahtar = `${BELIRTECLER[ad].katman} -> ${BELIRTECLER[h].katman}`;
  gecis[anahtar] = (gecis[anahtar] || 0) + 1;
}
console.log("\nkatman gecisi           basvuru  izinli mi");
for (const [g, n] of Object.entries(gecis).sort()) {
  const [kaynak, varis] = g.split(" -> ");
  console.log(`${g.padEnd(23)} ${String(n).padStart(7)}  ${IZIN[kaynak].includes(varis) ? "evet" : "HAYIR"}`);
}
katman     belirtec sayisi
ilkel                   15
anlamsal                17
bilesen                 12
toplam                  44

bilesen belirteci        zincir                                              deger
dugme-zemin              dugme-zemin > eylem-ana > ana-600                   #275ea5
dugme-metin              dugme-metin > eylem-ana-uzeri > notr-000            #ffffff
dugme-ic-bosluk-y        dugme-ic-bosluk-y > aralik-grup-ici > adim-2        8px
dugme-ic-bosluk-x        dugme-ic-bosluk-x > aralik-blok-arasi > adim-4      16px
dugme-yaricap            dugme-yaricap > yaricap-varsayilan > yaricap-1      4px
kart-zemin               kart-zemin > yuzey > notr-000                       #ffffff
kart-kenarlik            kart-kenarlik > notr-500                            #757e8a
kart-ic-bosluk           kart-ic-bosluk > aralik-blok-arasi > adim-4         16px
kayit-baslik-boyutu      kayit-baslik-boyutu > baslik-boyutu > basamak-1     20px
kayit-ustveri-rengi      kayit-ustveri-rengi > metin-ucuncul                 COZULEMEDI (tanimsiz: metin-ucuncul)
etiket-zemin             etiket-zemin > vurgu-soluk > ana-100                #dee9f7
etiket-metin             etiket-metin > vurgu-soluk-uzeri > ana-800          #15335b

cozulemeyen belirtecler
  uyari-zemini             dongu                    zincir: uyari-zemini > uyari-kenarligi > uyari-zemini
  uyari-kenarligi          dongu                    zincir: uyari-kenarligi > uyari-zemini > uyari-kenarligi
  kayit-ustveri-rengi      tanimsiz: metin-ucuncul  zincir: kayit-ustveri-rengi > metin-ucuncul

katman ihlalleri
  kart-kenarlik (bilesen) -> notr-500 (ilkel);  izin verilen: anlamsal

bosta kalan belirtecler (ne belirtecten ne bicem dosyasindan basvuru var)
  adim-3                   katman: ilkel
  aralik-sikisik           katman: anlamsal

zincir uzunlugu  belirtec sayisi
              1               15
              2               16
              3               10

katman gecisi           basvuru  izinli mi
anlamsal -> anlamsal          2  evet
anlamsal -> ilkel            15  evet
bilesen -> anlamsal          10  evet
bilesen -> ilkel              1  HAYIR

Grafik Dört Kusur Türü Üretir

Belirteç kümesi bir grafiktir: düğümler adlar, kenarlar başvurulardır. Grafik olarak görüldüğü anda üzerinde denetim yapılabilir hâle gelir ve dört ayrı kusur türü ortaya çıkar.

Döngü. uyari-zemini ile uyari-kenarligi birbirine başvuruyor. İkisi de hiçbir değer üretmiyor. Özel Özellikler dersinde CSS düzeyinde aynı davranış gösterilmişti: birbirine başvuran iki özel özellik tanımsız sayılır. Fark şudur ki oradaki sonuç çalışma zamanında ortaya çıkar; buradaki denetim yayından önce çalışır.

Tanımsız başvuru. kayit-ustveri-rengi belirteci metin-ucuncul adına başvuruyor ve böyle bir belirteç yok. Bu genellikle bir adın sonradan değiştirilmesinden ya da bir belirtecin taslakta kalmasından doğar. Denetim çalışmadığında bileşen sessizce yanlış renge düşer, çünkü tanımsız bir özel özellik hesaplanan değerde geçersizlik üretir ve renk ana ögeden kalıtılır.

Katman ihlali. kart-kenarlik bileşen katmanında ama doğrudan notr-500 ilkel belirtecine başvuruyor. Sonuç doğru bir renk üretiyor — çıktıda #757e8a görünüyor — ve bu kusuru tehlikeli kılan da budur. Değer doğru olduğu için hiçbir görsel belirti vermez. Etkisi ancak tema değiştiğinde ortaya çıkar: kart kenarlığı koyu temada açık temanın grisinde kalır, çünkü rol katmanını atlamıştır.

Boşta kalan belirteç. adim-3 ve aralik-sikisik ne bir belirteçten ne bir biçem dosyasından başvuru alıyor. Bunlar zararsız görünür ama sistemin okunmasını zorlaştırır: bir liste ne kadar çok kullanılmayan ad taşırsa, kullananların hangisini seçeceği o kadar belirsizleşir. Boşta kalan belirteç ya kaldırılır ya da neden durduğu yazılır.

Her Anlamsal Belirteç Bileşen Belirteci İstemez

Boşta kalan belirteç denetimi bir ayrım gerektiriyor ve bu ayrım mimari bir karardır.

metin-birincil, kenarlik, govde-boyutu gibi anlamsal belirteçlerin hiçbir bileşen belirteci karşılığı yok. Bunlar biçem dosyalarında doğrudan okunuyor. Kod bunları DOGRUDAN_KULLANIM kümesiyle biliyor ve boşta kalan sayılmıyorlar.

Ayrım şudur: bileşen katmanı her anlamsal belirteç için kurulmaz, yalnız bir ayar noktası açılan yerlerde kurulur. dugme-zemin vardır, çünkü düğmenin varyantları zemini değiştirir. kayit-baslik-boyutu vardır, çünkü kayıt kartının yoğun ve seyrek sürümleri başlık boyutunu farklı seçer. Buna karşılık gövde metninin rengi hiçbir bileşende ayarlanmaz; onun için bileşen belirteci açmak, hiçbir zaman kullanılmayacak bir ayar noktası üretir.

Katman geçişi tablosu bu dengeyi sayıyor: 10 bileşen belirteci anlamsal katmana başvuruyor, 15 anlamsal belirteç ilkel katmana. Bileşen katmanı anlamsal katmandan küçüktür ve olması gereken de budur. Bileşen katmanı anlamsal katmanla aynı boyuta ulaştıysa, ya her rol gereksiz yere sarmalanmıştır ya da anlamsal katman eksik kurulmuştur.

Zincir Uzunluğu Bir Ödünleşimdir

Zincir uzunluğu dağılımı üç değer gösteriyor: 15 belirteç doğrudan değer taşıyor, 16’sı bir adım sonra, 10’u iki adım sonra çözülüyor. Grafiğin derinliği üçle sınırlı.

Bu bir tesadüf değil, katman sayısının doğrudan sonucudur. Üç katmanlı bir sistemde en uzun zincir bileşen → anlamsal → ilkel olur. Anlamsal katmanın kendi içinde başvuru yapması bu sınırı esnetir — çıktıda iki anlamsal-anlamsal başvuru var — ve her esneme bir bedel taşır.

Bedel, izlenebilirliktir. Bir bileşenin neden o rengi aldığını anlamak için zincirin tamamı takip edilir. Üç adımlık bir zincir okunabilir; altı adımlık bir zincirde hangi adımın değiştirilmesi gerektiği belirsizleşir. Uzun zincir aynı zamanda bir işaret verir: aynı rol birden çok kez sarmalanmışsa, ara adımlardan biri gereksizdir.

Buna karşılık zinciri tümüyle düzleştirmek de yanlıştır. Bileşen belirteçlerinin doğrudan ilkel değerlere bağlandığı bir sistem, katman ihlalinin genelleştirilmiş hâlidir ve tema geçişini imkânsız kılar. Doğru hedef en kısa zincir değil, kural içinde en kısa zincirdir.

Yazılı Biçim ve Ad Sözleşmesi

Belirteçlerin biçemdeki karşılığı özel özelliklerdir. Katman ayrımı ad önekiyle görünür kılınır; Özel Özellikler dersindeki --kart- öneki sözleşmesi burada üç katmana genişler.

:root {
  /* ilkel */
  --notr-500: #757e8a;
  --ana-600: #275ea5;
  --adim-2: 8px;
  --adim-4: 16px;

  /* anlamsal */
  --kenarlik: var(--notr-500);
  --eylem-ana: var(--ana-600);
  --aralik-grup-ici: var(--adim-2);
  --aralik-blok-arasi: var(--adim-4);
}

.dugme {
  /* bilesen: yalniz anlamsal adlara basvurur */
  --dugme-zemin: var(--eylem-ana);
  --dugme-ic-bosluk-y: var(--aralik-grup-ici);
  --dugme-ic-bosluk-x: var(--aralik-blok-arasi);

  background-color: var(--dugme-zemin);
  padding: var(--dugme-ic-bosluk-y) var(--dugme-ic-bosluk-x);
}

Bileşen belirteçlerinin kök ögede değil bileşenin kendi kuralında bildirilmesi bir kapsam kararıdır. Bildirim bileşende durduğunda ad yalnız o alt ağaçta geçerli olur ve kök öge, her bileşenin ayar noktalarını taşıyan bir listeye dönüşmez. Özel Özellikler dersindeki hesaplanma anı kuralı burada da geçerlidir: --dugme-zemin düğme ögesinde hesaplanır, dolayısıyla düğmenin bir üst ögesinde --eylem-ana yeniden tanımlanırsa düğme bunu devralır.

Ad sözleşmesinin son parçası ilkel katmanın adlandırmasıdır. İlkel adlar rol taşımaz, konum taşır: notr-500, adim-2, basamak-1. Tipografik Ölçek dersinde basamak numarasının anlam taşıyan addan daha dayanıklı olduğu gösterilmişti; aynı gerekçe bütün ilkel katman için geçerlidir. Anlamı taşıyan tek katman anlamsal katmandır ve zaten adı bunu söyler.

Özet

  • Tasarım belirteci, bir tasarım kararının makine tarafından okunabilen adlandırılmış karşılığıdır; belirteçler tek liste olarak değil katmanlı bir grafik olarak düzenlenir.
  • Üç katman vardır: ilkel ham değeri, anlamsal işi, bileşen katmanı ayar noktasını taşır. İlkel katman başvuru yapmaz; bileşen katmanı yalnız anlamsal katmana başvurabilir.
  • Grafik dört kusur türü üretir: döngü, tanımsız başvuru, katman ihlali ve boşta kalan belirteç. Katman ihlali en tehlikelisidir, çünkü doğru değer üretir ve ancak tema değiştiğinde görünür.
  • Bileşen katmanı her anlamsal belirteç için kurulmaz, yalnız ayar noktası açılan yerlerde kurulur; bileşen katmanının anlamsal katmandan küçük kalması beklenir.
  • Zincir uzunluğu katman sayısının sonucudur; uzun zincir izlenebilirliği düşürür, tümüyle düzleştirmek tema geçişini imkânsız kılar. Hedef kural içinde en kısa zincirdir.
  • İlkel adlar konum taşır, anlamı yalnız anlamsal katman taşır; bileşen belirteçleri kök ögede değil bileşenin kendi kuralında bildirilir.

Sonraki Adım

Katman mimarisi kurulduğunda sıra katmanların içini doldurmaya gelir ve renk bu işin en çok kısıt taşıyan alanıdır. Bir renk belirteci yalnız bir ad ve bir değer değildir: hangi zemin üzerinde kullanılabileceği, hangi eşiği geçmesi gerektiği ve hangi durumda hangi türevine geçileceği de tanımın parçasıdır. Sonraki ders renk rollerini bir sözleşme olarak yazar, hangi ön planın hangi zemine düşebileceğini bildirir ve bu bildirimi kontrast oranıyla otomatik denetler.

İ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