popUpBox.astro 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. ---
  2. ---
  3. <div id="popup" class="popup-article">
  4. <div class="popup-article-content">
  5. <h3 id="title" class="popup-article-title"></h3>
  6. <div id="content"></div>
  7. <p class="popup-article-excerpt"></p>
  8. </div>
  9. <script>
  10. import { isOpen, content, type popupContent } from "@utils/popupStore";
  11. import sanitizeHtml from "sanitize-html";
  12. content.subscribe((content: popupContent) => {
  13. document.getElementById("title")!.textContent = content.title;
  14. document.getElementById("content")!.innerHTML = sanitizeHtml(
  15. content.html,
  16. {
  17. allowedClasses: {
  18. "*": ["*"],
  19. },
  20. transformTags: {
  21. header: function (tagName, attribs) {
  22. return {
  23. tagName: "details",
  24. attribs: {
  25. name: "Header",
  26. class: "dropdown-header",
  27. },
  28. };
  29. },
  30. nav: function (tagName, attribs) {
  31. return {
  32. tagName: "details",
  33. attribs: {
  34. name: "Header",
  35. class: "dropdown-header",
  36. },
  37. };
  38. },
  39. footer: function (tagName, attribs) {
  40. return {
  41. tagName: "details",
  42. attribs: {
  43. class: "dropdown-footer",
  44. },
  45. };
  46. },
  47. },
  48. allowedTags: sanitizeHtml.defaults.allowedTags.concat([
  49. "details",
  50. "summary",
  51. ]),
  52. },
  53. );
  54. });
  55. isOpen.subscribe((open: boolean) => {
  56. if (open) {
  57. document.getElementById("popup")!.style.display = "flex";
  58. document.getElementById("popup")?.scroll(0, 0);
  59. } else {
  60. const popup = document.getElementById("popup")!;
  61. popup.style.animation = "collapseToLine 0.5s ease-out";
  62. setTimeout(() => {
  63. popup.style.display = "none";
  64. popup.style.animation = "";
  65. }, 450);
  66. }
  67. });
  68. </script>
  69. </div>
  70. <style>
  71. #popup * {
  72. font-size: 16px;
  73. }
  74. @keyframes expandFromLine {
  75. from {
  76. transform: translateX(-50%) scaleY(0);
  77. opacity: 0;
  78. }
  79. to {
  80. transform: translateX(-50%) scaleY(1);
  81. opacity: 1;
  82. }
  83. }
  84. @keyframes collapseToLine {
  85. from {
  86. transform: translateX(-50%) scaleY(1);
  87. opacity: 1;
  88. }
  89. to {
  90. transform: translateX(-50%) scaleY(0);
  91. opacity: 0;
  92. }
  93. }
  94. @keyframes shimmer {
  95. 0% {
  96. background-position: -1000px 0;
  97. }
  98. 100% {
  99. background-position: 1000px 0;
  100. }
  101. }
  102. .popup-article {
  103. display: none;
  104. position: fixed;
  105. gap: 1rem;
  106. padding: 20px;
  107. left: 50%;
  108. transform: translateX(-50%) scaleY(1);
  109. background: black;
  110. border: 2px solid #ccc;
  111. border-radius: 5px;
  112. transition: border-color 0.3s ease;
  113. animation: expandFromLine 0.5s ease-out;
  114. transform-origin: center;
  115. width: 70%;
  116. max-height: 90%;
  117. margin: 1rem auto;
  118. overflow: scroll;
  119. word-wrap: break-word;
  120. z-index: 100000;
  121. }
  122. .popup-article:hover {
  123. border-color: #999;
  124. }
  125. .popup-article-content {
  126. flex: 1;
  127. display: flex;
  128. flex-direction: column;
  129. gap: 0.5rem;
  130. }
  131. .popup-article-title {
  132. margin: 0 0 10px 0;
  133. font-size: 28px !important;
  134. font-weight: 600;
  135. color: white;
  136. text-overflow: ellipsis;
  137. word-wrap: break-word;
  138. }
  139. .popup-article-excerpt {
  140. margin: 0;
  141. color: white;
  142. font-size: 16px;
  143. line-height: 1.6;
  144. overflow: hidden;
  145. display: -webkit-box;
  146. -webkit-line-clamp: 3;
  147. -webkit-box-orient: vertical;
  148. word-wrap: break-word;
  149. }
  150. .dropdown-header,
  151. .dropdown-footer {
  152. margin: 1rem 0;
  153. border: 1px solid #444;
  154. border-radius: 4px;
  155. background: #1a1a1a;
  156. }
  157. .dropdown-summary {
  158. padding: 0.5rem 1rem;
  159. cursor: pointer;
  160. user-select: none;
  161. font-weight: 600;
  162. color: #888;
  163. list-style: none;
  164. }
  165. .dropdown-summary:hover {
  166. color: #aaa;
  167. background: #222;
  168. }
  169. .dropdown-summary::marker {
  170. content: "";
  171. }
  172. .dropdown-summary::before {
  173. content: "▶ ";
  174. display: inline-block;
  175. transition: transform 0.2s;
  176. }
  177. details[open] .dropdown-summary::before {
  178. transform: rotate(90deg);
  179. }
  180. </style>