Files
sigpro-ui/docs/components_old/modal.md
2026-04-06 03:19:15 +02:00

22 KiB

Modal

Modal dialog component for displaying content in an overlay with customizable actions and backdrop.

Tag

Modal

Props

Prop Type Default Description
open boolean | Signal<boolean> false Modal visibility state
title string | VNode | Signal - Modal title text
buttons Array<VNode> | VNode - Action buttons to display (auto-closes on click)
class string '' Additional CSS classes (DaisyUI + Tailwind)
children string | VNode - Modal content

Live Examples

Basic Modal

Live Demo

const BasicDemo = () => {
  const isOpen = $(false);
  
  return Div({ class: 'flex justify-center' }, [
    Button({ 
      class: 'btn btn-primary',
      onclick: () => isOpen(true)
    }, 'Open Modal'),
    Modal({
      open: isOpen,
      title: 'Basic Modal',
      buttons: Button({ onclick: () => isOpen(false) }, 'Close')
    }, [
      Div({ class: 'py-4' }, 'This is a basic modal dialog. You can put any content here.')
    ])
  ]);
};
Mount(BasicDemo, '#demo-basic');

Modal with Actions

Live Demo

const ActionsDemo = () => {
  const isOpen = $(false);
  const confirmed = $(false);
  
  const handleConfirm = () => {
    confirmed(true);
    isOpen(false);
    Toast('Action confirmed!', 'alert-success', 2000);
  };
  
  return Div({ class: 'flex flex-col gap-4 items-center' }, [
    Button({ 
      class: 'btn btn-primary',
      onclick: () => isOpen(true)
    }, 'Confirm Action'),
    () => confirmed() ? Alert({ 
      type: 'success', 
      message: 'You confirmed the action!' 
    }) : null,
    Modal({
      open: isOpen,
      title: 'Confirm Action',
      buttons: [
        Button({ 
          class: 'btn btn-ghost',
          onclick: () => isOpen(false)
        }, 'Cancel'),
        Button({ 
          class: 'btn btn-primary',
          onclick: handleConfirm
        }, 'Confirm')
      ]
    }, [
      Div({ class: 'py-4' }, 'Are you sure you want to perform this action? This cannot be undone.')
    ])
  ]);
};
Mount(ActionsDemo, '#demo-actions');

Form Modal

Live Demo

const FormModal = () => {
  const isOpen = $(false);
  const name = $('');
  const email = $('');
  const submitted = $(false);
  
  const handleSubmit = () => {
    if (name() && email()) {
      submitted(true);
      isOpen(false);
      Toast(`Welcome ${name()}!`, 'alert-success', 2000);
      setTimeout(() => submitted(false), 3000);
    }
  };
  
  return Div({ class: 'flex flex-col gap-4 items-center' }, [
    Button({ 
      class: 'btn btn-primary',
      onclick: () => isOpen(true)
    }, 'Sign Up'),
    () => submitted() ? Alert({ 
      type: 'success', 
      message: 'Account created successfully!' 
    }) : null,
    Modal({
      open: isOpen,
      title: 'Create Account',
      buttons: [
        Button({ 
          class: 'btn btn-ghost',
          onclick: () => isOpen(false)
        }, 'Cancel'),
        Button({ 
          class: 'btn btn-primary',
          onclick: handleSubmit
        }, 'Sign Up')
      ]
    }, [
      Div({ class: 'flex flex-col gap-4 py-2' }, [
        Input({
          label: 'Full Name',
          value: name,
          placeholder: 'Enter your name',
          oninput: (e) => name(e.target.value)
        }),
        Input({
          label: 'Email',
          type: 'email',
          value: email,
          placeholder: 'Enter your email',
          oninput: (e) => email(e.target.value)
        })
      ])
    ])
  ]);
};
Mount(FormModal, '#demo-form');

Confirmation Modal

Live Demo

const ConfirmDemo = () => {
  const isOpen = $(false);
  const items = $([
    { id: 1, name: 'Document A' },
    { id: 2, name: 'Document B' },
    { id: 3, name: 'Document C' }
  ]);
  const pendingDelete = $(null);
  
  const confirmDelete = (item) => {
    pendingDelete(item);
    isOpen(true);
  };
  
  const handleDelete = () => {
    items(items().filter(i => i.id !== pendingDelete().id));
    isOpen(false);
    Toast(`Deleted: ${pendingDelete().name}`, 'alert-info', 2000);
  };
  
  return Div({ class: 'flex flex-col gap-4' }, [
    Div({ class: 'flex flex-col gap-2' }, items().map(item =>
      Div({ class: 'flex justify-between items-center p-3 bg-base-200 rounded-lg' }, [
        Span({}, item.name),
        Button({ 
          class: 'btn btn-xs btn-error',
          onclick: () => confirmDelete(item)
        }, 'Delete')
      ])
    )),
    Modal({
      open: isOpen,
      title: 'Delete Confirmation',
      buttons: [
        Button({ 
          class: 'btn btn-ghost',
          onclick: () => isOpen(false)
        }, 'Cancel'),
        Button({ 
          class: 'btn btn-error',
          onclick: handleDelete
        }, 'Delete')
      ]
    }, [
      Div({ class: 'py-4' }, () => `Are you sure you want to delete "${pendingDelete()?.name}"? This action cannot be undone.`)
    ])
  ]);
};
Mount(ConfirmDemo, '#demo-confirm');

Large Content Modal

Live Demo

const LargeDemo = () => {
  const isOpen = $(false);
  
  return Div({ class: 'flex justify-center' }, [
    Button({ 
      class: 'btn btn-primary',
      onclick: () => isOpen(true)
    }, 'Open Large Modal'),
    Modal({
      open: isOpen,
      title: 'Terms and Conditions',
      buttons: Button({ 
        class: 'btn btn-primary',
        onclick: () => isOpen(false)
      }, 'I Agree')
    }, [
      Div({ class: 'py-4 max-h-96 overflow-y-auto' }, [
        Div({ class: 'space-y-4' }, [
          Div({ class: 'text-sm' }, [
            Div({ class: 'font-bold mb-2' }, '1. Introduction'),
            'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris.'
          ]),
          Div({ class: 'text-sm' }, [
            Div({ class: 'font-bold mb-2' }, '2. User Obligations'),
            'Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident.'
          ]),
          Div({ class: 'text-sm' }, [
            Div({ class: 'font-bold mb-2' }, '3. Privacy Policy'),
            'Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam.'
          ]),
          Div({ class: 'text-sm' }, [
            Div({ class: 'font-bold mb-2' }, '4. Termination'),
            'At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores.'
          ])
        ])
      ])
    ])
  ]);
};
Mount(LargeDemo, '#demo-large');

Multiple Modals

Live Demo

const MultipleDemo = () => {
  const modal1 = $(false);
  const modal2 = $(false);
  const modal3 = $(false);
  
  return Div({ class: 'flex flex-wrap gap-4 justify-center' }, [
    Button({ class: 'btn', onclick: () => modal1(true) }, 'Info Modal'),
    Button({ class: 'btn', onclick: () => modal2(true) }, 'Success Modal'),
    Button({ class: 'btn', onclick: () => modal3(true) }, 'Warning Modal'),
    
    Modal({
      open: modal1,
      title: 'Information',
      buttons: Button({ onclick: () => modal1(false) }, 'OK')
    }, 'This is an informational message.'),
    
    Modal({
      open: modal2,
      title: 'Success!',
      buttons: Button({ onclick: () => modal2(false) }, 'Great!')
    }, 'Your operation was completed successfully.'),
    
    Modal({
      open: modal3,
      title: 'Warning',
      buttons: Button({ onclick: () => modal3(false) }, 'Understood')
    }, 'Please review your input before proceeding.')
  ]);
};
Mount(MultipleDemo, '#demo-multiple');

Custom Styled Modal

Live Demo

const CustomDemo = () => {
  const isOpen = $(false);
  
  return Div({ class: 'flex justify-center' }, [
    Button({ 
      class: 'btn btn-primary',
      onclick: () => isOpen(true)
    }, 'Open Custom Modal'),
    Modal({
      open: isOpen,
      class: 'bg-gradient-to-r from-primary to-secondary text-primary-content'
    }, [
      Div({ class: 'text-center py-8' }, [
        Div({ class: 'text-6xl mb-4' }, '🎉'),
        Div({ class: 'text-2xl font-bold mb-2' }, 'Congratulations!'),
        Div({ class: 'mb-6' }, 'You\'ve successfully completed the tutorial.'),
        Button({ 
          class: 'btn btn-ghost bg-white/20 hover:bg-white/30',
          onclick: () => isOpen(false)
        }, 'Get Started')
      ])
    ])
  ]);
};
Mount(CustomDemo, '#demo-custom');
<script> (function() { const initModalExamples = () => { // 1. Basic Modal const basicTarget = document.querySelector('#demo-basic'); if (basicTarget && !basicTarget.hasChildNodes()) { const BasicDemo = () => { const isOpen = $(false); return Div({ class: 'flex justify-center' }, [ Button({ class: 'btn btn-primary', onclick: () => isOpen(true) }, 'Open Modal'), Modal({ open: isOpen, title: 'Basic Modal', buttons: Button({ onclick: () => isOpen(false) }, 'Close') }, [ Div({ class: 'py-4' }, 'This is a basic modal dialog. You can put any content here.') ]) ]); }; Mount(BasicDemo, basicTarget); } // 2. Modal with Actions const actionsTarget = document.querySelector('#demo-actions'); if (actionsTarget && !actionsTarget.hasChildNodes()) { const ActionsDemo = () => { const isOpen = $(false); const confirmed = $(false); const handleConfirm = () => { confirmed(true); isOpen(false); Toast('Action confirmed!', 'alert-success', 2000); }; return Div({ class: 'flex flex-col gap-4 items-center' }, [ Button({ class: 'btn btn-primary', onclick: () => isOpen(true) }, 'Confirm Action'), () => confirmed() ? Alert({ type: 'success', message: 'You confirmed the action!' }) : null, Modal({ open: isOpen, title: 'Confirm Action', buttons: [ Button({ class: 'btn btn-ghost', onclick: () => isOpen(false) }, 'Cancel'), Button({ class: 'btn btn-primary', onclick: handleConfirm }, 'Confirm') ] }, [ Div({ class: 'py-4' }, 'Are you sure you want to perform this action? This cannot be undone.') ]) ]); }; Mount(ActionsDemo, actionsTarget); } // 3. Form Modal const formTarget = document.querySelector('#demo-form'); if (formTarget && !formTarget.hasChildNodes()) { const FormModal = () => { const isOpen = $(false); const name = $(''); const email = $(''); const submitted = $(false); const handleSubmit = () => { if (name() && email()) { submitted(true); isOpen(false); Toast(`Welcome ${name()}!`, 'alert-success', 2000); setTimeout(() => submitted(false), 3000); } }; return Div({ class: 'flex flex-col gap-4 items-center' }, [ Button({ class: 'btn btn-primary', onclick: () => isOpen(true) }, 'Sign Up'), () => submitted() ? Alert({ type: 'success', message: 'Account created successfully!' }) : null, Modal({ open: isOpen, title: 'Create Account', buttons: [ Button({ class: 'btn btn-ghost', onclick: () => isOpen(false) }, 'Cancel'), Button({ class: 'btn btn-primary', onclick: handleSubmit }, 'Sign Up') ] }, [ Div({ class: 'flex flex-col gap-4 py-2' }, [ Input({ label: 'Full Name', value: name, placeholder: 'Enter your name', oninput: (e) => name(e.target.value) }), Input({ label: 'Email', type: 'email', value: email, placeholder: 'Enter your email', oninput: (e) => email(e.target.value) }) ]) ]) ]); }; Mount(FormModal, formTarget); } // 4. Confirmation Modal const confirmTarget = document.querySelector('#demo-confirm'); if (confirmTarget && !confirmTarget.hasChildNodes()) { const ConfirmDemo = () => { const isOpen = $(false); const items = $([ { id: 1, name: 'Document A' }, { id: 2, name: 'Document B' }, { id: 3, name: 'Document C' } ]); const pendingDelete = $(null); const confirmDelete = (item) => { pendingDelete(item); isOpen(true); }; const handleDelete = () => { items(items().filter(i => i.id !== pendingDelete().id)); isOpen(false); Toast(`Deleted: ${pendingDelete().name}`, 'alert-info', 2000); }; return Div({ class: 'flex flex-col gap-4' }, [ Div({ class: 'flex flex-col gap-2' }, items().map(item => Div({ class: 'flex justify-between items-center p-3 bg-base-200 rounded-lg' }, [ Span({}, item.name), Button({ class: 'btn btn-xs btn-error', onclick: () => confirmDelete(item) }, 'Delete') ]) )), Modal({ open: isOpen, title: 'Delete Confirmation', buttons: [ Button({ class: 'btn btn-ghost', onclick: () => isOpen(false) }, 'Cancel'), Button({ class: 'btn btn-error', onclick: handleDelete }, 'Delete') ] }, [ Div({ class: 'py-4' }, () => `Are you sure you want to delete "${pendingDelete()?.name}"? This action cannot be undone.`) ]) ]); }; Mount(ConfirmDemo, confirmTarget); } // 5. Large Content Modal const largeTarget = document.querySelector('#demo-large'); if (largeTarget && !largeTarget.hasChildNodes()) { const LargeDemo = () => { const isOpen = $(false); return Div({ class: 'flex justify-center' }, [ Button({ class: 'btn btn-primary', onclick: () => isOpen(true) }, 'Open Large Modal'), Modal({ open: isOpen, title: 'Terms and Conditions', buttons: Button({ class: 'btn btn-primary', onclick: () => isOpen(false) }, 'I Agree') }, [ Div({ class: 'py-4 max-h-96 overflow-y-auto' }, [ Div({ class: 'space-y-4' }, [ Div({ class: 'text-sm' }, [ Div({ class: 'font-bold mb-2' }, '1. Introduction'), 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris.' ]), Div({ class: 'text-sm' }, [ Div({ class: 'font-bold mb-2' }, '2. User Obligations'), 'Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident.' ]), Div({ class: 'text-sm' }, [ Div({ class: 'font-bold mb-2' }, '3. Privacy Policy'), 'Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam.' ]), Div({ class: 'text-sm' }, [ Div({ class: 'font-bold mb-2' }, '4. Termination'), 'At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores.' ]) ]) ]) ]) ]); }; Mount(LargeDemo, largeTarget); } // 6. Multiple Modals const multipleTarget = document.querySelector('#demo-multiple'); if (multipleTarget && !multipleTarget.hasChildNodes()) { const MultipleDemo = () => { const modal1 = $(false); const modal2 = $(false); const modal3 = $(false); return Div({ class: 'flex flex-wrap gap-4 justify-center' }, [ Button({ class: 'btn', onclick: () => modal1(true) }, 'Info Modal'), Button({ class: 'btn', onclick: () => modal2(true) }, 'Success Modal'), Button({ class: 'btn', onclick: () => modal3(true) }, 'Warning Modal'), Modal({ open: modal1, title: 'Information', buttons: Button({ onclick: () => modal1(false) }, 'OK') }, 'This is an informational message.'), Modal({ open: modal2, title: 'Success!', buttons: Button({ onclick: () => modal2(false) }, 'Great!') }, 'Your operation was completed successfully.'), Modal({ open: modal3, title: 'Warning', buttons: Button({ onclick: () => modal3(false) }, 'Understood') }, 'Please review your input before proceeding.') ]); }; Mount(MultipleDemo, multipleTarget); } // 7. Custom Styled Modal const customTarget = document.querySelector('#demo-custom'); if (customTarget && !customTarget.hasChildNodes()) { const CustomDemo = () => { const isOpen = $(false); return Div({ class: 'flex justify-center' }, [ Button({ class: 'btn btn-primary', onclick: () => isOpen(true) }, 'Open Custom Modal'), Modal({ open: isOpen, class: 'bg-gradient-to-r from-primary to-secondary text-primary-content' }, [ Div({ class: 'text-center py-8' }, [ Div({ class: 'text-6xl mb-4' }, '🎉'), Div({ class: 'text-2xl font-bold mb-2' }, 'Congratulations!'), Div({ class: 'mb-6' }, 'You\'ve successfully completed the tutorial.'), Button({ class: 'btn btn-ghost bg-white/20 hover:bg-white/30', onclick: () => isOpen(false) }, 'Get Started') ]) ]) ]); }; Mount(CustomDemo, customTarget); } }; initModalExamples(); if (window.$docsify) { window.$docsify.plugins = [].concat(window.$docsify.plugins || [], (hook) => { hook.doneEach(initModalExamples); }); } })(); </script>