ConfirmDialog.svelte
1 <script lang="ts"> 2 import Button from './Button.svelte'; 3 import Modal from './Modal.svelte'; 4 5 interface Props { 6 open: boolean; 7 title?: string; 8 message: string; 9 confirmText?: string; 10 cancelText?: string; 11 variant?: 'danger' | 'warning' | 'info'; 12 onconfirm?: () => void; 13 oncancel?: () => void; 14 } 15 16 let { 17 open = $bindable(), 18 title = 'Confirm', 19 message, 20 confirmText = 'Confirm', 21 cancelText = 'Cancel', 22 variant = 'info', 23 onconfirm, 24 oncancel, 25 }: Props = $props(); 26 27 function handleConfirm() { 28 open = false; 29 onconfirm?.(); 30 } 31 32 function handleCancel() { 33 open = false; 34 oncancel?.(); 35 } 36 37 const iconPaths = { 38 danger: 'M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z', 39 warning: 'M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z', 40 info: 'M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z', 41 }; 42 43 const iconColors = { 44 danger: 'text-status-error', 45 warning: 'text-status-warning', 46 info: 'text-phosphor', 47 }; 48 </script> 49 50 <Modal bind:open {title} onclose={handleCancel}> 51 <div class="flex items-start gap-4"> 52 <div class="flex-shrink-0 {iconColors[variant]}"> 53 <svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24"> 54 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d={iconPaths[variant]} /> 55 </svg> 56 </div> 57 <p class="text-text-secondary text-sm">{message}</p> 58 </div> 59 60 {#snippet footer()} 61 <Button variant="ghost" onclick={handleCancel}> 62 {cancelText} 63 </Button> 64 <Button variant={variant === 'danger' ? 'danger' : 'primary'} onclick={handleConfirm}> 65 {confirmText} 66 </Button> 67 {/snippet} 68 </Modal>