When creating a theme or plugin for WordPress which requires users to read some documentation, it is a good idea to display the documentation right within the WordPress admin. Otherwise, making the user browse an external site could produce a negative experience from the additional friction.

I have written about displaying documentation within Gutenberg, which enables to make use of the available React-based components for different use cases. For instance, we can display our documentation by reusing the <Guide> component:

Gutenberg welcome guide

However, what happens if we are not operating within Gutenberg? For instance, we may have coded our plugin long time ago, and migrating it to Gutenberg is too much of an effort. In that case, how could we manage to open a modal window in the WordPress admin?

Unsurprisingly, we can reuse any functionality shipped anywhere by WordPress, not just through Gutenberg. And WordPress does already provide an implementation of a modal window, which is originally used to display plugin information:

Modal window showing information about the plugin

Even though designed for plugins, the modal window can nevertheless display any arbitrary content, since it is simply an iframe embedding the intended page, for any page from the same domain. And opening the modal window can be triggered from anywhere within the WordPress admin, not just from within the plugins page.

For instance, similar to the plugins page, our plugin could print a table with custom entries, and a “View details” link below each entry:

A list with information from a custom plugin

And when clicking on this link, it opens a modal window to display the entry’s corresponding documentation:

Showing documentation from the custom plugin in a modal window

In this article we will learn how to do this. The goal is to reuse the WordPress admin’s modal windows for our own themes or plugins, without depending on Gutenberg for this basic functionality.

Loading the JS/CSS assets

WordPress handles the modal windows through the following 3 files:

File wp-includes/js/thickbox/thickbox.js loads ThickBox, the library that provides the functionality for the modal window.

File wp-includes/js/thickbox/thickbox.css gives the styles for the modal window, including its placement on the page, and transitions when opening/closing the modal.

File wp-admin/js/plugin-install.js loads the event which, when clicking on a corresponding link, opens the modal window.

WordPress loads these 3 files for the plugins page:

Loaded assets in the plugins page

However, these files are not always loaded in the WordPress admin, only in the plugins page. So, we must add some code to load them in the page where we want to open the modal window. Since the 3 assets are already registered (through file wp-includes/script-loader.php), we can simply enqueue them for the corresponding page:

add_action('admin_enqueue_scripts', 'enqueue_modal_window_assets');

function enqueue_modal_window_assets()
{
  // Check that we are on the right screen
  if (get_current_screen()->id == 'my_menu_page') {
    // Enqueue the assets
    wp_enqueue_style('thickbox');
    wp_enqueue_script('plugin-install');
  }
}

This code loads the assets for a menu page with slug "my_menu_page". Enqueuing file plugin-install.js also loads thickbox.js, so we can skip enqueueing this latter one.

The JavaScript assets introduced above load the modal window in the page, and listen for certain links to be clicked; when that happens, the URL under the link’s href attribute is extracted, and loaded into the modal window’s iframe.

The following code will print a link which, upon clicking, will open the modal window and load within a custom page from the WordPress admin:

$url = admin_url('admin.php?page=my_menu_page&TB_iframe=true&width=600&height=550&modal_window=true');
printf(
  '<a href="https://www.designbombs.com/adding-modal-windows-in-the-wordpress-admin/%s" class="thickbox open-plugin-details-modal" data-title="https://www.designbombs.com/adding-modal-windows-in-the-wordpress-admin/%s">%s</a>',
  $url,
  __('View details', 'graphql-api'),
  __('Plugin documentation', 'graphql-api')
);

The link has the following attributes:

  • Mandatory classnames "thickbox" and "open-plugin-details-modal"; without these, when clicked the link would be treated normally, opening the URL in the browser window
  • URL parameter TB_iframe=true; otherwise, the modal window opens with an unsuitable format
  • URL parameters width and height are added by the ThickBox library when calculating the iframe dimensions based on the viewport’s size; the WordPress code contains these parameters in advance on the links (for instance, here) but manually adding them or not makes no difference
  • Optional attribute data-title allows to set the iframe‘s title attribute; otherwise, "Plugin details" is used

When clicking the link, the JavaScript logic creates a new iframe with the URL under the link’s href attribute, minus its parameters TB_iframe, width and height. Then, to let our page know that it is being opened inside the modal window, we further add URL parameter modal_window=true.

Printing the menu page or the modal window

In the WordPress admin, we add pages for our plugin through functions add_menu_page and add_submenu_page. Registered under its own slug, each page is accessed under admin.php?page=menu_page_slug.

In order to display content in the modal window, this has to be registered as a menu page; but then, this page would also be accessible through the admin menu on its own:

Unwanted link in the menu

This is something we want to avoid: a link to open the modal window’s contents on its own must not be added to the menu.

We use URL parameter modal_window added to the link above to provide a solution to this problem: we always register a single page under my_menu_page, and then print either the content for the normal page, or the content for the modal window, depending on parameter modal_window being present on the URL or not:

add_action('admin_menu', 'register_my_custom_menu_page');

function register_my_custom_menu_page() {
  // If requesting the modal window, print a different output
  $option_function = $_REQUEST['modal_window'] ? 'print_modal_window' : 'print_menu_page';
  add_menu_page( 
    __('My Menu Page'),
    'my menu',
    'manage_options',
    'my_menu_page',
    $output_function
  ); 
}

/**
 * Print the contents for the normal menu page
 */
function print_menu_page() {
  // ...
}

/**
 * Print the contents displayed within the modal window
 */
function print_modal_window() {
  // ...
}

Hiding the admin menu inside the modal window

Because the modal window is being registered as a menu page, it will display the top admin bar:

Modal window with top admin bar

To hide the admin bar, we create an extra modal-window.css file for the modal window:

#adminmenumain,
#wpadminbar {
  display: none;
}
html.wp-toolbar {
  padding-top: 0;
}

And we load this file whenever the parameter modal_window is present in the URL:

add_action('admin_enqueue_scripts', 'enqueue_modal_window_css');

function enqueue_modal_window_css()
{
  // Check that we are on the right screen
  if (get_current_screen()->id == 'my_menu_page' && $_REQUEST['modal_window']) {
    wp_enqueue_style('modal-window', plugins_url('css/modal-window.css', __FILE__));
  }
}

Adjusting the styles inside the modal window

Finally, when printing the contents of the modal window, they may not be directly suitable for this format. For instance, images are by default not resized to fit within the viewport:

The image is not resized to fit within the viewport

To fix this style (and any other that might arise from some particular content), we first wrap the content with a div with classname "modal-window-container":

function print_modal_window()
{
  print('<div class="modal-window-container">');
  // ...
  print('</div>');
}

And now, we can add the necessary styles in file modal-window.css (added above). To make the images fit within the viewport, we add this CSS code:

.modal-window-container img {
  max-width: 100%;
  width: auto;
  height: auto;
}

Now, images display properly within the modal window:

Images fit well within the viewport

End result and conclusion

Putting all pieces together, we can appreciate the end result:

Modal window in the WordPress admin

Opening modal windows in the WordPress admin can be useful for our themes and plugins, for displaying information to our users. Since this functionality is already shipped within WordPress, it can be achieved very easily, with just a few lines of PHP and CSS code.

Related Posts

Source link