Una descripción general fundamental de cómo compilar un componente de aviso adaptable y accesible
En esta publicación, quiero compartir ideas sobre cómo crear un componente de aviso. Prueba la demostración.
Si prefieres ver un video, aquí tienes una versión de YouTube de esta publicación:
Descripción general
Los avisos son mensajes cortos no interactivos, pasivos y asíncronos para los usuarios. Suelen usarse como patrón de comentarios de la interfaz para informar al usuario sobre los resultados de una acción.
Interacciones
Los avisos son, a diferencia de las notificaciones, las alertas y mensajes porque no son interactivos; no están diseñados para descartarse o persistir. Las notificaciones son para información más importante, mensajes síncronos que requiere interacción o mensajes a nivel del sistema (a diferencia del nivel de la página). Los avisos son más pasivos que otras estrategias de avisos.
Marca
El
<output>
es una buena opción para el aviso porque se anuncia
lectores. El HTML correcto brinda una base segura para que podamos mejorar con JavaScript y
CSS, y habrá mucho JavaScript.
Un brindis
<output class="gui-toast">Item added to cart</output>
Puede ser más
inclusivos
Para ello, agrega role="status"
. Esto proporciona un
alternativa si el navegador no le da a los elementos <output>
el elemento
puesto
según la especificación.
<output role="status" class="gui-toast">Item added to cart</output>
Un contenedor de avisos
Se puede mostrar más de un aviso a la vez. Para organizar varias los avisos, se usa un contenedor. Este contenedor también controla la posición de la avisos en la pantalla.
<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>
Diseños
Elegí fijar avisos
inset-block-end
del viewport y, si se agregan más avisos, se apilan desde el borde de la pantalla.
Contenedor de la GUI
El contenedor de avisos hace todo el trabajo de diseño para presentar avisos. Es
fixed
al viewport y usa la propiedad lógica
inset
para especificar
bordes para fijar, más un poco de padding
del mismo borde de block-end
.
.gui-toast-group {
position: fixed;
z-index: 1;
inset-block-end: 0;
inset-inline: 0;
padding-block-end: 5vh;
}
Además de posicionarse dentro del viewport, el contenedor del aviso es un
de cuadrícula que puede alinear y distribuir avisos. Los elementos se centran como
Grupo con justify-content
y centrado individualmente con justify-items
Agrega un poco de gap
para que los avisos no se toquen.
.gui-toast-group {
display: grid;
justify-items: center;
justify-content: center;
gap: 1vh;
}
Aviso de GUI
Un aviso individual tiene padding
, algunas esquinas más suaves,
border-radius
,
y una función min()
para
ayudan con el tamaño de dispositivos móviles y computadoras de escritorio. El tamaño responsivo del siguiente CSS
evita que los avisos aumenten su ancho más del 90% de la viewport o
25ch
.gui-toast {
max-inline-size: min(25ch, 90vw);
padding-block: .5ch;
padding-inline: 1ch;
border-radius: 3px;
font-size: 1rem;
}
Estilos
Con el diseño y el posicionamiento establecidos, agrega CSS que ayude a adaptarse al usuario la configuración y las interacciones.
Contenedor de aviso
Los avisos no son interactivos. Tocar o deslizar el dedo sobre ellos no hace nada, pero actualmente consumen eventos de puntero. Evita que los avisos roben clics con el siguiente CSS.
.gui-toast-group {
pointer-events: none;
}
Aviso de GUI
Brinda a los avisos un tema adaptable oscuro o claro con propiedades personalizadas, HSL y un consulta de medios de preferencia.
.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%;
}
}
Animación
Se debe presentar un nuevo aviso con una animación a medida que ingresa a la pantalla.
Para adaptarse al movimiento reducido, se deben establecer los valores de translate
en 0
predeterminada, pero actualizar el valor de movimiento a una longitud en un medio con preferencia de movimiento
consulta . Todos ven algo de animación, pero solo algunos usuarios tienen el viaje de aviso.
a distancia.
Estos son los fotogramas clave utilizados para la animación de aviso. CSS controlará el la entrada, la espera y la salida del aviso, todo en una animación.
@keyframes fade-in {
from { opacity: 0 }
}
@keyframes fade-out {
to { opacity: 0 }
}
@keyframes slide-in {
from { transform: translateY(var(--_travel-distance, 10px)) }
}
Luego, el elemento de aviso configura las variables y organiza los fotogramas clave.
.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
Como los estilos y el lector de pantalla están listos para usar con el formato HTML, se necesita JavaScript para organizar la creación, adición y destrucción de avisos basados en eventos. La experiencia del desarrollador con el componente de aviso debe ser mínima y para empezar, como se muestra a continuación:
import Toast from './toast.js'
Toast('My first toast')
Crea el grupo de avisos y los avisos
Cuando el módulo de aviso se carga desde JavaScript, debe crear un contenedor de aviso.
y agregarla a la página. Elegí agregar el elemento antes de body
, esto hará
Es poco probable que haya problemas de apilado de z-index
, ya que el contenedor se encuentra por encima del contenedor para
todos los elementos del cuerpo.
const init = () => {
const node = document.createElement('section')
node.classList.add('gui-toast-group')
document.firstElementChild.insertBefore(node, document.body)
return node
}
La función init()
se llama de forma interna al módulo y se guarda el elemento.
como Toaster
:
const Toaster = init()
La creación de elementos HTML de aviso se realiza con la función createToast()
. El
requiere texto para el aviso, crea un elemento <output>
y adorna
con algunas clases y atributos, configura el texto y muestra el nodo.
const createToast = text => {
const node = document.createElement('output')
node.innerText = text
node.classList.add('gui-toast')
node.setAttribute('role', 'status')
return node
}
Cómo administrar uno o más avisos
JavaScript ahora agrega un contenedor al documento para incluir avisos
Listo para agregar avisos creados. La función addToast()
organiza el manejo de uno
o muchos avisos. Primero verificando la cantidad de avisos y si el movimiento está bien,
luego, usar esta información para agregar el aviso
para que los demás avisos "hagan espacio" por el nuevo aviso.
const addToast = toast => {
const { matches:motionOK } = window.matchMedia(
'(prefers-reduced-motion: no-preference)'
)
Toaster.children.length && motionOK
? flipToast(toast)
: Toaster.appendChild(toast)
}
Cuando se agrega el primer aviso, Toaster.appendChild(toast)
lo hace a la
página que activa las animaciones de CSS: animar para entrar, esperar 3s
, animar fuera.
Se llama a flipToast()
cuando hay avisos existentes, mediante el uso de una técnica.
llamado FLIP por Paul
Lewis. La idea es calcular la diferencia
en posiciones del contenedor, antes y después de que se haya agregado el nuevo aviso.
Piensa en esto como marcar
dónde está la tostadora, dónde estará
animando desde donde estaba hasta donde está.
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 cuadrícula de CSS levanta el diseño. Cuando se agrega un nuevo aviso, la cuadrícula lo coloca al comienzo y los separa a los demás. Mientras tanto, una página web animación es que se usa para animar el contenedor desde la posición anterior.
Juntar todo el código JavaScript
Cuando se llama a Toast('my first toast')
, se crea un aviso que se agrega a la página.
(quizás incluso el contenedor esté animado para adaptarse al nuevo aviso), una
promesa
y el aviso que se creó se
mirado durante
Finalización de animación CSS (las tres animaciones de fotogramas clave) para la resolución de promesa.
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()
})
}
Me pareció que la parte confusa de este código está en la función Promise.allSettled()
.
y toast.getAnimations()
. Ya que usé varias animaciones de fotogramas clave
para el brindis, para saber con seguridad que todos terminaron, cada uno debe estar
solicitadas desde JavaScript y cada uno de sus
finished
y promesas observadas para su finalización.
allSettled
¿eso funciona para nosotros?
Se resuelve como completa una vez que
se completaron. Usar await Promise.allSettled()
significa que la siguiente línea de
código puede quitar con confianza el elemento y suponer que el aviso ha completado su
en el ciclo de vida del AA. Por último, llamar a resolve()
cumple con la promesa de aviso de alto nivel, por lo que
los desarrolladores pueden limpiar o hacer otro trabajo una vez que se haya mostrado el aviso.
export default Toast
Por último, la función Toast
se exporta del módulo para otras secuencias de comandos
importar y usar.
Cómo usar el componente de aviso
El uso del aviso, o de la experiencia del desarrollador, se hace importando
función Toast
y llamarla con una cadena de mensaje.
import Toast from './toast.js'
Toast('Wizard Rose added to cart')
Si el desarrollador quiere realizar una limpieza o cualquier otro elemento, luego de que se haya enviado el aviso pueden usar las funciones asíncronas esperar.
import Toast from './toast.js'
async function example() {
await Toast('Wizard Rose added to cart')
console.log('toast finished')
}
Conclusión
Ahora que sabes cómo lo hice, ¿cómo lo harías?‽ 🙂
Diversifiquemos nuestros enfoques y aprendamos todas las formas de desarrollar en la Web. Crear una demostración, twittearme vínculos y la agregaré. a la sección de remixes de la comunidad.
Remixes de la comunidad
- @_developit con HTML/CSS/JS: demostración y código
- Joost van der Schee con HTML/CSS/JS: demostración y código