Last updated Oct 12, 2021

Creating a modal

This is a continuation of the work started in 4. Custom HTML content.

Modals can be complicated to create since generally you'll need to use an external library, and then modify its design to match the product you're creating the modals for.

With Client-side Extensions (CSE), you can use an extension type called Modal that lets you create a modal dialog that works well with your product, and you can focus on your feature instead.

To create the modal extension, you need to use the ModalExtension factory. The CSE runtime will then use the onAction method to inject a Modal API object when the modal is ready for you to render the content in.

Remember that the onAction method behaves differently for each extension type. For more info, see extension API reference.

Rendering your content inside a modal

The modal API has the same onMount/onUnmount methods as panels to render your content, but also has some modal specific methods.

One of the modal specific APIs is setTitle that allows you to specify a title in the modal header.

Create a modal extension for the pull request diff toolbar

You're now going to create a modal extension that opens after clicking a button in the pull request diff toolbar.

In the /src/my-app/extensions/first-extension.js file:

  1. Use the diff toolbar extension point: bitbucket.ui.pullrequest.diff.toolbar.
  2. Use the label attribute to add a text to the button that will open your modal.
  3. Import ModalExtension from @atlassian/clientside-extensions, and use its factory to create a modal extension.
  4. Use the onAction to get a modal API object.
  5. Use the modal API to set a title.
  6. Use the modal API to render your content inside the modal body.
1
2
// #/src/my-app/extensions/first-extension.js
import { ModalExtension } from '@atlassian/clientside-extensions';

/**
 * @clientside-extension
 * @extension-point bitbucket.ui.pullrequest.diff.toolbar
 */
export default ModalExtension.factory((extensionAPI, context) => {
    return {
        label: 'Click to open a modal',
        onAction: (modalAPI) => {
            const getContent = () => `
                <p>And some content inside the modal too.</p>
            `;

            modalAPI.setTitle('Look, a Modal!');

            modalAPI.onMount((container) => {
                container.innerHTML = getContent();
            });

            modalAPI.onUnmount((container) => {
                container.innerHTML = '';
            });
        },
    };
});

The modal API provides a method called setActions that allows you to render action buttons in your modal footer, and execute arbitrary JavaScript when they are clicked.

You can also close the modal after executing an action by using closeModal.

Add action buttons to your modal

Modify your modal extension to have a pair of actions. One of them should modify your modal content, and the other close the modal when clicked.

In the /src/my-app/extensions/first-extension.js file:

  1. Define two actions for your modal using setActions.
  2. The first action should keep count of the times it's been clicked, and show it in the modal content.
  3. The second action should close the modal dialog when clicked.
1
2
// #/src/my-app/extensions/first-extension.js
import { ModalExtension } from '@atlassian/clientside-extensions';

/**
 * @clientside-extension
 * @extension-point bitbucket.ui.pullrequest.diff.toolbar
 */
export default ModalExtension.factory((extensionAPI, context) => {
    return {
        label: 'Click to open a modal',
        onAction: (modalAPI) => {
            let count = 0;

            const getContent = () => `
                <p>The primary button has been clicked ${count} times.</p>
            `;

            modalAPI.setTitle('Look, a Modal!');

            modalAPI.onMount((container) => {
                container.innerHTML = getContent();

                // setting the actions of the modal
                modalAPI.setActions([
                    {
                        text: 'Primary',
                        onClick: () => {
                            count++;
                            container.innerHTML = getContent();
                        },
                    },
                    {
                        text: 'Close',
                        onClick: () => modalAPI.closeModal(),
                    },
                ]);
            });

            modalAPI.onUnmount((container) => {
                container.innerHTML = '';
            });
        },
    };
});

Using custom content with React

Client-side Extensions (CSE) provides a utility that makes it easier to use React with the Modal extension. For more info, see Rendering elements as React.

Recap

You've learned:

  • How to use a modal created by CSE and render your feature in it.
  • How to add actions to your modal extension.
  • How to programmatically close your modal extension.

Make sure to check the modal API reference to explore more things you can do with modals.

Rate this page: