Uyarlanabilir ve erişilebilir bir bildirim bileşeninin nasıl oluşturulacağına dair temel bir genel bakış.
Bu yayında, bildirim bileşeninin nasıl oluşturulacağıyla ilgili düşüncelerimi paylaşmak istiyorum. Demoyu deneyin.
Video tercih ediyorsanız bu yayının YouTube versiyonunu aşağıda bulabilirsiniz:
Genel Bakış
Bildirimler, kullanıcılar için etkileşimli olmayan, pasif ve eşzamansız kısa mesajlardır. Genellikle, kullanıcıyı bir işlemin sonuçları hakkında bilgilendirmek için arayüz geri bildirim kalıbı olarak kullanılırlar.
Toast bileşeniEtkileşimler
Toast'lar, etkileşimli olmamaları, kapatılmamaları veya kalıcı olmamaları nedeniyle bildirimlerden, uyarılardan ve istemlerden farklıdır. Bildirimler; daha önemli bilgiler, etkileşim gerektiren eşzamanlı mesajlaşma veya sistem düzeyindeki mesajlar (sayfa düzeyindeki mesajların aksine) için kullanılır. Bildirimler, diğer bildirim stratejilerine kıyasla daha pasiftir.
Brüt kar
<output>
öğesi, ekran okuyuculara duyurulduğu için kısa mesaj için iyi bir seçimdir. Doğru HTML, JavaScript ve CSS ile geliştirmemiz için güvenli bir temel sağlar. Çok sayıda JavaScript olacaktır.
Kadeh kaldırma
<output class="gui-toast">Item added to cart</output>
role="status"
ekleyerek daha kapsayıcı hale getirebilirsiniz. Bu, tarayıcı spesifikasyona göre <output>
öğelerine örtülü rol vermediğinde yedek bir çözüm sağlar.
<output role="status" class="gui-toast">Item added to cart</output>
Tost kabı
Aynı anda birden fazla kısa mesaj gösterilebilir. Birden fazla bildirim mesajını düzenlemek için bir kapsayıcı kullanılır. Bu kapsayıcı, ekrandaki kısa mesajların konumunu da yönetir.
<section class="gui-toast-group">
<output role="status">Wizard Rose added to cart</output>
<output role="status">Self Watering Pot added to cart</output>
</section>
Düzenler
Bildirimleri görüntü alanının inset-block-end
kısmına sabitlemeyi seçtim. Başka bildirimler eklenirse bu ekran kenarından itibaren üst üste yerleştirilir.
GUI kapsayıcısı
Toasts kapsayıcısı, toasts'ı sunmak için tüm düzen işlerini yapar. Görüntü alanına fixed
ve hangi kenarların sabitleneceğini belirtmek için inset
mantıksal özelliğini kullanır. Ayrıca aynı block-end
kenarından biraz padding
da içerir.
.gui-toast-group {
position: fixed;
z-index: 1;
inset-block-end: 0;
inset-inline: 0;
padding-block-end: 5vh;
}
Görüntü alanında konumlanmasının yanı sıra, kısa mesaj kapsayıcısı, kısa mesajları hizalayabilen ve dağıtabilen bir ızgara kapsayıcısıdır. Öğeler, justify-content
ile grup olarak ortalanır ve justify-items
ile ayrı ayrı ortalanır.
Ekmeklerin birbirine değmemesi için biraz gap
ekleyin.
.gui-toast-group {
display: grid;
justify-items: center;
justify-content: center;
gap: 1vh;
}
GUI Toast
Tek bir tostta padding
, border-radius
ile daha yumuşak köşeler ve mobil cihazlarda ve masaüstünde boyutlandırmaya yardımcı olan bir min()
işlevi bulunur. Aşağıdaki CSS'deki duyarlı boyut, bildirimlerin görüntü alanının% 90'ından daha geniş olmasını veya 25ch
.
.gui-toast {
max-inline-size: min(25ch, 90vw);
padding-block: .5ch;
padding-inline: 1ch;
border-radius: 3px;
font-size: 1rem;
}
Stiller
Düzen ve konumlandırma ayarlandıktan sonra, kullanıcı ayarlarına ve etkileşimlerine uyum sağlamaya yardımcı olan CSS'yi ekleyin.
Tost kutusu
Bildirimler etkileşimli değildir. Bunlara dokunmak veya bunları kaydırmak herhangi bir işe yaramaz ancak şu anda işaretçi etkinliklerini kullanırlar. Aşağıdaki CSS ile pop-up'ların tıklamaları çalmasını önleyin.
.gui-toast-group {
pointer-events: none;
}
GUI Toast
Özel özellikler, HSL ve tercih medya sorgusu ile kısa mesajlara açık veya koyu uyarlanabilir tema uygulayın.
.gui-toast {
--_bg-lightness: 90%;
color: black;
background: hsl(0 0% var(--_bg-lightness) / 90%);
}
@media (prefers-color-scheme: dark) {
.gui-toast {
color: white;
--_bg-lightness: 20%;
}
}
Animasyon
Yeni bir bildirim, ekrana girerken animasyonla gösterilmelidir.
Hareket azaltma, translate
değerlerini varsayılan olarak 0
şeklinde ayarlayarak yapılır ancak hareket değeri, hareket tercihi medya sorgusunda bir uzunluk olarak güncellenir . Herkes animasyon görür ancak yalnızca bazı kullanıcılar toast'ın hareket mesafesini görür.
Bildirim animasyonu için kullanılan animasyon kareleri aşağıda verilmiştir. CSS, pop-up'ın girişini, beklemesini ve çıkışını tek bir animasyonla kontrol eder.
@keyframes fade-in {
from { opacity: 0 }
}
@keyframes fade-out {
to { opacity: 0 }
}
@keyframes slide-in {
from { transform: translateY(var(--_travel-distance, 10px)) }
}
Daha sonra uyarı öğesi değişkenleri ayarlar ve animasyon karelerini düzenler.
.gui-toast {
--_duration: 3s;
--_travel-distance: 0;
will-change: transform;
animation:
fade-in .3s ease,
slide-in .3s ease,
fade-out .3s ease var(--_duration);
}
@media (prefers-reduced-motion: no-preference) {
.gui-toast {
--_travel-distance: 5vh;
}
}
JavaScript
Stiller ve ekran okuyucu erişimine uygun HTML hazır olduğunda, kullanıcı etkinliklerine göre bildirimlerin oluşturulması, eklenmesi ve silinmesi için JavaScript gerekir. Toast bileşeninin geliştirici deneyimi minimum düzeyde olmalı ve aşağıdaki gibi kolayca kullanılmaya başlanabilmelidir:
import Toast from './toast.js'
Toast('My first toast')
Bildirim grubu ve bildirimleri oluşturma
Toast modülü JavaScript'ten yüklendiğinde bir toast kapsayıcısı oluşturup sayfaya eklemesi gerekir. Öğeyi body
öğesinden önce eklemeyi seçtim. Bu, kapsayıcı tüm gövde öğelerinin kapsayıcısının üzerinde olduğundan z-index
yığınlama sorunlarının oluşmasını önler.
const init = () => {
const node = document.createElement('section')
node.classList.add('gui-toast-group')
document.firstElementChild.insertBefore(node, document.body)
return node
}
init()
işlevi, öğeyi Toaster
olarak saklayarak modül içinde dahili olarak çağrılır:
const Toaster = init()
Toast HTML öğesi oluşturma işlemi createToast()
işleviyle yapılır. Bu işlev, bildirim için biraz metin gerektirir, bir <output>
öğesi oluşturur, bu öğeyi bazı sınıflar ve özelliklerle süsler, metni ayarlar ve düğümü döndürür.
const createToast = text => {
const node = document.createElement('output')
node.innerText = text
node.classList.add('gui-toast')
node.setAttribute('role', 'status')
return node
}
Bir veya daha fazla bildirim mesajını yönetme
JavaScript artık kısa mesajları içeren bir kapsayıcıyı dokümana ekliyor ve oluşturulan kısa mesajları eklemeye hazır. addToast()
işlevi, bir veya birden fazla kısa mesajın işlenmesini düzenler. Öncelikle bildirim sayısını ve hareketin uygun olup olmadığını kontrol edin. Ardından, bu bilgileri kullanarak bildirimi ekleyin veya diğer bildirimlerin yeni bildirim için "yer açtığı" izlenimini verecek şekilde şık bir animasyon yapın.
const addToast = toast => {
const { matches:motionOK } = window.matchMedia(
'(prefers-reduced-motion: no-preference)'
)
Toaster.children.length && motionOK
? flipToast(toast)
: Toaster.appendChild(toast)
}
İlk toast'u eklerken Toaster.appendChild(toast)
, CSS animasyonlarını tetikleyen sayfaya bir toast ekler: animasyonla görün, 3s
bekleyin, animasyonla kaybolun.
flipToast()
, mevcut bildirimler olduğunda çağrılır ve Paul
Lewis tarafından FLIP adı verilen bir teknik kullanılır. Buradaki amaç, yeni bildirim eklenmeden önce ve sonra kapsayıcının konumlarındaki farkı hesaplamaktır.
Bunu, ekmek kızartma makinesinin şu anda bulunduğu yeri, gideceği yeri işaretleyip bulunduğu yerden gittiği yere doğru animasyon oluşturmak gibi düşünebilirsiniz.
const flipToast = toast => {
// FIRST
const first = Toaster.offsetHeight
// add new child to change container size
Toaster.appendChild(toast)
// LAST
const last = Toaster.offsetHeight
// INVERT
const invert = last - first
// PLAY
const animation = Toaster.animate([
{ transform: `translateY(${invert}px)` },
{ transform: 'translateY(0)' }
], {
duration: 150,
easing: 'ease-out',
})
}
CSS ızgarası, düzenin ağır işlerini yapar. Yeni bir toast eklendiğinde, ızgara bunu başlangıca yerleştirir ve diğerleriyle arasına boşluk koyar. Bu sırada, kapsayıcıyı eski konumundan hareketlendirmek için web animasyonu kullanılır.
Tüm JavaScript'i bir araya getirme
Toast('my first toast')
çağrıldığında bir bildirim oluşturulur, sayfaya eklenir (belki de yeni bildirime yer açmak için kapsayıcıya animasyon eklenir), bir promise döndürülür ve oluşturulan bildirim, promise'in çözümlenmesi için CSS animasyonunun tamamlanması (üç anahtar kare animasyonu) açısından izlenir.
const Toast = text => {
let toast = createToast(text)
addToast(toast)
return new Promise(async (resolve, reject) => {
await Promise.allSettled(
toast.getAnimations().map(animation =>
animation.finished
)
)
Toaster.removeChild(toast)
resolve()
})
}
Bu kodun kafa karıştırıcı kısmının Promise.allSettled()
işlevi ve toast.getAnimations()
eşlemesi olduğunu düşünüyorum. Toast için birden fazla anahtar kare animasyonu kullandığımdan hepsinin tamamlandığından emin olmak için her birinin JavaScript'ten istenmesi ve her birinin finished
tamamlanma vaatlerine uyulması gerekir.
allSettled
tüm sözleri yerine getirildiğinde tamamlanmış olarak çözümlenir. await Promise.allSettled()
kullanıldığında, sonraki kod satırı öğeyi güvenle kaldırabilir ve kısa mesajın yaşam döngüsünü tamamladığını varsayabilir. Son olarak, resolve()
çağrısı üst düzey Toast sözünü yerine getirir. Böylece geliştiriciler, bildirim gösterildikten sonra temizlik yapabilir veya başka işler yapabilir.
export default Toast
Son olarak, Toast
işlevi, diğer komut dosyalarının içe aktarıp kullanabilmesi için modülden dışa aktarılır.
Toast bileşenini kullanma
Bildirim veya bildirimin geliştirici deneyimi, Toast
işlevi içe aktarılıp bir mesaj dizesiyle çağrılarak kullanılır.
import Toast from './toast.js'
Toast('Wizard Rose added to cart')
Geliştirici, kısa mesaj gösterildikten sonra temizlik yapmak veya başka bir işlem gerçekleştirmek istiyorsa asenkron işlevleri ve await işlevini kullanabilir.
import Toast from './toast.js'
async function example() {
await Toast('Wizard Rose added to cart')
console.log('toast finished')
}
Sonuç
Bunu nasıl yaptığımı öğrendiğinize göre, siz nasıl yapardınız? 🙂
Yaklaşımlarımızı çeşitlendirelim ve web'de içerik oluşturmanın tüm yollarını öğrenelim. Bir demo oluşturun, bağlantıları bana tweet atın. Ben de bu bağlantıları aşağıdaki topluluk remiksleri bölümüne ekleyeyim.
Topluluk remiksleri
- HTML/CSS/JS ile @_developit: demo ve kod
- HTML/CSS/JS ile Joost van der Schee: demo ve kod