Skip to main content

Modal Component

The Modal API allows you to display an overlay that prevents interaction with the rest of the app until dismissed.

It is used by customizing your Modal content with the Modal component and then opening it with the shopify.modal.show('modal-id') API.

The Modal component is available for use in your app. It configures a Modal to display in the Shopify Admin.

The content you provide can be simple React elements or a src prop with a URL that will be loaded.

HTMLCollection &

The content to display within a Modal. You can provide a single HTML element with children and the ui-title-bar element to configure the Modal title bar.

string

A unique identifier for the Modal

string

The URL of the content to display within a Modal. If provided, the Modal will display the content from the provided URL and any children other than the ui-title-bar and ui-save-bar elements will be ignored.

'small' | 'base' | 'large' | 'max'
Default: "base"

The size of the modal.

Before the Modal is shown, this can be changed to any of the provided values. After the Modal is shown, this can can only be changed between small, base, and large.

Was this section helpful?

Modal

import {Modal, TitleBar, useAppBridge} from '@shopify/app-bridge-react';

export function MyModal() {
const shopify = useAppBridge();

return (
<>
<button onClick={() => shopify.modal.show('my-modal')}>Open Modal</button>
<Modal id="my-modal">
<p>Message</p>
<TitleBar title="Title">
<button variant="primary">Label</button>
<button onClick={() => shopify.modal.hide('my-modal')}>Label</button>
</TitleBar>
</Modal>
</>
);
}

Preview

Modal options, variations, and events

Was this section helpful?

Opening a max size Modal

import {Modal, TitleBar, useAppBridge} from '@shopify/app-bridge-react';

export function MyModal() {
const shopify = useAppBridge();

return (
<>
<button onClick={() => shopify.modal.show('my-modal')}>Open Modal</button>
<Modal id="my-modal" variant="max">
<div></div>
<TitleBar>
<button variant="primary">Primary action</button>
<button>Secondary action</button>
</TitleBar>
</Modal>
</>
);
}

Preview

Using the onShow callback which is called when the Modal is opened

Using the onHide callback which is called when the Modal is closed

Was this section helpful?

Subscribing to Show

import {Modal, useAppBridge} from '@shopify/app-bridge-react';

export function MyModal() {
const shopify = useAppBridge();

return (
<>
<button onClick={() => shopify.modal.show('my-modal')}>Open Modal</button>
<Modal id="my-modal" onShow={() => console.log('Modal is showing')}>
<p>Message</p>
</Modal>
</>
);
}

Was this section helpful?

Showing a Modal with the `open` prop

import {useState} from 'react';
import {Modal, TitleBar} from '@shopify/app-bridge-react';

export function MyModal() {
const [modalOpen, setModalOpen] = useState(false);

return (
<>
<button onClick={() => setModalOpen(true)}>Open Modal</button>
<Modal id="my-modal" open={modalOpen}>
<p>Message</p>
<TitleBar title="My Modal">
<button onClick={() => setModalOpen(false)}>Label</button>
</TitleBar>
</Modal>
</>
);
}

Loading content from a URL

Was this section helpful?

Loading content from a URL

// main app
import {Modal, TitleBar, useAppBridge} from '@shopify/app-bridge-react';

export function MyModal() {
const shopify = useAppBridge();

return (
<>
<button onClick={() => shopify.modal.show('my-modal')}>Open Modal</button>
<Modal id="my-modal" src="/my-route">
<TitleBar title="Title">
<button variant="primary">Label</button>
<button onClick={() => shopify.modal.hide('my-modal')}>Label</button>
</TitleBar>
</Modal>
</>
);
}

// my-route.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="shopify-api-key" content="%SHOPIFY_API_KEY%" />
<script src="https://cdn.shopify.com/shopifycloud/app-bridge.js"></script>
</head>

<body>
<h1>My separate route</h1>
<script src="./my-route.jsx" type="module"></script>
</body>
</html>

// my-route.jsx
export function MyRoute() {
return (
<h1>My separate route</h1>
);
}