@rogieking/figui3 6.4.6 → 6.4.7
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/a11y/SKILL.md +96 -0
- package/.cursor/skills/css-render-performance/SKILL.md +46 -0
- package/.cursor/skills/frontend-performance-testing/SKILL.md +46 -0
- package/.cursor/skills/js-runtime-performance/SKILL.md +45 -0
- package/.cursor/skills/web-component-performance/SKILL.md +47 -0
- package/README.md +126 -17
- package/components.css +238 -318
- package/dist/components.css +1 -1
- package/dist/fig-editor.css +1 -1
- package/dist/fig-editor.js +62 -60
- package/dist/fig-lab.css +1 -1
- package/dist/fig-layer.css +1 -0
- package/dist/fig-layer.js +1 -0
- package/dist/fig.css +1 -1
- package/dist/fig.js +57 -55
- package/fig-editor.css +61 -0
- package/fig-editor.js +369 -61
- package/fig-lab.css +33 -5
- package/fig-layer.css +111 -0
- package/fig-layer.js +155 -0
- package/fig.js +2240 -919
- package/package.json +13 -4
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: a11y
|
|
3
|
+
description: Guides accessibility review and implementation for FigUI3 web components and playground examples. Use when the user mentions accessibility, a11y, ARIA, screen readers, keyboard navigation, focus rings, labels, roles, disabled states, contrast, dialogs, menus, or form control semantics.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Accessibility
|
|
7
|
+
|
|
8
|
+
Use this skill when adding, reviewing, or debugging accessibility behavior in FigUI3.
|
|
9
|
+
|
|
10
|
+
## Core Principles
|
|
11
|
+
|
|
12
|
+
1. Preserve native semantics first. Use native controls, form labels, `button`, `input`, `dialog`, and real focus behavior where possible.
|
|
13
|
+
2. Add ARIA only to complete semantics, not to replace correct markup.
|
|
14
|
+
3. Keyboard support is required for every interactive component.
|
|
15
|
+
4. Disabled and readonly states must affect behavior, focusability, ARIA, visuals, and emitted events consistently.
|
|
16
|
+
5. Focus indicators must be visible, token-based, and match existing FigUI3 patterns.
|
|
17
|
+
6. Custom elements must keep semantics stable across light/dark themes and React usage.
|
|
18
|
+
|
|
19
|
+
## Implementation Checklist
|
|
20
|
+
|
|
21
|
+
- Confirm the component role and accessible name.
|
|
22
|
+
- Confirm keyboard entry, movement, activation, escape/cancel, and tab order.
|
|
23
|
+
- Confirm focus rings on the visible interactive surface.
|
|
24
|
+
- Confirm `disabled` syncs to `aria-disabled` where the element is not natively disableable.
|
|
25
|
+
- Confirm disabled elements do not emit normal interaction changes.
|
|
26
|
+
- Confirm `aria-*`, `role`, and `tabindex` are updated when attributes change dynamically.
|
|
27
|
+
- Confirm customized built-ins like `<dialog is="fig-dialog">` and `<dialog is="fig-popup">` preserve native dialog behavior.
|
|
28
|
+
- Confirm playground examples demonstrate accessible usage.
|
|
29
|
+
|
|
30
|
+
## FigUI3 Patterns
|
|
31
|
+
|
|
32
|
+
### Disabled custom elements
|
|
33
|
+
|
|
34
|
+
For non-native interactive custom elements:
|
|
35
|
+
|
|
36
|
+
```js
|
|
37
|
+
const disabled =
|
|
38
|
+
this.hasAttribute("disabled") && this.getAttribute("disabled") !== "false";
|
|
39
|
+
|
|
40
|
+
if (disabled) {
|
|
41
|
+
this.setAttribute("aria-disabled", "true");
|
|
42
|
+
this.setAttribute("tabindex", "-1");
|
|
43
|
+
} else {
|
|
44
|
+
this.removeAttribute("aria-disabled");
|
|
45
|
+
this.setAttribute("tabindex", "0");
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
If a component uses roving tabindex, keep inactive and disabled items at `tabindex="-1"`.
|
|
50
|
+
|
|
51
|
+
### Focus rings
|
|
52
|
+
|
|
53
|
+
Prefer existing token patterns:
|
|
54
|
+
|
|
55
|
+
```css
|
|
56
|
+
&:focus-visible,
|
|
57
|
+
&[data-focus-visible] {
|
|
58
|
+
outline: 0;
|
|
59
|
+
box-shadow: inset 0 0 0 1px var(--figma-color-border-selected);
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
If focus lands on a hidden native input, apply the ring to the visible host surface:
|
|
64
|
+
|
|
65
|
+
```css
|
|
66
|
+
fig-button:has(> input:focus-visible) {
|
|
67
|
+
outline: 0;
|
|
68
|
+
box-shadow: inset 0 0 0 1px var(--figma-color-border-selected);
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Menus
|
|
73
|
+
|
|
74
|
+
- Menu popups use `role="menu"`.
|
|
75
|
+
- Items use `role="menuitem"`.
|
|
76
|
+
- Disabled menu items should have `aria-disabled="true"` and should not be included in roving keyboard focus.
|
|
77
|
+
- Arrow keys should skip disabled items.
|
|
78
|
+
|
|
79
|
+
### Dialogs and popups
|
|
80
|
+
|
|
81
|
+
- Use `<dialog is="fig-dialog">` for dialog workflows.
|
|
82
|
+
- Use `<dialog is="fig-popup">` for anchored popup surfaces.
|
|
83
|
+
- Verify close buttons have accessible names, usually `aria-label="Close dialog"`.
|
|
84
|
+
- Preserve native `close`/`cancel` behavior unless intentionally overridden.
|
|
85
|
+
|
|
86
|
+
## Review Output
|
|
87
|
+
|
|
88
|
+
When reviewing a11y work, lead with concrete issues:
|
|
89
|
+
|
|
90
|
+
- Missing or incorrect role/name/state.
|
|
91
|
+
- Keyboard trap or unreachable interaction.
|
|
92
|
+
- Focus ring missing on visible surface.
|
|
93
|
+
- Disabled state mismatch between behavior and semantics.
|
|
94
|
+
- Screen reader announcement likely misleading.
|
|
95
|
+
|
|
96
|
+
Include the component and file path for each finding.
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: css-render-performance
|
|
3
|
+
description: Guides CSS rendering and layout performance tests for component UIs. Use when checking selector cost, layout thrash, paint work, animation smoothness, CSS containment, computed styles, or visual regressions caused by CSS changes.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# CSS Render Performance
|
|
7
|
+
|
|
8
|
+
Test CSS performance in a browser with real stylesheets loaded. Pair this with `css-component-testing` when the risk is both correctness and render cost.
|
|
9
|
+
|
|
10
|
+
## Performance Risks
|
|
11
|
+
|
|
12
|
+
- Layout thrash from alternating DOM writes and layout reads.
|
|
13
|
+
- Expensive selectors over large component trees.
|
|
14
|
+
- Paint-heavy effects: filters, shadows, backdrops, gradients, large clipping, and opacity stacks.
|
|
15
|
+
- Animation of layout properties instead of transform/opacity.
|
|
16
|
+
- Missing containment around isolated panels, popups, lists, or preview surfaces.
|
|
17
|
+
- Theme/token changes that trigger broad restyles.
|
|
18
|
+
|
|
19
|
+
## Measurement Pattern
|
|
20
|
+
|
|
21
|
+
1. Mount a scaled fixture: enough nodes to expose the cost, but still deterministic.
|
|
22
|
+
2. Wait for styles, custom elements, and fonts to settle.
|
|
23
|
+
3. Measure a single operation: class toggle, attribute change, theme switch, popup open, resize, or list update.
|
|
24
|
+
4. Read layout at controlled points using `getBoundingClientRect` or computed styles.
|
|
25
|
+
5. Use `requestAnimationFrame` to separate write, style/layout flush, and visual completion.
|
|
26
|
+
|
|
27
|
+
## Useful Browser APIs
|
|
28
|
+
|
|
29
|
+
- `performance.now()` for scoped timings.
|
|
30
|
+
- `requestAnimationFrame` for frame-boundary checks.
|
|
31
|
+
- `getComputedStyle` for resolved token/state assertions.
|
|
32
|
+
- `getBoundingClientRect` for layout cost and final geometry.
|
|
33
|
+
- `PerformanceObserver` for long tasks when supported by the browser under test.
|
|
34
|
+
|
|
35
|
+
## CSS Fix Preferences
|
|
36
|
+
|
|
37
|
+
- Prefer transform/opacity for motion.
|
|
38
|
+
- Prefer `contain` or `content-visibility` only when it preserves layout, accessibility, and interaction behavior.
|
|
39
|
+
- Prefer narrower DOM updates over broader selector work.
|
|
40
|
+
- Keep selector specificity maintainable; do not trade readability for theoretical wins without measurement.
|
|
41
|
+
|
|
42
|
+
## Avoid
|
|
43
|
+
|
|
44
|
+
- Timing raw selector queries without the real component tree.
|
|
45
|
+
- Replacing stable computed-style assertions with broad screenshots.
|
|
46
|
+
- Adding CSS containment that breaks popups, focus rings, sticky positioning, or overlay geometry.
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: frontend-performance-testing
|
|
3
|
+
description: Guides browser-based performance testing for HTML, CSS, JavaScript, and UI interactions. Use when measuring frontend performance, adding Playwright perf tests, checking regressions, profiling load/render/interaction cost, or discussing performance budgets.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Frontend Performance Testing
|
|
7
|
+
|
|
8
|
+
Use real browsers for performance checks. In this repo, prefer Playwright because `playwright.config.ts` already boots `bun server.ts` and runs against Chromium.
|
|
9
|
+
|
|
10
|
+
## What To Measure
|
|
11
|
+
|
|
12
|
+
- Load readiness: time to fixture boot, first usable UI, and custom element definitions.
|
|
13
|
+
- Interaction latency: click, keyboard, pointer drag, slider movement, picker open/close.
|
|
14
|
+
- Render cost: layout, style recalculation, paint, animation frames, and DOM update loops.
|
|
15
|
+
- Bundle/build changes: output size and runtime behavior after `bun build`.
|
|
16
|
+
- Regressions under scale: repeated components, large option lists, nested controls, and overlay stacks.
|
|
17
|
+
|
|
18
|
+
## Test Pattern
|
|
19
|
+
|
|
20
|
+
1. Mount the smallest deterministic fixture that reproduces the performance risk.
|
|
21
|
+
2. Warm up once before measuring.
|
|
22
|
+
3. Use browser APIs inside `page.evaluate`: `performance.now()`, `PerformanceObserver`, `requestAnimationFrame`, `getBoundingClientRect`, and `document.fonts.ready` when relevant.
|
|
23
|
+
4. Repeat enough times to reduce noise; assert on median or bounded worst case, not one sample.
|
|
24
|
+
5. Keep budgets local and named after the scenario, not global magic numbers.
|
|
25
|
+
|
|
26
|
+
## Playwright Guidance
|
|
27
|
+
|
|
28
|
+
- Put stable performance checks near `tests/figui` unless they need a separate fixture.
|
|
29
|
+
- Fail on page errors and unexpected console errors before trusting timing data.
|
|
30
|
+
- Use `test.slow()` for intentionally heavier regression scenarios.
|
|
31
|
+
- Capture traces only for failing or investigative runs; do not turn every perf test into a trace artifact.
|
|
32
|
+
- Prefer `expect.poll` for readiness, then measure a synchronous scenario.
|
|
33
|
+
|
|
34
|
+
## Budget Rules
|
|
35
|
+
|
|
36
|
+
- Budgets should catch meaningful regressions without flaking on normal machine variance.
|
|
37
|
+
- Use relative comparisons when possible: changed implementation vs baseline path in the same page.
|
|
38
|
+
- Avoid hard sub-millisecond thresholds.
|
|
39
|
+
- Document what user-facing lag the budget protects.
|
|
40
|
+
|
|
41
|
+
## Avoid
|
|
42
|
+
|
|
43
|
+
- jsdom performance conclusions.
|
|
44
|
+
- Network-dependent timing assertions.
|
|
45
|
+
- Screenshot diffs as a proxy for performance.
|
|
46
|
+
- Microbenchmarks that skip the actual DOM/CSS/component path.
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: js-runtime-performance
|
|
3
|
+
description: Guides JavaScript runtime performance testing for frontend components. Use when profiling event handlers, DOM update loops, memory leaks, timers, animation frames, pointer/keyboard interactions, or regressions in vanilla JS component code.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# JS Runtime Performance
|
|
7
|
+
|
|
8
|
+
Measure JavaScript cost through real user-facing paths. For FigUI3, that usually means interactions on `fig-*` elements in Playwright, not isolated functions.
|
|
9
|
+
|
|
10
|
+
## What To Check
|
|
11
|
+
|
|
12
|
+
- Event handlers stay short during pointer drag, key repeat, input, and resize.
|
|
13
|
+
- Attribute/property updates avoid redundant DOM writes.
|
|
14
|
+
- Repeated mount/unmount cycles clean listeners, timers, observers, and animation frames.
|
|
15
|
+
- Expensive parsing or serialization does not run on every frame.
|
|
16
|
+
- Overlay and picker positioning does not do repeated forced layout work.
|
|
17
|
+
- Component registration and upgrade do not block page boot unexpectedly.
|
|
18
|
+
|
|
19
|
+
## Test Pattern
|
|
20
|
+
|
|
21
|
+
1. Reproduce the user path with real DOM and real events.
|
|
22
|
+
2. Warm up once, then measure repeated runs.
|
|
23
|
+
3. Collect timings with `performance.now()` around the smallest meaningful operation.
|
|
24
|
+
4. For leak risks, mount/unmount repeatedly and count retained DOM/listeners through observable public effects.
|
|
25
|
+
5. Assert behavior first, then assert timing or bounded operation counts.
|
|
26
|
+
|
|
27
|
+
## Instrumentation Ideas
|
|
28
|
+
|
|
29
|
+
- Wrap public methods or callbacks temporarily inside `page.evaluate` to count calls.
|
|
30
|
+
- Count emitted `input` and `change` events during interactions.
|
|
31
|
+
- Use `requestAnimationFrame` loops to detect frame starvation.
|
|
32
|
+
- Use console timing only for manual investigation; tests should return structured values to Playwright.
|
|
33
|
+
|
|
34
|
+
## Fix Preferences
|
|
35
|
+
|
|
36
|
+
- Batch DOM writes before layout reads.
|
|
37
|
+
- Cache parsed static data, but invalidate when public attributes/properties change.
|
|
38
|
+
- Prefer one listener on a stable root over many per-child listeners when behavior allows.
|
|
39
|
+
- Cancel timers, observers, and frame callbacks in `disconnectedCallback`.
|
|
40
|
+
|
|
41
|
+
## Avoid
|
|
42
|
+
|
|
43
|
+
- Optimizing private code paths that do not affect measured UI behavior.
|
|
44
|
+
- Adding debounce/throttle that changes `input` vs `change` semantics.
|
|
45
|
+
- Hiding slow work behind `setTimeout` without proving user-perceived latency improves.
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: web-component-performance
|
|
3
|
+
description: Guides performance testing for native Web Components and custom elements. Use when measuring custom element registration, upgrade cost, connected/disconnected callbacks, attributeChangedCallback churn, Shadow DOM work, slots, or fig-* component scalability.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Web Component Performance
|
|
7
|
+
|
|
8
|
+
Measure custom element performance in real browsers. Pair this with `web-component-testing` when validating both behavior contracts and performance regressions.
|
|
9
|
+
|
|
10
|
+
## Hot Paths
|
|
11
|
+
|
|
12
|
+
- `customElements.define` and `customElements.whenDefined` during boot.
|
|
13
|
+
- Initial upgrade of many existing elements.
|
|
14
|
+
- `connectedCallback` and `disconnectedCallback` during repeated mount/unmount.
|
|
15
|
+
- `attributeChangedCallback` and property setters during state sync.
|
|
16
|
+
- Shadow DOM creation, slot distribution, and internal event wiring.
|
|
17
|
+
- Form-style event emission during fast interactions.
|
|
18
|
+
|
|
19
|
+
## Test Pattern
|
|
20
|
+
|
|
21
|
+
1. Create a scaled fixture with representative `fig-*` markup.
|
|
22
|
+
2. Wait for definitions, then separate upgrade timing from interaction timing.
|
|
23
|
+
3. Measure repeated mount/unmount cycles for cleanup and callback cost.
|
|
24
|
+
4. Stress public APIs: attributes, properties, slots, and user interactions.
|
|
25
|
+
5. Assert no page errors, no console errors, correct final state, and bounded timing.
|
|
26
|
+
|
|
27
|
+
## Useful Checks
|
|
28
|
+
|
|
29
|
+
- Count how many times lifecycle callbacks run for one user-visible operation.
|
|
30
|
+
- Verify attribute writes do not emit user interaction events unless the component contract says so.
|
|
31
|
+
- Compare one component vs many components in the same page to catch nonlinear scaling.
|
|
32
|
+
- Test overlay/picker components with nested popups because geometry work can multiply.
|
|
33
|
+
- Confirm cleanup by removing hosts, re-adding them, and checking events are not duplicated.
|
|
34
|
+
|
|
35
|
+
## Fix Preferences
|
|
36
|
+
|
|
37
|
+
- Avoid rebuilding Shadow DOM when a targeted text/style/value update is enough.
|
|
38
|
+
- Coalesce repeated attribute/property sync when the public contract allows it.
|
|
39
|
+
- Keep event listeners stable and remove external listeners in `disconnectedCallback`.
|
|
40
|
+
- Prefer public host state for tests; inspect internals only to prove a suspected performance issue.
|
|
41
|
+
|
|
42
|
+
## Avoid
|
|
43
|
+
|
|
44
|
+
- Measuring autonomous custom elements in jsdom.
|
|
45
|
+
- Benchmarking constructors alone when the real cost is upgrade plus connected work.
|
|
46
|
+
- Adding caches that make attribute/property reflection stale.
|
|
47
|
+
- Changing public event timing to pass a benchmark.
|
package/README.md
CHANGED
|
@@ -17,6 +17,18 @@ A lightweight, zero-dependency web components library for building Figma plugin
|
|
|
17
17
|
- Accessible with ARIA attributes and keyboard navigation
|
|
18
18
|
- Framework agnostic (React, Vue, Svelte, or vanilla JS)
|
|
19
19
|
|
|
20
|
+
## Accessibility Coverage
|
|
21
|
+
|
|
22
|
+
FigUI3 components are built to preserve native semantics where possible and add ARIA only where custom elements need extra state or naming.
|
|
23
|
+
|
|
24
|
+
- Form primitives forward accessible names and state to their native controls, including combo inputs, dropdowns, text, number, slider, checkbox, radio, switch, color, and fill inputs.
|
|
25
|
+
- Selection components use standard keyboard patterns: tabs use roving focus and `aria-controls`, segmented controls expose a radio-group pattern with focus following arrow selection, choosers expose listbox/options, and menus support trigger state, item focus, Escape close, and disabled items.
|
|
26
|
+
- Dialog, popup, tooltip, and toast surfaces expose names, close affordances, live-region behavior, Escape dismissal, and focus return behavior appropriate to their role.
|
|
27
|
+
- Media components render their visual surface inside `fig-preview`; image/video semantics stay on the native media element, upload controls remain keyboard reachable, slotted image overlays stay in light DOM for framework ownership, and generated video controls render below the preview instead of as an overlay.
|
|
28
|
+
- Display and pointer components expose useful semantics when interactive or informative: handles, chits, color tips, layers, spinners, shimmers, and skeletons sync names, busy states, disabled states, keyboard movement, inert states, or hidden states as appropriate.
|
|
29
|
+
- Focus styling uses shared `--figma-focus-outline`, `--figma-focus-outline-offset`, and `--figma-focus-outline-radius` tokens so visible focus treatment stays consistent across components.
|
|
30
|
+
- Component contracts include Playwright keyboard/focus coverage plus an axe smoke suite for representative form, media, overlay, selection, and loading fixtures.
|
|
31
|
+
|
|
20
32
|
## Quick Start
|
|
21
33
|
|
|
22
34
|
Install:
|
|
@@ -32,7 +44,14 @@ import "@rogieking/figui3/fig.css";
|
|
|
32
44
|
import "@rogieking/figui3/fig.js";
|
|
33
45
|
```
|
|
34
46
|
|
|
35
|
-
Opt into
|
|
47
|
+
Opt into `<fig-layer>` when you need collapsible layer lists:
|
|
48
|
+
|
|
49
|
+
```js
|
|
50
|
+
import "@rogieking/figui3/fig-layer.css";
|
|
51
|
+
import "@rogieking/figui3/fig-layer.js";
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Opt into editor components like the full Figma-style fill picker when you need them:
|
|
36
55
|
|
|
37
56
|
```js
|
|
38
57
|
import "@rogieking/figui3/fig-editor.css";
|
|
@@ -94,8 +113,9 @@ Minimal example:
|
|
|
94
113
|
| [Popup](#popup) | `<fig-popup>` | Anchored floating surface |
|
|
95
114
|
| [Toast](#toast) | `<fig-toast>` | Toast notification |
|
|
96
115
|
| [Tooltip](#tooltip) | `<fig-tooltip>` | Hover/click tooltip |
|
|
116
|
+
| [Menu](#menu) | `<fig-menu>` | Triggered menu with keyboard navigation |
|
|
97
117
|
| [Header](#header) | `<fig-header>` | Section header |
|
|
98
|
-
| [Layer](#layer) | `<fig-layer>` | Collapsible layer list item |
|
|
118
|
+
| [Layer](#layer) | `<fig-layer>` | Collapsible layer list item from `fig-layer.js` |
|
|
99
119
|
| [Preview](#preview) | `<fig-preview>` | Thin visual preview layer |
|
|
100
120
|
| [Media](#media) | `<fig-media>` | Shared media host for image/video |
|
|
101
121
|
| [Image](#image) | `<fig-image>` | Image display/upload |
|
|
@@ -134,6 +154,8 @@ Minimal example:
|
|
|
134
154
|
</fig-button>
|
|
135
155
|
```
|
|
136
156
|
|
|
157
|
+
`type="select"` and `type="upload"` are visual wrappers for native select/file controls. They avoid nested native buttons, show the shared focus outline on the wrapper, and open the native picker from keyboard activation where supported.
|
|
158
|
+
|
|
137
159
|
---
|
|
138
160
|
|
|
139
161
|
#### Dropdown
|
|
@@ -145,6 +167,8 @@ Minimal example:
|
|
|
145
167
|
| `value` | string | — | Selected value |
|
|
146
168
|
| `type` | string | `"select"` | `"select"` or `"dropdown"` |
|
|
147
169
|
| `experimental` | string | — | Feature flags (e.g. `"modern"` for `appearance: base-select`) |
|
|
170
|
+
| `label` | string | — | Accessible label for the generated native `<select>` |
|
|
171
|
+
| `disabled` | boolean | `false` | Disabled state |
|
|
148
172
|
|
|
149
173
|
```html
|
|
150
174
|
<fig-dropdown value="2">
|
|
@@ -153,6 +177,8 @@ Minimal example:
|
|
|
153
177
|
</fig-dropdown>
|
|
154
178
|
```
|
|
155
179
|
|
|
180
|
+
Keyboard activation follows the native select pattern. Enter opens the closed picker, and when `experimental="modern"` is open, Enter is left to the browser so the focused option commits normally.
|
|
181
|
+
|
|
156
182
|
---
|
|
157
183
|
|
|
158
184
|
#### Combo Input
|
|
@@ -239,7 +265,7 @@ Minimal example:
|
|
|
239
265
|
| Attribute | Type | Default | Description |
|
|
240
266
|
|---|---|---|---|
|
|
241
267
|
| `type` | string | `"range"` | `"range"`, `"hue"`, `"opacity"`, `"delta"`, `"stepper"` |
|
|
242
|
-
| `value` | number |
|
|
268
|
+
| `value` | number | midpoint for `type="range"` | Current value |
|
|
243
269
|
| `min` | number | `0` | Minimum |
|
|
244
270
|
| `max` | number | `100` | Maximum |
|
|
245
271
|
| `step` | number | `1` | Step increment |
|
|
@@ -261,6 +287,8 @@ Minimal example:
|
|
|
261
287
|
<fig-slider type="opacity" value="75" color="#FF5733" units="%"></fig-slider>
|
|
262
288
|
```
|
|
263
289
|
|
|
290
|
+
For `type="range"`, omitting `value` follows native range behavior and starts at the midpoint of `min` and `max`. Arrow keys move by `step`; hold Shift to move by a larger step.
|
|
291
|
+
|
|
264
292
|
---
|
|
265
293
|
|
|
266
294
|
#### Field Slider
|
|
@@ -467,6 +495,8 @@ An editable palette of solid colors, each rendered as a `<fig-input-color>` swat
|
|
|
467
495
|
<fig-input-palette value='[{"color":"#FF0000","alpha":0.5},{"color":"#00FF00","alpha":1}]' open></fig-input-palette>
|
|
468
496
|
```
|
|
469
497
|
|
|
498
|
+
The collapsed palette is a single tab stop. Enter or Space expands it, and focus styling uses the shared focus outline tokens on the visible swatch row.
|
|
499
|
+
|
|
470
500
|
---
|
|
471
501
|
|
|
472
502
|
#### Gradient Input
|
|
@@ -516,6 +546,8 @@ A comprehensive fill input supporting solid, gradient, image, and video fills. W
|
|
|
516
546
|
| `alpha` | boolean | `true` | Show alpha controls |
|
|
517
547
|
| `picker-*` | string | — | Forwarded to `<fig-fill-picker>` when the optional picker is registered |
|
|
518
548
|
|
|
549
|
+
Add `aria-label` to name the generated picker, hex field, and opacity field as one fill control group.
|
|
550
|
+
|
|
519
551
|
**Events:**
|
|
520
552
|
|
|
521
553
|
| Event | Detail |
|
|
@@ -572,6 +604,8 @@ Optional full fill picker dialog supporting solid, gradient, image, video, and w
|
|
|
572
604
|
|
|
573
605
|
**Events:** `input`, `change` with selected tab value.
|
|
574
606
|
|
|
607
|
+
Tabs use `role="tablist"` / `role="tab"` and roving focus. Use `content="#panel-id"` on each `<fig-tab>` to associate generated tab panels. Focus-visible tabs use the shared focus outline tokens.
|
|
608
|
+
|
|
575
609
|
```html
|
|
576
610
|
<fig-tabs value="tab1">
|
|
577
611
|
<fig-tab value="tab1">General</fig-tab>
|
|
@@ -594,6 +628,8 @@ Optional full fill picker dialog supporting solid, gradient, image, video, and w
|
|
|
594
628
|
|
|
595
629
|
**Events:** `input`, `change` — detail contains the selected value.
|
|
596
630
|
|
|
631
|
+
Segmented controls expose a radio-group pattern. Arrow keys, Home, and End move selection between enabled segments and move focus to the selected segment.
|
|
632
|
+
|
|
597
633
|
```html
|
|
598
634
|
<fig-segmented-control>
|
|
599
635
|
<fig-segment value="left" selected="true">Left</fig-segment>
|
|
@@ -658,6 +694,7 @@ A 2D position input control with optional X/Y fields.
|
|
|
658
694
|
| `fields` | boolean | `false` | Show X/Y inputs |
|
|
659
695
|
| `coordinates` | string | `"screen"` | `"screen"` (0,0 top-left) or `"math"` (0,0 bottom-left) |
|
|
660
696
|
| `aspect-ratio` | string | `"1 / 1"` | Plane ratio |
|
|
697
|
+
| `axis-labels` | string | — | Comma- or space-delimited labels. 1 value: top. 2 values: x y. 4 values: left right top bottom |
|
|
661
698
|
|
|
662
699
|
**Events:**
|
|
663
700
|
|
|
@@ -670,6 +707,8 @@ A 2D position input control with optional X/Y fields.
|
|
|
670
707
|
<fig-joystick value="50% 50%" fields="true" precision="2"></fig-joystick>
|
|
671
708
|
```
|
|
672
709
|
|
|
710
|
+
Keyboard focus lands on the internal handle. Arrow keys move the handle and keep focus on it during interaction.
|
|
711
|
+
|
|
673
712
|
---
|
|
674
713
|
|
|
675
714
|
#### Origin Grid
|
|
@@ -697,6 +736,8 @@ A transform-origin grid control with a draggable handle and optional X/Y percent
|
|
|
697
736
|
<fig-origin-grid value="50% 50%" drag="true" fields="true"></fig-origin-grid>
|
|
698
737
|
```
|
|
699
738
|
|
|
739
|
+
The internal handle uses the shared focus outline and supports Arrow, Shift+Arrow, Home, and End keyboard movement.
|
|
740
|
+
|
|
700
741
|
---
|
|
701
742
|
|
|
702
743
|
#### Easing Curve
|
|
@@ -726,6 +767,8 @@ An interactive bezier or spring easing curve editor with a preset dropdown and m
|
|
|
726
767
|
<fig-easing-curve value="spring(200, 15, 1)" edit="false"></fig-easing-curve>
|
|
727
768
|
```
|
|
728
769
|
|
|
770
|
+
Editable bezier and spring handles are keyboard operable. Bezier handles keep tab order aligned with the visual handle order.
|
|
771
|
+
|
|
729
772
|
---
|
|
730
773
|
|
|
731
774
|
#### 3D Rotate
|
|
@@ -798,6 +841,8 @@ A draggable handle element. Positioned on a `drag-surface` container with axis c
|
|
|
798
841
|
</div>
|
|
799
842
|
```
|
|
800
843
|
|
|
844
|
+
When `drag="true"`, focused handles support Arrow key movement, Home/End jumps, and a tokenized focus outline with a 1px offset.
|
|
845
|
+
|
|
801
846
|
---
|
|
802
847
|
|
|
803
848
|
#### Canvas Control
|
|
@@ -892,6 +937,8 @@ A modal/non-modal dialog. Uses `is="fig-dialog"` on a native `<dialog>` element.
|
|
|
892
937
|
</dialog>
|
|
893
938
|
```
|
|
894
939
|
|
|
940
|
+
Dialog close paths restore focus to the element that opened the dialog.
|
|
941
|
+
|
|
895
942
|
---
|
|
896
943
|
|
|
897
944
|
#### Popup
|
|
@@ -920,6 +967,8 @@ An anchored floating surface built on `<dialog>` with collision-aware positionin
|
|
|
920
967
|
</dialog>
|
|
921
968
|
```
|
|
922
969
|
|
|
970
|
+
Popups restore focus on close. Escape dismissal is scoped so nested menu and overlay behavior can keep its own keyboard handling.
|
|
971
|
+
|
|
923
972
|
---
|
|
924
973
|
|
|
925
974
|
#### Toast
|
|
@@ -927,12 +976,14 @@ An anchored floating surface built on `<dialog>` with collision-aware positionin
|
|
|
927
976
|
`<fig-toast>` — [demo](https://rog.ie/figui3/#toast)
|
|
928
977
|
|
|
929
978
|
A toast notification. Uses `is="fig-toast"` on a native `<dialog>`.
|
|
979
|
+
Defaults to `role="status"`, `aria-live="polite"`, and `aria-atomic="true"`. Use `live="assertive"` or `theme="danger"` for assertive announcements.
|
|
930
980
|
|
|
931
981
|
| Attribute | Type | Default | Description |
|
|
932
982
|
|---|---|---|---|
|
|
933
983
|
| `duration` | number | `5000` | Auto-dismiss ms (0 = no dismiss) |
|
|
934
984
|
| `offset` | number | `16` | Distance from bottom |
|
|
935
985
|
| `theme` | string | `"dark"` | `"dark"`, `"light"`, `"danger"`, `"brand"`, `"auto"` |
|
|
986
|
+
| `live` | string | — | `"assertive"` for urgent announcements |
|
|
936
987
|
|
|
937
988
|
```html
|
|
938
989
|
<dialog is="fig-toast" id="myToast" theme="brand" duration="3000">
|
|
@@ -964,6 +1015,36 @@ Contextual tooltip on hover or click. Auto-repositions when the child element mo
|
|
|
964
1015
|
</fig-tooltip>
|
|
965
1016
|
```
|
|
966
1017
|
|
|
1018
|
+
Escape dismisses an open tooltip and returns focus to its trigger.
|
|
1019
|
+
|
|
1020
|
+
---
|
|
1021
|
+
|
|
1022
|
+
#### Menu
|
|
1023
|
+
|
|
1024
|
+
`<fig-menu>` / `<fig-menu-item>` / `<fig-menu-separator>` — [demo](https://rog.ie/figui3/#menu)
|
|
1025
|
+
|
|
1026
|
+
Triggered menu with native keyboard patterns. The trigger gets `aria-haspopup="menu"`, `aria-expanded`, and `aria-controls`; menu items use `role="menuitem"` and disabled items are skipped by keyboard navigation.
|
|
1027
|
+
|
|
1028
|
+
| Attribute | Type | Default | Description |
|
|
1029
|
+
|---|---|---|---|
|
|
1030
|
+
| `open` | boolean | `false` | Open state |
|
|
1031
|
+
| `disabled` | boolean | `false` | Disable trigger/menu |
|
|
1032
|
+
| `position` | string | `"bottom left"` | Popup placement |
|
|
1033
|
+
| `offset` | string | — | Popup offset |
|
|
1034
|
+
| `closedby` | string | — | Popup close behavior |
|
|
1035
|
+
|
|
1036
|
+
**Keyboard:** Arrow keys move between enabled items, Home/End jump to edges, Enter/Space selects, Escape closes and returns focus to the trigger.
|
|
1037
|
+
|
|
1038
|
+
```html
|
|
1039
|
+
<fig-menu position="bottom left">
|
|
1040
|
+
<fig-button fig-menu-trigger>Actions</fig-button>
|
|
1041
|
+
<fig-menu-item value="copy">Copy</fig-menu-item>
|
|
1042
|
+
<fig-menu-item value="paste">Paste</fig-menu-item>
|
|
1043
|
+
<fig-menu-separator></fig-menu-separator>
|
|
1044
|
+
<fig-menu-item value="delete" disabled>Delete</fig-menu-item>
|
|
1045
|
+
</fig-menu>
|
|
1046
|
+
```
|
|
1047
|
+
|
|
967
1048
|
---
|
|
968
1049
|
|
|
969
1050
|
#### Header
|
|
@@ -982,7 +1063,8 @@ A section header component.
|
|
|
982
1063
|
|
|
983
1064
|
`<fig-layer>` — [demo](https://rog.ie/figui3/#layer)
|
|
984
1065
|
|
|
985
|
-
A collapsible layer list item with expand/collapse and visibility toggling. Supports nesting.
|
|
1066
|
+
A collapsible layer list item with expand/collapse and visibility toggling. Supports nesting and exposes `role="treeitem"`, `aria-expanded`, `aria-hidden`, `aria-disabled`, and a keyboard-toggleable chevron button.
|
|
1067
|
+
Import `fig-layer.js` and `fig-layer.css` to register and style it. `fig-editor.js` also includes the layer registration.
|
|
986
1068
|
|
|
987
1069
|
| Attribute | Type | Default | Description |
|
|
988
1070
|
|---|---|---|---|
|
|
@@ -1036,7 +1118,7 @@ A thin styled layer for arbitrary visual content. Use it for generated previews,
|
|
|
1036
1118
|
|
|
1037
1119
|
`<fig-media>`
|
|
1038
1120
|
|
|
1039
|
-
Unified media component that supports image/video modes and shared sizing/upload behavior.
|
|
1121
|
+
Unified media component that supports image/video modes and shared sizing/upload behavior. The media surface is rendered inside a `fig-preview`; generated video controls render below that preview rather than as an overlay. Set `size` for a token-sized square, or `aspect-ratio` to fill the container width with a fixed ratio.
|
|
1040
1122
|
|
|
1041
1123
|
| Attribute | Type | Default | Description |
|
|
1042
1124
|
|---|---|---|---|
|
|
@@ -1054,11 +1136,14 @@ Unified media component that supports image/video modes and shared sizing/upload
|
|
|
1054
1136
|
| `loop` | boolean | `false` | Video loop |
|
|
1055
1137
|
| `muted` | boolean | `false` | Video muted |
|
|
1056
1138
|
| `poster` | string | — | Video poster URL |
|
|
1139
|
+
| `aria-label` | string | — | Accessible label forwarded to generated videos |
|
|
1140
|
+
|
|
1141
|
+
Use meaningful `alt` text for informative images. Use `alt=""` only when the image is decorative or already described by nearby text.
|
|
1057
1142
|
|
|
1058
1143
|
```html
|
|
1059
|
-
<fig-media type="image" src="photo.jpg"></fig-media>
|
|
1060
|
-
<fig-media type="image" src="photo.jpg" aspect-ratio="16 / 9" fit="cover"></fig-media>
|
|
1061
|
-
<fig-media type="video" src="clip.mp4" controls muted></fig-media>
|
|
1144
|
+
<fig-media type="image" src="photo.jpg" alt="Selected image"></fig-media>
|
|
1145
|
+
<fig-media type="image" src="photo.jpg" alt="Cover image" aspect-ratio="16 / 9" fit="cover"></fig-media>
|
|
1146
|
+
<fig-media type="video" src="clip.mp4" aria-label="Product demo video" controls muted></fig-media>
|
|
1062
1147
|
```
|
|
1063
1148
|
|
|
1064
1149
|
---
|
|
@@ -1067,7 +1152,7 @@ Unified media component that supports image/video modes and shared sizing/upload
|
|
|
1067
1152
|
|
|
1068
1153
|
`<fig-image>` — [demo](https://rog.ie/figui3/#image)
|
|
1069
1154
|
|
|
1070
|
-
An image display component with optional upload, aspect ratio, and object-fit control. Renders a real `<img>` inside
|
|
1155
|
+
An image display component with optional upload, aspect ratio, and object-fit control. Renders a real `<img>` inside a `fig-preview`.
|
|
1071
1156
|
|
|
1072
1157
|
| Attribute | Type | Default | Description |
|
|
1073
1158
|
|---|---|---|---|
|
|
@@ -1080,19 +1165,26 @@ An image display component with optional upload, aspect ratio, and object-fit co
|
|
|
1080
1165
|
| `fit` | string | `"contain"` | CSS object-fit (`"cover"`, `"contain"`, etc.) |
|
|
1081
1166
|
| `checkerboard` | boolean | `false` | Show checkerboard behind transparent images |
|
|
1082
1167
|
|
|
1168
|
+
Use meaningful `alt` text for informative images. Use `alt=""` for decorative previews, thumbnails with visible labels, or upload placeholders.
|
|
1169
|
+
|
|
1083
1170
|
```html
|
|
1084
|
-
<fig-image src="photo.jpg"></fig-image>
|
|
1085
|
-
<fig-image src="photo.jpg" aspect-ratio="16 / 9" fit="cover"></fig-image>
|
|
1086
|
-
<fig-image upload label="Upload Image"></fig-image>
|
|
1171
|
+
<fig-image src="photo.jpg" alt="Selected image"></fig-image>
|
|
1172
|
+
<fig-image src="photo.jpg" alt="Cover image" aspect-ratio="16 / 9" fit="cover"></fig-image>
|
|
1173
|
+
<fig-image upload label="Upload Image" alt=""></fig-image>
|
|
1174
|
+
<fig-image src="photo.jpg" alt="Selected image">
|
|
1175
|
+
<fig-input-file slot="overlay" variant="overlay" label="Change image"></fig-input-file>
|
|
1176
|
+
</fig-image>
|
|
1087
1177
|
```
|
|
1088
1178
|
|
|
1179
|
+
Use `slot="overlay"` for custom overlay controls. Slotted overlays stay as direct light-DOM children so frameworks like React keep ownership of their nodes, while CSS places them over the preview and keeps them visible on hover, focus, and active interaction.
|
|
1180
|
+
|
|
1089
1181
|
---
|
|
1090
1182
|
|
|
1091
1183
|
#### Video
|
|
1092
1184
|
|
|
1093
1185
|
`<fig-video>`
|
|
1094
1186
|
|
|
1095
|
-
Video display/upload component with the same
|
|
1187
|
+
Video display/upload component with the same preview styling model as `fig-image`. Renders a real `<video>` inside a `fig-preview`; generated playback controls tack onto the bottom.
|
|
1096
1188
|
|
|
1097
1189
|
| Attribute | Type | Default | Description |
|
|
1098
1190
|
|---|---|---|---|
|
|
@@ -1107,11 +1199,14 @@ Video display/upload component with the same host styling model as `fig-image`.
|
|
|
1107
1199
|
| `loop` | boolean | `false` | Loop video |
|
|
1108
1200
|
| `muted` | boolean | `false` | Mute video |
|
|
1109
1201
|
| `poster` | string | — | Poster image URL (forwarded to inner `<video>`) |
|
|
1202
|
+
| `aria-label` | string | — | Accessible label forwarded to the generated `<video>` |
|
|
1203
|
+
|
|
1204
|
+
Prefer `controls` for videos that play motion. Add captions with a slotted `<track>` when the video includes speech or essential audio.
|
|
1110
1205
|
|
|
1111
1206
|
```html
|
|
1112
|
-
<fig-video src="clip.mp4"></fig-video>
|
|
1113
|
-
<fig-video src="clip.mp4" aspect-ratio="16 / 9" controls></fig-video>
|
|
1114
|
-
<fig-video upload label="Upload Video" controls muted></fig-video>
|
|
1207
|
+
<fig-video src="clip.mp4" aria-label="Product demo video" controls></fig-video>
|
|
1208
|
+
<fig-video src="clip.mp4" aria-label="Product demo video" aspect-ratio="16 / 9" controls></fig-video>
|
|
1209
|
+
<fig-video upload label="Upload Video" aria-label="Uploaded video preview" controls muted></fig-video>
|
|
1115
1210
|
```
|
|
1116
1211
|
|
|
1117
1212
|
---
|
|
@@ -1162,6 +1257,8 @@ Legacy: `<span class="fig-mask-icon" style="--icon: var(--icon-24-add)"></span>`
|
|
|
1162
1257
|
|
|
1163
1258
|
A loading spinner.
|
|
1164
1259
|
|
|
1260
|
+
Defaults to `role="status"` and `aria-label="Loading"`; override the label when the loading target needs a more specific name.
|
|
1261
|
+
|
|
1165
1262
|
```html
|
|
1166
1263
|
<fig-spinner></fig-spinner>
|
|
1167
1264
|
```
|
|
@@ -1179,6 +1276,8 @@ A shimmer loading placeholder.
|
|
|
1179
1276
|
| `duration` | string | `"1.5s"` | Animation cycle duration |
|
|
1180
1277
|
| `playing` | boolean | `true` | Whether animating |
|
|
1181
1278
|
|
|
1279
|
+
Shimmer and skeleton placeholders are hidden from assistive tech unless you add `aria-label` or `aria-labelledby`; named placeholders expose `role="status"` and `aria-busy`.
|
|
1280
|
+
|
|
1182
1281
|
```html
|
|
1183
1282
|
<fig-shimmer style="width: 200px; height: 20px;"></fig-shimmer>
|
|
1184
1283
|
```
|
|
@@ -1189,7 +1288,7 @@ A shimmer loading placeholder.
|
|
|
1189
1288
|
|
|
1190
1289
|
`<fig-skeleton>`
|
|
1191
1290
|
|
|
1192
|
-
Extends `<fig-shimmer>`
|
|
1291
|
+
Extends `<fig-shimmer>` for structured loading placeholders. Skeletons are inert by default, so any placeholder inputs or buttons inside them are removed from tab focus while loading.
|
|
1193
1292
|
|
|
1194
1293
|
```html
|
|
1195
1294
|
<fig-skeleton style="width: 100%; height: 1rem; border-radius: 4px;"></fig-skeleton>
|
|
@@ -1222,6 +1321,16 @@ Force a theme manually:
|
|
|
1222
1321
|
</body>
|
|
1223
1322
|
```
|
|
1224
1323
|
|
|
1324
|
+
Focus indicators are controlled with shared tokens:
|
|
1325
|
+
|
|
1326
|
+
```css
|
|
1327
|
+
--figma-focus-outline
|
|
1328
|
+
--figma-focus-outline-offset
|
|
1329
|
+
--figma-focus-outline-radius
|
|
1330
|
+
```
|
|
1331
|
+
|
|
1332
|
+
`--figma-focus-outline-radius` defaults to `inherit`, so focused controls can inherit their component radius unless a component overrides it for a specific shape.
|
|
1333
|
+
|
|
1225
1334
|
---
|
|
1226
1335
|
|
|
1227
1336
|
## Framework Integration
|