.cursor/skills/figui3/SKILL.md
Guides development and maintenance of the FigUI3 web components library for Figma-style plugin UIs. Applies when adding or modifying `fig-*` custom elements, updating docs/demo pages, adjusting theme tokens, improving accessibility, or debugging component behavior in `fig.js`, `components.css`, `index.html`, and `README.md`.
npx skillsauth add rogie/figui3 figui3Install this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
A lightweight web components library for Figma UI3-style plugin and widget interfaces.
IMPORTANT: Prefer the project's native scripts and structure. Use
bun devfor local docs/demo work andbun buildfor production output.
!`node -e "const p=require('./package.json'); console.log(JSON.stringify({name:p.name,version:p.version,scripts:p.scripts,exports:p.exports},null,2))" 2>/dev/null || echo '{"error":"package.json not found"}'`
The JSON above is the source of truth for package name, build commands, and exported files.
fig-* components over one-off markup. Compose from current primitives before inventing new ones.input while interacting and change on committed value changes.npm i @rogieking/figui3 (or pnpm add / bun add).main.tsx / main.jsx): import "@rogieking/figui3/fig.css";import "@rogieking/figui3/fig.css";
const bootstrap = async () => {
// Prevent production tree-shaking from dropping registration side effects.
await import("@rogieking/figui3/fig.js");
createRoot(document.getElementById("app")!).render(<App />);
};
bootstrap();
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
export default defineConfig({
plugins: [react()],
});
<fig-slider text="true" />) and read values from e.target / e.detail.class (not className) for all FigUI3 web components (fig-* and <dialog is="fig-...">) to keep attribute behavior consistent.addEventListener when wiring complex input/change behavior.fig-input-color / fig-fill-picker)fig-input-color supports custom mode workflows only through picker="figma" (internally uses fig-fill-picker).mode attribute on fig-input-color is pass-through to inner fig-fill-picker; mode logic lives in fig-fill-picker.picker-* attrs on fig-input-color are forwarded to fig-fill-picker (except picker-anchor, which is handled separately).
picker-dialog-position, picker-experimental, etc.fig-fill-picker + slot API:
slot="mode-<name>" (and optional label).<name> in the mode attribute (e.g. mode="solid,react-demo").modeready and render into e.detail.container.modeready container as mount target.root per mode containerroot.unmount() when the host component unmountsmodeready listeners in cleanup to avoid duplicate mountsinput / change with detail payload so picker can store mode data and propagate events.fig-input-color expects solid color data (detail.color, optional detail.alpha) from the picker.fig-fill-picker custom modes use JSON with type set to mode name and remaining data in payload.picker-anchor behavior explicit in React:
picker-anchor="self" anchors to the color input element itself.document.querySelector).experimental as a feature-flag string for opt-in behavior. Treat it as progressive enhancement, not guaranteed baseline behavior.experimental="modern" when enabling modern customizable select/picker UI behavior.fig-dropdown, fig-fill-picker, fig-input-fill, fig-input-color).fig-input-color and fig-input-fill forward experimental-related picker settings into internal fig-fill-picker usage.variant="neue" for dropdown experimental behavior.variant="neue" handling only where it is still intentionally supported (for example slider visuals).fig-dialog, fig-popup)<dialog is="fig-dialog"> for modal/light-dismiss dialog workflows.<dialog is="fig-popup"> for anchored floating surfaces (menus, contextual panels, nested popups).fig-dialog should remain dialog-first (title/header/footer patterns, modal semantics).fig-popup should remain anchor/position-first (offset, collision handling, viewport margins).fig-dialog and fig-popup; do not regress manual placement rules.HTMLElement and implement lifecycle cleanup in disconnectedCallback.observedAttributes + attributeChangedCallback for attribute-driven reactivity.disabled behavior wherever interaction is possible.input and change events for form-like controls.event.detail when needed; keep names stable.color-scheme and current token strategy.README.md component docs when public API or behavior changes.index.html and playground/ routes where relevant) for visible behavior changes.fig-fill-picker concern, not a standalone fig-input-color concern.slot="mode-*")modeready usageinput from programmatic attribute writes (value updates); preserve current loop-avoidance behavior for React.<!-- Modal/dialog content container -->
<dialog is="fig-dialog" drag="true" handle="fig-header">
<fig-header>
Dialog Title
<fig-button variant="ghost" icon close-dialog aria-label="Close dialog">
<span class="fig-mask-icon" style="--icon: var(--icon-close)"></span>
</fig-button>
</fig-header>
<div>Dialog body</div>
</dialog>
<!-- Anchored popup surface -->
<dialog is="fig-popup" anchor="#trigger" position="bottom left" offset="8 8">
<div>Popup content</div>
</dialog>
// Event contract pattern: continuous + committed updates.
this.dispatchEvent(new CustomEvent("input", { detail, bubbles: true }));
this.dispatchEvent(new CustomEvent("change", { detail, bubbles: true }));
// Attribute-driven updates.
static get observedAttributes() { return ["value", "disabled"]; }
attributeChangedCallback(name, oldValue, newValue) {
if (oldValue === newValue) return;
// sync internal UI state
}
Event contract quick map:
- fig-slider: input/change -> current value on e.target.value
- fig-input-color: input/change -> value on e.target.value, structured color via e.detail (when available)
- fig-input-fill / fig-fill-picker: input/change -> fill payload in e.detail
<!-- Typical field composition -->
<fig-field direction="horizontal">
<label>Opacity</label>
<fig-slider value="75" min="0" max="100" text="true" units="%"></fig-slider>
</fig-field>
fig-popup vs fig-dialogfig-dialog when the UI is a dialog.
fig-popup when you need low-level floating control.
Rule of thumb: fig-dialog = dialog UX, fig-popup = popup primitive.
fig.js, components.css, and related demo usage before editing.bun dev for interactive verification and bun build for output sanity.bun build) and confirm custom elements are registered at runtime.input vs change behavior for touched controls in both vanilla usage and React integration.fig-dialog, fig-popup) including close/dismiss and drag behavior when applicable.README.md, demos, and CHANGELOG.md for any public API or behavior change.# Start docs/demo server
bun dev
# Build distributable files
bun build
fig.js - component implementations and behaviorcomponents.css - component-level styling and statesbase.css - foundational styles and variablesindex.html - main interactive docs/demoREADME.md - public API and usage documentationCHANGELOG.md - release history and migration notesdevelopment
Guides creation and refinement of Figma-style property panel patterns ("PropKit") using FigUI3 components. Applies when building or modifying property fields in the playground app (`/propkit` route), generating consistent field prompts, composing horizontal `fig-field` rows, or tuning panel UX for controls like image, color, fill, slider, switch, dropdown, segmented control, easing, and angle.
tools
Guides development and maintenance of the FigUI3 web components library for Figma-style plugin UIs. Applies when adding or modifying `fig-*` custom elements, updating docs/demo pages, adjusting theme tokens, improving accessibility, or debugging component behavior in `fig.js`, `components.css`, `index.html`, and `README.md`.
development
Guides creation and refinement of Figma-style property panel patterns ("PropKit") using FigUI3 components. Applies when building or modifying property fields in the playground app (`/propkit` route), generating consistent field prompts, composing horizontal `fig-field` rows, or tuning panel UX for controls like image, color, fill, slider, switch, dropdown, segmented control, easing, and angle.
development
Implements CSS nesting and advanced selectors with progressive enhancement and maintainable specificity. Use when writing or refactoring nested CSS, or when the user mentions :has, :is, :where, :not, or complex selector composition.