# Modal
**📖 Live documentation:** https://cds.coinbase.com/components/overlay/Modal/
A component that displays content in a window that requires user interaction.
## Import
```tsx
import { Modal } from '@coinbase/cds-web/overlays/modal/Modal'
```
## Examples
### Basic example
```jsx live
function Example() {
const [visible, setVisible] = useState(false);
return (
<>
setVisible(false)} visible={visible}>
setVisible(false)}
testID="Basic Modal Test ID"
title="Basic Modal"
/>
Body contents go here
setVisible(false)}>Save}
secondaryAction={
}
/>
>
);
}
```
### Portal Modal
:::warning This approach is deprecated
Use the `visible` and `onRequestClose` props as outlined above
:::
```jsx live
function Example() {
const { openModal, closeModal } = useModal();
const handlePress = useCallback(
() =>
openModal(
Body contents go hereSave}
secondaryAction={
}
/>
,
),
[openModal, closeModal],
);
return ;
}
```
### Chained Modals
:::tip Accessibility tip
For chained modals, set `restoreFocusOnUnmount={false}` on each one and return focus to the opener when exiting the chain (e.g., `triggerRef.current?.focus()`) to keep tab order predictable.
:::
```jsx live
function ChainedModalsExample() {
const triggerRef = useRef(null);
const [isFirstModalOpen, setIsFirstModalOpen] = useState(false);
const [isSecondModalOpen, setIsSecondModalOpen] = useState(false);
const closeFirstModal = () => {
setIsFirstModalOpen(false);
triggerRef.current?.focus();
};
const openSecondModal = () => {
setIsFirstModalOpen(false);
setIsSecondModalOpen(true);
};
const closeSecondModal = () => {
setIsSecondModalOpen(false);
triggerRef.current?.focus();
};
const goBackToFirstModal = () => {
setIsSecondModalOpen(false);
setIsFirstModalOpen(true);
};
return (
<>
First modal contentNext}
secondaryAction={
}
/>
Second modal contentClose}
secondaryAction={
}
/>
>
);
}
```
### Scrollable Modal Content
If the Modal has content which is expected to overflow and doesn't have focusable elements, set the following props to ensure the scrollable content can be navigated using keyboard arrows:
- `focusTabIndexElements`: `true`
- `disableArrowKeyNavigation`: `true`
As well, assign a `tabIndex` greater than or equal to `0` to the ModalBody so that the overflow can be reached via keyboard.
```jsx live
function Example() {
const [visible, setVisible] = useState(false);
return (
<>
setVisible(false)}
visible={visible}
>
setVisible(false)}
testID="Basic Modal Test ID"
title="Basic Modal"
/>
This tray has content which will overflow.
To enable keyboard scrolling, certain props have to be set.
Otherwise, the content won't be viewable to users who navigate using a keyboard.
It's important to account for this to ensure an accessible experience.
Here's some text that is in the overflow and needs to be scrolled to.
Here's some more text to help more easily showcase scrolling.
setVisible(false)}>Save}
secondaryAction={
}
/>
>
);
}
```
## Props
| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `onRequestClose` | `() => void` | Yes | `-` | Callback function fired when modal is closed. |
| `visible` | `boolean` | Yes | `false false` | Controls visibility of the Modal |
| `accessibilityLabelledBy` | `string` | No | `-` | On web, maps to aria-labelledby and lists the id(s) of the element(s) that label the element on which the attribute is set. On mobile (Android only), a reference to another element nativeID used to build complex forms. |
| `alignContent` | `ResponsiveProp