### Install Figma Widget and Plugin Typings Source: https://github.com/figma/widget-typings/blob/main/README.md Install both `@figma/plugin-typings` and `@figma/widget-typings` as development dependencies. ```sh npm i --save-dev @figma/plugin-typings @figma/widget-typings ``` -------------------------------- ### Install Figma Widget and Plugin Typings Source: https://context7.com/figma/widget-typings/llms.txt Install the necessary packages for Figma widget and plugin development. These typings extend `@figma/plugin-typings`. ```sh npm install --save-dev @figma/plugin-typings @figma/widget-typings ``` -------------------------------- ### Implement Widget Property Menus with `usePropertyMenu` Source: https://context7.com/figma/widget-typings/llms.txt Attach a property menu to a widget using `usePropertyMenu`. This example demonstrates various item types including color selectors, dropdowns, toggles, and links, along with their corresponding state management. ```tsx const { widget } = figma const { AutoLayout, Text, useSyncedState, usePropertyMenu } = widget type Theme = "light" | "dark" type Size = "small" | "medium" | "large" function ThemedWidget() { const [theme, setTheme] = useSyncedState("theme", "light") const [size, setSize] = useSyncedState("size", "medium") const [isLocked, setIsLocked] = useSyncedState("locked", false) usePropertyMenu( [ { itemType: "color-selector", propertyName: "theme", tooltip: "Background theme", selectedOption: theme === "light" ? "#FFFFFF" : "#1E1E1E", options: [ { option: "#FFFFFF", tooltip: "Light" }, { option: "#1E1E1E", tooltip: "Dark" }, ], }, { itemType: "separator" }, { itemType: "dropdown", propertyName: "size", tooltip: "Widget size", selectedOption: size, options: [ { option: "small", label: "Small" }, { option: "medium", label: "Medium" }, { option: "large", label: "Large" }, ], }, { itemType: "toggle", propertyName: "locked", tooltip: "Lock content", isToggled: isLocked, icon: "", }, { itemType: "link", propertyName: "docs", tooltip: "Open docs", href: "https://developers.figma.com/docs/widgets", icon: null, }, ], ({ propertyName, propertyValue }) => { if (propertyName === "theme") { setTheme(propertyValue === "#FFFFFF" ? "light" : "dark") } else if (propertyName === "size") { setSize(propertyValue as Size) } else if (propertyName === "locked") { setIsLocked(!isLocked) } } ) const bg = theme === "light" ? "#FFFFFF" : "#1E1E1E" const fg = theme === "light" ? "#111111" : "#EEEEEE" const paddingMap = { small: 8, medium: 16, large: 24 } return ( {isLocked ? "🔒 Locked" : "✏️ Editable"} — {theme} / {size} ) } widget.register(ThemedWidget) ``` -------------------------------- ### Handle Async Operations with `waitForTask` in Figma Widgets Source: https://context7.com/figma/widget-typings/llms.txt Use `waitForTask` inside `useEffect` to prevent widget termination during async operations like network requests. This example fetches weather data and updates the widget's UI. ```tsx const { widget } = figma const { Text, AutoLayout, useEffect, waitForTask, useSyncedState } = widget function WeatherWidget() { const [temp, setTemp] = useSyncedState("temperature", "Loading...") const [city, setCity] = useSyncedState("city", "San Francisco") useEffect(() => { waitForTask( new Promise(resolve => { // Show UI iframe to fetch data from the network figma.showUI(` `, { visible: false }) figma.ui.onmessage = (msg: { type: string; text: string }) => { if (msg.type === "weather") { setTemp(msg.text) figma.closePlugin() resolve() } } }) ) }) return ( {temp} ) } widget.register(WeatherWidget) ``` -------------------------------- ### Access Widget Node ID with useWidgetNodeId Source: https://context7.com/figma/widget-typings/llms.txt Use `useWidgetNodeId` to get the current widget's node ID. This is essential for interacting with the Figma plugin API, such as using `figma.getNodeById`. Ensure it's only called within event handlers or effects, not during rendering. ```tsx const { widget } = figma const { Text, useWidgetNodeId } = widget function CloningWidget() { const widgetId = useWidgetNodeId() return ( { // Safe to use figma API inside event handler const widgetNode = figma.getNodeById(widgetId) as WidgetNode const clone = widgetNode.clone() widgetNode.parent!.appendChild(clone) clone.x = widgetNode.x + widgetNode.width + 32 clone.y = widgetNode.y figma.notify("Widget cloned!") }} > Duplicate me → ) } widget.register(CloningWidget) ``` -------------------------------- ### `useStickableHost` Source: https://context7.com/figma/widget-typings/llms.txt Registers a widget as a host that can receive stickables (stamps, other stickable widgets). Called when stickables are attached or detached. This is specific to FigJam. ```APIDOC ## `useStickableHost` — Stickable Host Widget (FigJam only) *(FigJam only)* Registers a widget as a host that can receive stickables (stamps, other stickable widgets). Called when stickables are attached or detached. ```tsx const { widget } = figma const { AutoLayout, Text, useSyncedState, useStickableHost, useWidgetNodeId } = widget function VoteCollectorWidget() { const [votes, setVotes] = useSyncedState>("votes", {}) const widgetId = useWidgetNodeId() useStickableHost(() => { const node = figma.getNodeById(widgetId) as WidgetNode if (!node) return const tally: Record = {} for (const stuck of node.stuckNodes) { if (stuck?.type !== "STAMP") continue tally[stuck.name] = (tally[stuck.name] ?? 0) + 1 } setVotes(tally) }) const entries = Object.entries(votes) return ( Stamp Votes {entries.length === 0 ? Drop stamps here to vote : entries.map(([name, count]) => ( {name}: {count} )) } ) } widget.register(VoteCollectorWidget) ``` ``` -------------------------------- ### Define Solid, Gradient, and Image Paints Source: https://context7.com/figma/widget-typings/llms.txt Specifies how a component's surface is painted. Supports solid colors, linear/radial gradients, and image fills with various scaling options. ```ts const solidFill: WidgetJSX.SolidPaint = { type: "solid", color: "#FF5500", opacity: 0.9, blendMode: "multiply", } const gradientFill: WidgetJSX.GradientPaint = { type: "gradient-linear", gradientHandlePositions: [{ x: 0, y: 0 }, { x: 1, y: 1 }, { x: 0, y: 1 }], gradientStops: [ { position: 0, color: { r: 0.2, g: 0.4, b: 1, a: 1 } }, { position: 1, color: { r: 0.9, g: 0.1, b: 0.5, a: 1 } }, ], } const imageFill: WidgetJSX.ImagePaint = { type: "image", src: "https://example.com/photo.jpg", scaleMode: "fill", } ``` -------------------------------- ### `usePropertyMenu` — Widget Property Menu Source: https://context7.com/figma/widget-typings/llms.txt Attaches a property menu to the widget, which appears when the widget is selected. It supports various interactive elements like action buttons, color selectors, dropdowns, toggles, separators, and external links. ```APIDOC ## `usePropertyMenu` — Widget Property Menu Attaches a property menu to the widget shown when the widget is selected. Supports action buttons, color selectors, dropdowns, toggles, separators, and external links. ```tsx const { widget } = figma const { AutoLayout, Text, useSyncedState, usePropertyMenu } = widget type Theme = "light" | "dark" type Size = "small" | "medium" | "large" function ThemedWidget() { const [theme, setTheme] = useSyncedState("theme", "light") const [size, setSize] = useSyncedState("size", "medium") const [isLocked, setIsLocked] = useSyncedState("locked", false) usePropertyMenu( [ { itemType: "color-selector", propertyName: "theme", tooltip: "Background theme", selectedOption: theme === "light" ? "#FFFFFF" : "#1E1E1E", options: [ { option: "#FFFFFF", tooltip: "Light" }, { option: "#1E1E1E", tooltip: "Dark" }, ], }, { itemType: "separator" }, { itemType: "dropdown", propertyName: "size", tooltip: "Widget size", selectedOption: size, options: [ { option: "small", label: "Small" }, { option: "medium", label: "Medium" }, { option: "large", label: "Large" }, ], }, { itemType: "toggle", propertyName: "locked", tooltip: "Lock content", isToggled: isLocked, icon: ``, }, { itemType: "link", propertyName: "docs", tooltip: "Open docs", href: "https://developers.figma.com/docs/widgets", icon: null, }, ], ({ propertyName, propertyValue }) => { if (propertyName === "theme") { setTheme(propertyValue === "#FFFFFF" ? "light" : "dark") } else if (propertyName === "size") { setSize(propertyValue as Size) } else if (propertyName === "locked") { setIsLocked(!isLocked) } } ) const bg = theme === "light" ? "#FFFFFF" : "#1E1E1E" const fg = theme === "light" ? "#111111" : "#EEEEEE" const paddingMap = { small: 8, medium: 16, large: 24 } return ( {isLocked ? "🔒 Locked" : "✏️ Editable"} — {theme} / {size} ) } widget.register(ThemedWidget) ``` ``` -------------------------------- ### Import Specific Widget API Types Source: https://context7.com/figma/widget-typings/llms.txt Import specific types from the standalone entry point if explicit imports are needed, otherwise types are globally available. ```ts import type { WidgetJSXFrameProps, AutoLayoutProps } from "@figma/widget-typings/widget-api-standalone" ``` -------------------------------- ### Register Widget as a Stickable Host Source: https://context7.com/figma/widget-typings/llms.txt Use `useStickableHost` to designate a widget as a host capable of receiving stickables (stamps or other stickable widgets) in FigJam. This hook is called when stickables are attached or detached, allowing you to manage and react to these events. ```tsx const { widget } = figma const { AutoLayout, Text, useSyncedState, useStickableHost, useWidgetNodeId } = widget function VoteCollectorWidget() { const [votes, setVotes] = useSyncedState>("votes", {}) const widgetId = useWidgetNodeId() useStickableHost(() => { const node = figma.getNodeById(widgetId) as WidgetNode if (!node) return const tally: Record = {} for (const stuck of node.stuckNodes) { if (stuck?.type !== "STAMP") continue tally[stuck.name] = (tally[stuck.name] ?? 0) + 1 } setVotes(tally) }) const entries = Object.entries(votes) return ( Stamp Votes {entries.length === 0 ? Drop stamps here to vote : entries.map(([name, count]) => ( {name}: {count} )) } ) } widget.register(VoteCollectorWidget) ``` -------------------------------- ### Configure tsconfig.json for Figma Widgets Source: https://context7.com/figma/widget-typings/llms.txt Configure your tsconfig.json to include the `@figma` type roots and set up JSX compilation for Figma widgets. ```json { "compilerOptions": { "typeRoots": [ "./node_modules/@types", "./node_modules/@figma" ], "jsx": "react", "jsxFactory": "figma.widget.h" } } ``` -------------------------------- ### Implement Stickable Widget Behavior Source: https://context7.com/figma/widget-typings/llms.txt The `useStickable` hook makes a widget behave like a stamp in FigJam, sticking to other nodes. It accepts an optional callback that triggers when the widget's stuck node changes, allowing for visual feedback based on the host node's type. ```tsx const { widget } = figma const { Rectangle, useSyncedState, useStickable, useWidgetNodeId } = widget function StickyIndicatorWidget() { const [color, setColor] = useSyncedState("color", "#888888") const widgetId = useWidgetNodeId() useStickable(() => { const node = figma.getNodeById(widgetId) as WidgetNode const host = node?.stuckTo if (!host) { setColor("#888888") // Not stuck — grey return } switch (host.type) { case "STICKY": setColor("#FF4444"); break // Red for sticky notes case "SHAPE_WITH_TEXT": setColor("#44BB44"); break // Green for shapes default: setColor("#4488FF"); break // Blue for anything else } }) return ( ) } widget.register(StickyIndicatorWidget) ``` -------------------------------- ### widget.register Source: https://context7.com/figma/widget-typings/llms.txt The main entry point for registering a widget component. This function is called once with the root functional component and is re-invoked on every state update. ```APIDOC ## widget.register — Register a Widget Component The main entry point for every widget. Called once with the root functional component; re-invoked on every state update. ```tsx const { widget } = figma const { AutoLayout, Text, useSyncedState } = widget function CounterWidget() { const [count, setCount] = useSyncedState("count", 0) return ( Count: {count} setCount(count + 1)} > Increment ) } widget.register(CounterWidget) ``` ``` -------------------------------- ### Configure tsconfig.json for Figma Typings Source: https://github.com/figma/widget-typings/blob/main/README.md Configure `tsconfig.json` to include type definitions from `./node_modules/@types` and `./node_modules/@figma`. This ensures TypeScript can find the plugin and widget typings, which are hosted separately from standard DefinitelyTyped packages. ```json { "compilerOptions": { "typeRoots": [ "./node_modules/@types", "./node_modules/@figma" ] } } ``` -------------------------------- ### Configure AutoLayout for Flex Container Source: https://context7.com/figma/widget-typings/llms.txt The `AutoLayout` component provides flexbox-like layout capabilities for Figma widgets. Configure its properties such as direction, spacing, padding, alignment, and visual styles to create responsive and structured UI elements. ```tsx const { AutoLayout, Text, Rectangle } = figma.widget function LayoutDemo() { return ( Figma Widget ) } ``` -------------------------------- ### useSyncedMap Source: https://context7.com/figma/widget-typings/llms.txt A hook for creating a map-based state store that allows for concurrent-safe updates to individual keys. It's ideal for collaborative widgets where multiple users might modify the same data simultaneously. ```APIDOC ## `useSyncedMap` — Concurrent-Safe Key-Value State A map-based state store where individual keys are updated last-writer-wins, preventing full overwrites when multiple users edit simultaneously. Ideal for collaborative widgets. ### `SyncedMap` Interface Methods | Method | Signature | Description | |--------|-----------|-------------| | `has` | `(key: string) => boolean` | Returns whether a key exists | | `get` | `(key: string) => T \| undefined` | Returns value for the key | | `set` | `(key: string, value: T) => void` | Persists a key/value pair | | `delete` | `(key: string) => void` | Removes a key | | `keys` | `() => string[]` | Returns all keys | | `values` | `() => T[]` | Returns all values | | `entries` | `() => [string, T][]` | Returns key-value tuples | | `size` | `readonly number` | Returns number of keys | ``` -------------------------------- ### `useStickable` Source: https://context7.com/figma/widget-typings/llms.txt Makes a widget behave like a stamp, sticking to other nodes when dragged over them. Accepts an optional callback triggered when the widget's stuck node changes. This is specific to FigJam. ```APIDOC ## `useStickable` — Stickable Widget (FigJam only) *(FigJam only)* Makes a widget behave like a stamp — it sticks to other nodes when dragged over them. Accepts an optional callback triggered when the widget's stuck node changes. ```tsx const { widget } = figma const { Rectangle, useSyncedState, useStickable, useWidgetNodeId } = widget function StickyIndicatorWidget() { const [color, setColor] = useSyncedState("color", "#888888") const widgetId = useWidgetNodeId() useStickable(() => { const node = figma.getNodeById(widgetId) as WidgetNode const host = node?.stuckTo if (!host) { setColor("#888888") // Not stuck — grey return } switch (host.type) { case "STICKY": setColor("#FF4444"); break // Red for sticky notes case "SHAPE_WITH_TEXT": setColor("#44BB44"); break // Green for shapes default: setColor("#4488FF"); break // Blue for anything else } }) return ( ) } widget.register(StickyIndicatorWidget) ``` ``` -------------------------------- ### Create an Editable Text Field with Input Source: https://context7.com/figma/widget-typings/llms.txt Utilize the Input component for creating editable text fields. Supports placeholders, custom styling, and multiline input behavior. Use useSyncedState to manage the input's value. ```tsx const { AutoLayout, Input, useSyncedState } = figma.widget function EditableWidget() { const [text, setText] = useSyncedState("text", "") return ( setText(e.characters)} fontSize={14} fill="#111111" width={240} inputBehavior="multiline" inputFrameProps={{ padding: 8, fill: "#FAFAFA", cornerRadius: 4 }} /> ) } ``` -------------------------------- ### Convert Color Map to Widget Options Source: https://context7.com/figma/widget-typings/llms.txt Use `colorMapToOptions` to transform a `ColorPalette` map into an array of `WidgetPropertyMenuColorSelectorOption[]`. This is useful for populating color-selector property menus in FigJam widgets. ```tsx const { widget } = figma const { colorMapToOptions, useSyncedState, usePropertyMenu, AutoLayout, Text } = widget function FigJamColorWidget() { const [color, setColor] = useSyncedState( "color", figma.constants.colors.figJamBase.black ) usePropertyMenu( [ { itemType: "color-selector", propertyName: "color", tooltip: "Pick a color", selectedOption: color, options: [ // Spread the official FigJam palette and add a custom color ...colorMapToOptions(figma.constants.colors.figJamBase), { option: "#FF69B4", tooltip: "Hot Pink" }, ], }, ], ({ propertyName, propertyValue }) => { if (propertyName === "color") setColor(propertyValue!) } ) return ( {color} ) } widget.register(FigJamColorWidget) ``` -------------------------------- ### useEffect Source: https://context7.com/figma/widget-typings/llms.txt A hook for managing side effects and event handlers within a widget. It runs a callback after each render and supports returning a cleanup function. This is useful for setting up event listeners, fetching data, and synchronizing state. ```APIDOC ## `useEffect` — Side Effects and Event Handlers Runs a callback after every render. Supports returning a cleanup function. Used for setting up event listeners, data fetching with `waitForTask`, and syncing state from the plugin API. ``` -------------------------------- ### useSyncedState Source: https://context7.com/figma/widget-typings/llms.txt A hook similar to React's `useState` that persists state on the widget node and synchronizes it across all clients. It accepts a unique key, a default value, or a lazy initializer function. ```APIDOC ## useSyncedState — Synchronized Widget State React `useState`-like hook where state is persisted on the widget node and automatically synchronized across all clients. Accepts a unique key, a default value, or a lazy initializer function. ```tsx const { widget } = figma const { Text, AutoLayout, useSyncedState } = widget function TodoWidget() { // Simple value state const [title, setTitle] = useSyncedState("title", "My Todo List") // Lazy initializer for plugin API calls not allowed during render const [creator, setCreator] = useSyncedState("creator", () => { return figma.currentUser?.name ?? "Unknown" }) // Functional update using previous value const [completedCount, setCompletedCount] = useSyncedState("completedCount", 0) return ( {title} Created by: {creator} setCompletedCount(prev => prev + 1)} > Complete task ({completedCount} done) ) } widget.register(TodoWidget) ``` ``` -------------------------------- ### `colorMapToOptions` Source: https://context7.com/figma/widget-typings/llms.txt Converts a `ColorPalette` map into an array of `WidgetPropertyMenuColorSelectorOption[]` for use in a color-selector property menu item. This is specific to FigJam. ```APIDOC ## `colorMapToOptions` — FigJam Color Palette Helper *(FigJam only)* Converts a `ColorPalette` map (e.g., `figma.constants.colors.figJamBase`) into an array of `WidgetPropertyMenuColorSelectorOption[]` for use in a color-selector property menu item. ```tsx const { widget } = figma const { colorMapToOptions, useSyncedState, usePropertyMenu, AutoLayout, Text } = widget function FigJamColorWidget() { const [color, setColor] = useSyncedState( "color", figma.constants.colors.figJamBase.black ) usePropertyMenu( [ { itemType: "color-selector", propertyName: "color", tooltip: "Pick a color", selectedOption: color, options: [ // Spread the official FigJam palette and add a custom color ...colorMapToOptions(figma.constants.colors.figJamBase), { option: "#FF69B4", tooltip: "Hot Pink" }, ], }, ], ({ propertyName, propertyValue }) => { if (propertyName === "color") setColor(propertyValue!) } ) return ( {color} ) } widget.register(FigJamColorWidget) ``` ``` -------------------------------- ### Define Widget Padding in TypeScript Source: https://context7.com/figma/widget-typings/llms.txt Use WidgetJSX.Padding to define uniform, per-side, or vertical/horizontal padding values for widgets. ```typescript // Uniform padding const p1: WidgetJSX.Padding = 16 ``` ```typescript // Per-side padding const p2: WidgetJSX.Padding = { top: 8, right: 16, bottom: 8, left: 16 } ``` ```typescript // Vertical/horizontal shorthand const p3: WidgetJSX.Padding = { vertical: 12, horizontal: 24 } ``` -------------------------------- ### `AutoLayout` Component Source: https://context7.com/figma/widget-typings/llms.txt A flex container component for arranging child elements within a Figma widget. It supports various layout properties like direction, spacing, padding, alignment, and styling. ```APIDOC ### `AutoLayout` — Flex Container ```tsx const { AutoLayout, Text, Rectangle } = figma.widget function LayoutDemo() { return ( Figma Widget ) } ``` ``` -------------------------------- ### Define Drop Shadow and Layer Blur Effects Source: https://context7.com/figma/widget-typings/llms.txt Applies visual effects to components. Supports drop shadows with configurable color, offset, blur, and spread, as well as layer blurs. ```ts const shadow: WidgetJSX.DropShadowEffect = { type: "drop-shadow", color: { r: 0, g: 0, b: 0, a: 0.2 }, offset: { x: 0, y: 4 }, blur: 12, spread: 2, visible: true, } const blur: WidgetJSX.BlurEffect = { type: "layer-blur", blur: 8, visible: true, } ``` -------------------------------- ### Use SyncedMap for Collaborative Key-Value State Source: https://context7.com/figma/widget-typings/llms.txt Use `useSyncedMap` to manage key-value state that updates concurrently. Individual key updates are last-writer-wins, suitable for collaborative widgets. ```tsx const { widget } = figma const { Rectangle, AutoLayout, Text, useSyncedMap, useWidgetNodeId } = widget function VotingWidget() { // Each user's session ID maps to their vote choice const votes = useSyncedMap("userVotes") const widgetId = useWidgetNodeId() const tallyVotes = (option: string) => votes.values().filter(v => v === option).length return ( Cast your vote {["Option A", "Option B", "Option C"].map(option => ( { const sessionId = figma.activeUsers[0].sessionId.toString() votes.set(sessionId, option) }} > {option} ({tallyVotes(option)} votes) ))} { const sessionId = figma.activeUsers[0].sessionId.toString() votes.delete(sessionId) }} > Clear my vote ) } widget.register(VotingWidget) ``` -------------------------------- ### `waitForTask` — Async Work in Widgets Source: https://context7.com/figma/widget-typings/llms.txt Ensures a widget is not terminated while an asynchronous operation is in progress. This function must be used within a `useEffect` hook. ```APIDOC ## `waitForTask` — Async Work in Widgets Prevents the widget from being terminated while an async operation (network request, timer, UI interaction) is pending. Must be used inside `useEffect`. ```tsx const { widget } = figma const { Text, AutoLayout, useEffect, waitForTask, useSyncedState } = widget function WeatherWidget() { const [temp, setTemp] = useSyncedState("temperature", "Loading...") const [city, setCity] = useSyncedState("city", "San Francisco") useEffect(() => { waitForTask( new Promise(resolve => { // Show UI iframe to fetch data from the network figma.showUI(` `, { visible: false }) figma.ui.onmessage = (msg: { type: string; text: string }) => { if (msg.type === "weather") { setTemp(msg.text) figma.closePlugin() resolve() } } }) ) }) return ( {temp} ) } widget.register(WeatherWidget) ``` ``` -------------------------------- ### Register a Counter Widget Component Source: https://context7.com/figma/widget-typings/llms.txt Register the root functional component for a widget using `widget.register`. This component will be re-invoked on state updates. It uses `useSyncedState` for managing and synchronizing widget state. ```tsx const { widget } = figma const { AutoLayout, Text, useSyncedState } = widget function CounterWidget() { const [count, setCount] = useSyncedState("count", 0) return ( Count: {count} setCount(count + 1)} > Increment ) } widget.register(CounterWidget) ``` -------------------------------- ### Handle Side Effects with useEffect Source: https://context7.com/figma/widget-typings/llms.txt Use `useEffect` to run callbacks after renders for side effects like setting up event listeners or fetching data. It supports cleanup functions, which are crucial for preventing memory leaks by removing listeners before the next effect runs. ```tsx const { widget } = figma const { Text, AutoLayout, useEffect, waitForTask, useSyncedState } = widget function SelectionTrackerWidget() { const [selectionCount, setSelectionCount] = useSyncedState("selectionCount", () => figma.currentPage.selection.length ) const [lastMessage, setLastMessage] = useSyncedState("lastMessage", "") useEffect(() => { // Set up selection change listener; clean it up on next effect run const onSelectionChange = () => { setSelectionCount(figma.currentPage.selection.length) } figma.on("selectionchange", onSelectionChange) // Handle UI messages figma.ui.onmessage = (msg: { type: string; text: string }) => { if (msg.type === "update-text") { setLastMessage(msg.text) } } // Cleanup: remove listener before next effect return () => { figma.off("selectionchange", onSelectionChange) } }) return ( Selected nodes: {selectionCount} {lastMessage ? {lastMessage} : null} ) } widget.register(SelectionTrackerWidget) ``` -------------------------------- ### Use `useSyncedState` for Synchronized Widget State Source: https://context7.com/figma/widget-typings/llms.txt Utilize the `useSyncedState` hook, similar to React's `useState`, for persisting and synchronizing widget state across all clients. It accepts a unique key, a default value, or a lazy initializer. ```tsx const { widget } = figma const { Text, AutoLayout, useSyncedState } = widget function TodoWidget() { // Simple value state const [title, setTitle] = useSyncedState("title", "My Todo List") // Lazy initializer for plugin API calls not allowed during render const [creator, setCreator] = useSyncedState("creator", () => { return figma.currentUser?.name ?? "Unknown" }) // Functional update using previous value const [completedCount, setCompletedCount] = useSyncedState("completedCount", 0) return ( {title} Created by: {creator} setCompletedCount(prev => prev + 1)} > Complete task ({completedCount} done) ) } widget.register(TodoWidget) ``` -------------------------------- ### Display Images and SVGs with Image and SVG Components Source: https://context7.com/figma/widget-typings/llms.txt Embed images from URLs or SVG code using the Image and SVG components. Supports sizing, corner radius, and tooltips for interactive elements. ```tsx const { AutoLayout, Image, SVG } = figma.widget const ICON_SVG = ` W ` function MediaWidget() { return ( ) } ``` -------------------------------- ### Draw Lines with Line Component Source: https://context7.com/figma/widget-typings/llms.txt Use the Line component to render lines. Supports custom stroke color, width, dash patterns, and length. Can be set to 'fill-parent' for dynamic sizing. ```tsx const { AutoLayout, Line } = figma.widget function DividerWidget() { return ( ) } ``` -------------------------------- ### Create Shapes with Rectangle and Ellipse Source: https://context7.com/figma/widget-typings/llms.txt Draw basic shapes like rectangles and ellipses using dedicated components. Supports fills (solid, gradient), strokes, corner radius, and effects like inner shadows. ```tsx const { AutoLayout, Rectangle, Ellipse } = figma.widget function ShapesWidget() { return ( ) } ``` -------------------------------- ### Define RGBA and Hex Colors Source: https://context7.com/figma/widget-typings/llms.txt Represents colors using RGBA objects or hex color codes. Used for fills, strokes, and text colors within widget components. ```ts // RGBA color object const red: WidgetJSX.Color = { r: 1, g: 0, b: 0, a: 1 } // Hex shorthand also accepted where Color is expected const blue: HexCode = "#0044FF" ``` -------------------------------- ### useWidgetNodeId Source: https://context7.com/figma/widget-typings/llms.txt A hook that provides the ID of the current widget node. This ID can be used with the Figma plugin API, such as `figma.getNodeById`, to interact with the widget's node. It should only be called within event handlers or effects, not during rendering. ```APIDOC ## `useWidgetNodeId` — Access the Widget's Node ID Returns the ID of the current widget node for use inside event handlers with the plugin API (e.g., `figma.getNodeById`). Must not be called during rendering; use only inside event handlers or effects. ``` -------------------------------- ### Render Rich Text with Text and Span Source: https://context7.com/figma/widget-typings/llms.txt Use the Text and Span components to render styled text, including bold, italic, and underlined elements. Supports custom fonts, sizes, and colors. ```tsx const { Text, Span } = figma.widget function RichTextDemo() { return ( Normal text with{" "} bold red {" "}and{" "} italic underline ) } ``` -------------------------------- ### Handle Click Events with Coordinates in Figma Widgets Source: https://context7.com/figma/widget-typings/llms.txt The onClick handler for components like Rectangle receives a WidgetClickEvent object containing canvas-absolute and component-relative coordinates. ```tsx { // Canvas-absolute coordinates (same units as node.x, node.y) console.log(`Canvas: (${event.canvasX}, ${event.canvasY})`) // Coordinates relative to the clicked component console.log(`Offset: (${event.offsetX}, ${event.offsetY})`) }} /> ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.