Frontend developer focused on inclusive design

Toolbar with modal in WordPress block

A good modal is straightforward and focused. It conveys a specific message or call to action without overwhelming the person. This clarity and focus ensure the person understands the information or action required.

In this context, placing a button in the toolbar to trigger a modal can be effective.

The toolbar is an intuitive location where people often look for options, settings, or additional information. Having a button here to open the modal promotes a good user experience.

It ensures that the specific message or call to action is noticed. People can access it when needed. Importantly, this integration does not disrupt the overall flow of the webpage.

Core components

The Toolbar and Modal components are part of the WordPress components library. This eliminate the need to create these elements from scratch. Also, using these components ensures consistency and reliability across WordPress.

User-friendly modal

But what makes a modal user-friendly?

While working on a WordPress project using React, I was tasked to inform the person regarding outdated child blocks within the parent Sortable block in the Block editor. The key was not to overwhelm the person.

So, I started with simplicity.

Simplicity

No one (or at least no one I know) likes a cluttered modal. It’s like trying to read a novel on a postage stamp. The modal text is a crucial piece of communication. Thus, I have broken it down into three categories:

  1. Title: This is short and clear, quickly giving the person an understanding of the topic or problem.
  2. Info: This provides more detailed information, exploring the topic more deeply but still in an understandable way.
  3. Help: This offers guidance and specific, clear steps to solve or understand the problem or topic.

Here is an example of the title text:

<Modal
	title={__("This Block's Date is Old", "sortable")}
	onRequestClose={closeWarningModal}
	className="sortable-block__warning-modal"
>
...
</Modal>

In this snippet, the <Modal> component is being used to create a dialog box.

The title prop is set to a string that informs the user about an outdated block date, utilizing the WordPress __() function for translation readiness. This function is part of WordPress's internationalization utilities, ensuring that the text can be easily localized into different languages as needed.

The onRequestClose prop is a function to close the modal, and className prop is used for styling the modal.

Here is an example of the info text:

...
<p>
	{__(
		'You are seeing this notice because the date on this "Sortable Entry" block is older than the date you set on the "Sortable" block.',
		"sortable",
	)}
</p>
<p>
	<strong>
		{__("Here's a summary of the dates:", "sortable")}
	</strong>
</p>
<ul>
	<li>
		{__('Date set in "Sortable":', "sortable")}{" "}
		<strong>
			{filterDateObject.toLocaleString("en-US", {
				month: "long",
				day: "2-digit",
				year: "numeric",
			})}
		</strong>
	</li>
	<li>
		{__('Date on this "Sortable Entry":', "sortable")}{" "}
		<strong>
			{blockDateObject.toLocaleString("en-US", {
				month: "long",
				day: "2-digit",
				year: "numeric",
			})}
		</strong>
	</li>
</ul>
...

This snippet provides more detailed information to the person.

The first paragraph explains why the user is seeing the warning. The second paragraph serves as a header for a summary of dates, which is presented in a semantic HTML list.

Here is an example of the help text:

...
<p>
	<strong>{__("To resolve warning, you can:", "sortable")}</strong>
</p>
<ol>
	<li>
		{__(
			'Ignore warnings by changing a setting in the "Sortable" block.',
			"sortable",
		)}
	</li>
	<li>
		{__(
			'Change the date in the "Sortable" block to cover more dates.',
			"sortable",
		)}
	</li>
	<li>
		{__(
			'Update the date on this "Sortable Entry" block to a newer date.',
			"sortable",
		)}
	</li>
</ol>
<p>
	{__(
		"Changes can be made in the block settings sidebar.",
		"sortable",
	)}
</p>
...

This snippet provides clear instructions to the user on how to resolve the warning, using semantic markup in the modal’s content area.

An ordered list is used to enumerate the steps the person can take to address the issue, giving a structured and clear guidance. The final paragraph informs the person where these changes can be made.

Timing

Give people a moment. Let them breathe. Allow them look around before hitting them with a modal. Thus, I decided to use a toolbar for triggering a warning modal in the Block editor.

It makes the modal to appear only when the person clicks on the warning icon in the toolbar. This ensures that people are not ambushed by unexpected dialog messages but are informed at their own pace.

const isExpired = blockDateObject.getTime() < filterDateObject.getTime();
const [isOpenWarningModal, setIsOpenWarningModal] = useState(false);
...

return (
	...
	{isExpired && (
		<BlockControls>
			<Toolbar>
				<Button
					label={__("Inspect visibility problem", "sortable")}
					icon={warning}
					onClick={() => {
						setIsOpenWarningModal(!isOpenWarningModal);
					}}
					isPressed={isOpenWarningModal}
				/>
			</Toolbar>
		</BlockControls>
	)}
	...
);

The snippet above illustrates how the visibility of the warning modal is controlled, ensuring it's displayed only when the person opts to click on the warning icon in the toolbar.

First, a comparison is made between the blockDateObject and filterDateObject to check if the date on a block is earlier than the filter date. The result is stored in a constant called isExpired.

Second, using the useState hook from React, a state variable isOpenWarningModal is declared to manage the visibility of the warning modal. It's initially set to false, indicating that the modal is hidden by default.

Third, within the return statement, conditional rendering is used to display the warning toolbar button only if isExpired is true.

After that:

  • The <BlockControls> and <Toolbar> components are used to create a toolbar within the block editor.
  • A <Button> component is placed within the toolbar, labeled "Inspect visibility problem" and assigned with a warning icon.
  • The onClick handler of the button toggles the isOpenWarningModal state between true and false whenever the button is clicked, which in turn controls the visibility of the warning modal.
  • The isPressed prop of the button reflects the isOpenWarningModal state, providing a visual indication of whether the modal is open.

Note, components like BlockControls and Button are part of the WordPress components library as well.

Ease of exit

People should read the warning and then easily dismiss the modal. No fuss, no hassle, just a smooth interaction that respects the person’s autonomy. This is the reason why I added a close button at the bottom of the warning modal.

The button lets the people know that they are not trapped:

<Modal
	title={__("This Block's Date is Old", "sortable")}
	onRequestClose={closeWarningModal}
	className="sortable-block__warning-modal"
>
	...
	
	<Button variant="secondary" onClick={closeWarningModal}>
		{__("Close Warning", "sortable")}
	</Button>
</Modal>

In the code snippet above, the <Button> component is added at the bottom of the <Modal> component. This button allows people to close the modal once they have acknowledged the information presented within it.

Here’s a detailed breakdown of the properties used in the <Button> component:

  • variant: This prop sets the variant of the button to "secondary", which affects the button's appearance based on the defined styles for the "secondary" variant.
  • onClick: This prop accepts a function (closeWarningModal) that will be triggered when the button is clicked. The function is responsible for toggling the visibility of the modal.
  • children: The text "Close Warning" is passed as children to the <Button> component, which will be displayed on the button. The __() function is used to wrap this text, making the string translation-ready.

Responsiveness

The modal should act like a chameleon, adapting seamlessly across devices. Whether people are updating their WordPress site on a desktop or mobile, the modal must be fully functional and usable.

WordPress core handles the majority of this adaptability internally when using its core components. However, there are cases where custom CSS is required to ensure the modal meets specific needs and functions.

To address this, I've applied a custom sortable-block__warning-modal class directly to the <Modal> component.

Accessibility

Although accessibility is mentioned as the last characteristic of a good modal, it is probably the most important aspect of ensuring a modal is user-friendly.

The warning icon in the toolbar is not just a visual cue. It must include a label, a crucial element that serves as a concise explainer. This ensures that every person, equipped with any device, can understand the purpose of that icon button.

Just like with responsiveness, WordPress takes care of many accessibility aspects the <Modal> component. However, WordPress cannot control what is used inside the modal.

WordPress does provide a framework that supports accessibility, but the specific content and markup within a modal (or any other custom component) are under the control of the developer.

Therefore, it's up to the developer to follow best practices, like using semantic markup, to ensure that their content remains accessible.

But remember, semantic markup helps to provide clear structure and meaning to the content, which in turn supports accessibility by making it easier for assistive technologies to interpret and navigate the content.