Six Steps to Creating Your First XD Plugin Using React
A step by step guide to creating a panel plugin for Adobe XD using React, created at the Adobe Fund for Design Plugin Accelerator
“Today’s guest post is by Matt Holcombe, a Co-Founder and CTO of Pair, an NPM Module for product teams who review and critique front-end design. This summer, Pair took part in the Adobe Fund for Design Plugin Accelerator (cohort 1). The Plugin Accelerator was a three month in-house program where Pair had the opportunity to work 1:1 with the Adobe XD team.
In this article, Matt and Jason provide a solid panel plugin example (built with React) that populates shapes with random images from Unsplash, and exports
Editor’s Note: We’ve had several requests for plugins which export React code from Adobe XD. Please note, this article covers writing XD plugins using React.”
— Erin Finnegan, Community Engineer, Creative Cloud
A little background information
WebSocket in XD behave pretty much as expected. UXP is, however, not all encompassing as mentioned previously, supporting a limited number of elements and APIs. Plus only a subset of CSS is available to further style UI elements. (Editor’s Note: The file system access limitation is a constraint of Adobe XD, and not UXP as a whole. Also note that UXP continues to evolve; keep watching this blog for updates.)
The two fundamental resources that I exploited extensively during my time plugin developing this summer were the Adobe XD Platform Community Forums and the Adobe XD API References. The forum’s posts are never ignored or neglected; you can expect a response from a vetted Adobe employee or another knowledgeable forum member within a day’s time. The API documentation is pretty comprehensive and verbose, even housing several quick start tutorials for different plugin types and development strategies, plus many more miscellaneous technical references to check out.
Step 0: Modal or Panel?
There are two kinds of plugin flows supported by Adobe XD: dialog (or modal) and panel. Dialog plugins drop down from the top of the application and block further user interaction until dismissed. Think of the “Save File As…” dialog from the OS. They have their place, but not all tasks benefit from the need to interrupt workflow. Panel plugins fill that role, integrating nicely into a dedicated area off to the side (the plugins panel). Think of a color wheel, or a histogram / spectrum thingy monitoring document changes, affecting the plugin’s UI. A histogram presents relevant UI back to the user based on accurate data coming from the
SceneGraph (a data structure representing a hierarchical tree of nodes). That’s also the ticket to manipulating the document as the plugin’s controls are pressed, tweaked, and pushed in real-time. The plugin effectively becomes another tool to use, embedded right into Adobe XD’s native application.
Step 1: Setting up your Project
Getting up and running is a fairly simple process. The first thing on the list is getting a hold of Adobe XD v21 or greater. Additionally, you will need:
- A repository management tool like
git, used behind the scenes by the build tools. You’ll also need it to pull down the example code, and push it back up to your own repo if you wish.
Once you have Adobe XD and the required software installed, the next step is locating your local plugin development folder. This can be found easily by opening the Adobe XD application, navigating to the main menu, then selecting the Plugins menu item. From there, choose Development -> Show Develop Folder.
Step 2: Project Installation
For this demo, there’s already a simple project I created over on GitHub. Go ahead and
git clone https://github.com/de-ai/xd-blog-expo.git /your/plugin/folder. Once the project has been pulled down, execute
yarn install within the project’s root directory to pull in the necessary dependencies. Keep a file watcher going to recompile the project automatically, by typing
npm run watch (or
yarn watch) in the terminal also from the project’s root folder.
Step 3: How to Debug your Project
Adobe XD provides a developer output console, where runtime errors and
console.log() statements are logged. It can be opened via the menu Plugins -> Development -> Developer Console.
For your convenience, plugins in develop mode can be reloaded quickly to reflect their latest changes. From the menu: Plugins -> Development -> Reload plugins or by keyboard shortcut if you’re into that kind of thing: Shift+Cmd+R (macOS) / Ctrl+Shift+R (Windows).
Step 4: Specific Adobe XD Resources
A required configuration file named
manifest.json is first up in the sample project. It contains some definitions and metadata pertaining to a plugin. Read this section of the documentation for a detailed explanation about the file specification.
webpack.config.js file included is pretty standard, the only bit that deserves attention is the
externals entry. This is where imported native XD modules are listed. The webpacked code will use these from the installed XD binary instead of bundling them with the build. So the plugin user’s XD application will include these at runtime on their local machine.
Editor’s Note: The
react-shim.js below is no longer required as of XD 24.
With the configs squared away, let’s investigate the project’s
src folder. The plugin’s starting point is
main.jsx (defined in
webpack’s config). A pretty standard looking entry point, besides the first line that requires the helper file
react-shim.js as shown below:
window’s iframe element to the
HTMLIFrameElement built into XD.
After the plugin successfully loads,
show() is called, where the
App instance is attached to a generated root
div element, then rendered in typical React fashion. Afterwards, whenever the
SceneGraph changes, the
update() function is called, which calls
App, passing along the current selection with the
SceneGraph root node. When the plugin unloads,
hide() is invoked and
App is then unmounted. For the detailed plugin lifecycle explanation, check out this overview on the XD Platform site.
Step 5: Adding UI Components
App displays three inner components within the plugin panel area and handles a couple of their actions.
The most important (and exciting) XD specific happening here is the
editDocument function. The first parameter is the undo label (what the plugin user sees under the menu Edit -> Undo). The second is a function passing the current selection +
SceneGraph root node. It’s extremely important to note that this is the only place where document changes can be made from code. So in this instance of
App, a bounding rectangle is calculated from the union of one or more selected items on the canvas. The
viewport (canvas viewing area) is then panned and zoomed to those bounds.
To reiterate, the only way to make edits on the
SceneGraph is by using
editDocument(), and it can only be invoked by a user interaction like a button click or input change originating from the plugin’s UI. If the action is asynchronous, such as fetching remote data, the operation must use a
Promise or the
await keywords in order to “pause” the plugin until the action completes.
We’ll skip the two ancillary section components declared in
App, as they are made up of the usual standard React code. Have a look at them on your own if you wish, otherwise let’s move on to
Above, the UI is composed of three buttons demonstrating some plugin capabilities. Their
disabled attributes are set based on the current selection, and a
uxp-variant attribute provides basic built-in styling loosely adhering to XD’s native UI. A list of UXP variants can be found here.
The first button passes its click handler up to
App to pan and zoom the
viewport, which we already covered.
The second button fills a shape type object with a random JPEG image provided by Unsplash’s Dev API. Bear in mind, this API key provided is just a demo app with only 50 calls / hour, so please don’t abuse it. If you feel so inclined, create your own app and use that key in its place. Within the handler’s
editDocument(), a first
async call is made, which returns a JSON object describing the image. The
description entry is used to rename the layer, one of the source URLs is also grabbed for use on the following
fetch call. Taking the entry’s full size image URL through the second and last
fetch call, the response is converted from a data buffer to a binary string. Finally the selected node gets filled with the base-64 encoded representation of that binary image data.
Lastly, the third button exports an image file (PNG or SVG), depending on fill type for each of the selected canvas layers. An “Open File” dialog is presented courtesy of the file system to choose a location to write the rendition(s). After confirmed, a file handler is created at that path with a name generated from the layer’s
name plus it’s
guid (a UUID) properties. A set of export options are defined,
createRendition() is called, ultimately writing the file contents and closing the handle.
Final Step: Packaging your Plugin
Creating a distributable version of your React plugin is a fairly simple process. First execute
yarn build within the project’s root folder. The bundled JS is written by
main.js, located off the project’s root folder. Files imported in the source by using the
require statement will also be copied and renamed with a hash to this location (if you haven’t modified
webpack.config.js). You’ll first have to create a standard ZIP file adding
images folder, plus any other assets placed on the root folder by
webpack just mentioned previously. Then change the file extension from
.xdx, so Adobe XD recognises it as a plugin package. Double clicking on the renamed
.xdx file will install the plugin in the conventional plugin folder so long as the manifest checks out.
To publicly distribute the plugin to users through Adobe’s in-app Plugin Manager requires a few more steps:
- Head over to the Adobe I/O Console, and create a new application if you haven’t done so already.
- Upload the packaged XDX file to kick off the submission process. After the
manifest.jsonpasses validation, you’ll be prompted for some additional info, namely some product text descriptions, additional icons, plus a screenshot for the Plugin Manager storefront.
- Lastly, provide any review notes such as test account logins or other specific instructions needed for a complete review.
If everything checks out, you’ll be able to submit, and the Creative Cloud Integrations team will start the review process. After ten business days or less, the review team should get back to you with a response whether or not the submission was approved or rejected (with steps to remedy if need be). For more detailed publication steps, follow this guide. (For tips on avoiding a rejection check out this article.)
As you can see, creating a React plugin for Adobe XD is both simple and straight forward development. I hope this demonstration sparks your interest to create your own XD plugin(s) for your own use, but also to share with the rest of the XD community.
Here’s a list of resources mentioned you may find useful:
For more stories like this, subscribe to the Creative Cloud Developer Newsletter.