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.

222 lines
4.1 KiB

3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
  1. <script lang="ts">
  2. import { createEventDispatcher, onMount } from 'svelte';
  3. import Icon from './Icon.svelte';
  4. export let title: string = "";
  5. export let wide: boolean = false;
  6. export let error: string | null = null;
  7. export let closable: boolean = false;
  8. export let show: boolean = false;
  9. onMount(() => {
  10. const listener = (ev: KeyboardEvent) => {
  11. if ((ev.ctrlKey || ev.altKey) && (ev.key === "Escape" || ev.key.toLowerCase() === "q")) {
  12. dispatch("close");
  13. }
  14. }
  15. document.addEventListener("keyup", listener);
  16. return () => {
  17. document.removeEventListener("keyup", listener);
  18. }
  19. })
  20. const dispatch = createEventDispatcher();
  21. </script>
  22. {#if show}
  23. <div class="modal-background">
  24. <div class="modal" class:wide>
  25. <div class="header">
  26. <div class="title" class:noclose={!closable}>{title}</div>
  27. {#if (closable)}
  28. <div class="x">
  29. <div class="button" on:click={() => dispatch("close")}>
  30. <Icon name="times" />
  31. </div>
  32. </div>
  33. {/if}
  34. </div>
  35. <hr />
  36. {#if (error != null)}
  37. <div class="error">{error}</div>
  38. {/if}
  39. <div class="body">
  40. <slot></slot>
  41. </div>
  42. </div>
  43. </div>
  44. {/if}
  45. <style>
  46. div.modal-background {
  47. position: fixed;
  48. top: 0;
  49. left: 0;
  50. width: 100%;
  51. height: 100%;
  52. background: rgba(0,0,0,0.3);
  53. }
  54. div.modal {
  55. position: absolute;
  56. left: 50%;
  57. top: 50%;
  58. width: calc(100vw - 4em);
  59. max-width: 40ch;
  60. max-height: calc(100vh - 4em);
  61. overflow: auto;
  62. transform: translate(-50%,-50%);
  63. padding: 1em;
  64. border-radius: 0.2em;
  65. background: #333;
  66. }
  67. div.modal.wide {
  68. max-width: 60ch;
  69. }
  70. div.modal :global(hr) {
  71. border: 0.5px solid gray;
  72. margin: 0;
  73. }
  74. div.error {
  75. margin: 0.5em;
  76. padding: 0.5em;
  77. border: 1px solid rgb(204, 65, 65);
  78. border-radius: 0.2em;
  79. background-color: rgb(133, 39, 39);
  80. color: rgb(211, 141, 141);
  81. animation: fadein 0.5s;
  82. }
  83. div.body {
  84. margin: 1em 0.25ch;
  85. }
  86. div.title {
  87. color: #CCC;
  88. line-height: 1em;
  89. }
  90. div.title.noclose {
  91. margin-bottom: 1.2em;
  92. }
  93. div.x {
  94. position: relative;
  95. line-height: 1em;
  96. top: -1em;
  97. text-align: right;
  98. }
  99. div.x div.button {
  100. color: #CCC;
  101. display: inline-block;
  102. padding: 0em 0.5ch 0.1em 0.5ch;
  103. line-height: 1em;
  104. user-select: none;
  105. cursor: pointer;
  106. }
  107. div.x div.button:hover {
  108. color: #FFF;
  109. }
  110. div.modal :global(button) {
  111. display: inline-block;
  112. padding: 0.25em 0.75ch 0.26em 0.75ch;
  113. margin: 0.75em 0.25ch 0.25em 0.25ch;
  114. background: none;
  115. border: none;
  116. border-radius: 0.2em;
  117. color: #CCC;
  118. cursor: pointer;
  119. }
  120. div.modal :global(button:hover), div.modal :global(button:focus) {
  121. background: #222;
  122. color: #FFF;
  123. }
  124. div.modal :global(button:disabled) {
  125. background: #444;
  126. color: #AAA;
  127. }
  128. div.modal :global(label) {
  129. padding: 0 0 0.125em 0.25ch;
  130. font-size: 0.75em;
  131. user-select: none;
  132. -webkit-user-select: none;
  133. -moz-user-select: none;
  134. }
  135. div.modal :global(input), div.modal :global(select), div.modal :global(textarea) {
  136. width: 100%;
  137. margin-bottom: 0.5em;
  138. background: #222;
  139. color: #777;
  140. border: none;
  141. outline: none;
  142. resize: vertical;
  143. }
  144. div.modal :global(select) {
  145. padding-left: 0.5ch;
  146. }
  147. div.modal :global(input)::placeholder {
  148. opacity: 0.5;
  149. }
  150. div.modal :global(select:disabled) {
  151. background: #4a4a4a;
  152. color: #fff;
  153. }
  154. div.modal :global(input:disabled) {
  155. background: #444;
  156. color: #aaa;
  157. }
  158. div.modal :global(textarea) {
  159. min-height: 6em;
  160. height: 6em;
  161. }
  162. div.modal :global(textarea:disabled) {
  163. background: #444;
  164. color: #aaa;
  165. }
  166. div.modal :global(input.nolast) {
  167. margin-bottom: 0.5em;
  168. }
  169. div.modal :global(input[type="checkbox"]) {
  170. width: initial;
  171. display: inline-block;
  172. }
  173. div.modal :global(input[type="checkbox"] + label) {
  174. width: initial;
  175. display: inline-block;
  176. padding: 0;
  177. margin: 0;
  178. }
  179. div.modal :global(input:focus), div.modal :global(select:focus), div.modal :global(textarea:focus) {
  180. background: #111;
  181. color: #CCC;
  182. border: none;
  183. outline: none;
  184. }
  185. div.modal :global(p) {
  186. margin: 0.25em 1ch 1em 1ch;
  187. font-size: 0.9em;
  188. }
  189. @keyframes fadein {
  190. from { opacity: 0; }
  191. to { opacity: 1; }
  192. }
  193. </style>