Skip to content

Migrating react-overlay → CSS dialog

Edit on GitHub

We recommend using the native <dialog> element instead of the old react-overlay component. This guide walks you through the migration.

Install the headless hooks package:

Terminal window
yarn add @volvo-cars/react-headless

The CSS dialog is a headless component — you handle more of the state and logic yourself. The markup is flexible and the styles can be customised to fit your needs.


From a design perspective, we want to avoid full-screen modals. The new dialog is not full height by default.

react-overlay propCSS dialog equivalent
closeA button that calls closeDialog()
titlePass as a child element (e.g. <h2>)
colSpanUse dialog-small, dialog-large, or w-* classes
collapseNot needed — the dialog is not fullscreen by default

Before

import { TitledOverlay } from '@volvo-cars/react-overlay';
<TitledOverlay title="Title" close={() => {}} colSpan="8" collapse>
<p>
Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla
consequat massa quis enim. Donec.
</p>
</TitledOverlay>;

After

import { useDialog } from '@volvo-cars/react-headless';
import { IconButton } from '@volvo-cars/react-icons';
function MyDialog() {
const { dialogProps, showDialog, closeDialog } = useDialog();
return (
<>
<button className="button-filled" onClick={showDialog}>
Open dialog
</button>
<dialog
className="dialog-large"
aria-labelledby="dialog1-label"
{...dialogProps}
>
<header slot="header">
<div slot="close">
<IconButton
aria-label="Close"
bleed
iconName="navigation-close"
onClick={closeDialog}
variant="clear"
/>
</div>
<h2 className="font-medium" id="dialog1-label">
Title
</h2>
</header>
<article slot="main">
<p>
Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem.
Nulla consequat massa quis enim. Donec.
</p>
</article>
</dialog>
</>
);
}

  • Don’t use the open attribute declaratively. Always use the showDialog and closeDialog functions from useDialog() to control the dialog. Setting open directly on the element will not open it as a modal in an accessible manner.
  • Use dialog-small or dialog-large classes to control the dialog size. For custom widths, add w-* utility classes.
  • The useDialog hook returns dialogProps that should be spread onto the <dialog> element to handle focus management and backdrop behaviour.