<script setup lang="ts">
import {
  CheckCircleIcon,
  InformationCircleIcon,
  XCircleIcon,
  XMarkIcon,
} from '@heroicons/vue/24/outline';
import type {ToastType} from './useToast';
import {useToastStore} from './useToast';

const toastStore = useToastStore();

const icons = {
  success: CheckCircleIcon,
  error: XCircleIcon,
  info: InformationCircleIcon,
} as const;

const accent = (type: ToastType) => `accent-${type}`;
</script>

<template>
  <div class="toast-container">
    <TransitionGroup name="toast">
      <div v-for="toast in toastStore.toasts" :key="toast.id" class="toast" :class="accent(toast.type)">
        <component :is="icons[toast.type]" class="icon" />
        <div class="body">
          <span v-if="toast.title" class="title">{{ toast.title }}</span>
          <span class="message">{{ toast.message }}</span>
        </div>
        <button class="btn-icon close" @click="toastStore.dismiss(toast.id)">
          <XMarkIcon />
        </button>
      </div>
    </TransitionGroup>
  </div>
</template>

<style scoped>
@reference "@/style.css";

div.toast-container {
  @apply fixed top-4 right-4 z-50 flex flex-col gap-2 w-80 max-w-[calc(100vw-2rem)];
}

div.toast {
  @apply flex items-start gap-2 p-3 rounded bg-slate-700 border-l-4 shadow-lg;

  &.accent-success {
    @apply border-emerald-500;
    > .icon { @apply text-emerald-500; }
  }
  &.accent-error {
    @apply border-amber-700;
    > .icon { @apply text-amber-700; }
  }
  &.accent-info {
    @apply border-sky-600;
    > .icon { @apply text-sky-600; }
  }

  > .icon {
    @apply w-6 h-6 shrink-0;
  }

  > .body {
    @apply flex flex-col grow min-w-0;

    > .title {
      @apply font-semibold;
    }
    > .message {
      @apply break-words;
    }
  }

  > .close {
    @apply shrink-0;
  }
}

.toast-enter-active,
.toast-leave-active,
.toast-move {
  @apply transition-all duration-300;
}
.toast-enter-from {
  @apply opacity-0 translate-x-8;
}
.toast-leave-to {
  @apply opacity-0 -translate-y-8;
}
.toast-leave-active {
  @apply absolute w-full;
}
</style>
