Uyarlanabilir ve erişilebilir bir pop-up bileşeni oluşturmaya dair temel bilgiler.
Bu yayında, bir pop-up bileşeninin nasıl oluşturulacağıyla ilgili düşüncelerimizi paylaşmak istiyoruz. 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. Genellikle kullanıcıyı bir işlemin sonuçları hakkında bilgilendirmek için arayüz geri bildirimi kalıbı olarak kullanılırlar.
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
<output>
öğesi, ekran okuyuculara duyurulduğu için 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ı bir içerik oluşturabilirsiniz. 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>
Bir tost kapsayıcısı
Aynı anda birden fazla pop-up 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 tercih ettim. 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. Görünüm alanına fixed
olan bu öğe, hangi kenarların sabitleneceğini belirtmek için mantıksal mülkü inset
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 ve justify-items
ile ayrı ayrı 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
Birer pop-up'ın bazılarında padding
, bazılarında border-radius
ile daha yumuşak köşeler ve mobil ile masaüstü boyutlandırmasına yardımcı olan bir min()
işlevi bulunur. Aşağıdaki CSS'deki duyarlı boyut, pop-up'ların görüntü alanının% 90'ından veya 25ch
'den daha geniş olmasını engeller.
.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. Aşağıdaki CSS ile pop-up'ların tıklamaları çalmasını ö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, pop-up'ın girişini, bekleme süresini ve çıkışını tek bir animasyonda kontrol eder.
@keyframes fade-in {
from { opacity: 0 }
}
@keyframes fade-out {
to { opacity: 0 }
}
@keyframes slide-in {
from { transform: translateY(var(--_travel-distance, 10px)) }
}
Ardından pop-up öğ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
Stillerin ve ekran okuyucuya erişilebilir HTML'nin hazır olmasıyla birlikte, kullanıcı etkinliklerine göre pop-up'ların oluşturulmasını, eklenmesini ve kaldırılmasını koordine etmek 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ünmesi için şı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 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 pop-up'lar 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 animasyonla taşımak 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 pop-up eklendiğinde ızgara, pop-up'ı en başa yerleştirir ve diğer pop-up'larla eşit aralıklarla yerleştirir. Bu sırada, kapsayıcının eski konumdan 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şlevi ve toast.getAnimations()
eşlemesi olduğunu düşünüyorum. Bildirim için birden fazla anahtar kare animasyonu kullandığımdan, bunların hepsinin tamamlandığından emin olmak için her birinin JavaScript'ten istenmesi ve her birinin finished
sözünün tamamlanıp tamamlanmadığının gözlemlenmesi gerekir.
allSettled
bizim için bu şekilde çalışıyor. Tüm vaatleri yerine getirildiğinde tamamlanmış olarak çözülü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. Bir demo oluşturun, bağlantılarını bana tweetleyin. Ardından, 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