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.

277 lines
6.2 KiB

1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
  1. <script lang="ts">
  2. import { getModalContext, type ModalSelection } from "$lib/contexts/ModalContext.svelte";
  3. export let show: boolean = false;
  4. export let titleText: string = "Edit Form";
  5. export let submitText: string = "Submit";
  6. export let cancelLabel: string = "Cancel";
  7. export let wide: boolean = false;
  8. export let error: string | null = null;
  9. export let closable: boolean = false;
  10. export let disabled: boolean = false;
  11. export let nobody: boolean = false;
  12. export let closeInstruction: ModalSelection = { kind: "closed" };
  13. const { modal } = getModalContext();
  14. function onClose() {
  15. modal.set(closeInstruction);
  16. }
  17. function onKeyPress(e: KeyboardEvent) {
  18. if (e.key.toLocaleLowerCase() === "escape") {
  19. onClose();
  20. }
  21. }
  22. </script>
  23. {#if show}
  24. <!-- svelte-ignore a11y-no-noninteractive-element-interactions -->
  25. <div role="dialog" class="modal-background" on:keypress={onKeyPress}>
  26. <div class="modal" class:wide class:nobody>
  27. <div class="header" class:nobody>
  28. <div class="title" class:noclose={!closable}>{titleText}</div>
  29. {#if (closable)}
  30. <div class="x">
  31. <!-- svelte-ignore a11y-click-events-have-key-events -->
  32. <!-- svelte-ignore a11y-no-static-element-interactions -->
  33. <div class="button" on:click={onClose} class:nobody>&times;</div>
  34. </div>
  35. {/if}
  36. </div>
  37. {#if (error != null)}
  38. <div class="error">{error}</div>
  39. {/if}
  40. <div class="body" class:nobody>
  41. <slot></slot>
  42. </div>
  43. <div class="button-row" class:nobody>
  44. <button disabled={disabled} type="submit">{submitText}</button>
  45. <slot name="secondary-button-1"></slot>
  46. <slot name="secondary-button-2"></slot>
  47. <button disabled={!closable} on:click|preventDefault={onClose}>{cancelLabel}</button>
  48. </div>
  49. </div>
  50. </div>
  51. {/if}
  52. <style lang="scss">
  53. @import "$lib/css/colors.sass";
  54. div.modal-background {
  55. position: fixed;
  56. top: 0;
  57. left: 0;
  58. width: 100%;
  59. height: 100%;
  60. background: rgba(0,0,0,0.5);
  61. }
  62. div.modal {
  63. position: absolute;
  64. left: 50%;
  65. top: 50%;
  66. width: calc(100vw - 4em);
  67. max-width: 40ch;
  68. max-height: calc(100vh - 4em);
  69. overflow: auto;
  70. transform: translate(-50%,-50%);
  71. border-radius: 0.5em;
  72. box-shadow: 1px 1px 1px $color-main0;
  73. background: $color-main1;
  74. &.nobody {
  75. background: none;
  76. }
  77. &.fullheight {
  78. min-height: 100%
  79. }
  80. }
  81. div.modal.wide {
  82. max-width: 80ch;
  83. }
  84. div.header {
  85. padding: 1em;
  86. padding-bottom: 0;
  87. }
  88. div.error {
  89. margin: 0.5em;
  90. padding: 0.5em;
  91. border: 1px solid rgb(204, 65, 65);
  92. border-radius: 0.2em;
  93. background-color: rgb(133, 39, 39);
  94. color: rgb(211, 141, 141);
  95. animation: fadein 0.5s;
  96. }
  97. div.body {
  98. padding: 1em 0;
  99. margin-top: 0;
  100. padding-top: 0;
  101. display: flex;
  102. flex-direction: row;
  103. @media screen and (max-width: 749px) {
  104. display: block;
  105. }
  106. }
  107. div.title {
  108. color: $color-main9;
  109. line-height: 1em;
  110. }
  111. div.x {
  112. position: relative;
  113. line-height: 1em;
  114. top: -1em;
  115. text-align: right;
  116. }
  117. div.x div.button {
  118. color: $color-main9;
  119. display: inline-block;
  120. padding: 0em 0.5ch 0.1em 0.5ch;
  121. line-height: 1em;
  122. user-select: none;
  123. cursor: pointer;
  124. }
  125. div.x div.button:hover {
  126. color: $color-main9;
  127. }
  128. div.button-row {
  129. display: flex;
  130. flex-direction: row;
  131. border-top: 0.5px solid #000;
  132. :global(button) {
  133. display: inline-block;
  134. padding: 0.25em 1ch;
  135. font-size: 1.25em;
  136. background: none;
  137. border: none;
  138. color: $color-main9;
  139. border-left : 0.5px solid #111;
  140. cursor: pointer;
  141. }
  142. :global(button:first-of-type) {
  143. margin-left: auto;
  144. }
  145. :global(button:hover) {
  146. background-color: #111;
  147. }
  148. :global(button:disabled) {
  149. color: #444;
  150. }
  151. &.nobody {
  152. display: none;
  153. }
  154. }
  155. div.modal :global(label) {
  156. padding: 1em 0 0.125em 0.25ch;
  157. font-size: 0.9em;
  158. user-select: none;
  159. -webkit-user-select: none;
  160. -moz-user-select: none;
  161. }
  162. div.modal :global(input:not(.custom)), div.modal :global(select), div.modal :global(textarea) {
  163. width: calc(100% - 2ch);
  164. margin-bottom: 1em;
  165. margin-top: 0.25em;
  166. background: #121418;
  167. color: #789;
  168. border: none;
  169. outline: none;
  170. resize: vertical;
  171. padding: 0.5em 1ch;
  172. }
  173. div.modal :global(select) {
  174. padding-left: 0.5ch;
  175. padding: 0.45em 1ch;
  176. width: 100%;
  177. }
  178. div.modal :global(select option), div.modal :global(select optgroup) {
  179. -webkit-appearance: none;
  180. -moz-appearance: none;
  181. appearance: none;
  182. padding: 0.5em 0;
  183. }
  184. div.modal :global(input:not(.custom))::placeholder {
  185. opacity: 0.5;
  186. }
  187. div.modal :global(select:disabled) {
  188. background: #1a1c1f;
  189. opacity: 1;
  190. color: #789;
  191. }
  192. div.modal :global(input:not(.custom):disabled) {
  193. background: #1a1c1f;
  194. color: #789;
  195. }
  196. div.modal :global(textarea) {
  197. min-height: 6em;
  198. height: 6em;
  199. font-family: inherit;
  200. resize: none0;
  201. }
  202. div.modal :global(textarea:disabled) {
  203. background: #444;
  204. color: #aaa;
  205. }
  206. div.modal :global(input:not(.custom).nolast) {
  207. margin-bottom: 0.5em;
  208. }
  209. div.modal :global(input:not(.custom)[type="checkbox"]) {
  210. width: initial;
  211. display: inline-block;
  212. }
  213. div.modal :global(input:not(.custom)[type="checkbox"] + label) {
  214. width: initial;
  215. display: inline-block;
  216. padding: 0;
  217. margin: 0;
  218. }
  219. div.modal :global(input:not(.custom):focus), div.modal :global(select:focus), div.modal :global(textarea:focus) {
  220. background: #121418;
  221. color: $color-main9;
  222. border: none;
  223. outline: none;
  224. }
  225. div.modal :global(p) {
  226. margin: 0.25em 1ch 1em 1ch;
  227. font-size: 0.9em;
  228. }
  229. div.modal :global(input:not(.custom)::-webkit-outer-spin-button),
  230. div.modal :global(input:not(.custom)::-webkit-inner-spin-button) {
  231. -webkit-appearance: none;
  232. margin: 0;
  233. }
  234. div.modal :global(input:not(.custom)[type=number]) {
  235. appearance: textfield;
  236. -moz-appearance: textfield;
  237. }
  238. @keyframes fadein {
  239. from { opacity: 0; }
  240. to { opacity: 1; }
  241. }
  242. </style>