UI

Using the Preact component library#

@create-figma-plugin/ui is a library of production-grade Preact components that replicate the Figma/FigJam editor’s UI design.

UI components from @create-figma-plugin/ui: Button, File Upload Dropzone, Textbox Numeric, Textbox Autocomplete, Checkbox, Selectable Item, Segmented Control

See the full library of components in the Storybook.

The component library ships with three themes:

  1. Figma Design: Light
  2. Figma Design: Dark
  3. FigJam

If the UI is launched from a Figma plugin/widget, components will automatically render using the Figma Design theme (either Light or Dark, based on the user’s preferences as set in the Figma app). If the UI is launched from a FigJam plugin/widget, components will automatically render using the FigJam theme.

UI of the Insert Big Image plugin rendered using the Figma and FigJam themes

To install, do:

$ npm install @create-figma-plugin/ui preact

Then, include a call to showUI in your plugin/widget’s main entry point.

Consider a toy Figma plugin:

// src/main.ts
 
import { showUI } from '@create-figma-plugin/utilities'
 
export default function () {
  const options = { width: 240, height: 120 }
  const data = { greeting: 'Hello, World!' }
  showUI(options, data)
}

showUI takes two arguments, and the second data argument is useful for passing some initializing data to the UI.

Next, create a file for our UI (eg. src/ui.tsx):

// src/ui.tsx
 
import { render, Container, Text, VerticalSpace } from '@create-figma-plugin/ui'
import { h } from 'preact'
 
function Plugin (props: { greeting: string }) {
  return (
    <Container space='medium'>
      <VerticalSpace space='medium' />
      <Text>{props.greeting}</Text>
      <VerticalSpace space='medium' />
    </Container>
  )
}
 
export default render(Plugin)

See that:

  • render takes a single argument, Plugin, which is a Preact functional component.
  • The props received by the Plugin component is precisely the data object that was passed to showUI from the plugin/widget’s main entry point.

Finally, in package.json, point to our UI file on the "ui" key under "figma-plugin":

{
  // ...
  "figma-plugin": {
    // ...
    "name": "Hello World",
    "main": "src/main.ts",
    "ui": "src/ui.tsx"
  }
}

When we rebuild our plugin and run it, we’ll see:

Figma plugin UI modal with “Hello, World” text

See the Storybook for the full library of Preact components, and the recipe for passing data between the plugin/widget’s main and UI contexts.

Using React#

When building your plugin/widget, the build-figma-plugin CLI will detect and automatically swap out all react and react-dom imports with preact/compat. This means that it’s possible to seamlessly use React components alongside the Preact components from the @create-figma-plugin/ui library.

(If you still prefer to bundle React rather than Preact, see the recipe to disable the automatic swapping of React imports.)

To use React components in your UI, ensure that react and @types/react are installed:

$ npm install --save-dev react @types/react

For a runnable example, try the react-editor plugin template:

$ npx --yes create-figma-plugin --template plugin/react-editor

Using custom CSS#

Out of the box, the build-figma-plugin CLI supports CSS Modules:

/* src/styles.css */
 
.container {
  background-color: var(--figma-color-bg-secondary);
}
// src/ui.tsx
 
import { render } from '@create-figma-plugin/ui'
import { h } from 'preact'
import styles from './styles.css'
 
function Plugin () {
  // ...
  return (
    <div class={styles.container}>
      {/* ... */}
    </div>
  )
}
 
export default render(Plugin)

By default, all the class names in CSS files imported via an import statement (as in the above example) will be hashed. This is to ensure that each class name is globally unique.

To directly “inline” a CSS file in your UI without hashing its class names, add a ! prefix to the import path:

// src/ui.tsx
 
import { render } from '@create-figma-plugin/ui'
import { h } from 'preact'
import '!./styles.css'
 
function Plugin () {
  // ...
  return (
    <div class="container">
      {/* ... */}
    </div>
  )
}
 
export default render(Plugin)

Refer to the base.css file in @create-figma-plugin/ui for the list of CSS variables that are available for use in your custom CSS.

Using a custom UI library#

To use a custom UI library instead of @create-figma-plugin/ui, write your UI implementation as follows:

// src/ui.ts
 
export default function (rootNode: HTMLElement, data: { greeting: string }) {
  rootNode.innerHTML = `<p>${data.greeting}</p>` //=> <p>Hello, World!</p>
}

The exported function receives two arguments:

  • rootNode — An empty <div> element within which you can render your UI.
  • data — This corresponds to the data object that was passed to showUI from the plugin/widget’s main entry point.