Modal
The modal component provides the functionality to toggle dialogs that overlays the main content.
Usage
In the usage examples below, we use the Portal component to render the modal into a different part of the DOM and the TrapFocus component to trap keyboard focus inside the modal and to return focus to the previously focused element. This is not required, but it's recommended to avoid styling issues and increase accessibility.
import { useModal } from '@norr/components';
import { Portal } from './Portal';
import { TrapFocus } from './TrapFocus';
const Component = () => {
const {
modalProps,
modalTriggerProps,
modalCloseProps,
modalIsOpen,
} = useModal<HTMLDivElement>();
return (
<>
<button {...modalTriggerProps}>Trigger modal</button>
{modalIsOpen && (
<Portal>
<TrapFocus style={{ position: 'fixed', zIndex: 1337, inset: 0 }}>
<div {...modalProps} style={{ backgroundColor: 'teal' }}>
<span>Modal content.</span>
<button {...modalCloseProps}>Close modal</button>
</div>
</TrapFocus>
</Portal>
)}
</>
);
};
Click outside
The component is using useClickOutside() under the
hood, so by default will the modal be closed when the user clicks outside of
the modal (where you spread {...modalProps}
). This can be disabled by setting
the disableClickOutside
prop to true
.
import { useModal } from '@norr/components';
import { Portal } from './Portal';
import { TrapFocus } from './TrapFocus';
const Component = () => {
const {
modalProps,
modalTriggerProps,
modalCloseProps,
modalIsOpen,
} = useModal<HTMLDivElement>({
disableClickOutside: true,
});
return (
<>
<button {...modalTriggerProps}>Trigger modal</button>
{modalIsOpen && (
<Portal>
<TrapFocus style={{ position: 'fixed', zIndex: 1337, inset: 0 }}>
<div {...modalProps} style={{ backgroundColor: 'teal' }}>
<span>Will not be closed when clicked outside.</span>
<button {...modalCloseProps}>Close modal</button>
</div>
</TrapFocus>
</Portal>
)}
</>
);
};
Escape key
The component is using useEventListener() under the
hood to listen for when the escape key is pressed, so by default will the modal
be closed when the user presses the escape
key. This can be disabled by setting
the disableEscapeKey
prop to true
.
import { useModal } from '@norr/components';
import { Portal } from './Portal';
import { TrapFocus } from './TrapFocus';
const Component = () => {
const {
modalProps,
modalTriggerProps,
modalCloseProps,
modalIsOpen,
} = useModal<HTMLDivElement>({
disableEscapeKey: true,
});
return (
<>
<button {...modalTriggerProps}>Trigger modal</button>
{modalIsOpen && (
<Portal>
<TrapFocus style={{ position: 'fixed', zIndex: 1337, inset: 0 }}>
<div {...modalProps} style={{ backgroundColor: 'teal' }}>
<span>Will not be closed when escape key is pressed.</span>
<button {...modalCloseProps}>Close modal</button>
</div>
</TrapFocus>
</Portal>
)}
</>
);
};
Prevent scroll
The component is using usePreventScroll() under the
hood to prevent scroll when the modal is open. This can be disabled by setting
the disablePreventScroll
prop to true
.
import { useModal } from '@norr/components';
import { Portal } from './Portal';
import { TrapFocus } from './TrapFocus';
const Component = () => {
const {
modalProps,
modalTriggerProps,
modalCloseProps,
modalIsOpen,
} = useModal<HTMLDivElement>({
disablePreventScroll: true,
});
return (
<>
<button {...modalTriggerProps}>Trigger modal</button>
{modalIsOpen && (
<Portal>
<TrapFocus style={{ position: 'fixed', zIndex: 1337, inset: 0 }}>
<div {...modalProps} style={{ backgroundColor: 'teal' }}>
<span>You can scroll behind the modal.</span>
<button {...modalCloseProps}>Close modal</button>
</div>
</TrapFocus>
</Portal>
)}
</>
);
};