Files
stream.ui/src/components/dashboard/EmptyState.vue
2026-04-02 15:01:05 +00:00

50 lines
1.5 KiB
Vue

<script setup lang="ts">
interface Props {
title: string;
description?: string;
icon?: string;
actionLabel?: string;
onAction?: () => void;
imageUrl?: string;
}
const props = defineProps<Props>();
</script>
<template>
<div class="empty-state flex flex-col items-center justify-center py-12 px-6 text-center">
<!-- Icon or Image -->
<div v-if="imageUrl" class="mb-6">
<img :src="imageUrl" :alt="title" class="w-64 h-64 object-contain opacity-80" />
</div>
<div
v-else-if="icon"
class="mb-6 w-24 h-24 rounded-full bg-gray-100 flex items-center justify-center"
>
<span :class="[icon, 'w-12 h-12 text-gray-400']" />
</div>
<div v-else class="mb-6 w-24 h-24 rounded-full bg-gray-100 flex items-center justify-center">
<span class="i-heroicons-inbox w-12 h-12 text-gray-400" />
</div>
<!-- Content -->
<h3 class="text-xl font-semibold text-gray-900 mb-2">{{ title }}</h3>
<p v-if="description" class="text-gray-600 mb-6 max-w-md">{{ description }}</p>
<!-- Action Button -->
<button
v-if="actionLabel && onAction"
@click="onAction"
class="btn btn-outline-primary press-animated flex items-center gap-2"
>
<svg xmlns="http://www.w3.org/2000/svg" class="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4" />
</svg>
{{ actionLabel }}
</button>
<!-- Slot for custom actions -->
<slot name="actions" />
</div>
</template>