Notifier.svelte 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. <script>
  2. import { dismiss, notices } from '$lib/notifier.svelte.js';
  3. </script>
  4. {#if notices.length}
  5. <div class="notifier" aria-live="polite" aria-relevant="additions">
  6. {#each notices as notice (notice.id)}
  7. <div class="toast toast-{notice.kind}" role="status">
  8. <p class="message">{notice.message}</p>
  9. <button
  10. type="button"
  11. class="close"
  12. aria-label="Dismiss"
  13. onclick={() => dismiss(notice.id)}
  14. >
  15. ×
  16. </button>
  17. </div>
  18. {/each}
  19. </div>
  20. {/if}
  21. <style>
  22. .notifier {
  23. position: fixed;
  24. z-index: 1000;
  25. top: 16px;
  26. left: 50%;
  27. transform: translateX(-50%);
  28. width: min(360px, calc(100vw - 24px));
  29. display: grid;
  30. gap: 8px;
  31. pointer-events: none;
  32. }
  33. .toast {
  34. pointer-events: auto;
  35. display: grid;
  36. grid-template-columns: 1fr auto;
  37. align-items: start;
  38. gap: 10px;
  39. padding: 12px 12px 12px 14px;
  40. border-radius: var(--radius);
  41. border: 1px solid var(--border);
  42. background: var(--surface-2);
  43. box-shadow: 0 12px 32px color-mix(in srgb, black 45%, transparent);
  44. animation: toast-in 160ms ease-out;
  45. }
  46. .toast-ok {
  47. border-color: color-mix(in srgb, var(--ok) 45%, var(--border));
  48. background: color-mix(in srgb, var(--ok) 12%, var(--surface-2));
  49. }
  50. .toast-fail {
  51. border-color: color-mix(in srgb, var(--fail) 45%, var(--border));
  52. background: color-mix(in srgb, var(--fail) 12%, var(--surface-2));
  53. }
  54. .toast-warn {
  55. border-color: color-mix(in srgb, var(--warn) 45%, var(--border));
  56. background: color-mix(in srgb, var(--warn) 12%, var(--surface-2));
  57. }
  58. .toast-info {
  59. border-color: color-mix(in srgb, var(--ember) 40%, var(--border));
  60. background: color-mix(in srgb, var(--ember) 10%, var(--surface-2));
  61. }
  62. .message {
  63. margin: 0;
  64. font-size: 14px;
  65. font-weight: 650;
  66. line-height: 1.35;
  67. color: var(--bone);
  68. }
  69. .toast-ok .message {
  70. color: var(--ok);
  71. }
  72. .toast-fail .message {
  73. color: var(--fail);
  74. }
  75. .toast-warn .message {
  76. color: var(--warn);
  77. }
  78. .toast-info .message {
  79. color: var(--heat);
  80. }
  81. .close {
  82. margin: -4px -4px 0 0;
  83. padding: 0 6px;
  84. border: 0;
  85. border-radius: 6px;
  86. background: transparent;
  87. color: var(--text-muted);
  88. font-size: 18px;
  89. line-height: 1.2;
  90. cursor: pointer;
  91. }
  92. .close:hover,
  93. .close:focus-visible {
  94. color: var(--bone);
  95. background: var(--plate);
  96. }
  97. @keyframes toast-in {
  98. from {
  99. opacity: 0;
  100. transform: translateY(-6px);
  101. }
  102. to {
  103. opacity: 1;
  104. transform: translateY(0);
  105. }
  106. }
  107. </style>