Backpack UI
Components
Modal

Modal

The Modal component allows you to display content in a modal dialog. Three types are currently available: a version for showing content, a version for handling tasks and forms, and a lightbox version for galleries and video content.

Usage


_12
_12
import {
_12
Modal,
_12
TaskModal,
_12
ModalA11Description,
_12
ModalA11Title,
_12
ModalContent,
_12
ModalIconClose,
_12
ModalTrigger,
_12
ModalHeader,
_12
ModalFooter,
_12
} from '@ef-global/backpack/Modal'

Content modal (default)

This modal should be used to show text content. variant="content" prop is passed by default inside the component.



_25
<Modal modal={true}>
_25
<ModalTrigger asChild={true}>
_25
<Button as={'button'} variant='primary'>Trigger modal example</Button>
_25
</ModalTrigger>
_25
<ModalContent>
_25
<ModalA11Title>Demo</ModalA11Title>
_25
<ModalA11Description>
_25
This is amazing A11 Description
_25
</ModalA11Description>
_25
<p>
_25
Pellentesque habitant morbi tristique senectus et netus et malesuada
_25
fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae,
_25
ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam
_25
egestas semper. Aenean ultricies mi vitae est. Mauris placerat
_25
eleifend leo.
_25
</p>
_25
<p>
_25
Pellentesque habitant morbi tristique senectus et netus et malesuada
_25
fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae,
_25
ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam
_25
egestas semper. Aenean ultricies mi vitae est. Mauris placerat
_25
eleifend leo.
_25
</p>
_25
</ModalContent>
_25
</Modal>

Lightbox Modal

Adding the variant="lightbox" prop gives you a transparent modal better suited to image and video galleries



_11
<Modal modal={true} variant={"lightbox"}>
_11
<ModalTrigger asChild={true}>
_11
<Button as={'button'} variant='primary'>Trigger Lightbox Modal</Button>
_11
</ModalTrigger>
_11
<ModalContent>
_11
<img
_11
src='https://source.unsplash.com/1600x900/?beach'
_11
alt='This is image'
_11
/>
_11
</ModalContent>
_11
</Modal>

Content modal with Form inside

We can also easily show forms inside modal. As modal is extending radix primitives it is fully accessible.



_17
<Modal modal={true}>
_17
<ModalTrigger asChild={true}>
_17
<Button as={'button'} variant='primary'>Trigger modal withForm</Button>
_17
</ModalTrigger>
_17
<ModalContent>
_17
<h2>Demo With Form</h2>
_17
<form onSubmit={(e) => e.preventDefault()}>
_17
<FormGroup
_17
style={{ display: 'flex', flexDirection: 'column', gap: '24px' }}
_17
>
_17
<FormInput type='text' placeholder='Input text' />
_17
<FormInput type='password' placeholder='Enter password' />
_17
<Button as={'button'} variant='primary'>Submit</Button>
_17
</FormGroup>
_17
</form>
_17
</ModalContent>
_17
</Modal>

Content modal triggered from outside

Modal could be also triggered from outside as showed below



_43
const WithTriggerOutside = () => {
_43
const [isOpen, setIsOpen] = useState(false);
_43
_43
const openModal = () => {
_43
setIsOpen(true);
_43
};
_43
_43
const closeModal = () => {
_43
setIsOpen(false);
_43
};
_43
_43
return (
_43
<>
_43
<Button as={'button'} variant='primary' onClick={openModal}>
_43
Trigger modal (with trigger outside)
_43
</Button>
_43
<Modal open={isOpen} onOpenChange={setIsOpen} modal={true}>
_43
<ModalContent
_43
onEscapeKeyDown={closeModal}
_43
onPointerDownOutside={closeModal}
_43
onInteractOutside={closeModal}
_43
onCloseAutoFocus={closeModal}
_43
>
_43
<h2>Demo</h2>
_43
<p>
_43
Pellentesque habitant morbi tristique senectus et netus et malesuada
_43
fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae,
_43
ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam
_43
egestas semper. Aenean ultricies mi vitae est. Mauris placerat
_43
eleifend leo.
_43
</p>
_43
<p>
_43
Pellentesque habitant morbi tristique senectus et netus et malesuada
_43
fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae,
_43
ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam
_43
egestas semper. Aenean ultricies mi vitae est. Mauris placerat
_43
eleifend leo.
_43
</p>
_43
</ModalContent>
_43
</Modal>
_43
</>
_43
);
_43
};

Task Modal

The task modal is slightly different to the others. We can pass ModalHeader component with title prop which is a fixed header and an optional ModalFooter components which stays fixed to the bottom when present. Is up to you what will be the content of ModalFooter.


CustomModal.tsx

_32
<TaskModal modal={true}>
_32
<ModalTrigger asChild={true}>
_32
<Button as={'button'} variant='primary'>Trigger TaskModal Default</Button>
_32
</ModalTrigger>
_32
<ModalHeader title='This is modal header' />
_32
<ModalContent>
_32
<h2 className='ef-h6'>Participate in our competition</h2>
_32
<p>
_32
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Senectus
_32
pulvinar tortor maecenas ornare egestas. Urna sed hendrerit ac dapibus
_32
amet felis cursus. Leo proin blandit consectetur morbi. Dapibus
_32
aliquam, pharetra nunc convallis iaculis. Adipiscing sit aenean mauris
_32
fames nec enim lectus iaculis volutpat. Commodo lobortis id purus, est
_32
tristique ullamcorper. Tellus nisl, eget nisi orci, donec.
_32
</p>
_32
<form onSubmit={(e) => e.preventDefault()}>
_32
<FormGroup
_32
style={{ display: 'flex', flexDirection: 'column', gap: '24px' }}
_32
>
_32
<FormInput label='Email' type='text' placeholder='Input email' />
_32
</FormGroup>
_32
</form>
_32
</ModalContent>
_32
<ModalFooter className='myModalHeaderStyles'>
_32
<Button as={'button'} variant='link'>
_32
<IconChevronLeft />
_32
</Button>
_32
<Button as={'button'} variant='secondary' modifier='square'>
_32
Next
_32
</Button>
_32
</ModalFooter>
_32
</TaskModal>

customModal.scss

_10
.myModalHeaderStyles {
_10
display: flex;
_10
flex-direction: row;
_10
justify-content: space-between;
_10
align-items: center;
_10
padding: 0 24px;
_10
}

Task Modal without footer



_24
<TaskModal modal={true}>
_24
<ModalTrigger asChild={true}>
_24
<Button as={'button'} variant='primary'>Trigger TaskModal Without Footer</Button>
_24
</ModalTrigger>
_24
<ModalHeader title='This is modal header' />
_24
<ModalContent>
_24
<h2 className='ef-h6'>Participate in our competition</h2>
_24
<p>
_24
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Senectus
_24
pulvinar tortor maecenas ornare egestas. Urna sed hendrerit ac dapibus
_24
amet felis cursus. Leo proin blandit consectetur morbi. Dapibus
_24
aliquam, pharetra nunc convallis iaculis. Adipiscing sit aenean mauris
_24
fames nec enim lectus iaculis volutpat. Commodo lobortis id purus, est
_24
tristique ullamcorper. Tellus nisl, eget nisi orci, donec.
_24
</p>
_24
<form onSubmit={(e) => e.preventDefault()}>
_24
<FormGroup
_24
style={{ display: 'flex', flexDirection: 'column', gap: '24px' }}
_24
>
_24
<FormInput label='Email' type='text' placeholder='Input email' />
_24
</FormGroup>
_24
</form>
_24
</ModalContent>
_24
</TaskModal>