Hola a todos, dicen por ahí que es bueno escribir artículos técnicos porque así reafirmas lo aprendido, pues, en esta ocasión, voy a seguir con Vue3 y hoy particularmente con TailwindCSS y MerakiUI, creando un sencillo sistema de notificaciones para tu app.
TailwindCSS
Es una potente librería de utilidades para CSS, te ahorrará mucho tiempo a la hora de escribir tus estilos, aunque, NO reemplaza al CSS puro.
MerakiUI
Una librería de componentes responsivos y limpios, basada en Flexbox y Grid, completamente responsiva.
Motivación
En mi tiempo libre por las noches, he estado ¨rehaciendo¨ una app que tengo online y en producción desde principios de año, he querido hacerla lo mas ligera posible y por eso la estoy rediseñando y reescribiendo desde 0 con Vue3 y TailwindCSS, actualmente esta con Vue2 y Vuetify + otras deps, y no por hecharle tierra a Vuetify, pero está bastante pesadita.
Notificar o no notificar?
Una de las cosas mas importantes en tu app y UX es la interacción con el usuario, las buenas prácticas dictan de informar al usuario qué esta pasando con sus acciones, si se completaron o si terminaron en un error, aquí entran las alertas, hay N+1 librerías open source que te permiten gestionarlas, pero quiero depender lo menos de 3ros, asi que me puse a intentar construir mi propio sistema.
Manos a la obra
Lo primero que tuve en mente fue armar un composable que gestionara todo lo de las alertas
Archivo: useToast.ts
import { ref } from 'vue';
// Este arreglo contendrá las notificaciones
const messages = ref<ToastOptions[]>([]);
const useToast = () => {
// Empuja una nueva alerta al arreglo
const addAlert = (options: ToastOptions) => {
messages.value.push({
id: options.id,
message: options.message,
type: options.type || 'success',
});
// A los 3 segundos, que se disipe.
setTimeout(() => {
messages.value.length > 0 ? removeAlert(messages.value.findIndex((item) => item.id === options.id)) : null;
}, 3000);
};
// Remueve el elemento del arreglo de mensajes
const removeAlert = (index: number) => {
if (index > -1) {
messages.value.splice(index, 1);
}
};
return {
messages,
addAlert,
removeAlert,
};
};
export default useToast;
De esa forma podemos traernos useToast()
a cualquier parte de nuestra app.
Continuamos con el componente:
Archivo: alert.vue
<template>
<div
v-for="alert, index in messages"
:key="index"
ref="item"
class="absolute right-5 top-5 flex w-full max-w-sm mx-auto overflow-hidden bg-white rounded-lg shadow-lg dark:bg-gray-800 animate-fadeIn"
>
<div
:class="`flex items-center justify-center w-12 ${alert.type === 'error' ? 'bg-red-500' : 'bg-green-500'}`"
>
<svg
class="w-6 h-6 text-white fill-current"
viewBox="0 0 40 40"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M20 3.36667C10.8167 3.36667 3.3667 10.8167 3.3667 20C3.3667 29.1833 10.8167 36.6333 20 36.6333C29.1834 36.6333 36.6334 29.1833 36.6334 20C36.6334 10.8167 29.1834 3.36667 20 3.36667ZM19.1334 33.3333V22.9H13.3334L21.6667 6.66667V17.1H27.25L19.1334 33.3333Z"
/>
</svg>
</div>
<div class="px-4 py-2 -mx-3">
<div class="mx-3 w-11/12">
<span
:class="`font-semibold ${alert.type === 'error' ? 'text-red-500' : 'text-green-500'} dark:text-red-400`"
>{{ alert.type === 'error' ? 'Error' : 'Completado' }}</span>
<p class="text-sm text-gray-600 dark:text-gray-200 w-full">{{ alert.message }}</p>
</div>
</div>
</div>
</template>
<script lang="ts">
import { defineComponent, PropType } from "vue"; export default defineComponent({
props: {
messages: {
type: [] as PropType<ToastOptions[] | null>,
default: []
}
},
})
</script>
El componente recibirá como props el arreglo de mensajes que habíamos definido en useToast()
, ya luego solo queda usarlo en App.vue
Archivo: App.vue
<template>
<Alert :messages="messages" />
<default-vue />
</template>
<script lang="ts">
import DefaultVue from "./layouts/Default.vue";
import Alert from "./components/common/alert.vue"
import { defineComponent } from "vue";
import useToast from "./utils/useToast";
export default defineComponent({
components: {
DefaultVue, Alert
},
name: "App",
setup() {
const { messages } = useToast()
return {
messages,
}
}
})
</script>
Para llamar a la alerta desde cualquier lado:
import useToast from './useToast';
const { addAlert } = useToast();
addAlert({id: generateGuid(),
message: error.message,
type: 'error',
});
Y hasta aquí este sencillo artículo, espero les haya servido de algo
¿Para mejorarlo?:
- Hacer que una alerta este por debajo de la otra y se acumulen
- Adicionar un boton de cerrar la alerta.
Cualquier comentario y/o crítica es bienvenida!
Top comments (0)