# Overview

Source: https://docs.interop.io/desktop/capabilities/windows/modals/overview/index.html

## Overview

> ⚠️ *Note that this feature is still experimental in **io.Connect Desktop**.*

**io.Connect Desktop** supports a set of predefined modal windows (alerts and dialogs), which you can use in your interop-enabled apps via the [`@interopio/modals-api`](https://www.npmjs.com/package/@interopio/modals-api) library. The Modals API also enables you to display your own custom alerts and dialogs.

> ⚠️ *Note that you can also use the [`showDialog()`](https://docs.interop.io/desktop/reference/javascript/windows/ioconnectwindow/index.md#IOConnectWindow-showDialog) method of an [`IOConnectWindow`](https://docs.interop.io/desktop/reference/javascript/windows/ioconnectwindow/index.md) instance to [show dialogs](https://docs.interop.io/desktop/capabilities/windows/window-management/javascript/index.md#window_operations-dialogs) from your apps. This method is still supported and you can use it to show the already existing set of [predefined dialogs](https://docs.interop.io/desktop/capabilities/windows/window-management/javascript/index.md#window_operations-dialogs-predefined_dialogs), as well as [custom](https://docs.interop.io/desktop/capabilities/windows/window-management/javascript/index.md#window_operations-dialogs-custom_dialogs) ones, but it doesn't support the set of predefined dialogs available via the new [`@interopio/modals-api`](https://www.npmjs.com/package/@interopio/modals-api) library. Respectively, the `@interopio/modals-api` library doesn't support the predefined dialogs available via the `showDialog()` method.*

## Configuration

The following sections describe the available configuration settings for the io.Connect alerts and dialogs.

### Alerts

Available since io.Connect Desktop 9.9

To provide settings for alert windows, use the `"alerts"` top-level key in the `system.json` [system configuration](https://docs.interop.io/desktop/developers/configuration/system/index.md) file of **io.Connect Desktop**:

```json
{
    "alerts": {
        "enabled": true,
        "width": 450,
        "height": 100,
        "ttl": 7000,
        "roundedCorners": true
    }
}
```

The `"alerts"` object has the following properties:

| Property | Type | Description |
|----------|------|-------------|
| `"enabled"` | `boolean` | If `true` (default), will enable the io.Connect alerts. |
| `"height"` | `number` | Height in pixels for the io.Connect alerts. Defaults to `82`. |
| `"roundedCorners"` | `boolean` | If `true`, the io.Connect Window containing the alerts will have rounded corners. Defaults to `false`. |
| `"transparent"` | `boolean` | If `true` (default), the io.Connect Window containing the alerts will be transparent. |
| `"ttl"` | `number` | Interval in milliseconds that defines how long the alert is displayed to the user before it automatically disappears. Defaults to `5000`. |
| `"url"` | `string` | URL pointing to the location of the io.Connect alerts app. You can use this to provide a URL pointing to your custom alerts app. |
| `"width"` | `number` | Width in pixels for the io.Connect alerts. Defaults to `400`. |

### Dialogs

To provide settings for dialog windows, use the `"dialogs"` top-level key in the `system.json` [system configuration](https://docs.interop.io/desktop/developers/configuration/system/index.md) file of **io.Connect Desktop**:

```json
{
    "dialogs": {
        "url": "https://my-custom-dialog.com",
        "width": 380,
        "height": 150,
        "enableDefaultDialogs": {
            "preventShutdown": false,
            "preventWindowClose": false
        }
    }
}
```

The `"dialogs"` object has the following properties:

| Property | Type | Description |
|----------|------|-------------|
| `"enableDefaultDialogs"` | `object` | Enable or disable the default io.Connect dialog messages. |
| `"height"` | `number` | Height in pixels for the io.Connect dialogs. Defaults to `205`. |
| `"transparent"` | `boolean` | If `true`, the io.Connect Window containing the dialog will be transparent. |
| `"url"` | `string` | URL pointing to the location of the io.Connect dialog app. |
| `"width"` | `number` | Width in pixels for the io.Connect dialogs. Defaults to `400`. |

The `"enableDefaultDialogs"` object has the following properties:

 Property | Type | Description |
|----------|------|-------------|
| `"preventShutdown"` | `boolean` | If `true` (default), will enable the dialog message that appears when **io.Connect Desktop** is about to shutdown. |
| `"preventWindowClose"` | `boolean` | If `true` (default), will enable the dialog message that appears when the user tries to close an io.Connect Window that is programmatically prevented from closing. This dialog will appear also when such window participates in a Layout that is being closed. |
| `"unsavedLayoutChanges"` | `boolean` | If `true`, will enable the dialog message that appears when the user modifies the current [Global Layout](https://docs.interop.io/desktop/capabilities/windows/layouts/overview/index.md) and tries to restore another Global Layout. Defaults to `false`. *Available since **io.Connect Desktop** 9.2.* |

## Styles

To customize the styles of the io.Connect modal windows, use the [CSS variables](https://docs.interop.io/desktop/developers/platform-styles/index.md#modals) provided by the io.Connect themes.

## Custom Apps

### Alerts

Besides using the available io.Connect alerts, you can also define an entirely custom alert app to be used by the platform. To do so, set the `"url"` property of the `"alerts"` top-level key in the `system.json` [system configuration](https://docs.interop.io/desktop/developers/configuration/system/index.md#alerts) file of **io.Connect Desktop** to the location of your custom alert app:

```json
{
    "alerts": {
        "url": "https://my-custom-alert.com"
    }
}
```

When an interop-enabled app invokes the [`request()`](https://docs.interop.io/desktop/reference/javascript/modals/alertsapi/index.md#AlertsAPI-request) method of the Alerts API, **io.Connect Desktop** will load the custom alert app instead of the default one.

Available since io.Connect Desktop 10.2

The custom alert app can use the `ioAlert` service object injected in the global `window` object to receive the alert configuration sent by the client app and to communicate back to the platform.

The `ioAlert` object has the following methods:

| Method | Description |
|--------|-------------|
| `getConfig()` | Resolves with the [`AlertRequestConfig`](https://docs.interop.io/desktop/reference/javascript/modals/alertrequestconfig/index.md) object passed to the [`request()`](https://docs.interop.io/desktop/reference/javascript/modals/alertsapi/index.md#AlertsAPI-request) method by the client app. Use this method to receive the alert options provided by the app that triggered the alert. |
| `getTheme()` | Returns the name of the current io.Connect theme as a string. Use this to apply the appropriate theme styling to the custom alert. |
| `onThemeChanged()` | Notifies when the theme changes. Receives a callback function as an argument. The callback will be invoked with the name of the new theme as an argument. |
| `setResult()` | Sends the result of the user interaction back to the client app and closes the alert. Receives the data to return as an argument, which can be any type. |

The following example demonstrates how to use the `ioAlert` object in a custom alert app to retrieve the alert options provided by the client app and handle user interactions:

```javascript
// Retrieve the alert options provided by the client app.
const { variant, text, actions, showCloseButton } = await ioAlert.getConfig();

// Apply the alert options to the alert UI.
document.getElementById("alert-text").textContent = text;
document.getElementById("alert-container").classList.add(variant);

// Apply the current io.Connect theme.
const ioTheme = ioAlert.getTheme();

document.documentElement.classList.add(ioTheme);

// React to theme changes.
ioAlert.onThemeChanged((newTheme) => {
    document.documentElement.classList.replace(ioTheme, newTheme);
});

// Handle action button clicks.
if (actions) {
    actions.forEach((action) => {
        const button = document.createElement("button");

        button.textContent = action.title;
        button.addEventListener("click", () => {
            // Return the result to the client app and close the alert.
            ioAlert.setResult({ action: action.title });
        });
        document.getElementById("actions-container").appendChild(button);
    });
}

// Handle close button click.
if (showCloseButton) {
    document.getElementById("close-button").addEventListener("click", () => {
        ioAlert.setResult({ action: "dismissed" });
    });
}
```

### Dialogs

> ⚠️ *Note that the described functionalities are available when using the [`request()`](https://docs.interop.io/desktop/reference/javascript/modals/dialogsapi/index.md#DialogsAPI-request) of the [Dialogs API](https://docs.interop.io/desktop/capabilities/windows/modals/javascript/index.md#dialogs), as well as the [`showDialog()`](https://docs.interop.io/desktop/reference/javascript/windows/ioconnectwindow/index.md#IOConnectWindow-showDialog) method of an [`IOConnectWindow`](https://docs.interop.io/desktop/reference/javascript/windows/ioconnectwindow/index.md) or a [`Frame`](https://docs.interop.io/desktop/reference/javascript/workspaces/frame/index.md) instance. However, it's highly recommended to use the [Dialogs API](https://docs.interop.io/desktop/capabilities/windows/modals/javascript/index.md) to display dialogs instead of the `showDialog()` method.*

Besides using the available io.Connect dialogs, you can also define an entirely custom dialog app to be used by the platform. To do so, set the `"url"` property of the `"dialogs"` top-level key in the `system.json` [system configuration](https://docs.interop.io/desktop/developers/configuration/system/index.md#dialogs) file of **io.Connect Desktop** to the location of your custom dialog app:

```json
{
    "dialogs": {
        "url": "https://my-custom-dialog.com"
    }
}
```

When an interop-enabled app invokes the `request()` method of the Dialogs API, **io.Connect Desktop** will load the custom dialog app instead of the default one.

Available since io.Connect Desktop 10.2

The custom dialog app can use the `ioDialog` service object injected in the global `window` object to receive the dialog options sent by the client app and to return data back to it.

The `ioDialog` object has the following methods:

| Method | Description |
|--------|-------------|
| `getConfig()` | Resolves with the dialog options passed by the client app. If the dialog was triggered via the `request()` method of the Dialogs API, the returned value will be a [`DialogRequestConfig`](https://docs.interop.io/desktop/reference/javascript/modals/dialogrequestconfig/index.md) object. If the dialog was triggered via the `showDialog()` method of an `IOConnectWindow` or a Workspace `Frame` instance, the returned value will be a [`DialogOptions`](https://docs.interop.io/desktop/reference/javascript/windows/dialogoptions/index.md) object. Use this method to receive the dialog options and determine how to render the dialog. |
| `getTheme()` | Returns the name of the current io.Connect theme as a string. Use this to apply the appropriate theme styling to the custom dialog. |
| `onThemeChanged()` | Notifies when the theme changes. Receives a callback function as an argument. The callback will be invoked with the name of the new theme as an argument. |
| `setResult()` | Sends the result of the user interaction back to the client app and closes the dialog. Receives the data to return as an argument, which can be any type. |

The following example demonstrates how to use the `ioDialog` object in a custom dialog app to retrieve the dialog options provided by the client app and return data back to it:

```javascript
// Retrieve the dialog options provided by the client app.
const { templateName, variables } = await ioDialog.getConfig();

// Apply the dialog options to the dialog UI.
document.getElementById("dialog-title").textContent = variables.title;
document.getElementById("dialog-message").textContent = variables.text;

// Apply the current io.Connect theme.
const ioTheme = ioDialog.getTheme();

document.documentElement.classList.add(ioTheme);

// React to theme changes.
const themeHandler = newTheme => document.documentElement.classList.replace(ioTheme, newTheme);

ioDialog.onThemeChanged(themeHandler);

// React to user interaction and return the result to the client app.
// The returned data can be of any type.
const result = { buttonClicked: null, context: 42 };
// Determine the template of the requested dialog and react accordingly.
if (templateName === "MyCustomDialog") {
    result.buttonClicked = { id: "confirm", text: "Confirm" };
}

const clickHandler = () => ioDialog.setResult(result);

document.getElementById("confirm-button").addEventListener("click", clickHandler);
```

You can specify a custom `templateName` in your client app and invoke the [`request()`](https://docs.interop.io/desktop/reference/javascript/modals/dialogsapi/index.md#DialogsAPI-request) method with it:

```javascript
const myDialog = {
    // Specifying a custom dialog template.
    templateName: "MyCustomDialog",
    variables: {
        title: "Custom Title",
        text: "Custom Message"
    }
};
// The client app will receive the result from opening the custom dialog
// in the exact shape as returned by the custom dialog app.
const { buttonClicked, context } = await io.modals.dialogs.request(myDialog);

// Handle the dialog result with your custom logic.
handleDialogResult(responseButtonClicked, isClosed, inputs);
```
