Uyarlanabilir ve erişilebilir bir pop-up bileşeni oluşturmaya dair temel bilgiler.
Bu yayında, pop-up bileşeni oluşturma konusundaki düşüncelerimi paylaşmak istiyorum. Demoyu deneyin.
Videoyu tercih ediyorsanız bu yayının YouTube sürümünü burada bulabilirsiniz:
Genel Bakış
Bildirimler, kullanıcılara yönelik etkileşimsiz, pasif ve eşzamansız kısa mesajlardır. Bunlar genellikle kullanıcıyı bir işlemin sonuçları hakkında bilgilendirmek için arayüz geri bildirim kalıbı olarak kullanılır.
Etkileşimler
Bildirimler, uyarılar ve istemler ile karşılaştırıldığında, etkileşimli olmadıkları ve kapatılmaları ya da kalıcı olmaları amaçlanmadığı için pop-up'lar farklıdır. Bildirimler, daha önemli bilgiler, etkileşim gerektiren senkron mesajlar veya sistem düzeyinde mesajlar (sayfa düzeyinin aksine) içindir. Pop-up bildirimler, diğer bildirim stratejilerine kıyasla daha pasiftir.
Brüt kar
Ekran okuyuculara duyurulacağı için <output>
öğesi, pop-up için iyi bir seçimdir. Doğru HTML, JavaScript ve CSS ile geliştirme yapabileceğimiz güvenli bir temel sağlar. Bu süreçte çok fazla JavaScript kullanacağız.
Bir kadeh
<output class="gui-toast">Item added to cart</output>
role="status"
ekleyerek daha kapsayıcı hale getirebilirsiniz. Bu, tarayıcı <output>
öğelerine spesifikasyona göre örtülü rolü vermezse yedek bir seçenek sunar.
<output role="status" class="gui-toast">Item added to cart</output>
Tost kutusu
Aynı anda birden fazla durum mesajı gösterilebilir. Birden fazla pop-up'ı koordine etmek için bir kapsayıcı kullanılır. Bu kapsayıcı, ekrandaki pop-up'ları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. Daha fazla bildirim eklenirse bu ekran kenarından yığılır.
GUI kapsayıcısı
Bildirim kapsülü, bildirimlerin gösterilmesiyle ilgili tüm düzen çalışmalarını yapar. Bu değer, görüntü alanına fixed
şeklindedir ve hangi kenarların sabitleneceğini belirtmek için inset
mantıksal özelliğini ve aynı block-end
kenarından biraz padding
kullanır.
.gui-toast-group {
position: fixed;
z-index: 1;
inset-block-end: 0;
inset-inline: 0;
padding-block-end: 5vh;
}
Bildirim kapsayıcısı, görüntü alanında konumlanmanın yanı sıra bildirimleri hizalayabilen ve dağıtabilen bir ızgara kapsayıcısıdır. Öğeler justify-content
ile grup halinde, justify-items
ile ise tek tek ortalanır.
Tostların birbirine değmemesi için biraz gap
ekleyin.
.gui-toast-group {
display: grid;
justify-items: center;
justify-content: center;
gap: 1vh;
}
GUI Kısa İleti
Bir kısa açıklamada padding
, border-radius
ile daha yumuşak köşeler ve mobil ile masaüstünü boyutlandırmaya yardımcı olan bir min()
işlevi bulunur. Aşağıdaki CSS'de yer alan duyarlı boyut, kısa mesaj öğelerinin görüntü alanının% 90'ından veya 25ch
'dan daha geniş bir alana yayılmasını engelliyor.
.gui-toast {
max-inline-size: min(25ch, 90vw);
padding-block: .5ch;
padding-inline: 1ch;
border-radius: 3px;
font-size: 1rem;
}
Stiller
Düzen ve yerleşim belirlendikten sonra, kullanıcı ayarlarına ve etkileşimlerine uyum sağlamaya yardımcı olan CSS ekleyin.
Tost kutusu
Bildirimler etkileşimli değildir, üzerine dokunmak veya kaydırarak hareket ettirmek hiçbir şeye yaramaz ancak şu anda işaretçi etkinliklerini tüketir. Kısa mesajların tıklamaları çalmasını aşağıdaki CSS ile önleyin.
.gui-toast-group {
pointer-events: none;
}
GUI Kısa İleti
Bildirimlere özel özellikler, HSL ve tercih medya sorgusu içeren açık veya koyu uyarlanabilir bir tema verin.
.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 pop-up, ekrana girerken animasyonla gösterilmelidir.
Azaltılmış harekete uyum sağlamak için translate
değerleri varsayılan olarak 0
olarak ayarlanır ancak hareket değeri, hareket tercihi medya sorgusunda bir uzunluk değerine güncellenir. Herkes animasyon görür ancak yalnızca bazı kullanıcılar tostların bir mesafe kat etmesini görür.
Pop-up animasyonu için kullanılan animasyon kareleri aşağıda verilmiştir. CSS; girişi, beklemeyi ve kısa mesajın çıkışını tek bir animasyonda kontrol edecek.
@keyframes fade-in {
from { opacity: 0 }
}
@keyframes fade-out {
to { opacity: 0 }
}
@keyframes slide-in {
from { transform: translateY(var(--_travel-distance, 10px)) }
}
Ardından, durum mesajı öğ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 tarafından erişilebilen HTML hazır olduğunda, kısa mesajların kullanıcı etkinliklerine dayalı olarak oluşturulmasını, eklenmesini ve kaldırılmasını yönetmek için JavaScript gerekir. Toast bileşeninin geliştirici deneyimi minimum düzeyde olmalı ve kullanımı kolay olmalıdır. Örneğin:
import Toast from './toast.js'
Toast('My first toast')
Bildirim grubu ve bildirimleri oluşturma
Tost modülü JavaScript'den yüklendiğinde bir tost kapsayıcısı oluşturmalı ve bunu sayfaya eklemelidir. Öğeyi body
öğesinden önce eklemeyi tercih ettim. Bu, tüm body öğelerinin kapsayıcısı kapsayıcının üzerinde olduğu için z-index
yığın oluşturma sorunlarının olasılığını azaltır.
const init = () => {
const node = document.createElement('section')
node.classList.add('gui-toast-group')
document.firstElementChild.insertBefore(node, document.body)
return node
}
init()
işlevi modül içinde çağrılır ve öğeyi Toaster
olarak saklar:
const Toaster = init()
Toast HTML öğesi oluşturma işlemi createToast()
işleviyle yapılır. İşlev, pop-up için metin gerektirir, bir <output>
öğesi oluşturur, bu öğeyi bazı sınıf 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 pop-up'ı yönetme
JavaScript artık dokümana pop-up'ları içerecek bir kapsayıcı ekliyor ve oluşturulan pop-up'ları eklemeye hazır. addToast()
işlevi, bir veya daha fazla pop-up'ın işlenmesini koordine eder. Öncelikle pop-up sayısını ve hareketin uygun olup olmadığını kontrol edin. Ardından bu bilgileri kullanarak pop-up'ı ekleyin veya diğer pop-up'ların yeni pop-up için "yer açtığı" görünecek şekilde bazı animasyonlar 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 pop-up'ı eklerken Toaster.appendChild(toast)
, sayfaya CSS animasyonlarını tetikleyen bir pop-up ekler: animasyonla görün, 3s
saniye bekle, animasyonla kaybol.
flipToast()
, mevcut tostlar olduğunda çağrılır ve Paul Lewis tarafından geliştirilen FLIP adlı bir teknik kullanılır. Buradaki amaç, yeni pop-up eklenmeden önce ve sonra kapsayıcının konumlarındaki farkı hesaplamaktır.
Bunu, tost makinesinin şu anda nerede olduğunu, nereye gideceğini işaretleyip bulunduğu yerden bulunduğu yere animasyon olarak göstermek 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 ızgara, düzeni kaldırır. Yeni bir tost eklendiğinde, ızgara bunu en başa yerleştirir ve diğerleriyle birlikte yerleştirir. Bu sırada, kapsayıcının eski konumundan animasyonu için bir web animasyonu kullanılır.
Tüm JavaScript'i bir araya getirme
Toast('my first toast')
çağrıldığında bir pop-up oluşturulur, sayfaya eklenir (hatta kapsayıcı yeni pop-up'a uyum sağlamak için animasyonlu hale getirilebilir), bir promise döndürülür ve oluşturulan pop-up, promise çözümü için CSS animasyonunun tamamlanmasını (üç anahtar kare animasyonu) 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şlevinde ve toast.getAnimations()
eşlemesinde olduğunu hissettim. Kısa mesaj için birden fazla animasyon karesi animasyonu kullandığımdan, tümünün bittiğini güvenle emin olmak için her birinin JavaScript'ten istenmesi ve finished
vaatlerinin her birinin tamamlanma için gözlemlenmesi gerekir.
allSettled
bizim için uygun mu? Tüm vaatleri yerine getirildikten sonra kendini tamamlanmış olarak
çözüyor. await Promise.allSettled()
kullanılması, bir sonraki kod satırının öğeyi güvenle kaldırabileceği ve tost mesajının yaşam döngüsünü tamamladığını varsayabileceği anlamına gelir. Son olarak, resolve()
çağrısı yüksek düzeyde Toast vaadini yerine getirir. Böylece geliştiriciler, pop-up gösterildikten sonra temizlik yapabilir veya başka işler yapabilir.
export default Toast
Son olarak, diğer komut dosyalarının içe aktarıp kullanabilmesi için Toast
işlevi modülden dışa aktarılır.
Toast bileşenini kullanma
Pop-up'ı veya pop-up'ın geliştirici deneyimini kullanmak için Toast
işlevi içe aktarılır ve bir mesaj dizesiyle çağrılır.
import Toast from './toast.js'
Toast('Wizard Rose added to cart')
Geliştirici, pop-up gösterildikten sonra temizleme çalışması veya başka bir işlem yapmak istiyorsa async ve await'ı 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 ne yapardınız? 🙂
Yaklaşımlarımızı çeşitlendirelim ve web'de uygulama geliştirmenin tüm yollarını öğrenelim. Demo oluşturup beni tweet'le bağlantıları oluşturduğumda bunu aşağıdaki topluluk remiksleri bölümüne ekleyeceğim.
Topluluk remiksleri
- HTML/CSS/JS ile @_developit: demo ve kod
- HTML/CSS/JS ile Joost van der Schee: demo ve kod