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.