A lightweight, zero-dependency web components library for building Figma plugin and widget UIs with native look and feel.
View the interactive component documentation at rogie.github.io/figui3
- 🎨 Figma UI3 design system
- 📦 Zero dependencies
- 🚀 Lightweight (~50kb unminified)
- 🎯 Built with Web Components
- 🌗 Automatic light/dark theme support
- ♿ Accessible with ARIA attributes and keyboard navigation
- 🔧 Framework agnostic (works with React, Vue, Svelte, or vanilla JS)
npm install @rogieking/figui3
# or
yarn add @rogieking/figui3
# or
bun add @rogieking/figui3
# or
pnpm add @rogieking/figui3Then import in your JavaScript/TypeScript:
import "@rogieking/figui3/fig.css";
import "@rogieking/figui3/fig.js";<link rel="stylesheet" href="https://unpkg.com/@rogieking/figui3@latest/fig.css" />
<script src="https://unpkg.com/@rogieking/figui3@latest/fig.js"></script>Or via esm.sh:
<link rel="stylesheet" href="https://esm.sh/@rogieking/figui3@latest/fig.css" />
<script src="https://esm.sh/@rogieking/figui3@latest/fig.js"></script>git clone https://github.com/rogie/figui3.git
cd figui3
bun install
bun dev # Opens documentation at http://localhost:3000<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="https://unpkg.com/@rogieking/figui3@latest/fig.css" />
<script src="https://unpkg.com/@rogieking/figui3@latest/fig.js"></script>
</head>
<body>
<fig-field>
<label>Color</label>
<fig-input-color value="#FF5733" text="true" alpha="true"></fig-input-color>
</fig-field>
<fig-button variant="primary">Save</fig-button>
</body>
</html>A versatile button component with multiple variants and types.
| Attribute | Type | Default | Description |
|---|---|---|---|
variant |
string | "primary" |
Visual style: "primary", "secondary", "ghost", "link" |
type |
string | "button" |
Button type: "button", "toggle", "submit", "select", "upload" |
size |
string | — | Size variant: "large", "compact" |
selected |
boolean | false |
Whether button is in selected state (for toggle type) |
disabled |
boolean | false |
Whether button is disabled |
icon |
boolean | false |
Icon-only button styling |
href |
string | — | URL for link-style buttons |
target |
string | — | Target window for links (e.g., "_blank") |
<!-- Variants -->
<fig-button>Primary</fig-button>
<fig-button variant="secondary">Secondary</fig-button>
<fig-button variant="ghost">Ghost</fig-button>
<fig-button variant="link">Link</fig-button>
<!-- Types -->
<fig-button type="toggle" selected="true">Toggle</fig-button>
<fig-button type="submit">Submit</fig-button>
<!-- Icon button -->
<fig-button variant="ghost" icon>
<svg><!-- icon --></svg>
</fig-button>
<!-- Select button with dropdown -->
<fig-button type="select">
Select Option
<fig-dropdown>
<option value="1">Option 1</option>
<option value="2">Option 2</option>
</fig-dropdown>
</fig-button>
<!-- Upload button -->
<fig-button type="upload">
Upload File
<input type="file" />
</fig-button>A native select wrapper with Figma styling.
| Attribute | Type | Default | Description |
|---|---|---|---|
value |
string | — | Currently selected value |
type |
string | "select" |
Type: "select" or "dropdown" |
<fig-dropdown value="2">
<option value="1">Option 1</option>
<option value="2">Option 2</option>
<option value="3">Option 3</option>
</fig-dropdown>Displays contextual information on hover or click.
| Attribute | Type | Default | Description |
|---|---|---|---|
text |
string | — | Tooltip text content |
action |
string | "hover" |
Trigger: "hover" or "click" |
delay |
number | 500 |
Delay in ms before showing |
offset |
string | — | Position offset: "left,top,right,bottom" |
<fig-tooltip text="This is helpful info" action="hover">
<fig-button>Hover me</fig-button>
</fig-tooltip>
<fig-tooltip text="Click triggered" action="click" delay="0">
<fig-button>Click me</fig-button>
</fig-tooltip>A popover container for rich content.
| Attribute | Type | Default | Description |
|---|---|---|---|
action |
string | "click" |
Trigger: "click" or "hover" |
size |
string | — | Size of the popover |
<fig-popover action="click">
<fig-button slot="trigger">Open Popover</fig-button>
<div slot="content">
<h3>Popover Title</h3>
<p>Rich content goes here.</p>
</div>
</fig-popover>A modal dialog component with drag support.
| Attribute | Type | Default | Description |
|---|---|---|---|
open |
boolean | false |
Whether dialog is visible |
modal |
boolean | false |
Whether dialog is modal |
drag |
boolean | false |
Whether dialog is draggable |
handle |
string | — | CSS selector for drag handle |
position |
string | — | Position: "center center", "top left", etc. |
<fig-dialog id="myDialog" modal drag handle="fig-header">
<fig-header>Dialog Title</fig-header>
<div slot="content">
<p>Dialog content goes here.</p>
</div>
<div slot="footer">
<fig-button variant="secondary">Cancel</fig-button>
<fig-button>Confirm</fig-button>
</div>
</fig-dialog>
<script>
document.getElementById('myDialog').showModal();
</script>Tabbed navigation component.
| Attribute | Type | Default | Description |
|---|---|---|---|
value |
string | — | Currently selected tab value |
name |
string | — | Tabs group identifier |
disabled |
boolean | false |
Disable all tabs |
<fig-tabs value="tab1">
<fig-tab value="tab1" label="General">
<p>General settings content</p>
</fig-tab>
<fig-tab value="tab2" label="Advanced">
<p>Advanced settings content</p>
</fig-tab>
</fig-tabs>A segmented button group for exclusive selection.
| Attribute | Type | Default | Description |
|---|---|---|---|
name |
string | — | Control group identifier |
value |
string | — | Selected segment value |
<fig-segmented-control>
<fig-segment value="left" selected="true">Left</fig-segment>
<fig-segment value="center">Center</fig-segment>
<fig-segment value="right">Right</fig-segment>
</fig-segmented-control>A range slider with multiple types and optional text input.
| Attribute | Type | Default | Description |
|---|---|---|---|
type |
string | "range" |
Type: "range", "hue", "opacity", "delta", "stepper" |
value |
number | — | Current value |
min |
number | 0 |
Minimum value |
max |
number | 100 |
Maximum value |
step |
number | 1 |
Step increment |
text |
boolean | false |
Show text input |
units |
string | — | Unit label (e.g., "%", "px") |
transform |
number | — | Multiplier for display value |
color |
string | — | Track color (for opacity type) |
disabled |
boolean | false |
Disable slider |
<!-- Basic slider -->
<fig-slider min="0" max="100" value="50"></fig-slider>
<!-- With text input and units -->
<fig-slider min="0" max="100" value="75" text="true" units="%"></fig-slider>
<!-- Hue slider -->
<fig-slider type="hue" value="180"></fig-slider>
<!-- Opacity slider with color -->
<fig-slider type="opacity" value="75" color="#FF5733" text="true" units="%"></fig-slider>
<!-- Stepper with snap points -->
<fig-slider type="stepper" value="50" step="25">
<datalist>
<option value="0"></option>
<option value="25"></option>
<option value="50"></option>
<option value="75"></option>
<option value="100"></option>
</datalist>
</fig-slider>
<!-- Delta slider -->
<fig-slider type="delta" value="0" min="-5" max="5" step="0.25">
<datalist>
<option value="0"></option>
</datalist>
</fig-slider>A styled text input with optional slots.
| Attribute | Type | Default | Description |
|---|---|---|---|
value |
string | — | Input value |
placeholder |
string | — | Placeholder text |
type |
string | "text" |
Input type: "text" or "number" |
disabled |
boolean | false |
Disable input |
multiline |
boolean | false |
Use textarea |
min |
number | — | Min value (number type) |
max |
number | — | Max value (number type) |
step |
number | — | Step (number type) |
transform |
number | — | Display multiplier |
<!-- Basic text input -->
<fig-input-text value="Hello" placeholder="Enter text..."></fig-input-text>
<!-- With prepend/append slots -->
<fig-input-text>
<span slot="prepend">$</span>
<span slot="append">.00</span>
</fig-input-text>
<!-- Multiline -->
<fig-input-text multiline placeholder="Enter description..."></fig-input-text>A numeric input with units support.
| Attribute | Type | Default | Description |
|---|---|---|---|
value |
string | — | Numeric value |
placeholder |
string | — | Placeholder text |
min |
number | — | Minimum value |
max |
number | — | Maximum value |
step |
number | — | Step increment |
units |
string | — | Unit string (e.g., "px", "%") |
unit-position |
string | "suffix" |
"suffix" or "prefix" |
transform |
number | — | Display multiplier |
disabled |
boolean | false |
Disable input |
<fig-input-number value="100" units="px"></fig-input-number>
<fig-input-number value="50" units="%" min="0" max="100"></fig-input-number>
<fig-input-number value="45" units="°" step="15"></fig-input-number>A color picker with hex/alpha support.
| Attribute | Type | Default | Description |
|---|---|---|---|
value |
string | — | Hex color value (e.g., "#FF5733" or "#FF573380") |
text |
boolean | false |
Show hex text input |
alpha |
boolean | false |
Show alpha slider |
picker |
string | "native" |
Picker type: "native", "figma", "false" |
disabled |
boolean | false |
Disable input |
<!-- Basic color picker -->
<fig-input-color value="#FF5733"></fig-input-color>
<!-- With text and alpha -->
<fig-input-color value="#FF5733" text="true" alpha="true"></fig-input-color>
<!-- With Figma-style picker dialog -->
<fig-input-color value="#FF5733" text="true" alpha="true" picker="figma"></fig-input-color>A comprehensive fill input supporting colors, gradients, images, and video.
| Attribute | Type | Default | Description |
|---|---|---|---|
value |
string | — | JSON fill data |
disabled |
boolean | false |
Disable input |
<!-- Solid color -->
<fig-input-fill value='{"type":"solid","color":"#FF5733","opacity":100}'></fig-input-fill>
<!-- Gradient -->
<fig-input-fill value='{"type":"gradient","gradient":{"type":"linear","angle":90,"stops":[{"position":0,"color":"#FF0000"},{"position":100,"color":"#0000FF"}]}}'></fig-input-fill>
<!-- Image -->
<fig-input-fill value='{"type":"image","image":{"url":"path/to/image.jpg","scaleMode":"fill"}}'></fig-input-fill>A comprehensive fill picker dialog supporting solid colors, gradients, images, video, and webcam.
| Attribute | Type | Default | Description |
|---|---|---|---|
value |
string | — | JSON fill value |
disabled |
boolean | false |
Disable picker |
alpha |
boolean | true |
Show alpha controls |
mode |
string | — | Lock to mode: "solid", "gradient", "image", "video", "webcam" |
<!-- Wraps a trigger element -->
<fig-fill-picker value='{"type":"solid","color":"#FF5733"}'>
<fig-chit></fig-chit>
</fig-fill-picker>
<!-- Lock to solid color mode -->
<fig-fill-picker mode="solid" alpha="true">
<fig-button>Pick Color</fig-button>
</fig-fill-picker>A color/gradient/image swatch element.
| Attribute | Type | Default | Description |
|---|---|---|---|
background |
string | — | CSS background value |
size |
string | "small" |
Size: "small" or "large" |
selected |
boolean | false |
Show selection ring |
disabled |
boolean | false |
Disable interaction |
alpha |
number | — | Opacity (0-1) |
<fig-chit background="#FF5733"></fig-chit>
<fig-chit background="linear-gradient(90deg, #FF0000, #0000FF)"></fig-chit>
<fig-chit background="url(image.jpg)" size="large"></fig-chit>
<fig-chit background="#FF5733" alpha="0.5"></fig-chit>A checkbox input with indeterminate state support.
| Attribute | Type | Default | Description |
|---|---|---|---|
checked |
boolean | false |
Whether checked |
indeterminate |
boolean | false |
Indeterminate state |
disabled |
boolean | false |
Disable checkbox |
name |
string | — | Form field name |
value |
string | — | Value when checked |
<fig-checkbox>Accept terms</fig-checkbox>
<fig-checkbox checked>Selected option</fig-checkbox>
<fig-checkbox indeterminate>Parent option</fig-checkbox>A radio button input.
| Attribute | Type | Default | Description |
|---|---|---|---|
checked |
boolean | false |
Whether selected |
disabled |
boolean | false |
Disable radio |
name |
string | — | Radio group name |
value |
string | — | Value when selected |
<fig-radio name="size" value="small">Small</fig-radio>
<fig-radio name="size" value="medium" checked>Medium</fig-radio>
<fig-radio name="size" value="large">Large</fig-radio>A toggle switch component.
| Attribute | Type | Default | Description |
|---|---|---|---|
checked |
boolean | false |
Whether on |
disabled |
boolean | false |
Disable switch |
name |
string | — | Form field name |
value |
string | — | Value when on |
<fig-switch>Enable notifications</fig-switch>
<fig-switch checked>Active feature</fig-switch>A form field wrapper with flexible layout.
| Attribute | Type | Default | Description |
|---|---|---|---|
direction |
string | "column" |
Layout: "column", "row", "horizontal" |
<!-- Vertical (default) -->
<fig-field>
<label>Username</label>
<fig-input-text></fig-input-text>
</fig-field>
<!-- Horizontal -->
<fig-field direction="horizontal">
<label>Volume</label>
<fig-slider min="0" max="100" value="50"></fig-slider>
</fig-field>A text input with dropdown suggestions.
| Attribute | Type | Default | Description |
|---|---|---|---|
options |
string | — | Comma-separated options |
placeholder |
string | — | Placeholder text |
value |
string | — | Current value |
disabled |
boolean | false |
Disable input |
<fig-combo-input
options="House, Apartment, Condo, Other"
placeholder="Type of residence">
</fig-combo-input>Displays a user's profile image or initials.
| Attribute | Type | Default | Description |
|---|---|---|---|
src |
string | — | Image URL |
name |
string | — | Name for initials fallback |
size |
string | — | Size: "large" |
<fig-avatar src="https://example.com/photo.jpg" name="John Doe"></fig-avatar>
<fig-avatar name="Jane Smith" size="large"></fig-avatar>An image display or upload component.
| Attribute | Type | Default | Description |
|---|---|---|---|
src |
string | — | Image URL |
upload |
boolean | false |
Show upload button |
label |
string | — | Upload button label |
size |
string | — | Preview size |
<fig-image src="photo.jpg"></fig-image>
<fig-image upload label="Upload Image"></fig-image>A 2D position input control.
| Attribute | Type | Default | Description |
|---|---|---|---|
value |
string | — | Position: "x,y" (0-1 range) |
precision |
number | — | Decimal places |
transform |
number | — | Output scaling |
text |
boolean | false |
Show X/Y inputs |
<fig-input-joystick value="0.5,0.5"></fig-input-joystick>
<fig-input-joystick value="0.5,0.5" text="true" precision="2"></fig-input-joystick>An angle/rotation input control.
| Attribute | Type | Default | Description |
|---|---|---|---|
value |
number | — | Angle in degrees |
precision |
number | — | Decimal places |
text |
boolean | false |
Show text input |
<fig-input-angle value="45"></fig-input-angle>
<fig-input-angle value="90" text="true"></fig-input-angle>A toast notification component.
| Attribute | Type | Default | Description |
|---|---|---|---|
duration |
number | 5000 |
Auto-dismiss ms (0 = no dismiss) |
offset |
number | 16 |
Distance from bottom |
theme |
string | "dark" |
Theme: "dark", "light", "danger", "brand" |
open |
boolean | false |
Whether visible |
<fig-toast id="myToast" theme="brand" duration="3000">
Settings saved successfully!
</fig-toast>
<script>
document.getElementById('myToast').show();
</script>A loading spinner indicator.
<fig-spinner></fig-spinner>A loading placeholder with shimmer animation.
<fig-shimmer style="width: 200px; height: 20px;"></fig-shimmer>A layer list item component (for layer panels).
<fig-layer name="Rectangle 1" type="rectangle" selected></fig-layer>
<fig-layer name="Group 1" type="group" expanded>
<fig-layer name="Child 1" type="frame"></fig-layer>
</fig-layer>A section header component.
<fig-header>Section Title</fig-header>All form components emit standard input and change events:
input- Fires continuously during interaction (dragging, typing)change- Fires when interaction completes (mouse up, blur)
Events include a detail object with component-specific data:
// Color input events
colorInput.addEventListener('input', (e) => {
console.log(e.detail);
// { color: "#FF5733", alpha: 0.8, hsv: { h: 14, s: 80, v: 100, a: 0.8 } }
});
// Fill picker events
fillPicker.addEventListener('change', (e) => {
console.log(e.detail);
// { type: "gradient", gradient: { type: "linear", angle: 90, stops: [...] }, css: "linear-gradient(...)" }
});
// Slider events
slider.addEventListener('input', (e) => {
console.log(e.target.value); // "75"
});Web components work in React, but require some considerations:
import { useRef, useEffect } from 'react';
import '@rogieking/figui3/fig.css';
import '@rogieking/figui3/fig.js';
function ColorPicker({ value, onChange }) {
const ref = useRef(null);
useEffect(() => {
const el = ref.current;
if (!el) return;
const handleChange = (e) => onChange(e.detail);
el.addEventListener('change', handleChange);
return () => el.removeEventListener('change', handleChange);
}, [onChange]);
// Set initial value via ref to avoid infinite loops
useEffect(() => {
if (ref.current) {
ref.current.setAttribute('value', value);
}
}, [value]);
return (
<fig-input-color
ref={ref}
text="true"
alpha="true"
picker="figma"
/>
);
}Note: Avoid setting the
valueprop directly on web components in JSX during re-renders, asattributeChangedCallbackmay trigger events that cause infinite loops. Use refs to control updates.
<template>
<fig-input-color
:value="color"
text="true"
alpha="true"
@input="onInput"
@change="onChange"
/>
</template>
<script setup>
import { ref } from 'vue';
import '@rogieking/figui3/fig.css';
import '@rogieking/figui3/fig.js';
const color = ref('#FF5733');
const onInput = (e) => {
color.value = e.detail.color;
};
const onChange = (e) => {
console.log('Final color:', e.detail);
};
</script><script>
import '@rogieking/figui3/fig.css';
import '@rogieking/figui3/fig.js';
let color = '#FF5733';
function handleInput(e) {
color = e.detail.color;
}
</script>
<fig-input-color
value={color}
text="true"
alpha="true"
on:input={handleInput}
on:change={(e) => console.log('Saved:', e.detail)}
/>FigUI3 automatically adapts to light and dark themes using CSS custom properties. The library uses Figma's color variable naming convention:
/* Colors automatically switch based on color-scheme */
--figma-color-bg
--figma-color-bg-secondary
--figma-color-bg-hover
--figma-color-text
--figma-color-text-secondary
--figma-color-border
--figma-color-icon
/* ... and more */In Figma plugins, these variables are provided automatically. For standalone usage, the library includes fallback values that respond to prefers-color-scheme.
<body style="color-scheme: dark;">
<!-- Forces dark theme -->
</body>FigUI3 supports all modern browsers with Web Components support:
- Chrome/Edge 67+
- Firefox 63+
- Safari 10.1+
Contributions are welcome! Please read our contributing guidelines before submitting a pull request.
MIT License © Rogie King