Skip to main content

Plugins

Plugin UI Guide

Build polished plugin interfaces using HTML, CSS, and Figma's design patterns.

Plugin UIs run in an iframe and can use any web technology. This guide covers best practices for building interfaces that feel native to Figma.

UI Basics

The UI is an HTML file loaded in an iframe. It communicates with the plugin sandbox via postMessage:

<div id="app">
  <label>Layer name</label>
  <input type="text" id="name-input" placeholder="Enter name...">
  <button id="apply-btn">Apply</button>
</div>

<script>
  document.getElementById('apply-btn').onclick = () => {
    const name = document.getElementById('name-input').value;
    parent.postMessage(
      { pluginMessage: { type: 'rename', name } },
      '*'
    );
  };

  // Receive messages from the plugin
  onmessage = (event) => {
    const msg = event.data.pluginMessage;
    if (msg.type === 'selection-changed') {
      document.getElementById('name-input').value = msg.name;
    }
  };
</script>

Sizing the UI

Set the UI dimensions when showing it:

figma.showUI(__html__, {
  width: 320,
  height: 480,
  title: "My Plugin",
});

Styling Best Practices

Use styles that match Figma’s native interface:

/* Base styles matching Figma's UI */
:root {
  --figma-color-bg: #ffffff;
  --figma-color-text: #333333;
  --figma-color-border: #e5e5e5;
  --figma-color-primary: #0d99ff;
  --figma-radius: 6px;
  --figma-font: Inter, -apple-system, sans-serif;
}

body {
  margin: 0;
  padding: 12px;
  font-family: var(--figma-font);
  font-size: 11px;
  color: var(--figma-color-text);
  background: var(--figma-color-bg);
}

input, select {
  width: 100%;
  padding: 6px 8px;
  border: 1px solid var(--figma-color-border);
  border-radius: var(--figma-radius);
  font-size: 11px;
  font-family: inherit;
  outline: none;
}

input:focus {
  border-color: var(--figma-color-primary);
  box-shadow: 0 0 0 1px var(--figma-color-primary);
}

button {
  padding: 6px 16px;
  border: none;
  border-radius: var(--figma-radius);
  background: var(--figma-color-primary);
  color: white;
  font-size: 11px;
  font-weight: 500;
  cursor: pointer;
}

Figma provides CSS variables for theming. When running inside Figma, you can use figma-color-bg, figma-color-text, and other tokens to match the current Figma theme (light or dark).

Handling Network Requests

Since the main thread can’t access fetch, route network calls through the UI:

// code.ts — request data from UI
figma.ui.postMessage({ type: 'fetch-data', url: 'https://api.example.com/data' });

figma.ui.onmessage = (msg) => {
  if (msg.type === 'fetch-response') {
    // Use the fetched data
    console.log(msg.data);
  }
};
<!-- ui.html — handle fetch requests -->
<script>
onmessage = async (event) => {
  const msg = event.data.pluginMessage;
  if (msg.type === 'fetch-data') {
    const response = await fetch(msg.url);
    const data = await response.json();
    parent.postMessage(
      { pluginMessage: { type: 'fetch-response', data } },
      '*'
    );
  }
};
</script>

Consider using a framework like React or Svelte for complex plugin UIs. Bundle everything into a single ui.html using esbuild or Vite.