Create Figma Plugin

repository·main·Indexed 22 days ago

https://github.com/yuanqing/create-figma-plugin

A comprehensive toolkit for developers to build, scaffold, and manage Figma plugins and widgets using modern web technologies. It provides scaffolding, build tooling, and utilities to handle the separation of sandbox logic from UI logic, generating the required manifest.json and JavaScript bundles for the Figma desktop app.

Tokens
17.1K
Snippets
56
Records
97
Agent score
77%

What's inside create-figma-plugin

  1. Overview of Create Figma Plugin

    main

    Create Figma Plugin is a comprehensive toolkit designed for developing Figma plugins and widgets. It provides a local development environment with built-in support for TypeScript and CSS Modules, and uses the esbuild compiler to achieve sub-second build times.

    Key capabilities include:

    • Bootstrapping: Quickly start new projects using pre-configured templates.
    • Bundling: Automatic bundling and minification of TypeScript or JavaScript code.
    • UI Development: A library of Preact components that replicate the Figma/FigJam editor's UI design, including native support for dark mode.
    • Command Management: Support for defining plugin menu commands in separate files, allowing each command to have its own unique UI implementation.
    • Data Communication: Extensive utility functions for passing data between a plugin/widget's main context and its UI context.
  2. Get started with Create Figma Plugin

    main

    Create Figma Plugin is a comprehensive toolkit designed to simplify the development of Figma plugins and widgets. It provides scaffolding, build tooling, and utilities to manage the complexities of the Figma plugin environment (such as separating the sandbox logic from the UI logic).

    To begin developing, you can follow the official documentation for quick start guides, configuration details, and UI development patterns.

  3. Communicate between Main and UI contexts using Events

    main

    The emit, on, and once functions allow you to pass messages and data between the Figma plugin's main context and its UI context.

    • emit<Handler>(name, ...args):
      • If called in the main context, it invokes the handler with the matching name in the UI.
      • If called in the UI, it invokes the handler with the matching name in the main context.
      • All args passed after name are applied to the handler.
    • on<Handler>(name, handler): Registers a handler for the given name. Returns a function to deregister the handler.
    • once<Handler>(name, handler): Registers a handler that runs at most once for the given name. Returns a function to deregister the handler.
    import {
      emit,
      on,
      once
    } from '@create-figma-plugin/utilities'
  4. Pass data between plugin/widget main and UI contexts

    main

    Use the @create-figma-plugin/utilities library to facilitate two-way communication between the plugin's main context and its UI context.

    • on(name, handler): Registers an event handler for a specific event name in the current context.
    • once(name, handler): Registers an event handler that runs at most once.
    • emit(name, ...args): Triggers an event. Calling emit in the main context invokes the handler in the UI; calling emit in the UI invokes the handler in the main context. All args are passed directly to the handler.

    This allows you to send data from the UI (e.g., a button click) to the main context to perform Figma API operations, or vice versa.

    // src/main.ts
    import { once } from '@create-figma-plugin/utilities'
    
    export default function () {
      function handleSubmit (data) {
        console.log(data)
      }
      once('SUBMIT', handleSubmit)
    }
    
    // src/ui.tsx
    import { emit } from '@create-figma-plugin/utilities'
    import { render, Button } from '@create-figma-plugin/ui'
    import { h } from 'preact'
    
    function Plugin () {
      function handleClick () {
        const data = { greeting: 'Hello, World!' }
        emit('SUBMIT', data)
      }
      return <Button onClick={handleClick}>Submit</Button>
    }
    
    export default render(Plugin)
  5. Customize the manifest.json file

    main

    To modify the manifest.json file immediately before it is output by the build-figma-plugin CLI, create a build-figma-plugin.manifest.js file.

    The exported function receives the original manifest.json object (as generated by the CLI) and must return the modified plain object to be used as the final manifest.

    // build-figma-plugin.manifest.js
    
    module.exports = function (manifest) {
      // ...
      return {
        ...manifest,
        // ...
      }
    }
  6. Build the Preact + Tailwind CSS Figma plugin

    main

    To build the plugin, run the build script. This generates a manifest.json file and a build/ directory containing the JavaScript bundles required for the plugin to run in Figma.

    To automatically rebuild the plugin whenever you make code changes, use the watch script.

    # Build the plugin once
    $ npm run build
    
    # Watch for changes and rebuild automatically
    $ npm run watch
  7. Install and use the @create-figma-plugin/ui component library

    main

    The @create-figma-plugin/ui library provides Preact components that replicate Figma and FigJam's design system. It supports three themes: Figma (Light), Figma (Dark), and FigJam. Themes are automatically selected based on whether the plugin is running in Figma or FigJam and the user's app preferences.

    To use it:

    1. Install the packages:
      npm install @create-figma-plugin/ui preact
    2. Call showUI from your plugin's main entry point to pass data to the UI.
    3. Create a UI file (e.g., src/ui.tsx) and use the render function from @create-figma-plugin/ui to wrap your component. The props of your component will match the data object passed to showUI.
    // 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)
    }
    // 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)
  8. Use custom CSS with CSS Modules or Inlined CSS

    main

    The build-figma-plugin CLI supports CSS Modules. By default, imported CSS files have their class names hashed to ensure global uniqueness.

    CSS Modules (Hashed classes)

    import styles from './styles.css'
    // Use as: <div class={styles.container}>

    Inlined CSS (Unhashed classes)

    To use standard, unhashed class names (e.g., for global styles or third-party libraries), prefix the import path with a !:

    import '!./styles.css'
    // Use as: <div class="container">

    You can use Figma's design tokens via CSS variables defined in @create-figma-plugin/ui's base.css.

    // 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)
  9. Use image assets in your plugin/widget UI

    main

    Image assets (PNG, JPG, SVG, GIF) used in your UI must be "inlined" into the UI bundle. You can do this by importing the image directly in your UI component file. The build system will convert the image into a Base64-encoded data URL string.

    If using TypeScript, you must declare the modules for these file types in a .d.ts file in your src directory to avoid compilation errors.

    // src/ui.tsx
    import { render } from '@create-figma-plugin/ui'
    import { h } from 'preact'
    import image from './image.png'
    
    function Plugin () {
      return <img src={image} />
    }
    
    export default render(Plugin)
    
    // src/image-assets.d.ts
    declare module '*.gif' { const content: string; export default content }
    declare module '*.jpg' { const content: string; export default content }
    declare module '*.png' { const content: string; export default content }
    declare module '*.svg' { const content: string; export default content }