Files
web/app/components/snackbar/SnackBar.vue
2026-05-15 13:29:39 +07:00

81 lines
1.8 KiB
Vue

<template>
<div
class="snackbar is-flex is-align-items-center is-gap-3 pl-3 pr-1.5 py-2 rounded-md has-background-grey-25 has-text-white"
>
<component
:is="resolvedComponent"
v-bind="vbind"
@close="$emit('close')"
/>
<button
@click="$emit('close')"
class="button is-ghost is-small"
>
<span class="icon">
<Icon
name="material-symbols:close-rounded"
:size="18"
/>
</span>
</button>
</div>
</template>
<script setup>
import { defineAsyncComponent } from "vue";
import { useStore } from "@/stores/index";
const props = defineProps({
component: String,
width: String,
height: String,
vbind: Object,
title: String,
});
const store = useStore();
const componentFiles = import.meta.glob("@/components/**/*.vue");
const resolvedComponent = shallowRef(null);
function loadDynamicComponent() {
if (!props.component) {
resolvedComponent.value = null;
return;
}
const fullPath = `/components/snackbar/${props.component}.vue`;
const componentPath = Object.keys(componentFiles).find((path) => path.endsWith(fullPath));
if (componentPath) {
resolvedComponent.value = defineAsyncComponent(componentFiles[componentPath]);
} else {
console.error(`Không tìm thấy component tại: ${fullPath}`);
resolvedComponent.value = null;
}
}
// Theo dõi sự thay đổi của props.component để load lại nếu cần
watchEffect(() => {
loadDynamicComponent();
});
setTimeout(() => store.commit("snackbar", undefined), 3900);
</script>
<style scoped>
.snackbar {
position: fixed;
z-index: 999;
top: 50px;
left: 0;
right: 0;
margin-inline: auto;
width: fit-content;
max-width: 500px;
}
.button.is-ghost {
color: white;
}
.button.is-ghost:hover,
.button.is-ghost.is-hovered {
color: hsl(0, 0%, 100%, 0.6);
}
</style>