@wix/agent-skills 1.16.2 → 1.17.0
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/package.json +1 -1
- package/skills/wix-app/references/EDITOR_REACT_COMPONENT.md +134 -120
- package/skills/wix-app/references/EMBEDDED_SCRIPT.md +6 -0
- package/skills/wix-app/references/SITE_PLUGIN.md +2 -2
- package/skills/wix-app/references/backend-event/COMMON-EVENTS.md +2 -2
- package/skills/wix-app/references/editor-react-component/ACCESSIBILITY.md +182 -99
- package/skills/wix-app/references/editor-react-component/ANIMATED-COMPONENTS.md +92 -47
- package/skills/wix-app/references/editor-react-component/BRANDED-COMPONENTS.md +15 -6
- package/skills/wix-app/references/editor-react-component/COMPONENT-CONTRACT.md +275 -0
- package/skills/wix-app/references/editor-react-component/COMPONENT-PREVIEW.md +29 -42
- package/skills/wix-app/references/editor-react-component/CSS-GUIDELINES.md +153 -449
- package/skills/wix-app/references/editor-react-component/DESIGN-STATES.md +66 -19
- package/skills/wix-app/references/editor-react-component/DIRECTIONALITY.md +53 -158
- package/skills/wix-app/references/editor-react-component/EDITOR-EXTENSION-CONFIGURATION.md +78 -0
- package/skills/wix-app/references/editor-react-component/FUNCTION-HANDLERS.md +42 -134
- package/skills/wix-app/references/editor-react-component/MANIFEST-ERRORS.md +27 -0
- package/skills/wix-app/references/editor-react-component/PARTS.md +45 -24
- package/skills/wix-app/references/editor-react-component/PROPS-VS-CSS.md +63 -179
- package/skills/wix-app/references/editor-react-component/REACT-GUIDELINES.md +79 -163
- package/skills/wix-app/references/editor-react-component/SITE-CONTEXT-HOOKS.md +36 -21
- package/skills/wix-app/references/editor-react-component/SSR.md +30 -99
- package/skills/wix-base44-connector/SKILL.md +34 -17
- package/skills/wix-base44-connector/scripts/utils.js +33 -25
- package/skills/wix-headless/entry/bootstrap.mjs +9 -2
- package/skills/wix-headless/references/SDK_HANDOFF.md +1 -1
- package/skills/wix-headless/references/inline-recipes/how-to-code-a-store.md +42 -23
- package/skills/wix-headless/references/inline-recipes/how-to-code-pricing-plans.md +10 -8
- package/skills/wix-headless/references/inline-recipes/how-to-code-restaurant-orders.md +27 -24
- package/skills/wix-headless/references/managed/AUTHENTICATION.md +5 -0
- package/skills/wix-manage/SKILL.md +14 -2
- package/skills/wix-manage/references/bookings/booking-system-integration-gaps.md +20 -13
- package/skills/wix-manage/references/bookings/create-class-service.md +1 -1
- package/skills/wix-manage/references/bookings/end-to-end-booking-flow.md +24 -11
- package/skills/wix-manage/references/cms/cms-ecommerce-catalog-integration.md +5 -5
- package/skills/wix-manage/references/rich-content/author-ricos-rich-content.md +182 -5
- package/skills/wix-manage/references/seo/manage-seo-tags.md +315 -0
- package/skills/wix-manage/references/seo/manage-url-redirects.md +250 -0
- package/skills/wix-manage/references/sites/query-sites.md +72 -161
- package/skills/wix-replatform/resources/rp-mapper/wix-business-solutions-taxonomy.md +5 -6
- package/skills/wix-vibe-headless/platforms/base44-ecom-light-seed.md +13 -9
- package/skills/wix-vibe-headless/platforms/base44-ecom-light.md +10 -7
- package/skills/wix-vibe-headless/platforms/base44.md +13 -10
- package/skills/wix-vibe-headless/references/bookings/INSTRUCTIONS.md +2 -0
- package/skills/wix-vibe-headless/references/bookings/app/rest/wix-bookings-checkout.js +9 -8
- package/skills/wix-vibe-headless/references/restaurants/INSTRUCTIONS.md +4 -1
- package/skills/wix-vibe-headless/references/restaurants/app/components/OrderCartDrawer.jsx +23 -11
- package/skills/wix-vibe-headless/references/restaurants/app/context/OrderCartContext.jsx +1 -1
- package/skills/wix-vibe-headless/references/restaurants/app/rest/wix-restaurants-ordering.js +29 -31
- package/skills/wix-vibe-headless/references/storefront/INSTRUCTIONS.md +15 -8
- package/skills/wix-vibe-headless/references/storefront/app/components/CartDrawer.jsx +37 -38
- package/skills/wix-vibe-headless/references/storefront/app/context/CartContext.jsx +2 -2
- package/skills/wix-vibe-headless/references/storefront/app/rest/wix-store-cart.js +35 -35
- package/skills/wix-app/references/editor-react-component/A11Y-REVIEW-REFERENCE.md +0 -172
- package/skills/wix-app/references/editor-react-component/A11Y-REVIEW.md +0 -143
- package/skills/wix-app/references/editor-react-component/COMPONENT-API.md +0 -484
- package/skills/wix-app/references/editor-react-component/COMPONENT-CONFIGURATION.md +0 -225
- package/skills/wix-app/references/editor-react-component/EDIT-FLOW.md +0 -6
- package/skills/wix-app/references/editor-react-component/REACT-PATTERNS.md +0 -95
|
@@ -1,139 +1,222 @@
|
|
|
1
|
-
# Accessibility
|
|
1
|
+
# Accessibility Implementation and Review
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Use this reference while authoring Editor React Component props and JSX and
|
|
4
|
+
after every JSX edit.
|
|
4
5
|
|
|
5
|
-
|
|
6
|
+
## Contents
|
|
6
7
|
|
|
7
|
-
|
|
8
|
+
- [Implementation Contract](#implementation-contract)
|
|
9
|
+
- [Review Scope](#review-scope)
|
|
10
|
+
- [Automated Scanners](#automated-scanners)
|
|
11
|
+
- [Finding Triage](#finding-triage)
|
|
12
|
+
- [Manual Review](#manual-review)
|
|
13
|
+
- [Pre-Fix Checks for Non-Interactive Controls](#pre-fix-checks-for-non-interactive-controls)
|
|
14
|
+
- [Completion Criteria](#completion-criteria)
|
|
8
15
|
|
|
9
|
-
|
|
16
|
+
## Implementation Contract
|
|
10
17
|
|
|
11
|
-
|
|
12
|
-
- **ALL** accessibility attributes MUST come through the `a11y?: A11y` prop.
|
|
13
|
-
- The `A11y` type includes: `ariaLabel`, `ariaDescribedBy`, `ariaLabelledBy`, `role`, `ariaHidden`, `ariaLive`, and all other ARIA attributes.
|
|
14
|
-
- Users provide ARIA values through the `a11y` prop: `<Component a11y={{ ariaLabel: "..." }} />`
|
|
18
|
+
### Route ARIA Through `a11y`
|
|
15
19
|
|
|
16
|
-
|
|
20
|
+
Do not add individual public props such as `ariaLabel`, `ariaDescribedBy`, or
|
|
21
|
+
`role`. Use the platform `A11y` type and convert it at the semantic target.
|
|
17
22
|
|
|
18
|
-
|
|
23
|
+
```tsx
|
|
24
|
+
import type { A11y, Direction } from '@wix/editor-react-types';
|
|
25
|
+
import { convertA11yKeysToHtmlFormat } from '@wix/react-component-utils';
|
|
19
26
|
|
|
20
|
-
|
|
27
|
+
export type TabsProps = {
|
|
28
|
+
id?: string;
|
|
29
|
+
className?: string;
|
|
30
|
+
direction?: Direction;
|
|
31
|
+
a11y?: A11y;
|
|
32
|
+
};
|
|
21
33
|
|
|
22
|
-
|
|
34
|
+
<nav {...(a11y && convertA11yKeysToHtmlFormat(a11y))}>{tabs}</nav>;
|
|
35
|
+
```
|
|
23
36
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
37
|
+
Apply root accessibility to the elected root. If requirements assign
|
|
38
|
+
accessibility to a named inner part, route it through that part's
|
|
39
|
+
`elementProps.<name>.a11y` contract and convert it on the actual semantic
|
|
40
|
+
element.
|
|
27
41
|
|
|
28
|
-
|
|
42
|
+
### Provide Accessible Names
|
|
29
43
|
|
|
30
|
-
|
|
31
|
-
// User provides: <ComponentName a11y={{ ariaLabel: "Background music" }} />
|
|
32
|
-
// Component applies to root (using the a11y-to-HTML conversion utility):
|
|
33
|
-
{...(a11y && convertA11yKeysToHtmlFormat(a11y))}
|
|
44
|
+
Use this priority order:
|
|
34
45
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
46
|
+
1. Prefer visible text that already names the control.
|
|
47
|
+
2. Use user-configurable `a11y` when the name depends on site-owner content.
|
|
48
|
+
3. Use the project's translation mechanism or a `constants.ts` value only for a
|
|
49
|
+
stable system-owned label required by the component contract.
|
|
38
50
|
|
|
39
|
-
|
|
51
|
+
Never hardcode an `aria-label` string directly in JSX.
|
|
40
52
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
53
|
+
```tsx
|
|
54
|
+
// constants.ts
|
|
55
|
+
export const ARIA_LABELS = {
|
|
56
|
+
playButton: 'Play animation',
|
|
57
|
+
pauseButton: 'Pause animation',
|
|
58
|
+
} as const;
|
|
47
59
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
60
|
+
// component JSX
|
|
61
|
+
<button
|
|
62
|
+
aria-label={isPlaying ? ARIA_LABELS.pauseButton : ARIA_LABELS.playButton}
|
|
63
|
+
>
|
|
64
|
+
{isPlaying ? <PauseIcon /> : <PlayIcon />}
|
|
65
|
+
</button>;
|
|
66
|
+
```
|
|
52
67
|
|
|
53
|
-
|
|
68
|
+
Icon-only controls require an accessible name. Controls with visible text,
|
|
69
|
+
including an icon plus visible text, usually do not need another ARIA label.
|
|
54
70
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
71
|
+
### Preserve Semantic Ownership
|
|
72
|
+
|
|
73
|
+
- Put roles, labels, descriptions, keyboard handling, and focusability on the
|
|
74
|
+
element that owns the behavior, not on a layout wrapper.
|
|
75
|
+
- Prefer native elements over recreating their semantics with `role`.
|
|
76
|
+
- Hide decorative-only output with `aria-hidden="true"` when appropriate.
|
|
77
|
+
- Preserve heading, list, navigation, and landmark semantics through wrappers.
|
|
78
|
+
- Keep hidden or collapsed state consistent across visuals, focusability, and
|
|
79
|
+
the accessibility tree.
|
|
80
|
+
|
|
81
|
+
## Review Scope
|
|
82
|
+
|
|
83
|
+
Run this review after creating or editing JSX.
|
|
84
|
+
|
|
85
|
+
| Request | Scan and inspect |
|
|
86
|
+
| --- | --- |
|
|
87
|
+
| Specific file | That file and rendered wrappers or shared components it imports |
|
|
88
|
+
| A component name or "this component" | All hand-edited files in its component folder plus relevant shared imports |
|
|
89
|
+
| Full audit | Every component under `src/extensions/site/components/` plus relevant shared imports |
|
|
90
|
+
|
|
91
|
+
Exclude `*.generated.ts`; it is regenerated from JSX and CSS.
|
|
92
|
+
Imported shared components are inspection context, not automatic edit scope.
|
|
93
|
+
Report a confirmed shared-component issue instead of changing a broadly reused
|
|
94
|
+
primitive unless the requested fix requires that shared change and its impact is
|
|
95
|
+
understood.
|
|
96
|
+
|
|
97
|
+
## Automated Scanners
|
|
98
|
+
|
|
99
|
+
`<SKILL_ROOT>` is the absolute directory containing the active `SKILL.md`. Run
|
|
100
|
+
both commands from the consumer Wix package so dependencies resolve from that
|
|
101
|
+
project. Pass `.tsx` or `.jsx` paths relative to the current directory.
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
node <SKILL_ROOT>/scripts/scan-a11y-eslint.cjs <file1> [file2] ...
|
|
105
|
+
node <SKILL_ROOT>/scripts/scan-a11y-code.cjs <file1> [file2] ...
|
|
60
106
|
```
|
|
61
107
|
|
|
62
|
-
|
|
108
|
+
Do not treat scanner startup failure as a clean result. The ESLint scanner
|
|
109
|
+
reports JSX accessibility rules. The semantic scanner follows imports up to
|
|
110
|
+
four levels and emits resolution evidence and confidence. Neither scanner
|
|
111
|
+
covers every Editor React Component contract, so complete the manual review
|
|
112
|
+
even when both return zero findings.
|
|
63
113
|
|
|
64
|
-
|
|
65
|
-
- User-provided labels take precedence when available
|
|
66
|
-
- Constants allow centralized management and potential future translation
|
|
114
|
+
## Finding Triage
|
|
67
115
|
|
|
68
|
-
|
|
116
|
+
For every finding:
|
|
69
117
|
|
|
70
|
-
|
|
118
|
+
1. Trace the rendered semantic element through local and shared components.
|
|
119
|
+
2. Deduplicate findings for the same issue and location; keep the finding with
|
|
120
|
+
stronger evidence.
|
|
121
|
+
3. Assign `confirmed`, `false-positive`, or `not-relevant`.
|
|
122
|
+
4. Fix only confirmed findings.
|
|
71
123
|
|
|
72
|
-
|
|
73
|
-
| --------------------- | ----------------- | ----------------------------------------- |
|
|
74
|
-
| Visible text only | ❌ No | `<Button>Play</Button>` |
|
|
75
|
-
| Icon component + text | ❌ No | `<Button><PlayIcon />Play</Button>` |
|
|
76
|
-
| Icon/emoji only | ✅ YES | `<Button>▶</Button>` |
|
|
77
|
-
| Image only | ✅ YES | `<Button><img src="play.png" /></Button>` |
|
|
78
|
-
| SVG only | ✅ YES | `<Button><svg>...</svg></Button>` |
|
|
124
|
+
Scanner output is a lead, not permission to edit blindly.
|
|
79
125
|
|
|
80
|
-
|
|
126
|
+
### Confidence and Action
|
|
81
127
|
|
|
82
|
-
|
|
128
|
+
| Confidence | Evidence | Action |
|
|
129
|
+
| --- | --- | --- |
|
|
130
|
+
| High | The rendered element and static props directly establish the issue. | Confirm and fix when the change is safe and local. |
|
|
131
|
+
| Medium | Props or partial component resolution strongly imply the semantics. | Inspect surrounding code, then confirm or discard. |
|
|
132
|
+
| Low | Heuristics or unresolved runtime spreads are the main evidence. | Trace further and fix only after confirmation. |
|
|
133
|
+
| Unknown | The semantic target cannot be resolved. | Leave unchanged and report the ambiguity when material. |
|
|
83
134
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
pauseButton: 'Pause audio',
|
|
89
|
-
} as const;
|
|
135
|
+
Confidence establishes whether a finding is real, not whether its fix is safe.
|
|
136
|
+
Apply confirmed local, behavior-preserving fixes. Leave a confirmed issue
|
|
137
|
+
unchanged only when product intent is unknowable or the fix requires risky,
|
|
138
|
+
non-local behavior changes.
|
|
90
139
|
|
|
91
|
-
|
|
92
|
-
<Button
|
|
93
|
-
aria-label={isPlaying ? ARIA_LABELS.pauseButton : ARIA_LABELS.playButton}
|
|
94
|
-
>
|
|
95
|
-
{isPlaying ? '⏸' : '▶'}
|
|
96
|
-
</Button>;
|
|
97
|
-
```
|
|
140
|
+
### Semantic Resolution Order
|
|
98
141
|
|
|
99
|
-
|
|
142
|
+
Resolve rendered behavior in this order:
|
|
100
143
|
|
|
101
|
-
|
|
144
|
+
1. Flagged JSX element and static props
|
|
145
|
+
2. Explicit polymorphic props such as `as="a"` or `component="button"`
|
|
146
|
+
3. Local component implementation
|
|
147
|
+
4. Installed package source or declarations
|
|
148
|
+
5. Prop evidence such as `href`, `to`, `src`, `alt`, and `role`
|
|
149
|
+
6. Component-name heuristics
|
|
102
150
|
|
|
103
|
-
|
|
151
|
+
Follow local imports to their rendered root. For package imports, inspect the
|
|
152
|
+
resolved package entry when available. Do not assign more confidence than the
|
|
153
|
+
evidence supports.
|
|
104
154
|
|
|
105
|
-
|
|
106
|
-
import type { Direction } from '@wix/editor-react-types';
|
|
155
|
+
## Manual Review
|
|
107
156
|
|
|
108
|
-
|
|
109
|
-
id?: string;
|
|
110
|
-
className?: string;
|
|
111
|
-
direction?: Direction;
|
|
112
|
-
ariaLabel?: string; // ❌ Individual ARIA prop
|
|
113
|
-
ariaDescribedBy?: string; // ❌ Individual ARIA prop
|
|
114
|
-
role?: string; // ❌ Individual ARIA prop
|
|
115
|
-
}
|
|
116
|
-
```
|
|
157
|
+
Verify all of the following after triaging scanner output.
|
|
117
158
|
|
|
118
|
-
|
|
159
|
+
### Semantic Targeting
|
|
119
160
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
161
|
+
- `a11y` is typed and converted on the correct semantic element.
|
|
162
|
+
- Wrappers and polymorphic components preserve their documented semantics.
|
|
163
|
+
- Configurable heading or tag choices reach the rendered element.
|
|
164
|
+
- Extension overrides preserve generated accessibility fields.
|
|
123
165
|
|
|
124
|
-
|
|
125
|
-
id?: string;
|
|
126
|
-
className?: string;
|
|
127
|
-
direction?: Direction;
|
|
128
|
-
a11y?: A11y; // ✅ All ARIA attributes through this prop
|
|
129
|
-
}
|
|
166
|
+
### Names and Visual Content
|
|
130
167
|
|
|
131
|
-
|
|
132
|
-
|
|
168
|
+
- Icon-only controls have configurable or stable system-owned names.
|
|
169
|
+
- Visually hidden text remains in the accessibility tree when needed.
|
|
170
|
+
- Meaningful images and icons are named; decorative repetitions are hidden.
|
|
171
|
+
- Accessibility strings are not hardcoded directly in JSX.
|
|
133
172
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
173
|
+
### Hidden Content and Focus
|
|
174
|
+
|
|
175
|
+
- Hidden or collapsed state agrees across visuals, focusability, and the
|
|
176
|
+
accessibility tree.
|
|
177
|
+
- Invisible content cannot receive focus unless the interaction requires it.
|
|
178
|
+
- Disabled and inert states behave consistently for keyboard and assistive
|
|
179
|
+
technology users.
|
|
180
|
+
|
|
181
|
+
### Interaction and Structure
|
|
182
|
+
|
|
183
|
+
- Interactive-looking elements use native semantics or complete role, focus,
|
|
184
|
+
and keyboard behavior.
|
|
185
|
+
- `onClick` on a non-interactive tag is checked, including conditional spreads.
|
|
186
|
+
- Nested interactive children and existing focus management are inspected
|
|
187
|
+
before semantics are added to a wrapper.
|
|
188
|
+
- Lists, headings, landmarks, tabs, menus, dialogs, and breadcrumbs keep their
|
|
189
|
+
intended structure.
|
|
190
|
+
- The root implements the direction contract, and every `ReactNode` slot
|
|
191
|
+
isolates nested content with `dir="ltr"`.
|
|
192
|
+
|
|
193
|
+
## Pre-Fix Checks for Non-Interactive Controls
|
|
194
|
+
|
|
195
|
+
Before adding `role="button"`, `tabIndex`, and keyboard handlers to a non-native
|
|
196
|
+
control, verify:
|
|
197
|
+
|
|
198
|
+
1. **Interactive children:** it cannot contain a link, button, input, or another
|
|
199
|
+
interactive component in the active branch.
|
|
200
|
+
2. **Focus ownership:** existing `tabIndex` or accessibility spreads have a
|
|
201
|
+
clear merge order and one authoritative source.
|
|
202
|
+
3. **Interaction condition:** the same condition gates pointer, focus, and
|
|
203
|
+
keyboard behavior and excludes disabled or editor-controlled states when
|
|
204
|
+
needed.
|
|
205
|
+
4. **Accessible-name scope:** the label intentionally names the component or
|
|
206
|
+
action and persists in every state where it is needed.
|
|
207
|
+
|
|
208
|
+
Prefer a native element when it preserves product behavior.
|
|
209
|
+
|
|
210
|
+
## Completion Criteria
|
|
211
|
+
|
|
212
|
+
The accessibility review is complete only when:
|
|
137
213
|
|
|
138
|
-
|
|
214
|
+
- both scanners start successfully;
|
|
215
|
+
- every finding is triaged;
|
|
216
|
+
- confirmed issues are fixed when safe;
|
|
217
|
+
- the manual review is complete; and
|
|
218
|
+
- both scanners are rerun on every changed `.tsx` or `.jsx` file.
|
|
139
219
|
|
|
220
|
+
Preserve visual and runtime behavior. Fix the semantic owner: root, named inner
|
|
221
|
+
part, shared primitive, or call site. Then return to the main workflow for the
|
|
222
|
+
Wix build, manifest generation, TypeScript check, and relevant project tests.
|
|
@@ -1,14 +1,22 @@
|
|
|
1
|
-
# Animated Components
|
|
1
|
+
# Animated Components
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
animation
|
|
5
|
-
|
|
3
|
+
Use this reference when the component's primary content is a **playable
|
|
4
|
+
animation**—a Lottie/JSON animation, an animated GIF/SVG, a canvas/WebGL loop,
|
|
5
|
+
or a video-like surface.
|
|
6
6
|
|
|
7
|
-
Every such component
|
|
7
|
+
Every such component must ship an on-stage **play/pause button**.
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
## Contents
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
- [Apply When](#apply-when)
|
|
12
|
+
- [Required Contract](#required-contract)
|
|
13
|
+
- [Define Props](#1-define-props)
|
|
14
|
+
- [Manage Playback State](#2-manage-playback-state)
|
|
15
|
+
- [Add the Play/Pause Button](#3-add-the-playpause-button)
|
|
16
|
+
- [Suppress Autoplay in `component.preview.tsx`](#4-suppress-autoplay-in-componentpreviewtsx)
|
|
17
|
+
- [Checklist](#checklist)
|
|
18
|
+
|
|
19
|
+
## Apply When
|
|
12
20
|
|
|
13
21
|
Apply automatically — without being asked — whenever the component has an
|
|
14
22
|
`autoPlay` prop **or** its primary content is a **startable / loopable**
|
|
@@ -22,25 +30,28 @@ animation a visitor would reasonably want to start or stop:
|
|
|
22
30
|
|
|
23
31
|
**Key rule:** If the component accepts an `autoPlay` prop — even if the
|
|
24
32
|
underlying mechanism is a `setInterval` advancing an index rather than a media
|
|
25
|
-
player
|
|
33
|
+
player, it must expose a play/pause button so visitors can stop the
|
|
26
34
|
auto-advancing behavior. "Autoplay" is a behavior contract, not an
|
|
27
35
|
implementation detail.
|
|
28
36
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
## What to add (checklist)
|
|
37
|
+
## Required Contract
|
|
32
38
|
|
|
33
|
-
1. **Props** — `autoPlay
|
|
39
|
+
1. **Props** — for a new component, use `autoPlay` when it can start
|
|
40
|
+
automatically, `loop` only when repeat behavior is supported, and
|
|
41
|
+
`pauseButtonVisibility` for the on-stage control. When editing, preserve
|
|
42
|
+
existing playback prop names and add only the missing safety contract.
|
|
34
43
|
2. **Playback state** — `isPlaying` + `handlePause` / `handleResume`
|
|
35
|
-
3. **Play/pause button** — overlay `<button>` with inline SVG icon
|
|
44
|
+
3. **Play/pause button** — overlay `<button>` with inline SVG icon and CSS
|
|
45
|
+
positioning; it must be a named part with `elementProps` wiring, a hover
|
|
46
|
+
design state, and a standalone `:focus-visible` keyboard indicator
|
|
36
47
|
4. **Modify `component.preview.tsx`** — suppress autoplay in editor design mode
|
|
37
48
|
5. **Respect `prefers-reduced-motion`** — suppress autoplay when the OS requests reduced motion
|
|
38
49
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
## 1. Props
|
|
50
|
+
## 1. Define Props
|
|
42
51
|
|
|
43
|
-
Playback controls are
|
|
52
|
+
Playback controls are behavior props. `pauseButtonVisibility` is the documented
|
|
53
|
+
exception to the usual visual-visibility rule because editor preview must be
|
|
54
|
+
able to force the safety control visible.
|
|
44
55
|
|
|
45
56
|
```typescript
|
|
46
57
|
import type { A11y, Direction } from '@wix/editor-react-types';
|
|
@@ -59,12 +70,17 @@ export interface MyAnimationProps {
|
|
|
59
70
|
|
|
60
71
|
/** Show play/pause button. Default `'showOnHover'`. */
|
|
61
72
|
pauseButtonVisibility?: 'showAlways' | 'showOnHover';
|
|
73
|
+
|
|
74
|
+
elementProps?: {
|
|
75
|
+
playButton?: { className?: string };
|
|
76
|
+
};
|
|
62
77
|
}
|
|
63
78
|
```
|
|
64
79
|
|
|
65
|
-
|
|
80
|
+
The example shows a looping animation. Omit `loop` when the component does not
|
|
81
|
+
support repeat behavior; do not add it only to match the example.
|
|
66
82
|
|
|
67
|
-
## 2. Playback
|
|
83
|
+
## 2. Manage Playback State
|
|
68
84
|
|
|
69
85
|
Track play/pause state with `useState`. Initialize it from `autoPlay` and the OS reduced-motion preference — when the visitor has requested reduced motion, the animation starts paused:
|
|
70
86
|
|
|
@@ -97,9 +113,7 @@ const handleResume = () => setIsPlaying(true);
|
|
|
97
113
|
|
|
98
114
|
Pass `isPlaying` to the animation renderer and toggle between `handlePause` / `handleResume` on button click.
|
|
99
115
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
## 3. Play/pause button
|
|
116
|
+
## 3. Add the Play/Pause Button
|
|
103
117
|
|
|
104
118
|
Create play/pause icons that visually match the component's style. Use simple recognizable shapes — a triangle for play, two rectangles for pause — implemented as inline SVG so there is no external icon dependency. Size, stroke, and fill should feel native to the component's design.
|
|
105
119
|
|
|
@@ -126,30 +140,54 @@ Position the button absolutely so it overlays the content without pushing other
|
|
|
126
140
|
/* e.g. background: rgba(255, 255, 255, 1); */
|
|
127
141
|
}
|
|
128
142
|
|
|
129
|
-
|
|
143
|
+
/* Keyboard indicator only: focus is not an editor design state on a non-input
|
|
144
|
+
control unless editable focus styling was explicitly requested. */
|
|
130
145
|
.playButton:focus-visible {
|
|
131
146
|
outline: 2px solid currentColor;
|
|
132
147
|
outline-offset: 2px;
|
|
133
148
|
}
|
|
134
149
|
```
|
|
135
150
|
|
|
151
|
+
Define stable system-owned labels outside JSX:
|
|
152
|
+
|
|
153
|
+
```ts
|
|
154
|
+
// constants.ts
|
|
155
|
+
export const ARIA_LABELS = {
|
|
156
|
+
playButton: 'Play animation',
|
|
157
|
+
pauseButton: 'Pause animation',
|
|
158
|
+
} as const;
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Set the visibility data attribute on the existing elected root, preserving its
|
|
162
|
+
full root contract:
|
|
163
|
+
|
|
164
|
+
```tsx
|
|
165
|
+
data-pause-button-visibility={pauseButtonVisibility ?? 'showOnHover'}
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
Wire the named part completely:
|
|
169
|
+
|
|
136
170
|
```tsx
|
|
137
|
-
{/* ✅ Named part: play/pause is always a named part — site owners can style it independently */}
|
|
138
171
|
<button
|
|
139
172
|
type="button"
|
|
140
|
-
|
|
173
|
+
{...elementProps?.playButton}
|
|
174
|
+
className={classNames(
|
|
175
|
+
'my-animation-play-button',
|
|
176
|
+
styles.playButton,
|
|
177
|
+
elementProps?.playButton?.className,
|
|
178
|
+
)}
|
|
141
179
|
onClick={isPlaying ? handlePause : handleResume}
|
|
142
|
-
aria-label={
|
|
180
|
+
aria-label={
|
|
181
|
+
isPlaying ? ARIA_LABELS.pauseButton : ARIA_LABELS.playButton
|
|
182
|
+
}
|
|
143
183
|
>
|
|
144
184
|
{isPlaying ? <PauseIcon /> : <PlayIcon />}
|
|
145
185
|
</button>
|
|
146
186
|
```
|
|
147
187
|
|
|
148
188
|
```css
|
|
149
|
-
/*
|
|
150
|
-
|
|
151
|
-
The button itself is a named part (classNames('...-play-button', styles.playButton))
|
|
152
|
-
and must carry both a global class and design-state selectors (see above). */
|
|
189
|
+
/* Narrow behavior-only exception documented in CSS-GUIDELINES.md. Keep editable
|
|
190
|
+
appearance on .playButton and use this relationship only for visibility. */
|
|
153
191
|
|
|
154
192
|
/* showOnHover (default) */
|
|
155
193
|
.root[data-pause-button-visibility="showOnHover"] .playButton {
|
|
@@ -165,37 +203,44 @@ Position the button absolutely so it overlays the content without pushing other
|
|
|
165
203
|
/* showAlways — no extra CSS needed; button is visible by default */
|
|
166
204
|
```
|
|
167
205
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
## 4. Modify `component.preview.tsx` for autoplay suppression
|
|
206
|
+
## 4. Suppress Autoplay in `component.preview.tsx`
|
|
171
207
|
|
|
172
|
-
|
|
208
|
+
The Wix CLI scaffold generates `component.preview.tsx`. For animated components,
|
|
209
|
+
modify its passthrough preview component without replacing the generated
|
|
210
|
+
defaults or fallback-placeholder wiring.
|
|
173
211
|
|
|
174
|
-
###
|
|
212
|
+
### Adapt the generated `component.preview.tsx`
|
|
175
213
|
|
|
176
|
-
|
|
214
|
+
Add `useIsEditMode` to the existing `@wix/react-component-utils` import. In the
|
|
215
|
+
generated preview component, replace only the passthrough return with the gated
|
|
216
|
+
props below. Keep the generated `withFallbackPlaceholder`, required-data fields,
|
|
217
|
+
root class, and `withDefaults` export unchanged.
|
|
177
218
|
|
|
178
219
|
```tsx
|
|
179
|
-
|
|
180
|
-
import MyComponent from './component';
|
|
181
|
-
import { useIsEditMode } from '@wix/react-component-utils';
|
|
182
|
-
|
|
183
|
-
export default function MyComponentPreview(
|
|
184
|
-
props: React.ComponentProps<typeof MyComponent>,
|
|
185
|
-
) {
|
|
220
|
+
const MyAnimationPreview: FC<ComponentProps<typeof Component>> = (props) => {
|
|
186
221
|
const isEditMode = useIsEditMode();
|
|
187
222
|
|
|
188
223
|
return (
|
|
189
|
-
<
|
|
224
|
+
<Component
|
|
190
225
|
{...props}
|
|
191
226
|
autoPlay={isEditMode ? false : props.autoPlay}
|
|
192
227
|
pauseButtonVisibility={isEditMode ? 'showAlways' : props.pauseButtonVisibility}
|
|
193
228
|
/>
|
|
194
229
|
);
|
|
195
|
-
}
|
|
230
|
+
};
|
|
196
231
|
```
|
|
197
232
|
|
|
198
|
-
In editor design mode (`isEditMode` is `true`) → `autoPlay` is forced to `false` and `pauseButtonVisibility` is forced to `'showAlways'` so the site owner can always see and interact with the button.
|
|
233
|
+
In editor design mode (`isEditMode` is `true`) → `autoPlay` is forced to `false` and `pauseButtonVisibility` is forced to `'showAlways'` so the site owner can always see and interact with the button.
|
|
199
234
|
In preview mode (`isEditMode` is `false`) → both use the user's configured values.
|
|
200
235
|
|
|
201
|
-
|
|
236
|
+
## Checklist
|
|
237
|
+
|
|
238
|
+
- [ ] Autoplaying or loopable primary content has an on-stage play/pause control.
|
|
239
|
+
- [ ] Autoplay and pause-control props use the documented contract; `loop` is
|
|
240
|
+
present only when repeat behavior is supported.
|
|
241
|
+
- [ ] Reduced motion starts paused and never restarts playback automatically.
|
|
242
|
+
- [ ] The play/pause button is a fully wired named part with a stable accessible name.
|
|
243
|
+
- [ ] Hover has a paired editor design state; `:focus-visible` remains a
|
|
244
|
+
standalone keyboard indicator.
|
|
245
|
+
- [ ] Hover-only visibility changes behavior, not the button's editable styling surface.
|
|
246
|
+
- [ ] The preview preserves generated wrappers and forces autoplay off in design mode.
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
# Branded / Themed Components
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
**
|
|
3
|
+
Use this reference only when the prompt explicitly requests a **branded**,
|
|
4
|
+
**themed**, or **brand-aware** component. Do not infer this requirement from a
|
|
5
|
+
generic request for polished styling.
|
|
5
6
|
|
|
6
|
-
|
|
7
|
+
## Rules
|
|
7
8
|
|
|
8
9
|
Import theme tokens from `@wix/react-component-schema/theme-variables.module.css`
|
|
9
10
|
using CSS Modules `@value`, then consume with `var()`.
|
|
@@ -24,6 +25,14 @@ using CSS Modules `@value`, then consume with `var()`.
|
|
|
24
25
|
|
|
25
26
|
**Body:** `wst-paragraph-1..3-font` / `wst-paragraph-1..3-color`
|
|
26
27
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
- Do not use `var(--wst-*)` directly; import the `@value` alias first.
|
|
29
|
+
- Do not use `@import`; CSS Modules resolves theme aliases through `@value`.
|
|
30
|
+
- Do not use `wst-base-1-color` for text. Prefer heading/paragraph color tokens,
|
|
31
|
+
or `wst-base-2-color` when a base contrast color is required.
|
|
32
|
+
|
|
33
|
+
## Checklist
|
|
34
|
+
|
|
35
|
+
- [ ] Theme values are imported from `theme-variables.module.css` with `@value`.
|
|
36
|
+
- [ ] Imported aliases are consumed through `var()`.
|
|
37
|
+
- [ ] Typography uses heading/paragraph font and color token pairs.
|
|
38
|
+
- [ ] Text colors remain legible on the selected background token.
|