A modal is a secondary window that communicates or provides an action inside the same process.
install yarn add @clayui/modal version use import Modal from '@clayui/modal' ;
You may want to compose your content and customize with your use cases or add your own components while still keeping the logic of a modal.
import {Provider } from '@clayui/core' ;
import Modal , {useModal } from '@clayui/modal' ;
import Button from '@clayui/button' ;
import React from 'react' ;
export default function App () {
const {observer , onOpenChange , open } = useModal ();
return (
<Provider spritemap = "/icons.svg" >
<div className = "p-4" >
<>
{open && (
<Modal observer = {observer } size = "lg" status = "info" >
<Modal . Header >Documents</Modal . Header >
<Modal . Body >
<p >Do you want to save your documents?</p >
</Modal . Body >
<Modal . Footer
last = {
<Button . Group spaced >
<Button
displayType = "secondary"
onClick = {() => onOpenChange (false )}
>
Cancel
</Button >
<Button onClick = {() => onOpenChange (false )}>
Save changes
</Button >
</Button . Group >
}
/>
</Modal >
)}
<Button onClick = {() => onOpenChange (true )}>Open modal</Button >
</>
</div >
</Provider >
);
}Show code
Usage
Modal can be controlled using the useModal
hook without the need for additional state, it handles the animations for you.
const Dialog = () => {
const {observer , onOpenChange , open } = useModal ();
return (
<>
{open && (
<Modal observer = {observer }>
<Modal.Header >Title</Modal.Header >
<Modal.Body >Body</Modal.Body >
<Modal.Footer
last = {
<ClayButton onClick = {() => onOpenChange (false )}>Close</ClayButton >
}
/>
</Modal >
)}
<ClayButton onClick = {() => onOpenChange (true )}>Open modal</ClayButton >
</>
);
};Show code
useModal hook
The useModal
hook is required to create a Modal component in Clay, it is responsible for communicating with Modal and controlling states to make animations, this is necessary because Modal needs animation when opening and closing so we need to delay calls of the onClose
so you can safely control Modal’s visibility or do other things.
useModal
returns a signature with observer
and onClose
:
observer
- Observer is the communication channel that connects Modal with
useModal
.
onOpenChange
- Callback to change open state.
open
- Flag to indicate the open state of the modal.
const {observer , onOpenChange , open } = useModal ();
To avoid future problems, do not use the information or change the values of
observer
, it is considered a bad practice.
Modal.Header
offers two different APIs for use by toggling the prop withTitle
. By default(withTitle={true}
), Modal.Header
behaves like a high-level component. If you want to use the lower-level components in Header, all you need to do is set withTitle={false}
.
Here is an example of both APIs:
import {Provider } from '@clayui/core' ;
import Modal , {useModal } from '@clayui/modal' ;
import Button from '@clayui/button' ;
import Icon from '@clayui/icon' ;
import React from 'react' ;
export default function App () {
const {observer , onOpenChange , open } = useModal ();
return (
<Provider spritemap = "/icons.svg" >
<div className = "p-4" >
<>
<Modal . Header >{'Modal Title' }</Modal . Header >
<br />
<Modal . Header withTitle = {false }>
<Modal . ItemGroup >
<Modal . Item >
<Modal . TitleSection >
<Modal . Title >
<Modal . TitleIndicator >
<Icon symbol = "info-circle" />
</Modal . TitleIndicator >
{'Modal Title' }
</Modal . Title >
</Modal . TitleSection >
</Modal . Item >
<Modal . Item shrink >
<Modal . SubtitleSection >
<Modal . Subtitle >{'Modal Subtitle' }</Modal . Subtitle >
</Modal . SubtitleSection >
</Modal . Item >
</Modal . ItemGroup >
<Button
aria-label = "close"
className = "close"
displayType = "unstyled"
onClick = {() => {}}
>
<Icon symbol = "times" />
</Button >
</Modal . Header >
</>
</div >
</Provider >
);
}Show code
Provider
When your application uses a lot of modals, you can use <ClayModalProvider />
to have only one open Modal on the screen and the component centered on your application, you can invoke the modal from the context through the API. It is not recommended to have multiple modals open at the same time.
Add in the project root:
<ClayModalProvider spritemap = {spritemap }>
<MyApp />
</ClayModalProvider >
In any part of your application you can invoke modal.
import {Context } from '@clayui/modal' ;
import ClayButton from '@clayui/button' ;
const MyApp = () => {
const [state , dispatch ] = useContext (Context );
return (
<ClayButton
displayType = "primary"
onClick = {() =>
dispatch ({
payload: {
body: <h1 >{'Hello world!' }</h1 >,
footer: [
,
,
<ClayButton key = {3 } onClick = {state .onClose }>
{'Primary' }
</ClayButton >,
],
header: 'Title' ,
size: 'lg' ,
},
type: 1 ,
})
}
>
{'Open modal' }
</ClayButton >
);
};Show code
Provider contains two different states that you can control:
Close
- CLOSE
Open
- OPEN
The context signature is similar to a useReducer
, contains state
and dispatch
.
function Example () {
const [state , dispatch ] = useContext (Context );
return (
<Button
onClick = {() => dispatch ({payload: {header: 'Title' }, type: 'OPEN' })}
>
Open Modal
</Button >
);
}
state
returns all values that are passed to dispatch payload and you can pass body
, footer
, header
, size
, status
and url
to payload.
API Reference
Modal { ({ center , children , className , containerElementRef , containerProps , disableAutoClose , observer , role , size , spritemap , status , zIndex , ... otherProps }: IProps ): JSX .Element ; Body : ({ children , className , iFrameProps , scrollable , url , ... otherProps }: IBodyProps ) => JSX .Element ; Footer : ({ className , first , last , middle , ... otherProps }: IFooterProps ) => JSX .Element ; Header : ({ children , withTitle , ... otherProps }: IHeaderProps ) => JSX .Element ; Item : ({ children , className , shrink , ... otherProps }: IItemProps ) => JSX .Element ; ItemGroup : ({ children , className , ... otherProps }: React .HTMLAttributes <HTMLDivElement >) => JSX .Element ; Subtitle : ({ children , className , ... otherProps }: React .HTMLAttributes <HTMLDivElement >) => JSX .Element ; SubtitleSection : ({ children , className , ... otherProps }: React .HTMLAttributes <HTMLDivElement >) => JSX .Element ; Title : ({ children , className , ... otherProps }: React .HTMLAttributes <HTMLDivElement >) => JSX .Element ; TitleIndicator : ({ children , className , ... otherProps }: React .HTMLAttributes <HTMLDivElement >) => JSX .Element ; TitleSection : ({ children , className , ... otherProps }: React .HTMLAttributes <HTMLDivElement >) => JSX .Element ; }
Parameters Properties center boolean | undefined
Flag indicating to vertically center the modal.
containerElementRef React .RefObject < Element > | undefined
Container element to render modal into.
containerProps IPortalBaseProps | undefined
= {}
Props to add to the ClayPortal.
disableAutoClose boolean | undefined
A flag indicating if the modal shouldn’t
be closed when either the ESC key is pressed
or when clicking outside the modal
size "lg" | "sm" | "full-screen" | undefined
The size of element modal.
Observer is Modal’s communication system with useModal
hook, adds observer from useModal
hook here.
zIndex number | undefined
Allows setting a custom z-index value, overriding the default one which is 1040, modal body z-index will be +10 of this value
spritemap string | undefined
The path to the SVG spritemap file containing the icons.
status Status | undefined
Status messages.
Returns Element
ModalProvider ({ children , spritemap }: IProps ) => JSX .Element
Parameters Properties children * React .ReactNode
spritemap string | undefined
The path to the SVG spritemap file containing the icons.
Returns Element
useModal ({ defaultOpen , onClose , }?: Props ) => Return
Parameters * Props
= {"defaultOpen" :false }
defaultOpen boolean | undefined
Set the default value of the state of the modal dialog.
Deprecated onClose (() => void ) | undefined
Callback called to close the modal.
Returns Return
ItemGroup ({ children , className , ... otherProps }: React .HTMLAttributes <HTMLDivElement >) => JSX .Element
Item ({ children , className , shrink , ... otherProps }: IItemProps ) => JSX .Element
Parameters shrink boolean | undefined
Flag for indicating if item should autofitting the width
Returns Element
TitleSection ({ children , className , ... otherProps }: React .HTMLAttributes <HTMLDivElement >) => JSX .Element
Title ({ children , className , ... otherProps }: React .HTMLAttributes <HTMLDivElement >) => JSX .Element
TitleIndicator ({ children , className , ... otherProps }: React .HTMLAttributes <HTMLDivElement >) => JSX .Element
SubtitleSection ({ children , className , ... otherProps }: React .HTMLAttributes <HTMLDivElement >) => JSX .Element
Subtitle ({ children , className , ... otherProps }: React .HTMLAttributes <HTMLDivElement >) => JSX .Element
({ children , withTitle , ... otherProps }: IHeaderProps ) => JSX .Element
Parameters withTitle boolean | undefined
Flag for indicating if you want to use the Header its children being the title.
Set to false
if you want to use this as a low-level component.
Returns Element
Body ({ children , className , iFrameProps , scrollable , url , ... otherProps }: IBodyProps ) => JSX .Element
Parameters iFrameProps React .HTMLAttributes < HTMLIFrameElement > | undefined
Props to add to the iframe element
scrollable boolean | undefined
Flag to indicate if body should be a fixed height with a scrollable overflow.
Url to place an iframe in the body of the modal.
Returns ElementEdit this page on GitHub Contributors
Matuzalém Teles, Bryce Osterhaus, Diego Nascimento, Krešimir Čoko
Last edited May 12, 2025 at 11:20:36 PM