93 lines
		
	
	
		
			No EOL
		
	
	
		
			1.9 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
			
		
		
	
	
			93 lines
		
	
	
		
			No EOL
		
	
	
		
			1.9 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
| <div class="toast-modal {{shown ? 'shown' : ''}}" role="alert" aria-hidden="{{shown}}">
 | |
|   <div class="toast-container">
 | |
|     {{text}}
 | |
|   </div>
 | |
| </div>
 | |
| <style>
 | |
|   .toast-modal {
 | |
|     position: fixed;
 | |
|     bottom: 40px;
 | |
|     left: 0;
 | |
|     right: 0;
 | |
|     opacity: 0;
 | |
|     transition: opacity 333ms linear;
 | |
|     display: flex;
 | |
|     flex-direction: column;
 | |
|     align-items: center;
 | |
|     pointer-events: none;
 | |
|   }
 | |
| 
 | |
|   .toast-container {
 | |
|     max-width: 600px;
 | |
|     max-height: 20vh;
 | |
|     overflow: hidden;
 | |
|     display: flex;
 | |
|     flex-direction: column;
 | |
|     align-items: center;
 | |
|     border: 2px solid var(--toast-border);
 | |
|     background: var(--toast-bg);
 | |
|     border-radius: 5px;
 | |
|     margin: 0 40px;
 | |
|     padding: 20px;
 | |
|     font-size: 1.3em;
 | |
|     color: var(--toast-text);
 | |
|   }
 | |
| 
 | |
|   .toast-modal.shown {
 | |
|     opacity: 0.9;
 | |
|   }
 | |
| 
 | |
|   @media (max-width: 767px) {
 | |
|     .toast-container {
 | |
|       max-width: 80vw;
 | |
|     }
 | |
|   }
 | |
| </style>
 | |
| <script>
 | |
|   import { splice, push } from 'svelte-extras'
 | |
| 
 | |
|   const TIME_TO_SHOW_TOAST = 5000
 | |
|   const DELAY_BETWEEN_TOASTS = 1000
 | |
| 
 | |
|   export default {
 | |
|     oncreate () {
 | |
|       this._queue = Promise.resolve()
 | |
|       this.observe('messages', (messages) => {
 | |
|         if (messages.length) {
 | |
|           this.onNewToast(messages[0])
 | |
|           this.splice('messages', 0, 1)
 | |
|         }
 | |
|       })
 | |
|     },
 | |
|     data: () => ({
 | |
|       text: '',
 | |
|       shown: false,
 | |
|       messages: []
 | |
|     }),
 | |
|     methods: {
 | |
|       push,
 | |
|       splice,
 | |
|       say (text) {
 | |
|         this.push('messages', text)
 | |
|       },
 | |
|       onNewToast (text) {
 | |
|         this._queue = this._queue.then(() => {
 | |
|           this.set({
 | |
|             'text': text,
 | |
|             shown: true
 | |
|           })
 | |
|           return new Promise(resolve => {
 | |
|             setTimeout(resolve, TIME_TO_SHOW_TOAST)
 | |
|           })
 | |
|         }).then(() => {
 | |
|           this.set({
 | |
|             shown: false
 | |
|           })
 | |
|           return new Promise(resolve => {
 | |
|             setTimeout(resolve, DELAY_BETWEEN_TOASTS)
 | |
|           })
 | |
|         })
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| </script> |