Présentation générale de la création d'un composant de toast adaptatif et accessible.
Dans ce post, j'aimerais vous expliquer comment créer un composant toast. Essayez le demo.
<ph type="x-smartling-placeholder">Si vous préférez la vidéo, voici une version YouTube de cet article:
Présentation
Les toasts sont des messages courts non interactifs, passifs et asynchrones pour les utilisateurs. Elles servent généralement de modèle de rétroaction pour informer l'utilisateur sur les résultats d'une action.
Interactions
Les toasts sont différents des notifications, alertes et invites, car elles ne sont pas interactives ; ils ne sont pas destinés à être ignorés ni à persister. Les notifications sont destinées à des informations plus importantes, à la messagerie synchrone nécessite une interaction ou des messages au niveau du système (par opposition au niveau de la page). Les toasts sont plus passifs que les autres stratégies de notification.
Majoration
La
<output>
est un bon choix pour le toast, car il est annoncé à l'écran.
lecteurs. Le code HTML correct constitue une base sûre pour l'amélioration que nous pouvons apporter à l'aide de JavaScript et
et il y aura beaucoup de code JavaScript.
Un toast
<output class="gui-toast">Item added to cart</output>
Il peut s'agir de plus
inclusifs
en ajoutant role="status"
. Vous bénéficiez ainsi d'une
création de remplacement si le navigateur ne donne pas aux éléments <output>
les caractères implicites
rôle
conformément aux spécifications.
<output role="status" class="gui-toast">Item added to cart</output>
Conteneur de toast
Vous pouvez afficher plusieurs toasts à la fois. Pour orchestrer plusieurs des toasts, un conteneur est utilisé. Ce conteneur gère également la position des toasts à l'écran.
<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>
Mises en page
J'ai choisi d'épingler les toasts sur la
inset-block-end
de la fenêtre d'affichage. Si d'autres toasts sont ajoutés, ils s'empilent à partir du bord de l'écran.
Conteneur d'IUG
Le conteneur de toasts effectue toutes les opérations de mise en page pour présenter les toasts. Il est
fixed
à la fenêtre d'affichage et utilise la propriété logique ;
inset
pour spécifier
bords à épingler, plus un peu de padding
à partir du même bord block-end
.
.gui-toast-group {
position: fixed;
z-index: 1;
inset-block-end: 0;
inset-inline: 0;
padding-block-end: 5vh;
}
En plus de se positionner dans la fenêtre d'affichage, le conteneur de toast est
qui peut aligner et distribuer des toasts. Les éléments sont centrés
groupe avec justify-content
et centré individuellement avec justify-items
.
Ajoutez un peu de gap
pour que les toasts ne se touchent pas.
.gui-toast-group {
display: grid;
justify-items: center;
justify-content: center;
gap: 1vh;
}
Toast GUI
Un toast individuel comporte des padding
, des coins plus doux avec
border-radius
,
et une fonction min()
pour
qui permettent de dimensionner
les mobiles et les ordinateurs de bureau. La taille responsive dans le CSS suivant
empêche les toasts de passer sur plus de 90% de la fenêtre d'affichage
25ch
.gui-toast {
max-inline-size: min(25ch, 90vw);
padding-block: .5ch;
padding-inline: 1ch;
border-radius: 3px;
font-size: 1rem;
}
Styles
Une fois la mise en page et le positionnement définis, ajoutez du code CSS qui facilite l'adaptation à l'utilisateur paramètres et interactions.
Conteneur de toast
Les toasts ne sont pas interactifs. Appuyer dessus ou les balayer n'a aucun effet, ils consomment actuellement des événements de pointeur. Empêcher le vol des toasts avec le CSS suivant.
.gui-toast-group {
pointer-events: none;
}
Toast GUI
Donnez aux toasts un thème adaptatif clair ou sombre avec des propriétés personnalisées, un flux HSL requête média de préférence.
.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%;
}
}
Animation
Un nouveau toast doit s'afficher avec une animation lorsqu'il s'affiche à l'écran.
Pour prendre en compte les mouvements réduits, définissez les valeurs translate
sur 0
en
Valeur par défaut, mais mise à jour de la valeur du mouvement sur une durée dans un média de préférence de mouvement
requête . Tout le monde voit de l'animation, mais seuls certains utilisateurs se déplacent avec un toast
une distance.
Voici les images clés utilisées pour l'animation de toast. Le CSS contrôlera le l'entrée, l'attente et la sortie du toast, le tout en une seule animation.
@keyframes fade-in {
from { opacity: 0 }
}
@keyframes fade-out {
to { opacity: 0 }
}
@keyframes slide-in {
from { transform: translateY(var(--_travel-distance, 10px)) }
}
L'élément de toast configure ensuite les variables et orchestre les images clés.
.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
Les styles et le lecteur d'écran étant compatibles avec le code HTML, JavaScript est nécessaire pour d'orchestrer la création, l'ajout et la destruction de toasts en fonction de l'utilisateur événements. L'expérience du développeur avec le composant toast doit être minimale et sont faciles à prendre en main, comme ceci:
import Toast from './toast.js'
Toast('My first toast')
Créer le groupe de toasts et les toasts
Lorsque le module de toast se charge depuis JavaScript, il doit créer un conteneur de toast
et l'ajouter à la page. J'ai choisi d'ajouter l'élément avant body
.
z-index
problèmes d'empilement peu probables, car le conteneur se trouve au-dessus de celui-ci pendant
tous les éléments du corps.
const init = () => {
const node = document.createElement('section')
node.classList.add('gui-toast-group')
document.firstElementChild.insertBefore(node, document.body)
return node
}
La fonction init()
est appelée en interne dans le module, ce qui permet de cacher l'élément.
en tant que Toaster
:
const Toaster = init()
La création d'un élément HTML de toast s'effectue à l'aide de la fonction createToast()
. La
nécessite du texte pour le toast, crée un élément <output>
et décore
avec des classes et des attributs, définit le texte et renvoie le nœud.
const createToast = text => {
const node = document.createElement('output')
node.innerText = text
node.classList.add('gui-toast')
node.setAttribute('role', 'status')
return node
}
Gérer un ou plusieurs toasts
JavaScript ajoute maintenant au document un conteneur pour les toasts,
prêt à ajouter les toasts créés. La fonction addToast()
orchestre le traitement
ou plusieurs toasts. Tout d'abord, vérifiez le nombre de toasts
et s'il est normal de bouger.
puis d'utiliser ces informations pour
ajouter le toast ou pour faire un peu de fantaisie
pour que les autres toasts semblent "faire de la place" pour le nouveau toast.
const addToast = toast => {
const { matches:motionOK } = window.matchMedia(
'(prefers-reduced-motion: no-preference)'
)
Toaster.children.length && motionOK
? flipToast(toast)
: Toaster.appendChild(toast)
}
Lors de l'ajout du premier toast, Toaster.appendChild(toast)
ajoute un toast au
page déclenchant les animations CSS: animer à l'ouverture, attendre 3s
, animer.
flipToast()
est appelé lorsqu'il existe des toasts, à l'aide d'une technique
intitulée FLIP de Paul
Lewis L'idée est de calculer la différence
aux positions du conteneur, avant et après l'ajout du nouveau toast.
C'est comme si vous aviez indiqué
l'emplacement actuel du grille-pain,
s'animer de l'endroit où elle se trouvait jusqu'à l'endroit où elle se trouve.
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',
})
}
La grille CSS se charge de soulever la mise en page. Lorsqu'un toast est ajouté, la grille le place au début et l’espace entre les autres. Parallèlement, un site Web Animation est utilisée pour animer le conteneur depuis l'ancienne position.
Assembler tout le code JavaScript
Lorsque Toast('my first toast')
est appelé, un toast est créé et ajouté à la page.
(peut-être même que le conteneur est animé pour accueillir le nouveau toast), une
promesse
est renvoyé et le toast créé est
a regardé pendant
Finalisation de l'animation CSS (les trois animations d'images clés) pour la résolution de la promesse.
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()
})
}
J'ai senti que la partie de ce code déroutante se trouvait dans la fonction Promise.allSettled()
et toast.getAnimations()
. Comme j'ai utilisé plusieurs animations d'images clés,
d'un toast, de savoir avec certitude qu'elles sont toutes terminées, chacune doit être
demandée à partir de JavaScript,
finished
promesses observées pour être menées à bien.
allSettled
est-ce que cela fonctionne pour nous, et se considère comme complet une fois toutes ses promesses
ont été satisfaites. Si vous utilisez await Promise.allSettled()
, la ligne suivante de
code peut supprimer l'élément en toute confiance et supposer que le toast a terminé
tout au long du cycle de vie. Enfin, l'appel de resolve()
répond à la promesse de toast de haut niveau. Ainsi,
les développeurs peuvent nettoyer ou effectuer
d'autres tâches une fois le toast affiché.
export default Toast
Enfin, la fonction Toast
est exportée à partir du module, afin que les autres scripts soient
à importer et à utiliser.
Utiliser le composant Toast
Pour utiliser le toast, ou l'expérience de développement du toast, vous devez importer
Toast
et en l'appelant avec une chaîne de message.
import Toast from './toast.js'
Toast('Wizard Rose added to cart')
Si le développeur veut effectuer un nettoyage ou autre, une fois le toast terminé s'affichent, ils peuvent utiliser des métriques en attente.
import Toast from './toast.js'
async function example() {
await Toast('Wizard Rose added to cart')
console.log('toast finished')
}
Conclusion
Maintenant que vous savez comment j'ai fait, comment feriez-vous ? 😃
Diversifiez nos approches et découvrons toutes les manières de créer des applications sur le Web. Créer une démonstration, me envoyer des tweets et je l'ajouterai à la section des remix de la communauté ci-dessous.
Remix de la communauté
- @_developit avec HTML/CSS/JS: demo &
- Joost van der Schee avec HTML/CSS/JS: demo &