ConfirmDialog.svelte 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. <script lang="ts">
  2. import { onMount, createEventDispatcher } from 'svelte';
  3. import { fade } from 'svelte/transition';
  4. import { flyAndScale } from '$lib/utils/transitions';
  5. const dispatch = createEventDispatcher();
  6. export let title = 'Confirm your action';
  7. export let message = 'This action cannot be undone. Do you wish to continue?';
  8. export let show = false;
  9. let modalElement = null;
  10. let mounted = false;
  11. const handleKeyDown = (event: KeyboardEvent) => {
  12. if (event.key === 'Escape') {
  13. console.log('Escape');
  14. show = false;
  15. }
  16. };
  17. onMount(() => {
  18. mounted = true;
  19. });
  20. $: if (mounted) {
  21. if (show) {
  22. window.addEventListener('keydown', handleKeyDown);
  23. document.body.style.overflow = 'hidden';
  24. } else {
  25. window.removeEventListener('keydown', handleKeyDown);
  26. document.body.style.overflow = 'unset';
  27. }
  28. }
  29. </script>
  30. {#if show}
  31. <!-- svelte-ignore a11y-click-events-have-key-events -->
  32. <!-- svelte-ignore a11y-no-static-element-interactions -->
  33. <div
  34. bind:this={modalElement}
  35. class=" fixed top-0 right-0 left-0 bottom-0 bg-black/60 w-full min-h-screen h-screen flex justify-center z-[9999] overflow-hidden overscroll-contain"
  36. in:fade={{ duration: 10 }}
  37. on:mousedown={() => {
  38. show = false;
  39. }}
  40. >
  41. <div
  42. class=" m-auto rounded-2xl max-w-full w-[32rem] mx-2 bg-gray-50 dark:bg-gray-950 shadow-3xl border border-gray-850"
  43. in:flyAndScale
  44. on:mousedown={(e) => {
  45. e.stopPropagation();
  46. }}
  47. >
  48. <div class="px-[1.75rem] py-6">
  49. <div class=" text-lg font-semibold dark:text-gray-200 mb-2.5">{title}</div>
  50. <slot>
  51. <div class=" text-sm text-gray-500">
  52. {message}
  53. </div>
  54. </slot>
  55. <div class="mt-6 flex justify-between gap-1.5">
  56. <button
  57. class="bg-gray-100 hover:bg-gray-200 text-gray-800 dark:bg-gray-850 dark:hover:bg-gray-800 dark:text-white font-medium w-full py-2.5 rounded-lg transition"
  58. on:click={() => {
  59. show = false;
  60. }}
  61. type="button"
  62. >
  63. Cancel
  64. </button>
  65. <button
  66. class="bg-gray-900 hover:bg-gray-850 text-gray-100 dark:bg-gray-100 dark:hover:bg-white dark:text-gray-800 font-medium w-full py-2.5 rounded-lg transition"
  67. on:click={() => {
  68. show = false;
  69. dispatch('confirm');
  70. }}
  71. type="button"
  72. >
  73. Confirm
  74. </button>
  75. </div>
  76. </div>
  77. </div>
  78. </div>
  79. {/if}
  80. <style>
  81. .modal-content {
  82. animation: scaleUp 0.1s ease-out forwards;
  83. }
  84. @keyframes scaleUp {
  85. from {
  86. transform: scale(0.985);
  87. opacity: 0;
  88. }
  89. to {
  90. transform: scale(1);
  91. opacity: 1;
  92. }
  93. }
  94. </style>