Create a modal

Modals are used, for example, when user input is expected before an operation can be executed. Before creating a modal always check if the modal doesn't already exist. See our list of available modals for more information.

Create a modal component

Start by making a component which uses <Modal> as its root element. When the modal is opened with an operation step a few props are added to the component ('Use the modal component' explains this more):

  • cancelModal: A callback that closes the modal and cancels the running operation when called.
  • data: All operation data that is on the operation when the modal is opened.
  • submitModal: A callback that closes the modal and continues with executing the operation when called. The data that is submitted will be merged into the already existing operation data.

A simple modal can be made with <Modal>, <ModalHeader>, <ModalBody> and <ModalFooter>.

ExampleModal.jsx
import React, { useCallback, useEffect, useRef, useState } from 'react';

import { Button, Modal, ModalBody, ModalFooter, ModalHeader, TextInput } from 'fds/components';

function ExampleModal ({ cancelModal, data, submitModal }) {
	const textInputRef = useRef(null);

	const [exampleValue, setExampleValue] = useState(data.exampleValue || '');

	const handleKeyDown = useCallback(event => {
		switch (event.key) {
			case 'Escape':
				cancelModal();
				break;
			case 'Enter':
				if (exampleValue !== '') {
					submitModal({ exampleValue });
				}
				break;
		}
	}, [cancelModal, exampleValue, submitModal]);

	const handleTextInputRef = useCallback(ref => (textInputRef.current = ref), []);

	const handleSubmitButtonClick = useCallback(() => submitModal({ exampleValue }), [exampleValue, submitModal]);

	useEffect(() => {
		textInputRef.current.focus();
	}, []);

	return (
		<Modal size="s" onKeyDown={handleKeyDown}>
			<ModalHeader icon="clock-o" title="Enter the example value" />

			<ModalBody>
				<TextInput
					onChange={setExampleValue}
					onRef={handleTextInputRef}
					value={exampleValue}
				/>
			</ModalBody>

			<ModalFooter>
				<Button label="Cancel" onClick={cancelModal} />

				<Button
					isDisabled={exampleValue === ''}
					label={data.modalPrimaryButtonLabel || 'Insert'}
					onClick={handleSubmitButtonClick}
					type="primary"
				/>
			</ModalFooter>
		</Modal>
	);
}

export default ExampleModal;

If your modal needs a more complex layout; the content for your modal body needs to be divided into separate areas and/or a toolbar is needed, use the following components:

  • <ModalBodyToolbar>: Creates a toolbar, usually placed above the <ModalContent>. Generally used to contain components like <TabButtons>.
  • <ModalContent>: Can be used to make different bordered area's. As long as the modal content components are only nested in <ModalBody> or each other, they will handle which borders to draw. The flexDirection  and flex properties can be used to layout each modal content area as you would normally do with flexbox CSS.
  • <ModalContentToolbar>: A toolbar inside a <ModalContentfor a specific area. Generally used to to contain components like <Breadcrumbs> or <SearchInput>.
<ModalBody>
	<ModalBodyToolbar>
		<TabButtons>
			<TabButton label="All" isActive={activeTab === 'all'} onClick={handleAllTabButtonClick} />
			
			<TabButton label="Recent" isActive={activeTab === 'recent'} onClick={handleRecentTabButtonClick} />
			
			<TabButton label="Search" isActive={activeTab === 'search'} onClick={handleSearchTabButtonClick} />
		</TabButtons>
	</ModalBodyToolbar>

	<ModalContent flexDirection="column">
		<ModalContentToolbar justifyContent="flex-end">
			<SearchInput onChange={handleSearchInputChange} value={searchInputValue} />
		</ModalContentToolbar>
		
		<ModalContent flexDirection="row">
			<ModalContent flexDirection="column">left side</ModalContent>
			
			<ModalContent flex="2" flexDirection="column">
				<ModalContent flexDirection="column">right side above</ModalContent>

				<ModalContent flexDirection="column">right side below</ModalContent>
			</ModalContent>
		</ModalContent>
	</ModalContent>
</ModalBody>

Register the modal component

Register the modal component in the install.js. Now the modal can be used under the registered name.

install.js
import uiManager from 'fontoxml-modular-ui/src/uiManager.js';

import ExampleModal from './ui/ExampleModal.jsx';

export default function install() {
	uiManager.registerReactComponent('ExampleModal', ExampleModal);
}

Use the modal component from an operation

When the modal is used in an operation it is added in a step. The type of this step is 'modal' followed by the registered modal name. It is common practice to add the data the modal uses as data of the modal step.

operations.json
"open-example-modal": {
	"steps": {
		"type": "modal/ExampleModal",
		"data": {
			"exampleValue": "{{exampleValue}}",
			"modalPrimaryButtonLabel": "{{modalPrimaryButtonLabel}}"	
		}
	}
}

Use the modal from the attributes editor add-on

It is also possible to open a modal with <FxButtonWithValueFromModal>. This is a build-in option in the attributes editor, add the registered modal component name and display 'button-with-value-from-modal' to the configuration of the attribute.

{
	"self::example": {
		"value": {
			"localName": "value",
			"label": "Value",
			"display": "button-with-value-from-modal",
			"properties": {
				"buttonLabel": "Example value",
				"modalComponentName": "ExampleModal"
			}
		}
	}
}

Available modals

Apart from creating a custom modal, the platform offers some complete modals. Which can be used in configuration or if the package is open source it can be forked, in that case the modal can be altered so it will fit the use case.

Existing operations for browse modals:

State message modals:

  • WarningModal Add a operation step to open the WarningModal. Add data, to define the body, title and button labels of the modal.
  • Add a pleaseWaitMessage to the operation data, to show the please wait modal while the operation is running.

Modals for specific use cases with specific operations:

Was this page helpful?