Banner.svelte 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. <script lang="ts">
  2. import type { Banner } from '$lib/types';
  3. import { onMount, createEventDispatcher } from 'svelte';
  4. import { fade } from 'svelte/transition';
  5. import DOMPurify from 'dompurify';
  6. import { marked } from 'marked';
  7. const dispatch = createEventDispatcher();
  8. export let banner: Banner = {
  9. id: '',
  10. type: 'info',
  11. title: '',
  12. content: '',
  13. url: '',
  14. dismissable: true,
  15. timestamp: Math.floor(Date.now() / 1000)
  16. };
  17. export let className = 'mx-4';
  18. export let dismissed = false;
  19. let mounted = false;
  20. const classNames: Record<string, string> = {
  21. info: 'bg-blue-500/20 text-blue-700 dark:text-blue-200 ',
  22. success: 'bg-green-500/20 text-green-700 dark:text-green-200',
  23. warning: 'bg-yellow-500/20 text-yellow-700 dark:text-yellow-200',
  24. error: 'bg-red-500/20 text-red-700 dark:text-red-200'
  25. };
  26. const dismiss = (id) => {
  27. dismissed = true;
  28. dispatch('dismiss', id);
  29. };
  30. onMount(() => {
  31. mounted = true;
  32. });
  33. </script>
  34. {#if !dismissed}
  35. {#if mounted}
  36. <div
  37. class="{className} top-0 left-0 right-0 p-2 px-3 flex justify-center items-center relative rounded-xl border border-gray-100 dark:border-gray-850 text-gray-800 dark:text-gary-100 bg-white dark:bg-gray-900 backdrop-blur-xl z-30"
  38. transition:fade={{ delay: 100, duration: 300 }}
  39. >
  40. <div class=" flex flex-col md:flex-row md:items-center flex-1 text-sm w-fit gap-1.5">
  41. <div class="flex justify-between self-start">
  42. <div
  43. class=" text-xs font-bold {classNames[banner.type] ??
  44. classNames['info']} w-fit px-2 rounded-sm uppercase line-clamp-1 mr-0.5"
  45. >
  46. {banner.type}
  47. </div>
  48. {#if banner.url}
  49. <div class="flex md:hidden group w-fit md:items-center">
  50. <a
  51. class="text-gray-700 dark:text-white text-xs font-semibold underline"
  52. href="/assets/files/whitepaper.pdf"
  53. target="_blank">Learn More</a
  54. >
  55. <div
  56. class=" ml-1 text-gray-400 group-hover:text-gray-600 dark:group-hover:text-white"
  57. >
  58. <!-- -->
  59. <svg
  60. xmlns="http://www.w3.org/2000/svg"
  61. viewBox="0 0 16 16"
  62. fill="currentColor"
  63. class="w-4 h-4"
  64. >
  65. <path
  66. fill-rule="evenodd"
  67. d="M4.22 11.78a.75.75 0 0 1 0-1.06L9.44 5.5H5.75a.75.75 0 0 1 0-1.5h5.5a.75.75 0 0 1 .75.75v5.5a.75.75 0 0 1-1.5 0V6.56l-5.22 5.22a.75.75 0 0 1-1.06 0Z"
  68. clip-rule="evenodd"
  69. />
  70. </svg>
  71. </div>
  72. </div>
  73. {/if}
  74. </div>
  75. <div class="flex-1 text-xs text-gray-700 dark:text-white">
  76. {@html marked.parse(DOMPurify.sanitize(banner.content))}
  77. </div>
  78. </div>
  79. {#if banner.url}
  80. <div class="hidden md:flex group w-fit md:items-center">
  81. <a
  82. class="text-gray-700 dark:text-white text-xs font-semibold underline"
  83. href="/"
  84. target="_blank">Learn More</a
  85. >
  86. <div class=" ml-1 text-gray-400 group-hover:text-gray-600 dark:group-hover:text-white">
  87. <!-- -->
  88. <svg
  89. xmlns="http://www.w3.org/2000/svg"
  90. viewBox="0 0 16 16"
  91. fill="currentColor"
  92. class="size-4"
  93. >
  94. <path
  95. fill-rule="evenodd"
  96. d="M4.22 11.78a.75.75 0 0 1 0-1.06L9.44 5.5H5.75a.75.75 0 0 1 0-1.5h5.5a.75.75 0 0 1 .75.75v5.5a.75.75 0 0 1-1.5 0V6.56l-5.22 5.22a.75.75 0 0 1-1.06 0Z"
  97. clip-rule="evenodd"
  98. />
  99. </svg>
  100. </div>
  101. </div>
  102. {/if}
  103. <div class="flex self-start">
  104. {#if banner.dismissible}
  105. <button
  106. on:click={() => {
  107. dismiss(banner.id);
  108. }}
  109. class=" -mt-1 -mb-2 -translate-y-[1px] ml-1.5 mr-1 text-gray-400 dark:hover:text-white"
  110. >&times;</button
  111. >
  112. {/if}
  113. </div>
  114. </div>
  115. {/if}
  116. {/if}