Migrating react-overlay → CSS dialog
We recommend using the native <dialog> element instead of the old react-overlay component. This guide walks you through the migration.
Prerequisites
Section titled “Prerequisites”Install the headless hooks package:
yarn add @volvo-cars/react-headlessThe 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.
What’s different
Section titled “What’s different”From a design perspective, we want to avoid full-screen modals. The new dialog is not full height by default.
react-overlay prop | CSS dialog equivalent |
|---|---|
close | A button that calls closeDialog() |
title | Pass as a child element (e.g. <h2>) |
colSpan | Use dialog-small, dialog-large, or w-* classes |
collapse | Not needed — the dialog is not fullscreen by default |
Before & after
Section titled “Before & after”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> </> );}Important notes
Section titled “Important notes”- Don’t use the
openattribute declaratively. Always use theshowDialogandcloseDialogfunctions fromuseDialog()to control the dialog. Settingopendirectly on the element will not open it as a modal in an accessible manner. - Use
dialog-smallordialog-largeclasses to control the dialog size. For custom widths, addw-*utility classes. - The
useDialoghook returnsdialogPropsthat should be spread onto the<dialog>element to handle focus management and backdrop behaviour.