Nordhealth'in Web Bileşenlerinde Özel Mülkleri Nasıl Kullandığı

Tasarım sistemlerinde ve bileşen kitaplıklarında Özel Mülk kullanmanın avantajları.

David Darnes
David Darnes

Adım Dave, Nordhealth'te Kıdemli Kullanıcı Arabirimi Geliştiricisiyim. Bileşen kitaplığımız için Web Bileşenleri oluşturmayı içeren tasarım sistemimiz Nord'un tasarımı ve geliştirilmesi üzerinde çalışıyorum. CSS Özel Özellikleri'ni kullanarak Web Bileşenleri'nin stil özelliklerini ayarlamayla ilgili sorunları nasıl çözdüğümüzü ve tasarım sistemlerinde ve bileşen kitaplıklarında Özel Özellikleri kullanmanın diğer bazı avantajlarını sizinle paylaşmak istiyorum.

Web Bileşenlerini nasıl oluştururuz?

Web Bileşenlerimizi oluşturmak için durum, kapsamlı stiller ve şablon gibi çok sayıda standart kod sağlayan Lit kitaplığını kullanıyoruz. Lit hafif olmakla kalmaz, aynı zamanda yerel JavaScript API'leri üzerine de geliştirilmiştir. Böylece, tarayıcının sahip olduğu özelliklerden yararlanan yalın bir kod paketi sunabiliriz.


import {html, css, LitElement} from 'lit';

export class SimpleGreeting extends LitElement {
  static styles = css`:host { color: blue; font-family: sans-serif; }`;

  static properties = {
    name: {type: String},
  };

  constructor() {
    super();
    this.name = 'there';
  }

  render() {
    return html`

Hey ${this.name}, welcome to Web Components!

`; } } customElements.define('simple-greeting', SimpleGreeting);
Lit.ile yazılmış bir Web Bileşeni

Ancak Web Bileşenlerinin en çekici yanı, hemen hemen tüm mevcut JavaScript çerçeveleriyle, hatta hiç çerçeveyle çalışmamalarıdır. Sayfada ana JavaScript paketi referans gösterildikten sonra Web Bileşeni kullanımı, yerel bir HTML öğesinin kullanılmasına çok benzer. Bunun yerel bir HTML öğesi olmadığını söyleyen tek gerçek işaret, etiketlerde yer alan tutarlı kısa çizgidir. Bu, tarayıcıya bunun bir Web Bileşeni olduğunu belirtmek için kullanılan bir standarttır.


// TODO: DevSite - Code sample removed as it used inline event handlers
Yukarıda oluşturulan Web Bileşenini bir sayfada kullanma.

Gölge DOM stili kapsülleme

Yerel HTML öğelerinin bir Gölge DOM'una sahip olması gibi, Web Bileşenleri de bu işleve sahiptir. Gölge DOM, bir öğe içindeki gizli bir düğüm ağacıdır. Bunu görselleştirmenin en iyi yolu, web denetleyicinizi açıp "Gölge DOM ağacını göster" seçeneğini etkinleştirmektir. Bunu yaptıktan sonra, denetleyicide yerel bir giriş öğesine bakmayı deneyin. Artık bu girişi açıp içindeki tüm öğeleri görme seçeneğiniz olacaktır. Bunu Web Bileşenlerimizden biriyle bile deneyebilirsiniz. Gölge DOM'yi görmek için özel giriş bileşenimizi incelemeyi deneyin.

Geliştirici Araçları'nda incelenen gölge DOM.
Normal metin giriş öğesi ve Nord girişi Web Bileşeni'ndeki Gölge DOM örneği.

Gölge DOM'un avantajlarından (veya bakış açınıza bağlı olarak dezavantajlarından) biri stil kapsüllemedir. Web Bileşeninizin içinde CSS yazarsanız, bu stiller sızdırılamaz ve ana sayfayı veya diğer öğeleri etkilemez. Bunlar tamamen bileşenin içinde yer alır. Ayrıca, ana sayfa veya bir üst Web Bileşeni için yazılan CSS, Web Bileşeninize sızdıramaz.

Stillerin bu şekilde bir araya getirilmesi, bileşen kitaplığımızın avantajlarından biridir. Böylece, bir kullanıcı bileşenlerimizden birini kullandığında, üst sayfaya uygulanan stillerden bağımsız olarak içeriğin istediğiniz gibi görüneceğini daha fazla garanti ederiz. Daha da emin olmak için tüm Web Bileşenlerimizin kök veya "barındırıcısına" all: unset; ekliyoruz.


:host {
  all: unset;
  display: block;
  box-sizing: border-box;
  text-align: start;
  /* ... */
}
Gölge köke veya ana makine seçiciye uygulanan bazı bileşen standart kodları.

Ancak Web Bileşeninizi kullanan birinin belirli stilleri değiştirmek için geçerli bir nedeni varsa ne olur? Belki bağlamı nedeniyle daha fazla kontrast gerektiren bir metin satırı vardır veya bir kenarlığın daha kalın olması gerekir? Bileşeninize stil giremiyorsa bu stil seçeneklerinin kilidini nasıl açabilirsiniz?

CSS Özel Mülkleri burada devreye girer.

CSS Özel Özellikleri

Özel Mülkler oldukça uygun bir şekilde adlandırılmıştır. Tamamen kendiniz adlandırabileceğiniz ve gereken değeri uygulayabileceğiniz CSS özellikleridir. Tek şart, önlerine iki kısa çizgi koymanızdır. Özel mülkünüzü tanımladıktan sonra değer, var() işlevi kullanılarak CSS'de kullanılabilir.


:root {
  --n-color-accent: rgb(53, 89, 199);
  /* ... */
}

.n-color-accent-text {
  color: var(--n-color-accent);
}
Tasarım jetonunun Özel Mülk olarak gösterildiği ve yardımcı sınıfta kullanıldığı CSS Çerçevemizden örnek.

Devralma söz konusu olduğunda, tüm Özel Mülkler devralınır. Bu da normal CSS mülklerinin ve değerlerinin tipik davranışını izler. Bir üst öğeye veya öğenin kendisine uygulanan herhangi bir özel özellik, diğer mülklerde değer olarak kullanılabilir. Özel Özellikleri, CSS çerçevemiz aracılığıyla kök öğeye uygulayarak tasarım jetonlarımız için yoğun bir şekilde kullanırız. Diğer bir deyişle, ister bir Web Bileşeni, ister CSS yardımcı sınıfı ister jeton listemizden bir değer çıkarmak isteyen bir geliştirici olsun, sayfadaki tüm öğeler bu jeton değerlerini kullanabilir.

Web Bileşenlerinin Gölge DOM'sini devirme ve geliştiricilerin bileşenlerimizin stilini belirlerken daha hassas bir kontrole sahip olmasını sağlamak için var() işlevini kullanarak Özel Özellikleri devralma olanağını kullanıyorduk.

Bir Nord Web Bileşenindeki Özel Mülkler

Tasarım sistemimizin bir bileşenini geliştirirken, CSS'ye ilişkin düşünceli bir yaklaşım benimsiyoruz. Böylece yalın ve bakımı kolay bir kod oluşturmayı amaçlıyoruz. Tasarım jetonları, kök öğedeki ana CSS Çerçevemizde Özel Mülkler olarak tanımlanır.


:root {
  --n-space-m: 16px;
  --n-space-l: 24px;
  /* ... */
  --n-color-background: rgb(255, 255, 255);
  --n-color-border: rgb(216, 222, 228);
  /* ... */
}
Kök seçicide tanımlanan CSS Özel Özellikleri.

Daha sonra bu jeton değerlerine bileşenlerimizde başvurulur. Bazı durumlarda, değeri doğrudan CSS mülküne uygularız ancak bazılarında, bazen yeni bir içeriğe dayalı Özel Mülk tanımlar ve değeri buna uygularız.


:host {
  --n-tab-group-padding: 0;
  --n-tab-list-background: var(--n-color-background);
  --n-tab-list-border: inset 0 -1px 0 0 var(--n-color-border);
  /* ... */
}

.n-tab-group-list {
  box-shadow: var(--n-tab-list-border);
  background-color: var(--n-tab-list-background);
  gap: var(--n-space-s);
  /* ... */
}
Bileşenin gölge kökünde tanımlanan ve ardından bileşen stillerinde kullanılan Özel Özellikler. Tasarım jetonları listesindeki özel Mülkler de kullanılıyor.

Ayrıca, bileşene özgü olan ancak jetonlarımızda bulunmayan bazı değerleri soyutlayarak bunları bağlamsal bir Özel Mülk'e dönüştüreceğiz. Bileşene dayalı özel mülkler bize iki önemli avantaj sağlar. İlk olarak, bu değer bileşenin içindeki birden fazla özelliğe uygulanabileceğinden CSS'mizde daha "kritik" olabileceğimiz anlamına gelir.


.n-tab-group-list::before {
  /* ... */
  padding-inline-start: var(--n-tab-group-padding);
}

.n-tab-group-list::after {
  /* ... */
  padding-inline-end: var(--n-tab-group-padding);
}
Bileşen kodunun birden çok yerinde kullanılan sekme grubu dolgusu içeriğe dayalı Özel Mülk.

İkinci olarak, bileşen durumu ve varyasyon değişikliklerini gerçekten açık hale getirir. Örneğin, bir fareyle üzerine gelme veya etkin durumun stilini oluştururken ya da bu örnekte varyasyon oluştururken tüm bu özelliklerin güncellenmesi için yalnızca özel özelliğin değiştirilmesi gerekir.


:host([padding="l"]) {
  --n-tab-group-padding: var(--n-space-l);
}
Dolgunun, birden çok güncelleme yerine tek bir Özel Mülk güncellemesi kullanılarak değiştirildiği sekme bileşeninin bir varyasyonu.

Ancak en büyük faydası, bir bileşende bu bağlamsal Özel Özellikler'i tanımladığımızda, her bileşenimiz için söz konusu bileşenin kullanıcısı tarafından kullanılabilen bir tür özel CSS API'sı oluşturmamızdır.


<nord-tab-group label="Title">
  <!-- ... -->
</nord-tab-group>

<style>
  nord-tab-group {
    --n-tab-group-padding: var(--n-space-xl);
  }
</style>
Sayfadaki sekme grubu bileşenini kullanma ve dolgu Özel Mülkünü daha büyük bir boyuta güncelleme.

Yukarıdaki örnek, bağlamsal bir özel mülkü olan Web Bileşenlerimizden birinin seçici aracılığıyla değiştirildiğini göstermektedir. Bu yaklaşımın bütünüyle, gerçek stillerin büyük bir kısmını kontrol altında tutarken kullanıcıya yeterli stil esnekliği sunan bir bileşen ortaya çıkar. Ayrıca, bileşen geliştiricileri olarak kullanıcı tarafından uygulanan bu stilleri engelleme olanağına da sahibiz. Bu özelliklerden birini ayarlamak veya genişletmek istediğimizde, kullanıcının kodlarında herhangi bir değişiklik yapmasına gerek kalmadan bunu yapabiliriz.

Bu yaklaşımın, yalnızca tasarım sistemi bileşenlerinin yaratıcıları olarak bizim için değil, bu bileşenleri ürünlerimizde kullanan geliştirme ekibimiz için de son derece güçlü olduğunu düşünüyoruz.

Özel Mülkler'i daha ileri taşıma

Bu bağlamsal Özel Mülkleri, yazıldığı sırada belgelerimizde açıklayamıyoruz. Ancak, daha kapsamlı geliştirme ekibimizin bu mülkleri anlayıp yararlanabilmesi için bunu yapmayı planlıyoruz. Bileşenlerimiz, hakkında bilmeniz gereken her şeyi içeren bir manifest dosyası ile npm'de paketlenir. Daha sonra, dokümantasyon sitemiz dağıtıldığında manifest dosyasını veri olarak kullanırız. Bu işlem, Eleventy'yi ve Global Veri özelliğini kullanarak yapılır. Bağlamsal Özel Mülkleri, bu manifest veri dosyasına eklemeyi planlıyoruz.

Geliştirmek istediğimiz bir başka alan da bu içeriğe dayalı Özel Mülklerin değerleri devralmasıdır. Şu anda, örneğin iki ayırıcı bileşenin rengini ayarlamak istiyorsanız özellikle seçicilerle bu bileşenlerin ikisini de hedeflemeniz veya özel özelliği doğrudan style özelliğine sahip öğeye uygulamanız gerekir. Bu seçenek iyi gibi görünebilir, ancak geliştirici bu stilleri kapsayıcı öğede veya kök düzeyinde tanımlayabilirse daha faydalı olur.


<nord-divider></nord-divider>

<section>
  <nord-divider></nord-divider>
   <!-- ... -->
</section>

<style>
  nord-divider {
    --n-divider-color: var(--n-color-status-danger);
  }

  section {
    padding: var(--n-space-s);
    background: var(--n-color-surface-raised);
  }
  
  section nord-divider {
    --n-divider-color: var(--n-color-status-success);
  }
</style>
Bölen bileşenimizin, iki farklı renk uygulanması gereken iki örneği. Bunlardan biri, daha spesifik bir seçici için kullanabileceğimiz bir bölümün içine yerleştirilmiş ama ayırıcıyı özellikle hedeflememiz gerekiyor.

Özel Mülk değerini doğrudan bileşen üzerinde ayarlamanızın nedeni, aynı öğede bileşen ana makine seçici aracılığıyla bunları tanımlıyor olmamızdır. Doğrudan bileşende kullandığımız genel tasarım jetonları doğrudan geçer, bu sorundan etkilenmez ve üst öğelerde bile ele geçirilebilir. Her iki platformdan da en iyi şekilde yararlanmak için neler yapabiliriz?

Özel ve herkese açık Özel Mülkler

Özel özel mülkler Lea Verou tarafından derlenen bir yapıdır. Lea Verou, bileşenin kendisinde içeriğe dayalı "gizli" bir Özel Mülk olup, yedekli "herkese açık" bir Özel Mülk olarak ayarlanmıştır.



:host {
  --_n-divider-color: var(--n-divider-color, var(--n-color-border));
  --_n-divider-size: var(--n-divider-size, 1px);
}

.n-divider {
  border-block-start: solid var(--_n-divider-size) var(--_n-divider-color);
  /* ... */
}
Bölen Web Bileşeni CSS'sinin, bağlamsal Özel Mülkler bölümü, dahili CSS'nin, herkese açık bir özel mülk olarak ayarlanmış özel bir özel mülkü temel alacağı şekilde ayarlandı.

İçeriğe dayalı Özel Mülklerimizi bu şekilde tanımlamak, global jeton değerlerini devralma ve değerleri bileşen kodumuz genelinde yeniden kullanma gibi daha önce yaptığımız tüm işlemleri yapabildiğimiz anlamına gelir. Ancak bileşen, kendi üzerinde veya herhangi bir üst öğede söz konusu mülkün yeni tanımlarını da incelikle devralacaktır.


<nord-divider></nord-divider>

<section>
  <nord-divider></nord-divider>
   <!-- ... -->
</section>

<style>
  nord-divider {
    --n-divider-color: var(--n-color-status-danger);
  }

  section {
    padding: var(--n-space-s);
    background: var(--n-color-surface-raised);
    --n-divider-color: var(--n-color-status-success);
  }
</style>
Yine iki ayırıcıyı tekrar görebilirsiniz. Ancak bu kez, bölüm seçiciye ayırıcının içeriğe dayalı Özel Mülkü eklenerek ayırıcı yeniden renklendirilebilir. Ayırıcı bunu devralarak daha temiz ve esnek bir kod parçası üretecektir.

Bu yöntemin gerçekten "gizli" olmadığı düşünülse de, bu yöntemin endişe ettiğimiz bir sorun için oldukça şık bir çözüm olduğunu düşünüyoruz. Fırsat bulduğumuzda bu sorunu bileşenlerimizde ele alacağız. Böylece geliştirme ekibimiz hem bileşen kullanımı üzerinde daha fazla kontrole sahip olur hem de uygulanmakta olan güvenlik önlemlerinden yararlanmaya devam eder.

CSS Özel Mülkleri ile Web Bileşenleri'ni nasıl kullandığımıza dair bu bilgiyi yararlı bulduğunuzu umuyoruz. Düşüncelerinizi bizimle paylaşabilirsiniz. Bu yöntemlerden herhangi birini kendi çalışmanızda kullanmaya karar verirseniz beni Twitter'da @DavidDarnes adresinden bulabilirsiniz. Ayrıca, bu tasarım sistemini bir araya getirmek ve bu makalede bahsedilen özellikleri uygulamak için büyük emek veren ekip arkadaşlarımın yanı sıra @NordhealthHQ Twitter'da da Twitter'da bulabilirsiniz: @Viljamis, @WickyNilliams ve @eric_habich.

Dan Cristian Pădurelerinize ait bir hero resim