AI Assistant

Modal

The Modal component renders an animated dialog on top of the page. It portals into document.body so the overlay always sits above transformed or clipped ancestors, and it closes on Escape, on a click outside, or with the built-in close button.

The Modal is a controlled component: the parent owns the open state. The dialog surface carries role="dialog" and aria-modal="true", and takes its accessible name from $title.

"use client";
import React, { useState } from "react";
import { Button, Modal } from "cherry-styled-components";

export default function Page() {
  const [isOpen, setIsOpen] = useState(false);

  return (
    <>
      <Button onClick={() => setIsOpen(true)}>Open Modal</Button>
      <Modal
        $isOpen={isOpen}
        $onClose={() => setIsOpen(false)}
        $title="Modal Title"
      >
        Modal content goes here.
      </Modal>
    </>
  );
}

With a custom width for larger content:

<Modal $isOpen={isOpen} $onClose={close} $width={800}>
  Content
</Modal>

Restyling

To restyle the modal from your app, pass a className (or style). Both are applied to the overlay root, and the inner parts expose stable class hooks: .modal-inner, .modal-close, .modal-title, and .modal-content.

<Modal $isOpen={isOpen} $onClose={close} className="checkout-modal">
  Content
</Modal>
.checkout-modal .modal-inner {
  border-radius: 24px;
}

Wrapping with styled(Modal) does not work: styled-components strips transient $-props before they reach the wrapped component, so the modal never receives $isOpen or $onClose. Target a passed class instead.

Properties

childrenReact.ReactNode

The modal content. It scrolls internally when taller than the viewport.

$isOpenbooleanrequired

Whether the modal is visible. The modal animates in and out on change.

$onClose() => voidrequired

Called when the user dismisses the modal (Escape, outside click, or the close button).

$titlestring

Optional title rendered with a divider below it. Also used as the dialog's aria-label.

$widthnumber

Maximum width in pixels on large screens. Defaults to 500.

$hideCloseButtonboolean

Omits the built-in close button in the top-right corner. Escape and outside click still dismiss the modal.

classNamestring

Applied to the overlay root, for app-level restyling. See the Restyling section above.

styleReact.CSSProperties

Inline styles applied to the overlay root.

The Modal is SSR-safe: it renders nothing on the server and during the first client render, then portals once hydration has completed.

The modal unmounts its children once the exit animation finishes, so state inside the modal (such as form inputs) resets between openings. To keep state across openings, lift it into the parent.