@rogieking/figui3 8.9.9 → 8.9.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.cursor/skills/fig-editor/SKILL.md +184 -0
- package/.cursor/skills/fig-editor/reference.md +46 -0
- package/.cursor/skills/fig-lab/SKILL.md +159 -0
- package/.cursor/skills/fig-lab/reference.md +67 -0
- package/.cursor/skills/figui3/SKILL.md +160 -188
- package/.cursor/skills/figui3/reference.md +90 -0
- package/.cursor/skills/propkit/SKILL.md +66 -185
- package/README.md +42 -1
- package/components.css +31 -0
- package/dist/components.css +1 -1
- package/dist/fig-editor.css +1 -1
- package/dist/fig-editor.js +1 -1
- package/dist/fig.css +1 -1
- package/dist/fig.js +1 -1
- package/fig-editor.css +9 -0
- package/fig-editor.js +5 -0
- package/fig.js +2 -1
- package/package.json +1 -1
|
@@ -1,242 +1,214 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: figui3
|
|
3
|
-
description:
|
|
3
|
+
description: >-
|
|
4
|
+
Guides FigUI3 core (`fig.js` / `fig.css`) web components for Figma-style plugin UIs.
|
|
5
|
+
Use when adding, using, or debugging fig-* elements from the core bundle—buttons,
|
|
6
|
+
fields, overlays, menus, sliders, color/fill inputs, media, dialogs, popups, toasts—or
|
|
7
|
+
when working in the /figui3 playground. Not for fig-select or fig-fill-picker
|
|
8
|
+
(fig-editor), propskit-* / AI / canvas / angle / reorder (fig-lab), or fig-layer.
|
|
4
9
|
user-invocable: false
|
|
5
10
|
---
|
|
6
11
|
|
|
7
|
-
# FigUI3
|
|
12
|
+
# FigUI3 core (`fig.js`)
|
|
8
13
|
|
|
9
|
-
|
|
14
|
+
Zero-dependency web components for Figma UI3 plugin and widget UIs.
|
|
10
15
|
|
|
11
|
-
|
|
16
|
+
Canonical examples live in the **playground**, not `index.html`.
|
|
12
17
|
|
|
13
|
-
|
|
18
|
+
- Live: https://rog.ie/figui3/
|
|
19
|
+
- Local: `npm run dev:playground` → `/figui3`
|
|
20
|
+
- Sections: `playground/src/data/figui3Sections.ts`
|
|
21
|
+
- Attribute inspector: `playground/src/lib/attributeRules.ts`
|
|
22
|
+
- Public API: `README.md`
|
|
14
23
|
|
|
15
|
-
|
|
16
|
-
|
|
24
|
+
Related skills: `fig-editor` (`fig-select`, `fig-fill-picker`), `fig-lab` (`propskit-*`, AI, canvas), `propkit` (`/propskit` field composition).
|
|
25
|
+
|
|
26
|
+
## Bundles
|
|
27
|
+
|
|
28
|
+
Always import CSS with JS. Register before first render.
|
|
29
|
+
|
|
30
|
+
```js
|
|
31
|
+
import "@rogieking/figui3/fig.css";
|
|
32
|
+
import "@rogieking/figui3/fig.js";
|
|
17
33
|
```
|
|
18
34
|
|
|
19
|
-
|
|
35
|
+
| Bundle | CSS + JS | Components |
|
|
36
|
+
|---|---|---|
|
|
37
|
+
| **Core** (this skill) | `fig.css` + `fig.js` | All `fig-*` below |
|
|
38
|
+
| **Editor** | `fig-editor.css` + `fig-editor.js` | `fig-select*`, `fig-fill-picker`, `fig-interpolation-swatch` |
|
|
39
|
+
| **Lab** (unstable) | `fig-lab.css` + `fig-lab.js` | `propskit-*`, `fig-ai-*`, `fig-canvas-control`, `fig-input-angle`, `fig-reorder` |
|
|
40
|
+
| **Layer** | `fig-layer.css` + `fig-layer.js` | `fig-layer` |
|
|
20
41
|
|
|
21
|
-
|
|
42
|
+
`fig-editor.js` also imports `fig.js` and `fig-lab.js`. Lab CSS is still separate. `fig-layer` is **not** registered by `fig-editor.js`.
|
|
22
43
|
|
|
23
|
-
|
|
24
|
-
2. **Prefer existing `fig-*` components over one-off markup.** Compose from current primitives before inventing new ones.
|
|
25
|
-
3. **Keep Figma UI3 visual consistency.** Use existing CSS variables and spacing/radius conventions.
|
|
26
|
-
4. **Honor interaction semantics.** Emit `input` while interacting and `change` on committed value changes.
|
|
27
|
-
5. **Treat accessibility as required behavior.** Preserve labels, keyboard support, ARIA attributes, and disabled states.
|
|
44
|
+
Playground “Full editor” toggle reveals `#select`, `#fill-picker`, `#layer`, and `#toast`. That grouping is UI-only: toast is core; layer is `fig-layer.js`.
|
|
28
45
|
|
|
29
|
-
##
|
|
46
|
+
## Principles
|
|
30
47
|
|
|
31
|
-
|
|
48
|
+
1. Prefer existing `fig-*` tags over one-off markup.
|
|
49
|
+
2. Use design tokens (`--figma-color-*`, `--radius-*`, `--spacer-*`). Do not hardcode Figma colors.
|
|
50
|
+
3. Emit `input` while interacting and `change` on commit. Do not fire `input` from programmatic attribute writes.
|
|
51
|
+
4. Preserve a11y: labels, keyboard, ARIA, disabled. See the `a11y` skill.
|
|
52
|
+
5. Keep components framework-agnostic. No React internals.
|
|
32
53
|
|
|
33
|
-
|
|
34
|
-
- Import CSS once in app entry (`main.tsx` / `main.jsx`): `import "@rogieking/figui3/fig.css";`
|
|
35
|
-
- Register custom elements before first render. In Vite/React, prefer an explicit bootstrap:
|
|
54
|
+
## React + Vite
|
|
36
55
|
|
|
37
56
|
```tsx
|
|
38
57
|
import "@rogieking/figui3/fig.css";
|
|
39
58
|
|
|
40
59
|
const bootstrap = async () => {
|
|
41
|
-
// Prevent production tree-shaking from dropping registration side effects.
|
|
42
60
|
await import("@rogieking/figui3/fig.js");
|
|
43
61
|
createRoot(document.getElementById("app")!).render(<App />);
|
|
44
62
|
};
|
|
45
|
-
|
|
46
63
|
bootstrap();
|
|
47
64
|
```
|
|
48
65
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
-
|
|
52
|
-
|
|
53
|
-
```ts
|
|
54
|
-
import { defineConfig } from "vite";
|
|
55
|
-
import react from "@vitejs/plugin-react";
|
|
56
|
-
|
|
57
|
-
export default defineConfig({
|
|
58
|
-
plugins: [react()],
|
|
59
|
-
});
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
- Keep FigUI3 registration import at the top-level app bootstrap (not inside leaf components).
|
|
63
|
-
- If a production build appears to tree-shake element registration, use the explicit dynamic import pattern above.
|
|
64
|
-
|
|
65
|
-
### React usage rules for web components
|
|
66
|
-
|
|
67
|
-
- Use DOM attrs on custom elements (`<fig-slider text="true" />`) and read values from `e.target` / `e.detail`.
|
|
68
|
-
- In React, use `class` (not `className`) for all FigUI3 web components (`fig-*` and `<dialog is="fig-...">`) to keep attribute behavior consistent.
|
|
69
|
-
- Prefer refs + `addEventListener` when wiring complex `input`/`change` behavior.
|
|
70
|
-
|
|
71
|
-
### React + color picker modes (`fig-input-color` / `fig-fill-picker`)
|
|
72
|
-
|
|
73
|
-
- `fig-fill-picker` is optional. Import `fig-editor.js` and `fig-editor.css` when full picker behavior is needed.
|
|
74
|
-
- Do not use `picker` or `picker-anchor` on `fig-input-color`; components auto-detect `fig-fill-picker` at interaction time.
|
|
75
|
-
- `picker-*` attrs on `fig-input-color` are forwarded to `fig-fill-picker` only when the optional picker is registered.
|
|
76
|
-
- Example: `picker-dialog-position`.
|
|
77
|
-
- For React custom modes, use `fig-fill-picker` + slot API:
|
|
78
|
-
- Add a child with `slot="mode-<name>"` (and optional `label`).
|
|
79
|
-
- Include `<name>` in the `mode` attribute (e.g. `mode="solid,react-demo"`).
|
|
80
|
-
- Listen for `modeready` and render into `e.detail.container`.
|
|
81
|
-
- Do not reparent React-owned DOM into the picker after render; use the provided `modeready` container as mount target.
|
|
82
|
-
- Keep React lifecycle cleanup explicit for custom mode mounts:
|
|
83
|
-
- keep one `root` per mode container
|
|
84
|
-
- call `root.unmount()` when the host component unmounts
|
|
85
|
-
- remove `modeready` listeners in cleanup to avoid duplicate mounts
|
|
86
|
-
- Custom mode content must dispatch `input` / `change` with `detail` payload so picker can store mode data and propagate events.
|
|
87
|
-
- Preserve value shape expectations:
|
|
88
|
-
- `fig-input-color` expects solid color data (`detail.color`, optional `detail.alpha`) from the picker.
|
|
89
|
-
- `fig-fill-picker` custom modes use JSON with `type` set to mode name and remaining data in payload.
|
|
90
|
-
- Direct color events expose additive `{ color, alpha, opacity }` aliases: opaque `#RRGGBB`, `0–1`, and `0–100`, respectively.
|
|
91
|
-
- Keep `fig-input-color`'s legacy `value`, `hex`, and `rgba` event-detail fields unchanged; consume the aliases for a shared contract.
|
|
92
|
-
|
|
93
|
-
## Critical Rules
|
|
94
|
-
|
|
95
|
-
### Overlay Components (`fig-dialog`, `fig-popup`)
|
|
96
|
-
|
|
97
|
-
- Choose the overlay primitive intentionally:
|
|
98
|
-
- **`<dialog is="fig-dialog">`** for modal/light-dismiss dialog workflows.
|
|
99
|
-
- **`<dialog is="fig-popup">`** for anchored floating surfaces (menus, contextual panels, nested popups).
|
|
100
|
-
- Keep overlay semantics stable:
|
|
101
|
-
- `fig-dialog` should remain dialog-first (title/header/footer patterns, modal semantics).
|
|
102
|
-
- `fig-popup` should remain anchor/position-first (offset, collision handling, viewport margins).
|
|
103
|
-
- Preserve drag and positioning behavior on both `fig-dialog` and `fig-popup`; do not regress manual placement rules.
|
|
104
|
-
- For popup chains, maintain containment and dismissal logic across descendant popups.
|
|
105
|
-
- Document any overlay behavior change in demos and changelog with a concrete before/after note.
|
|
106
|
-
|
|
107
|
-
### Component Architecture
|
|
108
|
-
|
|
109
|
-
- Extend `HTMLElement` and implement lifecycle cleanup in `disconnectedCallback`.
|
|
110
|
-
- Use `observedAttributes` + `attributeChangedCallback` for attribute-driven reactivity.
|
|
111
|
-
- Keep attribute names and behavior backward-compatible unless explicitly doing a breaking change.
|
|
112
|
-
- Support `disabled` behavior wherever interaction is possible.
|
|
113
|
-
- Avoid introducing framework-specific assumptions in component internals.
|
|
66
|
+
- Use DOM attrs (`text="true"`). Read values from `e.target` / `e.detail`.
|
|
67
|
+
- On `fig-*` and `<dialog is="fig-...">`, use `class` not `className`.
|
|
68
|
+
- Prefer refs + `addEventListener` for `input`/`change`.
|
|
114
69
|
|
|
115
|
-
|
|
70
|
+
Color picker modes: `fig-fill-picker` is optional editor. Do not use `picker` / `picker-anchor` on `fig-input-color`. `picker-*` attrs forward to the picker only when it is registered. See `fig-editor`.
|
|
116
71
|
|
|
117
|
-
|
|
118
|
-
- Put rich payloads in `event.detail` when needed; keep names stable.
|
|
119
|
-
- Do not silently change event payload shape for existing components.
|
|
120
|
-
- When adding new events, document trigger timing and payload fields.
|
|
72
|
+
## Overlay rules
|
|
121
73
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
-
|
|
125
|
-
-
|
|
126
|
-
- Avoid ad-hoc hardcoded colors when semantic tokens already exist.
|
|
127
|
-
- Preserve current sizing, spacing, and radius rhythm unless intentionally refactoring system-wide.
|
|
128
|
-
|
|
129
|
-
### Documentation and Demos
|
|
130
|
-
|
|
131
|
-
- Update `README.md` component docs when public API or behavior changes.
|
|
132
|
-
- Update demo surfaces (`index.html` and `playground/` routes where relevant) for visible behavior changes.
|
|
133
|
-
- Prefer realistic examples that mirror plugin/property panel usage.
|
|
134
|
-
|
|
135
|
-
### Compatibility and Safety
|
|
136
|
-
|
|
137
|
-
- Keep browser support expectations aligned with current README claims.
|
|
138
|
-
- Use progressive enhancement for bleeding-edge CSS features.
|
|
139
|
-
- Avoid regressions in existing attributes, defaults, and emitted events.
|
|
140
|
-
|
|
141
|
-
### Color Picker Mode Extensibility
|
|
142
|
-
|
|
143
|
-
- Treat custom modes as a `fig-fill-picker` concern, not a standalone `fig-input-color` concern.
|
|
144
|
-
- When adding a new mode, update demos/docs with both:
|
|
145
|
-
- vanilla slot usage (`slot="mode-*"`)
|
|
146
|
-
- React `modeready` usage
|
|
147
|
-
- Do not emit `input` from programmatic attribute writes (`value` updates); preserve current loop-avoidance behavior for React.
|
|
148
|
-
|
|
149
|
-
## Key Patterns
|
|
74
|
+
- `<dialog is="fig-dialog">` — modal/task dialog. `position` is viewport placement. No `anchor`.
|
|
75
|
+
- `<dialog is="fig-popup">` — anchored float (`anchor`, `position`, `offset`, `viewport-margin`). `variant="popover"` uses CSS `filter` (containing block for `position: fixed`).
|
|
76
|
+
- `<dialog is="fig-toast">` — call `showToast()`. `theme`, `duration`, `live`, `dismiss`, `icon`.
|
|
77
|
+
- `fig-menu` and `fig-select` use `popover="manual"` so lists escape filter-containing popups to the top layer. Nested menus inside popovers must keep that.
|
|
150
78
|
|
|
151
79
|
```html
|
|
152
|
-
|
|
153
|
-
<dialog is="fig-dialog" drag="true" handle="fig-header">
|
|
80
|
+
<dialog is="fig-dialog" drag handle="fig-header">
|
|
154
81
|
<fig-header>
|
|
155
|
-
|
|
156
|
-
<fig-button variant="ghost" icon close-dialog aria-label="Close
|
|
82
|
+
Title
|
|
83
|
+
<fig-button variant="ghost" icon close-dialog aria-label="Close">
|
|
157
84
|
<fig-icon name="close"></fig-icon>
|
|
158
85
|
</fig-button>
|
|
159
86
|
</fig-header>
|
|
160
|
-
<
|
|
87
|
+
<fig-content>Body</fig-content>
|
|
161
88
|
</dialog>
|
|
162
89
|
|
|
163
|
-
<!-- Anchored popup surface -->
|
|
164
90
|
<dialog is="fig-popup" anchor="#trigger" position="bottom left" offset="8 8">
|
|
165
|
-
|
|
91
|
+
Popup content
|
|
166
92
|
</dialog>
|
|
167
93
|
```
|
|
168
94
|
|
|
169
|
-
|
|
170
|
-
// Event contract pattern: continuous + committed updates.
|
|
171
|
-
this.dispatchEvent(new CustomEvent("input", { detail, bubbles: true }));
|
|
172
|
-
this.dispatchEvent(new CustomEvent("change", { detail, bubbles: true }));
|
|
173
|
-
|
|
174
|
-
// Attribute-driven updates.
|
|
175
|
-
static get observedAttributes() { return ["value", "disabled"]; }
|
|
176
|
-
attributeChangedCallback(name, oldValue, newValue) {
|
|
177
|
-
if (oldValue === newValue) return;
|
|
178
|
-
// sync internal UI state
|
|
179
|
-
}
|
|
180
|
-
```
|
|
95
|
+
## Field composition
|
|
181
96
|
|
|
182
|
-
|
|
183
|
-
Event contract quick map:
|
|
184
|
-
- fig-slider: input/change -> current value on e.target.value
|
|
185
|
-
- fig-input-color: input/change -> legacy value/hex/rgba plus color/alpha/opacity aliases in e.detail
|
|
186
|
-
- fig-input-fill / fig-fill-picker: input/change -> fill payload in e.detail
|
|
187
|
-
```
|
|
97
|
+
Default property row:
|
|
188
98
|
|
|
189
99
|
```html
|
|
190
|
-
<!-- Typical field composition -->
|
|
191
100
|
<fig-field direction="horizontal">
|
|
192
101
|
<label>Opacity</label>
|
|
193
|
-
<fig-slider value="75" min="0" max="100" text="true" units="%"></fig-slider>
|
|
102
|
+
<fig-slider value="75" min="0" max="100" text="true" units="%" full></fig-slider>
|
|
194
103
|
</fig-field>
|
|
195
104
|
```
|
|
196
105
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
106
|
+
Labeled property wrappers (`propskit-*`) are lab. For `/propskit` playground patterns, use the `propkit` skill.
|
|
107
|
+
|
|
108
|
+
## Select vs dropdown
|
|
109
|
+
|
|
110
|
+
| Tag | Bundle | Use |
|
|
111
|
+
|---|---|---|
|
|
112
|
+
| `fig-dropdown` | core | Native `<select>` wrapper. `type="select\|dropdown"`, `variant="ghost"` |
|
|
113
|
+
| `fig-select` | editor | Custom listbox: groups, overflow chevrons, sticky separators, rich options |
|
|
114
|
+
| `propskit-select` | lab | Full-surface labeled field around `fig-select` |
|
|
115
|
+
|
|
116
|
+
Prefer `fig-select` for Figma-style menus. Use `fig-dropdown` only for a native select.
|
|
117
|
+
|
|
118
|
+
## Core catalog
|
|
119
|
+
|
|
120
|
+
Playground hashes: `/figui3#{id}`. Full attrs: [reference.md](reference.md).
|
|
121
|
+
|
|
122
|
+
### Buttons and inputs
|
|
123
|
+
|
|
124
|
+
| Tag | Playground | Notes |
|
|
125
|
+
|---|---|---|
|
|
126
|
+
| `fig-button` | `#button` | `variant`: secondary, ghost, link, destructive*, overlay, input. `type`: button, toggle, submit, select, upload. `size`, `icon`, `selected` |
|
|
127
|
+
| `fig-dropdown` | `#dropdown` | Native select. Options as `<option>` / `<optgroup>`. `variant="ghost"` |
|
|
128
|
+
| `fig-combo-input` | `#combo-input` | Text + suggestions (`options`) |
|
|
129
|
+
| `fig-input-text` | `#text-input` | `multiline` for textarea |
|
|
130
|
+
| `fig-input-number` | `#number-input` | `min`, `max`, `step`, `units`, `precision` |
|
|
131
|
+
| `fig-input-file` | `#file-input` | `accepts`, `multiple`, button `variant` |
|
|
132
|
+
| `fig-checkbox` / `fig-radio` / `fig-switch` | `#checkbox` `#radio` `#switch` | Switch supports `indeterminate` |
|
|
133
|
+
| `fig-slider` | `#slider` | `type`: range, opacity, hue, stepper, delta. `text`, `units`, `transform`, `variant="classic"` |
|
|
134
|
+
| `fig-options` | (propkit `#options`) | Option list helper; same option string formats as select |
|
|
135
|
+
|
|
136
|
+
### Color and fill (no picker dialog)
|
|
137
|
+
|
|
138
|
+
| Tag | Playground | Notes |
|
|
139
|
+
|---|---|---|
|
|
140
|
+
| `fig-input-color` | (propkit `#color`) | Solid color. `text`, `alpha`. Auto-detects `fig-fill-picker` |
|
|
141
|
+
| `fig-input-fill` | `#fill-input` | Solid/gradient/image/video JSON `value`. `picker-*` forwarded if picker registered |
|
|
142
|
+
| `fig-input-palette` | (propkit `#palette`) | Multi-color. `fixed`, `open` |
|
|
143
|
+
| `fig-input-gradient` | (propkit `#gradient`) | Stops. `edit`, `mode="handle\|tip"` |
|
|
144
|
+
| `fig-swatch` | `#swatch` | `size`, `selected`, `alpha` |
|
|
145
|
+
| `fig-color-tip` | `#color-tip` | `control="color\|add\|remove"` |
|
|
146
|
+
| `fig-chit` | — | Alias-style color chip |
|
|
147
|
+
|
|
148
|
+
### Layout and chrome
|
|
149
|
+
|
|
150
|
+
| Tag | Playground | Notes |
|
|
151
|
+
|---|---|---|
|
|
152
|
+
| `fig-field` | `#field` | `direction="horizontal\|vertical"`, `label` |
|
|
153
|
+
| `fig-group` | (containers) | `name`, `collapsible`, `open`, `compact` |
|
|
154
|
+
| `fig-header` / `fig-footer` / `fig-content` | (containers) | Header: `borderless`, `compact`. Footer: `sticky` |
|
|
155
|
+
| `fig-tabs` / `fig-tab` | `#tabs` | Roving tabs. `content="#id"` for panels |
|
|
156
|
+
| `fig-segmented-control` / `fig-segment` | `#segmented-control` | Radio-group pattern |
|
|
157
|
+
| `fig-chooser` / `fig-choice` | (containers) | Listbox selection |
|
|
158
|
+
| `fig-separator` / `fig-menu-separator` | `#separator` | Optional `label`, `sticky`, `borderless` |
|
|
159
|
+
| `fig-menu` / `fig-menu-item` | `#menu` | `fig-menu-trigger`, `trigger="contextmenu"`, `position`, `offset` |
|
|
160
|
+
| `fig-icon` | `#icon` | Token mask (`name`, `size="small"`, `color`) |
|
|
161
|
+
| `fig-avatar` | `#avatar` | `src` / `name`, `size="large"` |
|
|
162
|
+
| `fig-truncate` | `#truncate` | `position="right\|left\|middle"`, `tooltip`, `tail` |
|
|
163
|
+
|
|
164
|
+
### Overlays
|
|
165
|
+
|
|
166
|
+
| Tag | Playground | Notes |
|
|
167
|
+
|---|---|---|
|
|
168
|
+
| `dialog is="fig-dialog"` | `#dialog` | `modal`, `drag`, `resizable`, `autoresize`, `handle`, `closedby`, `position` |
|
|
169
|
+
| `dialog is="fig-popup"` | `#popup` | `anchor`, `position`, `offset`, `viewport-margin`, `variant`, `theme` |
|
|
170
|
+
| `dialog is="fig-toast"` | `#toast` | `showToast()`. `theme`, `duration`, `live`, `dismiss`, `icon` |
|
|
171
|
+
| `fig-tooltip` | `#tooltip` | `text`, `action="hover\|click\|manual"`, `delay`, `theme` |
|
|
172
|
+
|
|
173
|
+
### Media
|
|
174
|
+
|
|
175
|
+
| Tag | Playground | Notes |
|
|
176
|
+
|---|---|---|
|
|
177
|
+
| `fig-preview` | (propkit `#preview`) | `aspect-ratio`, `fit`, `full`, `checkerboard` |
|
|
178
|
+
| `fig-media` / `fig-image` / `fig-video` | `#media` `#image` `#video` | Upload via `upload`. Video controls below preview |
|
|
179
|
+
| `fig-card` | `#card` | Media + label + selection |
|
|
180
|
+
| `fig-media-controls` | `#media-controls` | Play/pause chrome |
|
|
181
|
+
| `fig-input-file` | `#file-input` | File picker button |
|
|
182
|
+
|
|
183
|
+
### Specialized
|
|
184
|
+
|
|
185
|
+
| Tag | Playground | Notes |
|
|
186
|
+
|---|---|---|
|
|
187
|
+
| `fig-easing-curve` | (propkit `#easing`) | Bezier/spring |
|
|
188
|
+
| `fig-3d-rotate` | (containers) | Cube rotate |
|
|
189
|
+
| `fig-origin-grid` | (propkit) | Transform origin |
|
|
190
|
+
| `fig-joystick` | (propkit `#joystick`) | 2D position |
|
|
191
|
+
| `fig-handle` | `#handle` | `type="default\|minimal\|color\|canvas"`, `drag`, `drag-snapping` |
|
|
192
|
+
| `fig-spinner` / `fig-shimmer` / `fig-skeleton` | `#spinner` `#shimmer` | Loading |
|
|
193
|
+
|
|
194
|
+
`fig-input-angle` is **lab**, not core.
|
|
195
|
+
|
|
196
|
+
## Events
|
|
218
197
|
|
|
219
|
-
|
|
220
|
-
-
|
|
221
|
-
-
|
|
222
|
-
|
|
223
|
-
-
|
|
224
|
-
|
|
225
|
-
## Quick Reference
|
|
226
|
-
|
|
227
|
-
```bash
|
|
228
|
-
# Start docs/demo server
|
|
229
|
-
bun dev
|
|
230
|
-
|
|
231
|
-
# Build distributable files
|
|
232
|
-
bun build
|
|
198
|
+
```txt
|
|
199
|
+
fig-slider input/change → e.target.value
|
|
200
|
+
fig-input-color input/change → detail { color, alpha, opacity } plus legacy value/hex/rgba
|
|
201
|
+
fig-input-fill input/change → fill payload in e.detail
|
|
202
|
+
fig-menu change → detail { value }
|
|
203
|
+
fig-dialog/popup native dialog close plus FigUI3 positioning attrs
|
|
233
204
|
```
|
|
234
205
|
|
|
235
|
-
##
|
|
206
|
+
## Maintainer workflow
|
|
207
|
+
|
|
208
|
+
1. Read `fig.js` + `components.css` before editing.
|
|
209
|
+
2. Mirror playground examples in `figui3Sections.ts` and `attributeRules.ts`.
|
|
210
|
+
3. Update `README.md` + `CHANGELOG.md` for public API changes.
|
|
211
|
+
4. `bun build` for dist. Never kill `npm run dev:playground`.
|
|
212
|
+
5. Tests: `npm run test:components` (Playwright). Do not start a second playground if one is running.
|
|
236
213
|
|
|
237
|
-
|
|
238
|
-
- `components.css` - component-level styling and states
|
|
239
|
-
- `base.css` - foundational styles and variables
|
|
240
|
-
- `index.html` - main interactive docs/demo
|
|
241
|
-
- `README.md` - public API and usage documentation
|
|
242
|
-
- `CHANGELOG.md` - release history and migration notes
|
|
214
|
+
Primary files: `fig.js`, `components.css`, `base.css`, `README.md`, `playground/src/data/figui3Sections.ts`.
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# FigUI3 core API reference
|
|
2
|
+
|
|
3
|
+
Source of truth for live attrs: `playground/src/lib/attributeRules.ts` and `README.md`.
|
|
4
|
+
Playground: `/figui3#{section}`.
|
|
5
|
+
|
|
6
|
+
## Option string formats
|
|
7
|
+
|
|
8
|
+
Shared by `fig-dropdown`/`fig-options`/`fig-select`/`propskit-select` `options`:
|
|
9
|
+
|
|
10
|
+
- Comma-separated: `Left,Center,Right`
|
|
11
|
+
- Newline-delimited
|
|
12
|
+
- JSON array: `["Left","Center"]` or `[{"value":"left","label":"Left"}]`
|
|
13
|
+
|
|
14
|
+
## `fig-button`
|
|
15
|
+
|
|
16
|
+
- `variant`: `""` (primary), `secondary`, `destructive`, `destructiveSecondary`, `destructiveGhost`, `destructiveLink`, `ghost`, `link`, `input`, `overlay`
|
|
17
|
+
- `type`: `button`, `toggle`, `submit`, `select`, `upload`
|
|
18
|
+
- `size`: `""`, `large`, `compact`
|
|
19
|
+
- `selected`, `disabled`, `icon` (presence)
|
|
20
|
+
|
|
21
|
+
## `fig-dropdown`
|
|
22
|
+
|
|
23
|
+
- `value`, `type="select|dropdown"`, `variant="ghost"`, `full`, `disabled`
|
|
24
|
+
- Children: native `<option>` / `<optgroup>`
|
|
25
|
+
|
|
26
|
+
## `fig-slider`
|
|
27
|
+
|
|
28
|
+
- `type`: `range` (default), `opacity`, `hue`, `stepper`, `delta`
|
|
29
|
+
- `text` default true; `text="false"` hides the number field
|
|
30
|
+
- Always set `min`, `max`, `step`; `units` when displayed
|
|
31
|
+
- `transform` when internal scale ≠ UI scale
|
|
32
|
+
- `variant="classic"` for the older appearance
|
|
33
|
+
- Opacity: set `color` and usually `units="%"`
|
|
34
|
+
- Delta: include `default` and typically symmetric min/max
|
|
35
|
+
- Stepper: include a `<datalist>` of stops
|
|
36
|
+
|
|
37
|
+
## `fig-field`
|
|
38
|
+
|
|
39
|
+
- `direction="horizontal|vertical"`
|
|
40
|
+
- `label` or a child `<label>`
|
|
41
|
+
|
|
42
|
+
## `fig-popup` vs `fig-dialog`
|
|
43
|
+
|
|
44
|
+
Dialog: `modal`, `drag`, `resizable`, `autoresize`, `handle`, `closedby="any|closerequest|none"`, `position` (viewport: `top left` … `bottom right`).
|
|
45
|
+
|
|
46
|
+
Popup: `anchor` (selector or element), `position` (side or corner), `offset="8 8"`, `viewport-margin`, `theme="default|light|dark|menu"`, `variant="popover|tooltip"`.
|
|
47
|
+
|
|
48
|
+
Toast: `theme`, `duration`, `offset`, `dismiss`, `live="polite|assertive"`, `icon`. Method: `showToast()`.
|
|
49
|
+
|
|
50
|
+
## `fig-menu`
|
|
51
|
+
|
|
52
|
+
- Trigger: child with `fig-menu-trigger`, or `trigger="contextmenu"`
|
|
53
|
+
- `position`, `offset`, `closedby="auto|any|none"`, `open`
|
|
54
|
+
- Items: `fig-menu-item` (`value`, `disabled`, `subtle`)
|
|
55
|
+
- Dividers: `fig-separator` / `fig-menu-separator` (`label`, `sticky`, `borderless`)
|
|
56
|
+
- Popup uses `popover="manual"` (top layer)
|
|
57
|
+
|
|
58
|
+
## Color / fill values
|
|
59
|
+
|
|
60
|
+
`fig-input-color` events: `{ color, alpha, opacity }` aliases (opaque `#RRGGBB`, `0–1`, `0–100`) plus legacy `value` / `hex` / `rgba`.
|
|
61
|
+
|
|
62
|
+
`fig-input-fill` value JSON:
|
|
63
|
+
|
|
64
|
+
```json
|
|
65
|
+
{"type":"solid","color":"#FF5733","opacity":100}
|
|
66
|
+
{"type":"gradient","gradient":{}}
|
|
67
|
+
{"type":"image","image":{"url":"...","scaleMode":"fill"}}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Without `fig-fill-picker`, fill/color render a preview. With the picker registered, click opens the editor dialog.
|
|
71
|
+
|
|
72
|
+
## Media
|
|
73
|
+
|
|
74
|
+
- Surface lives in `fig-preview`
|
|
75
|
+
- `fig-image` / `fig-video`: `upload`, `fit`, `aspect-ratio`, `checkerboard`, `loading-indicator`
|
|
76
|
+
- Video controls render **below** the preview, not as an overlay
|
|
77
|
+
- Slotted image overlays stay in light DOM
|
|
78
|
+
|
|
79
|
+
## `fig-layer` (separate bundle)
|
|
80
|
+
|
|
81
|
+
```js
|
|
82
|
+
import "@rogieking/figui3/fig-layer.css";
|
|
83
|
+
import "@rogieking/figui3/fig-layer.js";
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Attrs: `open`, `visible`, `disabled`. Markup: child `.fig-layer-row` plus nested `fig-layer`. Events: `openchange`, `visibilitychange`. Playground: `/figui3#layer` (behind Full editor).
|
|
87
|
+
|
|
88
|
+
## Native elements
|
|
89
|
+
|
|
90
|
+
`/figui3` also demos styled native `button`, `select`, `input`, `textarea`, `checkbox`, `.switch`, `radio`, `color`, `progress`, `fieldset`, `details`, `hr` under group “Native elements”. Use these when a custom element is unnecessary.
|