इस लेख में, अडैप्टिव और सुलभता सुविधाओं वाला टोस्ट कॉम्पोनेंट बनाने के बारे में बुनियादी जानकारी दी गई है.
इस पोस्ट में, मैं यह शेयर करना चाहता हूं कि टोस्ट कॉम्पोनेंट कैसे बनाया जाता है. डेमो आज़माएं.
अगर आपको वीडियो देखना ज़्यादा पसंद है, तो इस पोस्ट का YouTube वर्शन यहां दिया गया है:
खास जानकारी
सूचनाएं, उपयोगकर्ताओं के लिए छोटे मैसेज होती हैं. ये इंटरैक्टिव नहीं होती हैं. साथ ही, ये पैसिव और एसिंक्रोनस होती हैं. आम तौर पर, इनका इस्तेमाल यूज़र इंटरफ़ेस के फ़ीडबैक पैटर्न के तौर पर किया जाता है. इससे उपयोगकर्ता को किसी कार्रवाई के नतीजों के बारे में जानकारी मिलती है.
इंटरैक्शन
सूचनाओं, चेतावनी, और प्रॉम्प्ट के उलट, सूचनाएं इंटरैक्टिव नहीं होती हैं. इन्हें खारिज नहीं किया जा सकता और न ही ये बनी रहती हैं. सूचनाएं ज़्यादा अहम जानकारी के लिए होती हैं. साथ ही, ये ऐसी सिंक्रोनस मैसेजिंग के लिए होती हैं जिसमें इंटरैक्शन की ज़रूरत होती है या सिस्टम लेवल के मैसेज (पेज लेवल के मैसेज के बजाय) के लिए होती हैं. सूचना दिखाने की अन्य रणनीतियों की तुलना में, सूचनाएं ज़्यादा पैसिव होती हैं.
मार्कअप
टॉस्ट के लिए, <output>
एलिमेंट एक अच्छा विकल्प है, क्योंकि इसे स्क्रीन रीडर के लिए उपलब्ध कराया जाता है. सही एचटीएमएल, JavaScript और सीएसएस की मदद से बेहतर बनाने के लिए एक सुरक्षित आधार उपलब्ध कराता है. साथ ही, इसमें बहुत सारी JavaScript शामिल होंगी.
टोस्ट
<output class="gui-toast">Item added to cart</output>
role="status"
जोड़कर, इसे ज़्यादा समावेशी बनाया जा सकता है. अगर ब्राउज़र, स्पेसिफ़िकेशन के मुताबिक <output>
एलिमेंट को इंप्लिसिट रोल नहीं देता है, तो यह फ़ॉलबैक उपलब्ध कराता है.
<output role="status" class="gui-toast">Item added to cart</output>
टोस्ट का कंटेनर
एक बार में एक से ज़्यादा सूचनाएं दिखाई जा सकती हैं. एक से ज़्यादा सूचनाओं को व्यवस्थित करने के लिए, कंटेनर का इस्तेमाल किया जाता है. यह कंटेनर, स्क्रीन पर सूचनाओं की जगह को भी मैनेज करता है.
<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>
लेआउट
मैंने सूचनाओं को व्यूपोर्ट के inset-block-end
पर पिन करने का विकल्प चुना है. अगर और सूचनाएं जोड़ी जाती हैं, तो वे स्क्रीन के किनारे से स्टैक हो जाती हैं.
GUI कंटेनर
तोस्ट कंटेनर, तोस्ट दिखाने के लिए लेआउट से जुड़ा सारा काम करता है. यह व्यूपोर्ट के fixed
पर होता है और लॉजिकल प्रॉपर्टी inset
का इस्तेमाल करके यह तय करता है कि किन किनारों पर पिन करना है. साथ ही, इसमें block-end
किनारे से थोड़ा सा padding
भी होता है.
.gui-toast-group {
position: fixed;
z-index: 1;
inset-block-end: 0;
inset-inline: 0;
padding-block-end: 5vh;
}
व्यूपोर्ट में खुद को पोज़िशन करने के साथ-साथ, टोस्ट कंटेनर एक ग्रिड कंटेनर भी होता है. यह टोस्ट को अलाइन और डिस्ट्रिब्यूट कर सकता है. आइटम को ग्रुप के तौर पर justify-content
की मदद से बीच में अलाइन किया जाता है. साथ ही, उन्हें अलग-अलग justify-items
की मदद से बीच में अलाइन किया जाता है.
तोस्ट के बीच में थोड़ी सी gap
डालें, ताकि वे एक-दूसरे से न चिपके.
.gui-toast-group {
display: grid;
justify-items: center;
justify-content: center;
gap: 1vh;
}
GUI Toast
किसी एक टोस्ट में कुछ padding
, कुछ हल्के कॉर्नर border-radius
के साथ, और मोबाइल और डेस्कटॉप के साइज़ में मदद करने के लिए min()
फ़ंक्शन होता है. नीचे दिए गए सीएसएस में रिस्पॉन्सिव साइज़ की वजह से, सूचनाएं व्यूपोर्ट के 90% से ज़्यादा चौड़ी नहीं होती हैं या 25ch
.
.gui-toast {
max-inline-size: min(25ch, 90vw);
padding-block: .5ch;
padding-inline: 1ch;
border-radius: 3px;
font-size: 1rem;
}
स्टाइल
लेआउट और पोज़िशनिंग सेट करने के बाद, ऐसा सीएसएस जोड़ें जो उपयोगकर्ता की सेटिंग और इंटरैक्शन के हिसाब से ढलने में मदद करे.
Toast कंटेनर
सूचनाएं इंटरैक्टिव नहीं होती हैं. इन पर टैप या स्वाइप करने से कुछ नहीं होता. हालांकि, फ़िलहाल ये पॉइंटर इवेंट का इस्तेमाल करती हैं. नीचे दिए गए सीएसएस का इस्तेमाल करके, सूचनाओं को क्लिक चुराने से रोकें.
.gui-toast-group {
pointer-events: none;
}
GUI Toast
कस्टम प्रॉपर्टी, एचएसएल, और प्रेफ़रेंस मीडिया क्वेरी की मदद से, सूचनाओं को हल्के या गहरे रंग वाली अडैप्टिव थीम दें.
.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%;
}
}
ऐनिमेशन
स्क्रीन पर आने पर, नए टोस्ट को ऐनिमेशन के साथ दिखना चाहिए.
मोशन कम करने की सुविधा को चालू करने के लिए, translate
की वैल्यू को डिफ़ॉल्ट रूप से 0
पर सेट किया जाता है. हालांकि, मोशन की वैल्यू को मोशन की प्राथमिकता वाली मीडिया क्वेरी में किसी अवधि के लिए अपडेट किया जाता है. सभी को कुछ ऐनिमेशन मिलते हैं, लेकिन सिर्फ़ कुछ उपयोगकर्ताओं को सूचना वाली पॉप-अप विंडो को एक जगह से दूसरी जगह ले जाने की सुविधा मिलती है.
यहां टोस्ट ऐनिमेशन के लिए इस्तेमाल किए गए मुख्य फ़्रेम दिए गए हैं. सीएसएस, एक ही ऐनिमेशन में सूचना के दिखने, रुकने, और गायब होने की प्रोसेस को कंट्रोल करेगी.
@keyframes fade-in {
from { opacity: 0 }
}
@keyframes fade-out {
to { opacity: 0 }
}
@keyframes slide-in {
from { transform: translateY(var(--_travel-distance, 10px)) }
}
इसके बाद, टोस्ट एलिमेंट वैरिएबल सेट अप करता है और कीफ़्रेम को व्यवस्थित करता है.
.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
स्टाइल और स्क्रीन रीडर के साथ काम करने वाले एचटीएमएल के तैयार होने के बाद, JavaScript की ज़रूरत होती है. इसकी मदद से, उपयोगकर्ता के इवेंट के आधार पर सूचनाएं बनाई, जोड़ी, और हटाई जा सकती हैं. डेवलपर को टोस्ट कॉम्पोनेंट का इस्तेमाल करने में कम से कम समय लगना चाहिए. साथ ही, इसे आसानी से इस्तेमाल किया जा सके. जैसे:
import Toast from './toast.js'
Toast('My first toast')
सूचनाओं का ग्रुप और सूचनाएं बनाना
जब JavaScript से सूचना वाला मॉड्यूल लोड होता है, तो उसे सूचना वाला कंटेनर बनाना होगा और उसे पेज में जोड़ना होगा. मैंने body
से पहले एलिमेंट जोड़ने का विकल्प चुना है. इससे z-index
के स्टैक होने से जुड़ी समस्याएं नहीं होंगी, क्योंकि कंटेनर, सभी बॉडी एलिमेंट के कंटेनर से ऊपर है.
const init = () => {
const node = document.createElement('section')
node.classList.add('gui-toast-group')
document.firstElementChild.insertBefore(node, document.body)
return node
}
init()
फ़ंक्शन को मॉड्यूल में इंटरनल तौर पर कॉल किया जाता है. इससे एलिमेंट को Toaster
के तौर पर सेव किया जाता है:
const Toaster = init()
createToast()
फ़ंक्शन का इस्तेमाल करके, टोस्ट एचटीएमएल एलिमेंट बनाया जाता है. इस फ़ंक्शन को सूचना के लिए कुछ टेक्स्ट की ज़रूरत होती है. यह एक <output>
एलिमेंट बनाता है, इसे कुछ क्लास और एट्रिब्यूट से सजाता है, टेक्स्ट सेट करता है, और नोड दिखाता है.
const createToast = text => {
const node = document.createElement('output')
node.innerText = text
node.classList.add('gui-toast')
node.setAttribute('role', 'status')
return node
}
एक या कई सूचनाएं मैनेज करना
JavaScript अब दस्तावेज़ में एक कंटेनर जोड़ता है, ताकि सूचनाएं दिखाई जा सकें. साथ ही, बनाई गई सूचनाएं जोड़ने के लिए तैयार है. addToast()
फ़ंक्शन, एक या कई सूचनाओं को मैनेज करता है. सबसे पहले, सूचनाओं की संख्या की जांच करना और यह देखना कि मोशन ठीक है या नहीं. इसके बाद, इस जानकारी का इस्तेमाल करके सूचना को जोड़ना या कुछ शानदार ऐनिमेशन करना, ताकि अन्य सूचनाएं नई सूचना के लिए "जगह बना सकें".
const addToast = toast => {
const { matches:motionOK } = window.matchMedia(
'(prefers-reduced-motion: no-preference)'
)
Toaster.children.length && motionOK
? flipToast(toast)
: Toaster.appendChild(toast)
}
पहला सूचना वाला मैसेज जोड़ते समय, Toaster.appendChild(toast)
सीएसएस ऐनिमेशन को ट्रिगर करने वाले पेज में सूचना वाला मैसेज जोड़ता है: ऐनिमेट इन, 3s
तक इंतज़ार करें, ऐनिमेट आउट.
flipToast()
को तब कॉल किया जाता है, जब पहले से कोई सूचना मौजूद हो. इसमें Paul Lewis की FLIP नाम की तकनीक का इस्तेमाल किया जाता है. इसका मकसद, नए टोस्ट को जोड़ने से पहले और बाद में कंटेनर की पोज़िशन में अंतर का हिसाब लगाना है.
इसे ऐसे समझें कि टोस्टर की मौजूदा जगह और उसकी अगली जगह को मार्क किया जाता है. इसके बाद, टोस्टर को उसकी पिछली जगह से मौजूदा जगह तक ऐनिमेट किया जाता है.
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',
})
}
सीएसएस ग्रिड, लेआउट को ऊपर की ओर ले जाता है. कोई नया सूचना मैसेज जोड़े जाने पर, ग्रिड उसे सबसे ऊपर रखता है और अन्य मैसेज के साथ स्पेस देता है. इस दौरान, कंटेनर को पुरानी जगह से ऐनिमेट करने के लिए, वेब ऐनिमेशन का इस्तेमाल किया जाता है.
सभी JavaScript को एक साथ रखना
Toast('my first toast')
को कॉल करने पर, एक टोस्ट बनाया जाता है और उसे पेज में जोड़ा जाता है. ऐसा हो सकता है कि नए टोस्ट को दिखाने के लिए कंटेनर को ऐनिमेट किया गया हो. इसके बाद, एक प्रॉमिस वापस किया जाता है और बनाए गए टोस्ट को देखा जाता है. ऐसा प्रॉमिस रिज़ॉल्यूशन के लिए, सीएसएस ऐनिमेशन (तीन मुख्य फ़्रेम ऐनिमेशन) पूरा होने तक किया जाता है.
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()
})
}
मुझे लगता है कि इस कोड में Promise.allSettled()
फ़ंक्शन और toast.getAnimations()
मैपिंग को समझना मुश्किल है. मैंने टोस्ट के लिए कई कीफ़्रेम ऐनिमेशन का इस्तेमाल किया है. इसलिए, यह पक्का करने के लिए कि सभी ऐनिमेशन पूरे हो गए हैं, हर ऐनिमेशन को JavaScript से अनुरोध किया जाना चाहिए. साथ ही, हर ऐनिमेशन के finished
प्रॉमिस को पूरा होने के लिए मॉनिटर किया जाना चाहिए.
allSettled
हमारे लिए काम करता है. इसमें किए गए सभी वादे पूरे होने के बाद, यह अपने-आप पूरा हो जाता है. await Promise.allSettled()
का इस्तेमाल करने का मतलब है कि कोड की अगली लाइन, एलिमेंट को आसानी से हटा सकती है. साथ ही, यह मान सकती है कि सूचना का लाइफ़साइकल पूरा हो गया है. आखिर में, resolve()
को कॉल करने से, Toast के हाई लेवल का प्रॉमिस पूरा हो जाता है. इसलिए, Toast दिखने के बाद डेवलपर, साफ़-सफ़ाई कर सकते हैं या अन्य काम कर सकते हैं.
export default Toast
आखिर में, Toast
फ़ंक्शन को मॉड्यूल से एक्सपोर्ट किया जाता है, ताकि अन्य स्क्रिप्ट इसे इंपोर्ट और इस्तेमाल कर सकें.
Toast कॉम्पोनेंट का इस्तेमाल करना
टॉस्ट या टॉस्ट के डेवलपर अनुभव का इस्तेमाल करने के लिए, Toast
फ़ंक्शन को इंपोर्ट किया जाता है. इसके बाद, इसे मैसेज स्ट्रिंग के साथ कॉल किया जाता है.
import Toast from './toast.js'
Toast('Wizard Rose added to cart')
अगर डेवलपर को सूचना दिखने के बाद, कुछ काम करना है, तो वह एसिंक और await का इस्तेमाल कर सकता है.
import Toast from './toast.js'
async function example() {
await Toast('Wizard Rose added to cart')
console.log('toast finished')
}
नतीजा
अब आपको पता चल गया है कि मैंने यह कैसे किया. अब आप कैसे करेंगे‽ 🙂
आइए, हम अपने तरीकों में विविधता लाएं और वेब पर काॅन्टेंट पोस्ट करने के सभी तरीके जानें. डेमो बनाएं और मुझे ट्वीट करें. इसके बाद, मैं इसे यहां कम्यूनिटी रीमिक्स सेक्शन में जोड़ दूंगा!
कम्यूनिटी रीमिक्स
- एचटीएमएल/सीएसएस/जेएस के साथ @_developit: डेमो और कोड
- HTML/CSS/JS का इस्तेमाल करके Joost van der Schee: डेमो और कोड