Skip to content

🌳 Welcome to FigmaVars, a React hooks library designed to simplify the integration of Figma variables into your React applications.

License

Notifications You must be signed in to change notification settings

marklearst/figma-vars-hooks

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

FigmaVars Logo

A fast, typed React 19 hooks library for the Figma Variables API: fetch, update, and manage design tokens via the official Figma REST API.

Built for the modern web, this library provides a suite of hooks to fetch, manage, and mutate your design tokens, making it easy to sync them between Figma and your React applications, Storybooks, or design system dashboards.

Status CI codecov Test Coverage License GitHub last commit GitHub code size TypeScript npm npm downloads


πŸš€ Features

  • βœ… Token Agnostic for the Best DX: Our library doesn't care how you get your Figma token. Use environment variables, localStorage, a state management library, or even a simple input field. This framework-agnostic approach means it works seamlessly with Vite, Next.js, Create React App, and more, without locking you into a specific build tool.
  • βš›οΈ Modern React Hooks: A full suite of hooks for fetching and mutating Figma variables, collections, and modes.
  • ✍️ Ergonomic Mutations: A useMutation-style API for creating, updating, and deleting variables, providing clear loading and error states.
  • πŸ”’ TypeScript-first: Strictly typed for an ergonomic and safe developer experience. Get autocompletion for all API responses.
  • πŸ“– Storybook & Next.js Ready: Perfect for building live design token dashboards or style guides.
  • πŸ”„ Local JSON Support: Use local JSON files exported from Figma Dev Mode plugins when you don't have a Figma Enterprise account, enabling offline development and static deployments.
  • 🚧 Style Dictionary Integration: Coming soon in future beta releases - seamless integration with Amazon's Style Dictionary for multi-platform design token distribution.

🧱 Architecture Highlights

  • βœ… 100% Test Coverage - Comprehensive test suite with 78 tests covering all hooks, utilities, and edge cases via Vitest
  • βœ… Consistent Error Handling - Standardized error propagation with clear messages from the Figma API
  • βœ… Strictly Typed APIs - Modern TypeScript best practices with full type inference and autocompletion
  • βœ… Predictable Hook Signatures - Consistent, composable patterns designed for safe React integrations
  • βœ… Developer-First Architecture - Clean folder structure, path aliases, and logical component separation
  • βœ… React Ecosystem - Built specifically for React apps, Storybook, Next.js, and design system dashboards
  • βœ… Ergonomic DX - Intuitive API that's easy to use in both prototype and production environments
  • βœ… Minimal Dependencies - Leverages SWR for caching with careful dependency selection for optimal bundle size

πŸ“¦ Install

npm install @figma-vars/hooks
# or
yarn add @figma-vars/hooks
# or
pnpm add @figma-vars/hooks

Peer dependencies: You'll need react and react-dom.


πŸ› οΈ Setup & Usage

The library is designed to be as flexible as possible. You provide the Figma token and file key, and the hooks handle the rest.

Wrap your application (or the relevant component tree) with the FigmaVarsProvider. This makes the Figma token and file key available to all the hooks.

// src/main.tsx or App.tsx
import React from 'react'
import ReactDOM from 'react-dom/client'
import { FigmaVarsProvider } from '@figma-vars/hooks'
import App from './App'

// The token can come from anywhere: .env, localStorage, state, etc.
const FIGMA_TOKEN = import.meta.env.VITE_FIGMA_TOKEN
const FIGMA_FILE_KEY = 'your-figma-file-key'

ReactDOM.createRoot(document.getElementById('root')!).render(
  <React.StrictMode>
    <FigmaVarsProvider
      token={FIGMA_TOKEN}
      fileKey={FIGMA_FILE_KEY}>
      <App />
    </FigmaVarsProvider>
  </React.StrictMode>
)

Fetching Data

Now, you can use the query hooks anywhere in your app:

// src/components/TokenList.tsx
import { useVariables } from '@figma-vars/hooks'

export function TokenList() {
  const { data, isLoading, error } = useVariables()

  if (isLoading) return <div>Loading tokens...</div>
  if (error) return <div>Error: {error.message}</div>

  // The 'data' object contains variables, collections, and modes
  const variables = Object.values(data?.variables ?? {})

  return (
    <ul>
      {variables.map(variable => (
        <li key={variable.id}>
          {variable.name}: {JSON.stringify(variable.valuesByMode)}
        </li>
      ))}
    </ul>
  )
}

Mutating Data

To create, update, or delete variables, use the provided mutation hooks. They follow a standard pattern, returning a mutate function and states for data, isLoading, and error.

Here's an example of creating a new variable:

// src/components/CreateVariableForm.tsx
import { useCreateVariable } from '@figma-vars/hooks'
import type { CreateVariablePayload } from '@figma-vars/hooks'

function CreateVariableForm({ collectionId }: { collectionId: string }) {
  const { mutate, data, isLoading, error } = useCreateVariable()

  const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
    event.preventDefault()
    const form = event.currentTarget
    const variableName = (form.elements.namedItem('variableName') as HTMLInputElement)?.value

    if (!variableName) return

    const payload: CreateVariablePayload = {
      name: variableName,
      variableCollectionId: collectionId,
      resolvedType: 'COLOR', // Example type
    }
    mutate(payload)
  }

  return (
    <form onSubmit={handleSubmit}>
      <input
        name='variableName'
        placeholder='New variable name'
      />
      <button
        type='submit'
        disabled={isLoading}>
        {isLoading ? 'Creating...' : 'Create Variable'}
      </button>
      {error && <p>Error: {error.message}</p>}
      {data && <p>Created variable with ID: {data.id}</p>}
    </form>
  )
}

Using Local JSON Files (No Enterprise Account Required)

If you don't have a Figma Enterprise account (required for the Variables API), you can still use this library with local JSON files exported from Figma Dev Mode plugins. This is perfect for:

  • Offline Development: Work on your design system without an internet connection
  • Static Deployments: Deploy design token dashboards to static hosting
  • CI/CD Pipelines: Use exported JSON files in automated workflows
  • Team Collaboration: Share design tokens without API access

Getting Your JSON File

We recommend using the Variables Exporter for Dev Mode plugin:

  1. Install the plugin in Figma
  2. Open your Figma file in Dev Mode
  3. Run the plugin and export your variables as JSON
  4. Save the JSON file to your project (e.g., src/assets/figma-variables.json)

This plugin exports the exact same format that the Figma Variables API returns, ensuring perfect compatibility with this library.

Using the Fallback File

// src/main.tsx or App.tsx
import React from 'react'
import ReactDOM from 'react-dom/client'
import { FigmaVarsProvider } from '@figma-vars/hooks'
import App from './App'
import variablesData from './assets/figma-variables.json'

ReactDOM.createRoot(document.getElementById('root')!).render(
  <React.StrictMode>
    <FigmaVarsProvider
      token={null} // No token needed when using fallbackFile
      fileKey={null} // No fileKey needed when using fallbackFile
      fallbackFile={variablesData}>
      <App />
    </FigmaVarsProvider>
  </React.StrictMode>
)

You can also pass the JSON as a string if you prefer:

import variablesJson from './assets/figma-variables.json?raw'
;<FigmaVarsProvider
  token={null}
  fileKey={null}
  fallbackFile={variablesJson}>
  <App />
</FigmaVarsProvider>

Figma PAT Security

When using the Figma API, it's essential to keep your Personal Access Token (PAT) secure. Here are some best practices:

  • Never hardcode your PAT in your code.
  • Use environment variables or a secure storage mechanism to store your PAT.
  • Limit the scope of your PAT to only the necessary permissions.
  • Rotate your PAT regularly.

Advanced Usage

For advanced use cases, you can use the useFigmaToken hook to access the token and file key from the context.

// src/components/AdvancedUsage.tsx
import { useFigmaToken } from '@figma-vars/hooks'

function AdvancedUsage() {
  const { token, fileKey } = useFigmaToken()

  // Use the token and file key to make custom API requests
  const apiRequest = async () => {
    const response = await fetch(`https://api.figma.com/v1/files/${fileKey}/variables`, {
      headers: {
        'X-Figma-Token': token,
      },
    })

    const data = await response.json()
    console.log(data)
  }

  return <button onClick={apiRequest}>Make API Request</button>
}

Error Handling

All hooks return an error state that you can use to handle errors.

// src/components/ErrorHandling.tsx
import { useVariables } from '@figma-vars/hooks'

function ErrorHandling() {
  const { data, isLoading, error } = useVariables()

  if (error) {
    return (
      <div>
        <h2>Error</h2>
        <p>{error.message}</p>
      </div>
    )
  }

  // Render data or loading state
}

🧩 API Reference

Core Hooks

  • useVariables(): Fetches all local variables for the file key provided to the FigmaVarsProvider. Returns a SWR hook state with data, isLoading, and error properties. The actual Figma response is in data.data. When fallbackFile is provided, it uses the local JSON data instead of making an API request.
  • useVariableCollections(): A convenience hook that returns just the variable collections from the main useVariables data.
  • useVariableModes(): A convenience hook that returns just the variable modes from the main useVariables data.
  • useFigmaToken(): A simple hook to access the token and file key from the context.

Provider Props

The FigmaVarsProvider accepts the following props:

  • token: Figma Personal Access Token (PAT) for API authentication. Can be null when using fallbackFile.
  • fileKey: Figma file key for the target file. Required for API requests but can be null when using fallbackFile.
  • fallbackFile: Optional local JSON file (as object or string) to use instead of API requests. Perfect for users without Figma Enterprise accounts.

Mutation Hooks

All mutation hooks return an object with the following shape: { mutate, data, isLoading, error }.

  • useCreateVariable(): Creates a new variable. The mutate function expects a CreateVariablePayload object.
  • useUpdateVariable(): Updates an existing variable. The mutate function expects an object { variableId, payload } where payload is an UpdateVariablePayload.
  • useDeleteVariable(): Deletes a variable. The mutate function expects the variableId (string) of the variable to delete.
  • useBulkUpdateVariables(): Creates, updates, or deletes multiple entities in a single batch operation. The mutate function expects a BulkUpdatePayload object.

Types

All types are exported from @figma-vars/hooks. The core response type from Figma for local variables is LocalVariablesResponse.


πŸ“š Storybook & Next.js Integration

The provider model makes integration trivial. Simply wrap your Storybook stories or Next.js pages with the FigmaVarsProvider.

// In a Storybook story
import { FigmaVarsProvider, useVariables } from '@figma-vars/hooks'

export const TokensStory = () => (
  <FigmaVarsProvider
    token='YOUR_TOKEN'
    fileKey='YOUR_FILE_KEY'>
    <TokenList />
  </FigmaVarsProvider>
)

const TokenList = () => {
  const { data } = useVariables()
  return <pre>{JSON.stringify(data?.variables, null, 2)}</pre>
}

πŸ“ Contributing

PRs and issues are welcome! Please see CONTRIBUTING.md for guidelines.

πŸ“ License

This project is licensed under the MIT License. Β© 2024–2025 Mark Learst