Modal

Modals are overlays that prevent merchants from interacting with the rest of the app until a specific action is taken.

Modals can be disruptive because they require merchants to take an action before they can continue interacting with the rest of Shopify. As such, modals should be used thoughtfully and sparingly.

The Modal action set allows you to open two types of modal: message and iframe.

Setup

Create an app and import the Modal module from @shopify/app-bridge/actions. Note that we'll be referring to this sample application throughout the examples below.

import createApp from '@shopify/app-bridge';
import {Modal} from '@shopify/app-bridge/actions';

const app = createApp({
  apiKey: '12345',
  shopOrigin: shopOrigin,
});

Create a message modal

const modalOptions = {
  title: 'My Modal',
  message: 'Hello world!',
};

const myModal = Modal.create(app, modalOptions);

Create an iframe modal with an absolute url

const modalOptions = {
  title: 'My Modal',
  url: 'http://example.com',
};

const myModal = Modal.create(app, modalOptions);

Create an iframe modal a relative path

The iframe URL will be set to a path that's relative to your app root:

const modalOptions = {
  title: 'My Modal',
  path: '/setting',
};

const myModal = Modal.create(app, modalOptions);

You can attach buttons to the modal footer. To learn more about buttons, see Button.

const okButton = Button.create(app, {label: 'Ok'});
const cancelButton = Button.create(app, {label: 'Cancel'});
const modalOptions = {
  title: 'My Modal',
  message: 'Hello world!',
  footer: {
    buttons: {
      primary: okButton,
      secondary: [cancelButton],
    },
  },
};

const myModal = Modal.create(app, modalOptions);

Subscribe to actions

You can subscribe to modal actions by calling subscribe. This returns a function that you can call to unsubscribe from the action:

const modalOptions = {
  title: 'My Modal',
  url: 'http://example.com',
};

const myModal = Modal.create(app, modalOptions);

const openUnsubscribe = myModal.subscribe(Modal.Action.OPEN, () => {
  // Do something with the open event
});

const closeUnsubscribe = myModal.subscribe(Modal.Action.CLOSE, () => {
  // Do something with the close event
});

// Unsubscribe to actions
openUnsubscribe();
closeUnsubscribe();

Unsubscribe

You can call unsubscribe to remove all subscriptions on the modal and its children (including buttons):

const okButton = Button.create(app, {label: 'Ok'});
okButton.subscribe(Button.Action.CLICK, () => {
  // Do something with the click action
});
const cancelButton = Button.create(app, {label: 'Cancel'});
cancelButton.subscribe(Button.Action.CLICK, () => {
  // Do something with the click action
});
const modalOptions = {
  title: 'My Modal',
  url: 'http://example.com',
  footer: {
    buttons: {
      primary: okButton,
      secondary: [cancelButton],
    },
  },
};

const myModal = Modal.create(app, modalOptions);

myModal.subscribe(Modal.Action.OPEN, () => {
  // Do something with the open event
});

myModal.subscribe(Modal.Action.CLOSE, () => {
  // Do something with the close event
});

// Unsubscribe from modal open and close actions
// Unsubscribe from okButton and cancelButton click actions
myModal.unsubscribe();

Unsubscribe from modal actions only

You can call unsubscribe with false to remove only modal subscriptions while leaving child subscriptions intact. For example, you might want to unsubscribe from the modal but keep button listeners so that the buttons can be reused in a different modal.

const okButton = Button.create(app, {label: 'Ok'});
okButton.subscribe(Button.Action.CLICK, () => {
  // Do something with the click action
});
const cancelButton = Button.create(app, {label: 'Cancel'});
cancelButton.subscribe(Button.Action.CLICK, () => {
  // Do something with the click action
});

const modalOptions = {
  title: 'My Modal',
  message: 'Hello world!',
  footer: {
    buttons: {
      primary: okButton,
      secondary: [cancelButton],
    },
  },
};

const myModal = Modal.create(app, modalOptions);

// Unsubscribe only from modal open and close actions
myModal.unsubscribe(false);

// The buttons above can be reused in a new modal
// Their subscriptions will be left intact

const newModalOptions = {
  title: 'Confirm',
  message: 'Are you sure?',
  footer: {
    buttons: {
      primary: okButton,
      secondary: [cancelButton],
    },
  },
};

const confirmModal = Modal.create(app, newModalOptions);

Dispatch actions

const modalOptions = {
  title: 'My Modal',
  url: 'http://example.com',
};

const myModal = Modal.create(app, modalOptions);

myModal.dispatch(Modal.Action.OPEN);

// Close modal
myModal.dispatch(Modal.Action.CLOSE);

Update options

You can call the set method with partial modal options to update the options of an existing modal. This automatically triggers the update action on the modal and merges the given options with the existing options.

const modalOptions = {
  title: 'My Modal',
  url: 'http://example.com',
};

const myModal = Modal.create(app, modalOptions);

myModal.set({title: 'My new title'});

You can update buttons attached to a modal's footer. Any updates made to the modal's children automatically trigger an update action on the modal:

const okButton = Button.create(app, {label: 'Ok'});
const cancelButton = Button.create(app, {label: 'Cancel'});
const modalOptions = {
  title: 'My Modal',
  message: 'Hello world!',
  footer: {
    buttons: {
      primary: okButton,
      secondary: [cancelButton],
    },
  },
};

const myModal = Modal.create(app, modalOptions);
myModal.dispatch(Modal.Action.OPEN);

okButton.set({label: 'Good to go!'});

Set modal size

By default, modals have a fixed size of Small. You can customize the size of a modal by passing in a different Modal.Size value:

const modalOptions = {
  title: 'My Modal',
  message: 'Hello world!',
  size: Modal.Size.Large,
};

const myModal = Modal.create(app, modalOptions);
myModal.dispatch(Modal.Action.OPEN);

There are four values for Modal.Size: Small, Medium, Large, Auto.

Set modal size automatically

Iframe modals can automatically expand to fit their contents, using the Auto size:

const modalOptions = {
  title: 'My Modal',
  path: '/modal',
  size: Modal.Size.Auto,
};

const myModal = Modal.create(app, modalOptions);
myModal.dispatch(Modal.Action.OPEN);

Automatic modal sizing requires the style overflow: hidden on the <body> element of your modal page. Otherwise, you’ll see double scrollbars.

Avoid setting height, margin or padding styles on the <body> element of your modal page, as these will interfere with automatic modal sizing. As a workaround, set these styles on a wrapper element instead.

If you are using Shopify Polaris, be aware that it applies height: 100% to the <body> element by default. You will need to override this style on your modal page.

Sign up for a Partner account to get started.

Sign up