# Modal Drawer

A modal detail panel with focused operator actions.

## Installation

Download: /api/catalog/modal-drawer/download

Ignition Perspective 8.3. In a development project, choose Designer > File > Import and select the ZIP. Preserve the view and style-class paths. Review resource conflicts before replacing anything.

No separate stylesheet snippet is included.

Add an Embedded View (ia.display.view), set props.path to Overlays/ModalDrawer, and configure props.params using the contract below. Connect your own data in the host view. The package does not include live tags, page configuration or Gateway settings.

## Parameters

Types are inferred from saved defaults; directions come from native propConfig. These are not full schemas or validated ranges.

| Parameter | Type | Direction | Default |

| --- | --- | --- | --- |

| title | string | input | "Edit profile" |

| description | string | input | "Make changes to your profile here. Click save when you are done." |

| variant | string | input | "modal" |

| side | string | input | "right" |

| primaryLabel | string | input | "Save changes" |

| secondaryLabel | string | input | "Cancel" |

| popupId | string | input | "vc2-profile" |

| instanceId | string | input | "" |

| onPrimaryMessage | string | input | "viewcraft.modaldrawer.primary" |

| onCloseMessage | string | input | "viewcraft.modaldrawer.close" |

| name | string | inout | "Pedro Duarte" |

| username | string | inout | "@peduarte" |

## Embedded View usage

```json

{
  "type": "ia.display.view",
  "props": {
    "path": "Overlays/ModalDrawer",
    "params": {
      "title": "Edit profile",
      "description": "Make changes to your profile here. Click save when you are done.",
      "variant": "modal",
      "side": "right",
      "primaryLabel": "Save changes",
      "secondaryLabel": "Cancel",
      "popupId": "vc2-profile",
      "instanceId": "",
      "onPrimaryMessage": "viewcraft.modaldrawer.primary",
      "onCloseMessage": "viewcraft.modaldrawer.close",
      "name": "Pedro Duarte",
      "username": "@peduarte"
    },
    "useDefaultViewWidth": false,
    "useDefaultViewHeight": false
  }
}

```

## Verification

Source and archive hashes are checked. Designer import acceptance has not been completed for this archive; test in your development project before production.

## Files

### com.inductiveautomation.perspective/views/Overlays/ModalDrawer/view.json

```json

{
  "custom": {
    "reason": "dismiss"
  },
  "params": {
    "title": "Edit profile",
    "description": "Make changes to your profile here. Click save when you are done.",
    "variant": "modal",
    "side": "right",
    "primaryLabel": "Save changes",
    "secondaryLabel": "Cancel",
    "popupId": "vc2-profile",
    "instanceId": "",
    "onPrimaryMessage": "viewcraft.modaldrawer.primary",
    "onCloseMessage": "viewcraft.modaldrawer.close",
    "name": "Pedro Duarte",
    "username": "@peduarte"
  },
  "propConfig": {
    "params.title": {
      "paramDirection": "input"
    },
    "params.description": {
      "paramDirection": "input"
    },
    "params.variant": {
      "paramDirection": "input"
    },
    "params.side": {
      "paramDirection": "input"
    },
    "params.primaryLabel": {
      "paramDirection": "input"
    },
    "params.secondaryLabel": {
      "paramDirection": "input"
    },
    "params.popupId": {
      "paramDirection": "input"
    },
    "params.instanceId": {
      "paramDirection": "input"
    },
    "params.onPrimaryMessage": {
      "paramDirection": "input"
    },
    "params.onCloseMessage": {
      "paramDirection": "input"
    },
    "params.name": {
      "paramDirection": "inout"
    },
    "params.username": {
      "paramDirection": "inout"
    }
  },
  "props": {
    "defaultSize": {
      "width": 480,
      "height": 420
    }
  },
  "root": {
    "type": "ia.container.flex",
    "version": 0,
    "meta": {
      "name": "ModalDrawer"
    },
    "props": {
      "direction": "column",
      "style": {
        "classes": "vc2-dialog"
      }
    },
    "position": {
      "grow": 0,
      "shrink": 0,
      "basis": "auto"
    },
    "children": [
      {
        "type": "ia.input.button",
        "version": 0,
        "meta": {
          "name": "Close"
        },
        "props": {
          "text": "Close",
          "style": {
            "classes": "vc2-button vc2-close"
          }
        },
        "position": {
          "grow": 0,
          "shrink": 0,
          "basis": "36px"
        },
        "events": {
          "component": {
            "onActionPerformed": {
              "type": "script",
              "scope": "G",
              "config": {
                "script": "\tself.view.custom.reason = \"cancel\"\n\tsystem.perspective.closePopup(str(self.view.params.popupId))\n"
              }
            }
          }
        }
      },
      {
        "type": "ia.display.label",
        "version": 0,
        "meta": {
          "name": "Title"
        },
        "props": {
          "text": "Edit profile",
          "style": {
            "classes": "vc2-dialog-title"
          }
        },
        "position": {
          "grow": 0,
          "shrink": 0,
          "basis": "auto"
        },
        "propConfig": {
          "props.text": {
            "binding": {
              "type": "property",
              "config": {
                "path": "view.params.title"
              }
            }
          }
        }
      },
      {
        "type": "ia.display.label",
        "version": 0,
        "meta": {
          "name": "Description"
        },
        "props": {
          "text": "",
          "style": {
            "classes": "vc2-muted"
          }
        },
        "position": {
          "grow": 0,
          "shrink": 0,
          "basis": "auto"
        },
        "propConfig": {
          "props.text": {
            "binding": {
              "type": "property",
              "config": {
                "path": "view.params.description"
              }
            }
          }
        }
      },
      {
        "type": "ia.container.flex",
        "version": 0,
        "meta": {
          "name": "Fields"
        },
        "props": {
          "direction": "column",
          "style": {
            "classes": "vc2-fields"
          }
        },
        "position": {
          "grow": 0,
          "shrink": 0,
          "basis": "auto"
        },
        "children": [
          {
            "type": "ia.container.flex",
            "version": 0,
            "meta": {
              "name": "nameField"
            },
            "props": {
              "direction": "column",
              "style": {
                "classes": "vc2-field"
              }
            },
            "position": {
              "grow": 0,
              "shrink": 0,
              "basis": "auto"
            },
            "children": [
              {
                "type": "ia.display.label",
                "version": 0,
                "meta": {
                  "name": "nameLabel"
                },
                "props": {
                  "text": "Name",
                  "style": {
                    "classes": "vc2-field-label"
                  }
                },
                "position": {
                  "grow": 0,
                  "shrink": 0,
                  "basis": "auto"
                }
              },
              {
                "type": "ia.input.text-field",
                "version": 0,
                "meta": {
                  "name": "NameInput"
                },
                "props": {
                  "text": "",
                  "placeholder": "Name",
                  "deferUpdates": false,
                  "style": {
                    "classes": "vc2-input"
                  }
                },
                "position": {
                  "grow": 0,
                  "shrink": 0,
                  "basis": "36px"
                },
                "propConfig": {
                  "props.text": {
                    "binding": {
                      "type": "property",
                      "config": {
                        "path": "view.params.name",
                        "bidirectional": true
                      }
                    }
                  }
                }
              }
            ]
          },
          {
            "type": "ia.container.flex",
            "version": 0,
            "meta": {
              "name": "usernameField"
            },
            "props": {
              "direction": "column",
              "style": {
                "classes": "vc2-field"
              }
            },
            "position": {
              "grow": 0,
              "shrink": 0,
              "basis": "auto"
            },
            "children": [
              {
                "type": "ia.display.label",
                "version": 0,
                "meta": {
                  "name": "usernameLabel"
                },
                "props": {
                  "text": "Username",
                  "style": {
                    "classes": "vc2-field-label"
                  }
                },
                "position": {
                  "grow": 0,
                  "shrink": 0,
                  "basis": "auto"
                }
              },
              {
                "type": "ia.input.text-field",
                "version": 0,
                "meta": {
                  "name": "UsernameInput"
                },
                "props": {
                  "text": "",
                  "placeholder": "Username",
                  "deferUpdates": false,
                  "style": {
                    "classes": "vc2-input"
                  }
                },
                "position": {
                  "grow": 0,
                  "shrink": 0,
                  "basis": "36px"
                },
                "propConfig": {
                  "props.text": {
                    "binding": {
                      "type": "property",
                      "config": {
                        "path": "view.params.username",
                        "bidirectional": true
                      }
                    }
                  }
                }
              }
            ]
          }
        ]
      },
      {
        "type": "ia.container.flex",
        "version": 0,
        "meta": {
          "name": "Footer"
        },
        "props": {
          "direction": "row",
          "style": {
            "classes": "vc2-actions"
          }
        },
        "position": {
          "grow": 0,
          "shrink": 0,
          "basis": "auto"
        },
        "children": [
          {
            "type": "ia.input.button",
            "version": 0,
            "meta": {
              "name": "Cancel"
            },
            "props": {
              "text": "Cancel",
              "style": {
                "classes": "vc2-button"
              }
            },
            "position": {
              "grow": 0,
              "shrink": 0,
              "basis": "36px"
            },
            "events": {
              "component": {
                "onActionPerformed": {
                  "type": "script",
                  "scope": "G",
                  "config": {
                    "script": "\tself.view.custom.reason = \"cancel\"\n\tsystem.perspective.closePopup(str(self.view.params.popupId))\n"
                  }
                }
              }
            },
            "propConfig": {
              "props.text": {
                "binding": {
                  "type": "property",
                  "config": {
                    "path": "view.params.secondaryLabel"
                  }
                }
              }
            }
          },
          {
            "type": "ia.input.button",
            "version": 0,
            "meta": {
              "name": "Save"
            },
            "props": {
              "text": "Save changes",
              "style": {
                "classes": "vc2-button vc2-primary"
              }
            },
            "position": {
              "grow": 0,
              "shrink": 0,
              "basis": "36px"
            },
            "events": {
              "component": {
                "onActionPerformed": {
                  "type": "script",
                  "scope": "G",
                  "config": {
                    "script": "\tself.view.custom.reason = \"save\"\n\tmessage = str(self.view.params.onPrimaryMessage)\n\tif message:\n\t\tsystem.perspective.sendMessage(message, {\"instanceId\":str(self.view.params.instanceId),\"name\":str(self.view.params.name),\"username\":str(self.view.params.username),\"variant\":str(self.view.params.variant)}, scope=\"page\")\n\tsystem.perspective.closePopup(str(self.view.params.popupId))\n"
                  }
                }
              }
            },
            "propConfig": {
              "props.text": {
                "binding": {
                  "type": "property",
                  "config": {
                    "path": "view.params.primaryLabel"
                  }
                }
              }
            }
          }
        ]
      }
    ],
    "propConfig": {
      "props.style.classes": {
        "binding": {
          "type": "expr",
          "config": {
            "expression": "\"vc2-dialog\" + if({view.params.variant}=\"drawer\", \" vc2-sheet vc2-sheet-\"+{view.params.side}, \"\")"
          }
        }
      }
    },
    "events": {
      "dom": {
        "onKeyDown": {
          "type": "script",
          "scope": "G",
          "config": {
            "script": "\tif event.key == \"Escape\":\n\t\tself.view.custom.reason = \"dismiss\"\n\t\tsystem.perspective.closePopup(str(self.view.params.popupId))\n"
          }
        }
      },
      "system": {
        "onShutdown": {
          "type": "script",
          "scope": "G",
          "config": {
            "script": "\tmessage = str(self.view.params.onCloseMessage)\n\tif message:\n\t\tsystem.perspective.sendMessage(message, {\"instanceId\":str(self.view.params.instanceId),\"reason\":str(self.view.custom.reason)}, scope=\"page\")\n"
          }
        }
      }
    }
  }
}


```

### com.inductiveautomation.perspective/views/Overlays/ModalDrawer/resource.json

```json

{
  "scope": "G",
  "version": 1,
  "restricted": false,
  "overridable": true,
  "files": [
    "view.json"
  ]
}

```