A lightweight, modern Svelte component library for building Figma plugin interfaces that feel native to Figma's UI3 design system.
⨠Native Figma Design Language ā Components built to match Figma's UI3 specifications
šØ Automatic Dark Mode ā Seamless light/dark theme support using Figma's CSS variables
šŖ¶ Lightweight ā Minimal bundle size optimized for plugin environments
ā” Svelte-First ā Built with Svelte 4.x for maximum performance
āæ Accessible ā Keyboard navigation and ARIA support out of the box
šÆ Zero Config ā Import and use ā no theme setup required
npm install figma-ui3-kit-svelte
// Import the global CSS with Figma's design tokens
import { GlobalCSS } from 'figma-ui3-kit-svelte';
// Import the components you need
import { Button, Input, Modal, Text } from 'figma-ui3-kit-svelte';
<Button variant="primary" on:click={handleClick}>
Create Selection
</Button>
<Input
bind:value={searchQuery}
placeholder="Search layers..."
/>
<Text variant="body-medium">
Components that feel native to Figma
</Text>
To enable automatic dark mode in your plugin, pass themeColors: true when showing your UI:
figma.showUI(__html__, {
themeColors: true,
width: 400,
height: 300
});
This enables Figma's native CSS variables that automatically adapt to the user's theme preference.
This project includes Storybook for component development and documentation:
# Start Storybook development server
npm run storybook
# Build static Storybook for deployment
npm run build-storybook
Storybook opens at http://localhost:6006 where you can browse, test, and document components.
Online Documentation:
The Storybook is automatically deployed to GitHub Pages on every push to main.
Available Stories: Button, Checkbox, Input (more coming soon)
Features:
figma-development-theme.css for proper theming outside plugin contextThis library is built on three core principles:
Figma-Native ā Every component uses Figma's design tokens for colors, typography, spacing, and borders. Your plugin UI will automatically match Figma's interface.
Plugin-Optimized ā Small bundle size and zero heavy dependencies. Built specifically for the constraints of plugin environments.
Developer Experience ā Intuitive APIs, comprehensive prop support, and sensible defaults. Build faster without sacrificing flexibility.
All components accept a class prop for custom styling and utility classes.
The Button component provides primary, secondary, and tertiary button variants with destructive styling options.
import { Button } from 'figma-ui3-kit-svelte';
<Button on:click={handleSave}>Save Changes</Button>
<Button variant="secondary" on:click={handleCancel}>Cancel</Button>
<Button variant="tertiary" on:click={handleMore}>More Options</Button>
<Button variant="secondary" destructive on:click={handleDelete}>Delete</Button>
<Button disabled>Disabled State</Button>
Props
| Prop | Type | Options/notes |
|---|---|---|
variant |
String | Default: "primary", Options: "secondary", "tertiary" |
destructive |
Boolean | Default: false; Applies destructive styling (red) |
disabled |
Boolean | Default: false |
on:click |
Func | Click handler. Ex: on:click={handleClick} |
import { Checkbox } from 'figma-ui3-kit-svelte';
<Checkbox bind:checked={includeHidden}>
Include hidden layers
</Checkbox>
<Checkbox checked on:change={handleChange}>
Pre-checked option
</Checkbox>
<Checkbox disabled>
Disabled option
</Checkbox>
Props
| Prop | Type | Options/notes |
|---|---|---|
checked |
Boolean | Default: false; Bind with bind:checked={variable} |
value |
Boolean | Default: false; Current checkbox state |
disabled |
Boolean | Default: false |
on:change |
Func | Change handler. Ex: on:change={handleChange} |
Collapsible panels for organizing content. Only one panel can be open at a time.
import { Disclosure, DisclosureItem } from 'figma-ui3-kit-svelte';
<Disclosure>
<DisclosureItem title="Export Settings" open>
<Input placeholder="File name..." />
<Checkbox>Include annotations</Checkbox>
</DisclosureItem>
<DisclosureItem title="Advanced Options">
<Switch>Optimize for web</Switch>
</DisclosureItem>
<DisclosureItem title="History" section>
<Text variant="body-small">Recent exports appear here</Text>
</DisclosureItem>
</Disclosure>
Props
| Prop | Type | Options/notes |
|---|---|---|
title |
String | Panel title text |
open |
Boolean | Default: false; Only one panel can be open at once |
section |
Boolean | Default: false; Bold section header styling |
Display icons from the included icon set or your own custom SVG icons. The library includes 700+ icons in 16px and 24px sizes.
import { Icon } from 'figma-ui3-kit-svelte';
// Import icons from the library (24px default)
import Icon24Visible from 'figma-ui3-kit-svelte/src/icons/24/icon.24.visible.svg';
import Icon24Search from 'figma-ui3-kit-svelte/src/icons/24/icon.24.search.large.svg';
// Or 16px icons for compact spaces
import Icon16Check from 'figma-ui3-kit-svelte/src/icons/16/icon.16.check.svg';
// Or use your own SVG
import CustomIcon from './assets/custom-icon.svg';
<!-- Standard icon with color -->
<Icon iconName={Icon24Visible} color="--figma-color-icon" />
<!-- Loading spinner -->
<Icon iconName={Icon24Search} color="--figma-color-icon-brand" spin />
<!-- Text icon (useful for letter indicators) -->
<Icon iconText="W" color="--figma-color-text-brand" />
<!-- Custom icon -->
<Icon iconName={CustomIcon} color="--figma-color-icon-danger" />
Props
| Prop | Type | Options/notes |
|---|---|---|
iconName |
Var | Imported SVG icon. Ex: iconName={Icon24Visible} |
iconText |
String | Text character to display instead of icon. Ex: iconText="W" |
color |
String | Figma color variable. Ex: "--figma-color-icon-brand" |
spin |
Boolean | Default: false; Rotates icon continuously (for loaders) |
Icon Sizes
/icons/24//icons/16/Clickable icon buttons with hover and selected states.
import { IconButton } from 'figma-ui3-kit-svelte';
import Icon24Visible from 'figma-ui3-kit-svelte/src/icons/24/icon.24.visible.svg';
<IconButton
iconName={Icon24Visible}
on:click={toggleVisibility}
/>
<IconButton
iconName={Icon24Visible}
selected
on:click={toggleVisibility}
/>
<IconButton
iconText="@"
on:click={handleMention}
/>
Props
| Prop | Type | Options/notes |
|---|---|---|
iconName |
Var | Imported SVG icon |
iconText |
String | Text character to display |
selected |
Boolean | Default: false; Selected/active state |
spin |
Boolean | Default: false; Rotates icon continuously |
on:click |
Func | Click handler |
Contextual help tooltips that add hover functionality to any interactive element. Wrap any element to add tooltip behavior.
import { Tooltip } from 'figma-ui3-kit-svelte';
<!-- Basic tooltip on button -->
<Tooltip label="Save your changes" hotkeyText="āS">
<Button variant="primary">Save</Button>
</Tooltip>
<!-- Without hotkey -->
<Tooltip label="Cancel and discard changes" hotkey={false}>
<Button variant="secondary">Cancel</Button>
</Tooltip>
<!-- Different directions -->
<Tooltip label="Settings" direction="Bottom">
<IconButton iconName={IconSettings} />
</Tooltip>
<Tooltip label="Previous page" direction="Left">
<IconButton iconName={IconChevronRight} />
</Tooltip>
<!-- Custom elements -->
<Tooltip label="This is a custom div with a tooltip" direction="Top">
<div style="padding: 8px 12px; background: var(--figma-color-bg-secondary); border-radius: 4px; cursor: pointer;">
Hover me
</div>
</Tooltip>
Props
| Prop | Type | Options/notes |
|---|---|---|
label |
String | Default: "Tooltip text"; Tooltip content |
hotkey |
Boolean | Default: true; Show hotkey text |
hotkeyText |
String | Default: "āV"; Hotkey to display |
direction |
String | Default: "Top"; Tooltip position relative to trigger (see below) |
disabled |
Boolean | Default: false; Disable tooltip functionality |
Direction Options
Top ā Tooltip appears above trigger, centeredTopLeft ā Tooltip appears above trigger, left-alignedTopRight ā Tooltip appears above trigger, right-alignedBottom ā Tooltip appears below trigger, centeredBottomLeft ā Tooltip appears below trigger, left-alignedBottomRight ā Tooltip appears below trigger, right-alignedLeft ā Tooltip appears to the left of trigger, centeredRight ā Tooltip appears to the right of trigger, centeredBehavior
Text input field with optional icon support and various styling options.
import { Input } from 'figma-ui3-kit-svelte';
import Icon24Search from 'figma-ui3-kit-svelte/src/icons/24/icon.24.search.large.svg';
<!-- Basic input -->
<Input
bind:value={layerName}
placeholder="Layer name..."
/>
<!-- With icon -->
<Input
bind:value={searchQuery}
iconName={Icon24Search}
placeholder="Search..."
/>
<!-- Loading state -->
<Input
value={fetchingData}
iconName={Icon24Spinner}
spin
placeholder="Loading..."
/>
<!-- With borders (default is borderless) -->
<Input value="Value" borders />
<!-- Disabled -->
<Input value="Locked" disabled />
Props
| Prop | Type | Options/notes |
|---|---|---|
value |
String | Input value. Bind with bind:value={variable} |
placeholder |
String | Placeholder text |
borders |
Boolean | Default: false; Show visible border |
disabled |
Boolean | Default: false |
iconName |
Var | Optional icon to display in input |
iconText |
String | Optional text character to display |
spin |
Boolean | Default: false; Rotates icon (for loading states) |
on:change |
Func | Change handler |
on:input |
Func | Input handler (fires on every keystroke) |
Semantic labels for form controls.
import { Label } from 'figma-ui3-kit-svelte';
<!-- Label with sizes -->
<Label>Default label (medium)</Label>
<Label size="medium">Medium label</Label>
<Label size="small">Small label</Label>
<!-- Label with form control -->
<Label>Layer name</Label>
<Input bind:value={name} />
Label Props
| Prop | Type | Options/notes |
|---|---|---|
size |
String | Default: "medium", Options: "medium", "small" |
Flexible modal dialogs with header, content area, and configurable footer layouts. Supports center positioning or side panels.
import { Modal } from 'figma-ui3-kit-svelte';
<!-- Basic modal with actions -->
<Modal bind:isOpen={showExportModal} title="Export Selection">
<Text variant="body-medium">Choose your export format and settings.</Text>
<svelte:fragment slot="footer-right">
<Button variant="secondary" on:click={() => showExportModal = false}>
Cancel
</Button>
<Button variant="primary" on:click={handleExport}>
Export
</Button>
</svelte:fragment>
</Modal>
<!-- Modal with footer checkbox -->
<Modal bind:isOpen={showWarning} title="Delete Layers">
<Text variant="body-medium">This action cannot be undone.</Text>
<svelte:fragment slot="footer-left">
<Checkbox bind:checked={dontAskAgain}>
Don't ask again
</Checkbox>
</svelte:fragment>
<svelte:fragment slot="footer-right">
<Button variant="secondary" on:click={() => showWarning = false}>
Cancel
</Button>
<Button variant="secondary" destructive on:click={handleDelete}>
Delete
</Button>
</svelte:fragment>
</Modal>
<!-- Modal with full-width action -->
<Modal bind:isOpen={showComplete} title="Complete Setup">
<Text variant="body-medium">Setup is complete. Click below to get started.</Text>
<svelte:fragment slot="footer-full">
<Button variant="primary" on:click={handleStart}>
Get Started
</Button>
</svelte:fragment>
</Modal>
<!-- Side panel modal -->
<Modal
bind:isOpen={showProperties}
title="Layer Properties"
position="right"
width="large"
>
<Label>Opacity</Label>
<Input type="number" bind:value={opacity} />
<Label>Blend Mode</Label>
<Dropdown bind:value={blendMode} menuItems={blendModes} />
<svelte:fragment slot="footer-right">
<Button variant="primary">Apply</Button>
</svelte:fragment>
</Modal>
Props
| Prop | Type | Options/notes |
|---|---|---|
isOpen |
Boolean | Controls visibility. Use bind:isOpen={variable} |
title |
String | Modal header title |
width |
String | Default: "medium"; Options: "small" (240px), "medium" (320px), "large" (480px), or custom CSS value |
height |
String | Default: "auto"; Custom height value (e.g., "50vh", "400px") |
position |
String | Default: "center"; Options: "center", "left", "right", "bottom" |
overlayPadding |
String | Default: "16px"; Padding around modal viewport |
showOverlay |
Boolean | Default: true; Show backdrop overlay |
closeOnOverlayClick |
Boolean | Default: true; Close when clicking backdrop |
closeOnEscape |
Boolean | Default: true; Close when pressing ESC |
onClose |
Func | Callback function when modal closes |
icon2 |
Boolean | Default: false; Show additional icon button in header |
icon2Name |
Var | Icon for secondary header button |
onIcon2Click |
Func | Click handler for secondary header button |
Slots
| Slot | Description |
|---|---|
default |
Main modal content area |
footer-left |
Left side of footer (checkboxes, switches, etc.) |
footer-right |
Right side of footer (action buttons) |
footer-full |
Full-width footer (single primary actions) |
Radio buttons for mutually exclusive selections.
import { Radio } from 'figma-ui3-kit-svelte';
let exportFormat = 'png'; // Selected value
<Radio bind:group={exportFormat} value="png">
PNG
</Radio>
<Radio bind:group={exportFormat} value="jpg">
JPG
</Radio>
<Radio bind:group={exportFormat} value="svg">
SVG
</Radio>
<Radio bind:group={exportFormat} value="pdf" disabled>
PDF (Coming Soon)
</Radio>
Props
| Prop | Type | Options/notes |
|---|---|---|
group |
Var | Bind to variable to track selected value. Ex: bind:group={var} |
value |
String | Value when this radio is selected |
disabled |
Boolean | Default: false |
on:change |
Func | Change handler |
The Slider component provides a range input with variants for different use cases. All variants use a single handle.
import { Slider } from 'figma-ui3-kit-svelte';
<!-- Delta: for adjusting from a default value (e.g., exposure) -->
<Slider bind:value={exposure} variant="delta" min={-100} max={100} defaultValue={0} />
<!-- Range: fill from start to handle -->
<Slider bind:value={opacity} variant="range" min={0} max={100} />
<!-- Stepper: with visible tick marks -->
<Slider bind:value={step} variant="stepper" min={0} max={100} step={10} />
<Slider bind:value={value} disabled />
Props
| Prop | Type | Options/notes |
|---|---|---|
value |
Number | Current slider value; Bind with bind:value={variable} |
variant |
String | Default: "range", Options: "delta", "range", "stepper" |
min |
Number | Default: 0 |
max |
Number | Default: 100 |
step |
Number | Default: 1 (used for stepper variant) |
defaultValue |
Number | Default position for delta variant (defaults to midpoint if null) |
disabled |
Boolean | Default: false |
tabindex |
Number | Default: 0 |
class |
String | Custom CSS class |
on:change |
Func | Change handler. Ex: on:change={handler} |
on:input |
Func | Input handler (fires during drag) |
on:focus |
Func | Focus handler |
on:blur |
Func | Blur handler |
Toggle switch for boolean settings.
import { Switch } from 'figma-ui3-kit-svelte';
<Switch bind:checked={autoSave}>
Auto-save changes
</Switch>
<Switch bind:checked={notifications} on:change={handleNotificationToggle}>
Enable notifications
</Switch>
<Switch checked disabled>
Required setting
</Switch>
Props
| Prop | Type | Options/notes |
|---|---|---|
checked |
Boolean | Default: false; Bind with bind:checked={variable} |
value |
Boolean | Default: false; Current switch state |
disabled |
Boolean | Default: false |
on:change |
Func | Change handler |
Modern typography component using Figma's UI3 design system. Provides semantic variants for headings and body text with consistent sizing, line height, and letter spacing.
import { Text } from 'figma-ui3-kit-svelte';
<!-- Headings -->
<Text variant="heading-large">Plugin Settings</Text>
<Text variant="heading-medium">Export Options</Text>
<Text variant="heading-small">Advanced</Text>
<!-- Body text -->
<Text variant="body-large">
This is large body text, ideal for primary content and descriptions.
</Text>
<Text variant="body-large-strong">
Large body text with strong weight for emphasis.
</Text>
<Text variant="body-medium">
Default medium body text for most UI elements.
</Text>
<Text variant="body-medium-strong">
Medium body text with strong weight.
</Text>
<Text variant="body-small">
Small body text for secondary information.
</Text>
<!-- Additional styling -->
<Text variant="body-medium" align="center" block>
Centered block text
</Text>
<Text variant="body-large" color="--figma-color-text-brand">
Branded text color
</Text>
<Text variant="body-small" color="--figma-color-text-danger">
Error message
</Text>
Props
| Prop | Type | Options/notes |
|---|---|---|
variant |
String | Default: "body-medium"; Options: "heading-large", "heading-medium", "heading-small", "body-large", "body-large-strong", "body-medium", "body-medium-strong", "body-small", "body-small-strong" |
align |
String | Default: "start"; Options: "start", "center", "end" |
block |
Boolean | Default: false; Display as block element |
color |
String | Default: "--figma-color-text"; Any Figma color variable |
Typography Scale
| Variant | Size | Line Height | Weight | Usage |
|---|---|---|---|---|
heading-large |
24px | 32px | 550 | Primary page titles |
heading-medium |
15px | 25px | 550 | Section headings |
heading-small |
13px | 22px | 550 | Subsection headings |
body-large |
13px | 22px | 450 | Multiline text, descriptions |
body-large-strong |
13px | 22px | 550 | Emphasized multiline text |
body-medium |
11px | 16px | 450 | Default UI text (buttons, inputs) |
body-medium-strong |
11px | 16px | 550 | Emphasized UI text |
body-small |
9px | 14px | 450 | Small UI elements (badges, labels) |
body-small-strong |
9px | 14px | 550 | Emphasized small text |
Multi-line text input for longer content.
import { Textarea } from 'figma-ui3-kit-svelte';
<Textarea
bind:value={description}
placeholder="Enter description..."
/>
<Textarea
bind:value={notes}
rows={4}
placeholder="Additional notes..."
/>
<Textarea
value="Read only content"
disabled
/>
Props
| Prop | Type | Options/notes |
|---|---|---|
value |
String | Textarea value. Bind with bind:value={variable} |
placeholder |
String | Placeholder text |
rows |
Number | Default: 2; Number of visible text rows (height) |
disabled |
Boolean | Default: false |
on:change |
Func | Change handler |
on:input |
Func | Input handler (fires on every keystroke) |
The library includes several other specialized components:
Status and count indicators
import { Badge } from 'figma-ui3-kit-svelte';
Informational banners with icons
import { Banner } from 'figma-ui3-kit-svelte';
Removable tags for filtering and selection
import { Chip } from 'figma-ui3-kit-svelte';
Action-based dropdown menus with items, dividers, headings, and nested sub-menus.
import { Menu, MenuItem, MenuDivider, MenuHeading } from 'figma-ui3-kit-svelte';
<Menu
bind:isOpen={menuOpen}
menuItems={menuItems}
anchorElement={triggerElement}
position="bottom-left"
on:select={handleSelect}
/>
Nested Menus: Items can include a subMenu property for unlimited nesting levels. Sub-menus open on hover and support keyboard navigation.
const menuItems = [
{ value: 'copy', label: 'Copy' },
{
value: 'export',
label: 'Export',
subMenu: [
{ value: 'png', label: 'PNG' },
{ value: 'svg', label: 'SVG' }
]
}
];
Note: Menu is action-based (not select-like). Use Dropdown for select behavior.
Select dropdown for choosing from options.
import { Dropdown } from 'figma-ui3-kit-svelte';
const options = [
{ value: 'option1', label: 'Option 1' },
{ value: 'option2', label: 'Option 2' },
{ value: 'option3', label: 'Option 3', group: 'Group 1' }
];
let selected = options[0];
<Dropdown
bind:value={selected}
menuItems={options}
placeholder="Select an option"
/>
<Dropdown
bind:value={selected}
menuItems={options}
disabled
/>
Props
| Prop | Type | Options/notes |
|---|---|---|
value |
Object | Selected item object. Bind with bind:value={variable} |
menuItems |
Array | Array of objects { value, label, group, selected } |
placeholder |
String | Default: "Please make a selection." |
showGroupLabels |
Boolean | Default: false; Show group headers in menu |
disabled |
Boolean | Default: false |
iconName |
Var | Optional icon to display in trigger |
on:change |
Func | Change handler |
Tab navigation component
import { Tabs } from 'figma-ui3-kit-svelte';
The library uses Figma's native design tokens for consistency and automatic theme support. All tokens are available through CSS variables.
Figma provides comprehensive color tokens that automatically adapt to light/dark themes:
Text Colors
--figma-color-text ā Primary text--figma-color-text-secondary ā Secondary/dimmed text--figma-color-text-brand ā Brand blue text--figma-color-text-danger ā Error/destructive text--figma-color-text-disabled ā Disabled state text--figma-color-text-onbrand ā Text on brand backgroundsBackground Colors
--figma-color-bg ā Primary background--figma-color-bg-secondary ā Secondary background--figma-color-bg-brand ā Brand blue background--figma-color-bg-danger ā Error/destructive background--figma-color-bg-disabled ā Disabled state backgroundBorder Colors
--figma-color-border ā Standard borders--figma-color-border-selected ā Selected state borders--figma-color-border-danger ā Error borders--figma-color-border-disabled ā Disabled bordersIcon Colors
--figma-color-icon ā Standard icons--figma-color-icon-brand ā Brand icons--figma-color-icon-danger ā Error/warning icons--figma-color-icon-onbrand ā Icons on brand backgrounds--figma-color-icon-ondisabled ā Icons on disabled backgroundsUse Figma's spacing scale for consistent layouts:
| Token | Value | Common Usage |
|---|---|---|
--size-xxxsmall |
4px | Tight gaps, icon spacing |
--size-xxsmall |
8px | Button padding, small gaps |
--size-xsmall |
16px | Standard gaps, padding |
--size-small |
24px | Section spacing, icon button |
--size-medium |
32px | Large gaps, modal padding |
--size-large |
40px | Section padding |
--size-xlarge |
48px | Page margins |
--size-xxlarge |
64px | Hero spacing |
--size-huge |
80px | Extra large spacing |
| Token | Value | Usage |
|---|---|---|
--border-radius-small |
2px | Input borders, icon buttons |
--border-radius-medium |
5px | Cards, tooltips |
--border-radius-large |
13px | Buttons, modals |
The library uses semantic typography tokens that combine size, weight, line height, and letter spacing:
Headings
--heading-large-* (24px/32px/550)--heading-medium-* (15px/25px/550)--heading-small-* (13px/22px/550)Body Text
--body-large-* (13px/22px/450)--body-medium-* (11px/16px/450) ā Default UI text--body-small-* (9px/14px/450)Each semantic token includes:
*-font-size*-line-height*-font-weight*-letter-spacingExample Usage:
.custom-text {
font-family: var(--font-stack);
font-size: var(--body-medium-font-size);
line-height: var(--body-medium-line-height);
font-weight: var(--body-medium-font-weight);
letter-spacing: var(--body-medium-letter-spacing);
color: var(--figma-color-text);
}
--shadow-hud ā Menus, tooltips, toasts--shadow-floating-window ā Modals, dialogsmy-plugin/
āāā src/
ā āāā main.js # Main plugin code (runs in Figma sandbox)
ā āāā ui.html # UI HTML
ā āāā App.svelte # Your Svelte app
āāā package.json
āāā manifest.json # Figma plugin manifest
manifest.json
{
"name": "My Plugin",
"id": "123456789",
"api": "1.0.0",
"main": "dist/main.js",
"ui": "dist/ui.html",
"editorType": ["figma"]
}
main.js
figma.showUI(__html__, {
themeColors: true, // Enable automatic dark mode
width: 400,
height: 500
});
// Listen for messages from UI
figma.ui.onmessage = (msg) => {
if (msg.type === 'create-rectangles') {
const nodes = [];
for (let i = 0; i < msg.count; i++) {
const rect = figma.createRectangle();
rect.x = i * 150;
rect.fills = [{type: 'SOLID', color: {r: 1, g: 0.5, b: 0}}];
figma.currentPage.appendChild(rect);
nodes.push(rect);
}
figma.currentPage.selection = nodes;
figma.viewport.scrollAndZoomIntoView(nodes);
}
figma.closePlugin();
};
App.svelte
<script>
import { GlobalCSS, Button, Input, Text } from 'figma-ui3-kit-svelte';
let count = 5;
function create() {
parent.postMessage({
pluginMessage: {
type: 'create-rectangles',
count: parseInt(count)
}
}, '*');
}
</script>
<GlobalCSS />
<div class="plugin-container">
<Text variant="heading-medium">Create Rectangles</Text>
<Input
type="number"
bind:value={count}
placeholder="Number of rectangles..."
/>
<Button variant="primary" on:click={create}>
Create
</Button>
</div>
<style>
.plugin-container {
padding: var(--size-xsmall);
display: flex;
flex-direction: column;
gap: var(--size-xxsmall);
}
</style>
Always use Figma's CSS variables instead of hardcoding values:
/* ā
Good - uses design tokens */
.my-component {
background: var(--figma-color-bg);
color: var(--figma-color-text);
padding: var(--size-xsmall);
border-radius: var(--border-radius-medium);
}
/* ā Bad - hardcoded values break theme support */
.my-component {
background: #ffffff;
color: #000000;
padding: 16px;
border-radius: 5px;
}
Use the Text component or semantic typography tokens for all text to maintain consistency:
<!-- ā
Good -->
<Text variant="body-medium">Consistent text</Text>
<!-- ā Avoid -->
<span style="font-size: 11px;">Inconsistent text</span>
Use Figma's spacing tokens with CSS Grid or Flexbox:
.layout {
display: flex;
flex-direction: column;
gap: var(--size-xsmall);
padding: var(--size-xsmall);
}
This library is designed for modern Figma plugin environments, which use a recent Chromium-based webview. All modern CSS and JavaScript features are supported.
Contributions are welcome! If you find bugs or have feature requests, please open an issue on GitHub.
# Clone the repository
git clone https://github.com/mariusroosendaal/figma-ui3-kit-svelte.git
# Install dependencies
npm install
# Run development server
npm run dev
# Build for production
npm run build
The development server runs playground/App.svelte as a playground for testing components.
MIT License ā feel free to use in your projects.
Built with ā¤ļø for the Figma plugin community.