You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
125 lines
2.3 KiB
125 lines
2.3 KiB
<script setup lang="ts">
|
|
/**
|
|
* ExperimentaStatusMessage Component
|
|
*
|
|
* Status message component with animated icon.
|
|
* Used for success, error, warning, and info states.
|
|
*
|
|
* @example
|
|
* <ExperimentaStatusMessage type="success" title="Erfolg!">
|
|
* Ihre Aktion war erfolgreich.
|
|
* </ExperimentaStatusMessage>
|
|
*
|
|
* <ExperimentaStatusMessage type="error" title="Fehler">
|
|
* Ein Fehler ist aufgetreten.
|
|
* </ExperimentaStatusMessage>
|
|
*/
|
|
|
|
interface Props {
|
|
/** Status type */
|
|
type: 'success' | 'error' | 'warning' | 'info'
|
|
/** Status title */
|
|
title?: string
|
|
/** Custom icon (overrides default) */
|
|
icon?: string
|
|
}
|
|
|
|
const props = withDefaults(defineProps<Props>(), {
|
|
icon: undefined,
|
|
})
|
|
|
|
// Default icons for each type
|
|
const defaultIcons = {
|
|
success: '✓',
|
|
error: '✖',
|
|
warning: '!',
|
|
info: 'i',
|
|
}
|
|
|
|
const displayIcon = computed(() => props.icon || defaultIcons[props.type])
|
|
</script>
|
|
|
|
<template>
|
|
<div class="status-message">
|
|
<!-- Animated Status Icon -->
|
|
<div :class="['status-icon', `status-icon-${type}`]" role="img" :aria-label="`${type} icon`">
|
|
{{ displayIcon }}
|
|
</div>
|
|
|
|
<!-- Title -->
|
|
<h1 v-if="title || $slots.title" class="status-title">
|
|
<slot name="title">{{ title }}</slot>
|
|
</h1>
|
|
|
|
<!-- Message Content -->
|
|
<div class="status-content">
|
|
<slot />
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<style scoped>
|
|
/* Status Message Container */
|
|
.status-message {
|
|
@apply text-center;
|
|
}
|
|
|
|
/* Status Icon */
|
|
.status-icon {
|
|
@apply flex items-center justify-center;
|
|
@apply w-25 h-25 rounded-full;
|
|
@apply text-6xl text-white;
|
|
@apply mb-8 mx-auto;
|
|
@apply animate-pulse;
|
|
}
|
|
|
|
/* Icon Colors by Type */
|
|
.status-icon-success {
|
|
@apply bg-success;
|
|
}
|
|
|
|
.status-icon-error {
|
|
@apply bg-error;
|
|
}
|
|
|
|
.status-icon-warning {
|
|
@apply bg-warning;
|
|
}
|
|
|
|
.status-icon-info {
|
|
@apply bg-info;
|
|
}
|
|
|
|
/* Responsive Icon Size */
|
|
@media (max-width: 480px) {
|
|
.status-icon {
|
|
@apply text-5xl;
|
|
}
|
|
}
|
|
|
|
/* Status Title */
|
|
.status-title {
|
|
@apply text-4xl md:text-3xl sm:text-2xl;
|
|
@apply font-light tracking-tight;
|
|
@apply mb-8;
|
|
@apply text-white;
|
|
}
|
|
|
|
/* Status Content */
|
|
.status-content {
|
|
@apply text-lg md:text-base sm:text-sm;
|
|
@apply text-white/90;
|
|
@apply leading-relaxed;
|
|
}
|
|
|
|
/* Pulse Animation Override (Custom) */
|
|
@keyframes pulse {
|
|
0%,
|
|
100% {
|
|
transform: scale(1);
|
|
}
|
|
50% {
|
|
transform: scale(1.1);
|
|
}
|
|
}
|
|
</style>
|
|
|