@wix/agent-skills 1.23.0 → 1.25.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/README.md +1 -0
- package/package.json +2 -1
- package/skills/wix-app/SKILL.md +4 -1
- package/skills/wix-app/references/BUSINESS_MANAGER_THEME.md +108 -0
- package/skills/wix-app/references/BUSINESS_MANAGER_TOKENS.md +81 -0
- package/skills/wix-app/references/DASHBOARD_MODAL.md +41 -0
- package/skills/wix-app/references/DASHBOARD_PAGE.md +2 -0
- package/skills/wix-app/references/DASHBOARD_PLUGIN.md +19 -4
- package/skills/wix-app/references/EDITOR_REACT_COMPONENT.md +64 -50
- package/skills/wix-app/references/dashboard-page/DRAFT_TEMPLATE.md +5 -4
- package/skills/wix-app/references/dashboard-page/DRAFT_TEMPLATE_ROUTER.md +8 -7
- package/skills/wix-app/references/dashboard-page/DYNAMIC_PARAMETERS.md +21 -38
- package/skills/wix-app/references/editor-react-component/ACCESSIBILITY.md +4 -3
- package/skills/wix-app/references/editor-react-component/ANIMATED-COMPONENTS.md +28 -25
- package/skills/wix-app/references/editor-react-component/BRANDED-COMPONENTS.md +8 -2
- package/skills/wix-app/references/editor-react-component/COMPONENT-CONTRACT.md +12 -14
- package/skills/wix-app/references/editor-react-component/CSS-GUIDELINES.md +4 -3
- package/skills/wix-app/references/editor-react-component/DESIGN-STATES.md +66 -9
- package/skills/wix-app/references/editor-react-component/EDITOR-EXTENSION-CONFIGURATION.md +25 -0
- package/skills/wix-app/references/editor-react-component/OVERFLOW.md +146 -0
- package/skills/wix-app/references/editor-react-component/PARTS.md +6 -0
- package/skills/wix-app/scripts/scan-a11y-eslint.cjs +25 -1
- package/skills/wix-headless/SKILL.md +0 -1
- package/skills/wix-headless/references/CAPABILITIES.md +3 -3
- package/skills/wix-headless/references/DISCOVERY.md +1 -1
- package/skills/wix-headless/references/SDK_HANDOFF.md +1 -1
- package/skills/wix-headless/references/SEED.md +1 -1
- package/skills/wix-headless/references/SETUP.md +1 -1
- package/skills/wix-headless/references/inline-recipes/how-to-code-restaurant-reservations.md +1 -1
- package/skills/wix-headless/references/inline-recipes/setup-restaurant-experiences.md +2 -2
- package/skills/wix-headless/references/managed/AUTHENTICATION.md +3 -14
- package/skills/wix-headless/scripts/bootstrap.mjs +156 -0
- package/skills/{wix-headless-fast → wix-headless-kit}/SKILL.md +83 -64
- package/skills/{wix-headless-fast → wix-headless-kit}/cold-start/bootstrap.mjs +2 -2
- package/skills/{wix-headless-fast → wix-headless-kit}/cold-start/cold-start.md +26 -35
- package/skills/wix-headless-kit/guides/capabilities.md +76 -0
- package/skills/wix-headless-kit/guides/feedback.md +98 -0
- package/skills/{wix-headless-fast → wix-headless-kit}/guides/migration.md +20 -9
- package/skills/{wix-headless-fast → wix-headless-kit}/install/AGENTS.md +5 -2
- package/skills/{wix-headless-fast → wix-headless-kit}/install/attach.mjs +5 -2
- package/skills/wix-headless-kit/install/bootstrap.mjs +156 -0
- package/skills/{wix-headless-fast → wix-headless-kit}/install/check.mjs +2 -2
- package/skills/wix-headless-kit/install/context.mjs +169 -0
- package/skills/{wix-headless-fast → wix-headless-kit}/install/deploy.mjs +17 -4
- package/skills/{wix-headless-fast → wix-headless-kit}/install/setup.mjs +89 -55
- package/skills/{wix-headless-fast → wix-headless-kit}/install/templates.mjs +1 -1
- package/skills/wix-manage/SKILL.md +2 -8
- package/skills/wix-manage/references/cms/cms-dashboard-navigation.md +2 -2
- package/skills/wix-manage/references/cms/cms-data-items-crud.md +263 -31
- package/skills/wix-manage/references/cms/cms-publishing-flow.md +15 -15
- package/skills/wix-manage/references/cms/cms-schema-management.md +58 -7
- package/skills/wix-manage/references/sites/query-sites.md +1 -8
- package/skills/wix-auth/SKILL.md +0 -12
- package/skills/wix-auth/references/device-flow.md +0 -140
- package/skills/wix-headless-fast/install/context.mjs +0 -126
- package/skills/wix-manage/references/cms/cms-data-operations-extended.md +0 -263
- package/skills/wix-manage/references/cms/cms-references-and-relationships.md +0 -162
- /package/skills/{wix-headless-fast → wix-headless-kit}/guides/existing-site.md +0 -0
- /package/skills/{wix-headless-fast → wix-headless-kit}/guides/reference-mode.md +0 -0
- /package/skills/{wix-headless-fast → wix-headless-kit}/install/agents-md.mjs +0 -0
- /package/skills/{wix-headless-fast → wix-headless-kit}/install/lock.mjs +0 -0
|
@@ -136,49 +136,35 @@ This dashboard page manages dynamic parameters for an embedded script. The param
|
|
|
136
136
|
- Display the preview alongside the settings form using Layout and Cell components
|
|
137
137
|
- The preview should react to parameter changes in real-time
|
|
138
138
|
|
|
139
|
-
##
|
|
139
|
+
## Files to Generate
|
|
140
140
|
|
|
141
|
-
|
|
142
|
-
- src/extensions/dashboard/withProviders.tsx - Provider wrapper with WDS
|
|
143
|
-
- src/extensions/dashboard/pages/page.tsx - Dashboard page with parameter management (wrapped with withProviders)
|
|
144
|
-
- src/extensions/dashboard/components/site-popup-settings.tsx - Settings form component
|
|
145
|
-
- src/extensions/dashboard/types.ts - Type definitions
|
|
141
|
+
When dynamic parameters are present, generate all of these — the two wrapper files are not optional:
|
|
146
142
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
143
|
+
| File | Role |
|
|
144
|
+
| --- | --- |
|
|
145
|
+
| `dashboard/BusinessManagerTheme.tsx` | Theme wrapper — [BUSINESS_MANAGER_THEME.md § 2](../BUSINESS_MANAGER_THEME.md#2-the-wrapper--write-this-file-once-per-app) |
|
|
146
|
+
| `dashboard/withProviders.tsx` | Provider wrapper (below) |
|
|
147
|
+
| `dashboard/pages/page.tsx` | The page, exported wrapped in `withProviders` |
|
|
148
|
+
| `dashboard/types.ts` | Parameter type definitions |
|
|
149
|
+
| Component files | Settings forms, previews |
|
|
153
150
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
When dynamic parameters are present, you MUST generate these files:
|
|
157
|
-
1. src/extensions/dashboard/withProviders.tsx - Provider wrapper (REQUIRED for WDS)
|
|
158
|
-
2. src/extensions/dashboard/pages/page.tsx - The main dashboard page component
|
|
159
|
-
3. src/extensions/dashboard/types.ts - Type definitions for the parameters (if needed)
|
|
160
|
-
4. Any additional component files (settings forms, previews, etc.)
|
|
161
|
-
|
|
162
|
-
The withProviders.tsx is NOT optional - it must always be generated when there are dynamic parameters.
|
|
151
|
+
Parameters are saved as individual string fields, never as one JSON string, and converted back to their real types on load. Use `embeddedScripts` directly from `@wix/app-management`.
|
|
163
152
|
|
|
164
153
|
## Provider Wrapper Implementation
|
|
165
154
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
This file is REQUIRED to wrap dashboard components with the Wix Design System provider.
|
|
155
|
+
Generate `src/extensions/dashboard/withProviders.tsx`:
|
|
169
156
|
|
|
170
157
|
```typescript
|
|
171
158
|
import React from 'react';
|
|
172
|
-
import { WixDesignSystemProvider } from '@wix/design-system';
|
|
173
159
|
import { i18n } from '@wix/essentials';
|
|
160
|
+
import { BusinessManagerTheme } from './BusinessManagerTheme';
|
|
174
161
|
|
|
175
162
|
export default function withProviders<P extends {} = {}>(Component: React.FC<P>) {
|
|
176
163
|
return function DashboardProviders(props: P) {
|
|
177
|
-
const locale = i18n.getLocale();
|
|
178
164
|
return (
|
|
179
|
-
<
|
|
165
|
+
<BusinessManagerTheme locale={i18n.getLocale()}>
|
|
180
166
|
<Component {...props} />
|
|
181
|
-
</
|
|
167
|
+
</BusinessManagerTheme>
|
|
182
168
|
);
|
|
183
169
|
};
|
|
184
170
|
}
|
|
@@ -187,16 +173,16 @@ export default function withProviders<P extends {} = {}>(Component: React.FC<P>)
|
|
|
187
173
|
export { withProviders };
|
|
188
174
|
```
|
|
189
175
|
|
|
190
|
-
|
|
176
|
+
Business Manager passes none of the redesign through the extension's iframe, so a wrapper holding `WixDesignSystemProvider` alone renders the pre-redesign look while compiling and previewing cleanly. `features={{ newColorsBranding: true }}` predates the theme and does not substitute for it.
|
|
191
177
|
|
|
192
178
|
## Using Provider Wrapper
|
|
193
179
|
|
|
194
180
|
In your dashboard page component (page.tsx):
|
|
195
|
-
1.
|
|
181
|
+
1. `import withProviders from '../../withProviders';`
|
|
196
182
|
2. Import embeddedScripts from '@wix/app-management'
|
|
197
|
-
3.
|
|
198
|
-
4. Export
|
|
199
|
-
5.
|
|
183
|
+
3. Add no design-system providers in the page — `withProviders` owns them
|
|
184
|
+
4. Export wrapped: `export default withProviders(MyComponent);`
|
|
185
|
+
5. The component holds the Page and its content, not providers
|
|
200
186
|
|
|
201
187
|
Example structure:
|
|
202
188
|
```typescript
|
|
@@ -204,8 +190,7 @@ import { useEffect, useState, type FC } from 'react';
|
|
|
204
190
|
import { dashboard } from '@wix/dashboard';
|
|
205
191
|
import { embeddedScripts } from '@wix/app-management';
|
|
206
192
|
import { Page, Card, Button, ... } from '@wix/design-system';
|
|
207
|
-
import '
|
|
208
|
-
import withProviders from '../../withProviders';
|
|
193
|
+
import withProviders from '../../withProviders'; // owns the stylesheets and providers
|
|
209
194
|
|
|
210
195
|
const MyDashboardPage: FC = () => {
|
|
211
196
|
const [options, setOptions] = useState<MyScriptOptions>(defaultOptions);
|
|
@@ -253,9 +238,7 @@ export default withProviders(MyDashboardPage);
|
|
|
253
238
|
## Critical Notes
|
|
254
239
|
|
|
255
240
|
- Only implement UI for parameters that are relevant to your specific use case - ignore parameters that don't apply
|
|
256
|
-
- ALWAYS generate withProviders.tsx
|
|
257
|
-
- ALWAYS wrap the dashboard page export with withProviders()
|
|
258
|
-
- DO NOT use WixDesignSystemProvider directly in the dashboard page component - use withProviders instead
|
|
241
|
+
- ALWAYS generate `BusinessManagerTheme.tsx` and `withProviders.tsx`, and wrap the page export with `withProviders()` — no design-system providers in the page itself
|
|
259
242
|
- ALWAYS use embeddedScripts directly from '@wix/app-management'
|
|
260
243
|
- ALWAYS convert parameter values to strings when saving (embeddedScripts.embedScript must receive all string values in the parameters object)
|
|
261
244
|
- ALWAYS convert string parameters back to proper types when loading (e.g., 'true' -> true for booleans, string to number for numbers)
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
# Accessibility Implementation and Review
|
|
2
2
|
|
|
3
|
-
Use
|
|
4
|
-
run the review command once the JSX is complete.
|
|
3
|
+
Use while authoring; run the review after JSX is complete.
|
|
5
4
|
|
|
6
5
|
## Contents
|
|
7
6
|
|
|
@@ -41,7 +40,9 @@ function Toggle({ elementProps }: ToggleProps) {
|
|
|
41
40
|
|
|
42
41
|
return (
|
|
43
42
|
<button {...toggleProps} aria-label={toggleA11y?.ariaLabel ?? ARIA_LABELS.toggle}>
|
|
44
|
-
<
|
|
43
|
+
<svg aria-hidden="true" viewBox="0 0 16 16">
|
|
44
|
+
<path d="m3 6 5 5 5-5" fill="none" stroke="currentColor" />
|
|
45
|
+
</svg>
|
|
45
46
|
</button>
|
|
46
47
|
);
|
|
47
48
|
}
|
|
@@ -5,23 +5,9 @@ Use this reference when the component's primary content **auto-advances or plays
|
|
|
5
5
|
|
|
6
6
|
Every such component must ship an on-stage **play/pause button**.
|
|
7
7
|
|
|
8
|
-
## Contents
|
|
9
|
-
|
|
10
|
-
- [Apply When](#apply-when)
|
|
11
|
-
- [Required Contract](#required-contract)
|
|
12
|
-
- [Announce Manually Selected Parallel Content](#announce-manually-selected-parallel-content)
|
|
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
|
-
- [Edit the generated `component.preview.tsx`](#edit-the-generated-componentpreviewtsx)
|
|
18
|
-
- [Checklist](#checklist)
|
|
19
|
-
|
|
20
8
|
## Apply When
|
|
21
9
|
|
|
22
|
-
Apply
|
|
23
|
-
`autoPlay` prop **or** its primary content is a **startable / loopable**
|
|
24
|
-
animation a visitor would reasonably want to start or stop:
|
|
10
|
+
Apply whenever the component has `autoPlay` or startable/loopable primary content:
|
|
25
11
|
|
|
26
12
|
- Slideshow, carousel, slider, or gallery that advances slides/cards
|
|
27
13
|
- Lottie / JSON vector animations
|
|
@@ -94,8 +80,20 @@ export interface MyAnimationProps {
|
|
|
94
80
|
}
|
|
95
81
|
```
|
|
96
82
|
|
|
97
|
-
|
|
98
|
-
|
|
83
|
+
Omit `loop` when repeat is unsupported.
|
|
84
|
+
|
|
85
|
+
### Lottie / JSON source
|
|
86
|
+
|
|
87
|
+
For Lottie, `animationUrl?: string` is a JSON URL, not `VectorArt` (SVG).
|
|
88
|
+
This and its renderer are exceptions to the generic media/dependency rules in
|
|
89
|
+
`COMPONENT-CONTRACT.md`. Check `package.json`: use `lottie-web` if present,
|
|
90
|
+
otherwise add it as a runtime dependency. Import `lottie` and
|
|
91
|
+
`type AnimationItem` from it. In an effect, call
|
|
92
|
+
`lottie.loadAnimation({ container, renderer: 'svg', path: animationUrl,
|
|
93
|
+
loop, autoplay: false })`; keep the item in a ref, destroy it on cleanup,
|
|
94
|
+
and use `play()` / `pause()` when `isPlaying` changes. Browser work belongs in
|
|
95
|
+
effects. If no URL is supplied, bundle a valid local Lottie JSON asset and
|
|
96
|
+
import it with `?url` as the component default; a placeholder URL renders blank.
|
|
99
97
|
|
|
100
98
|
## 2. Manage Playback State
|
|
101
99
|
|
|
@@ -109,20 +107,22 @@ const reducedMotion = useReducedMotion();
|
|
|
109
107
|
|
|
110
108
|
const [isPlayOn, setIsPlayOn] = React.useState(() => (autoPlay ?? true) && !reducedMotion);
|
|
111
109
|
|
|
112
|
-
const
|
|
110
|
+
const previousAutoPlay = React.useRef(autoPlay);
|
|
113
111
|
React.useEffect(() => {
|
|
114
|
-
if (
|
|
115
|
-
|
|
116
|
-
|
|
112
|
+
if (previousAutoPlay.current !== autoPlay) {
|
|
113
|
+
setIsPlayOn((autoPlay ?? true) && !reducedMotion);
|
|
114
|
+
} else if (reducedMotion) {
|
|
115
|
+
setIsPlayOn(false);
|
|
117
116
|
}
|
|
118
|
-
|
|
119
|
-
}, [autoPlay]);
|
|
117
|
+
previousAutoPlay.current = autoPlay;
|
|
118
|
+
}, [autoPlay, reducedMotion]);
|
|
120
119
|
|
|
121
120
|
const handlePause = () => setIsPlayOn(false);
|
|
122
121
|
const handleResume = () => setIsPlayOn(true);
|
|
123
122
|
```
|
|
124
123
|
|
|
125
|
-
`reducedMotion` is
|
|
124
|
+
`reducedMotion` is runtime-only. Pause when the OS turns reduced motion on, but
|
|
125
|
+
do not restart when it turns off. Resume can still override the preference.
|
|
126
126
|
|
|
127
127
|
Derive runtime playback from `isPlayOn` plus only needed conditions. Without
|
|
128
128
|
another condition, use `const isPlaying = isPlayOn`. A carousel, slideshow,
|
|
@@ -140,7 +140,10 @@ clears `isStoppedByFocus`.
|
|
|
140
140
|
|
|
141
141
|
## 3. Add the Play/Pause Button
|
|
142
142
|
|
|
143
|
-
|
|
143
|
+
Use inline SVG icons: a triangle for play and two bars for pause. Declare
|
|
144
|
+
`--icon-size` and `--icon-color` on the button. Apply `var(--icon-size)` to the
|
|
145
|
+
SVG's CSS `width` and `height` (or React `style`), not raw SVG attributes;
|
|
146
|
+
set button `color: var(--icon-color)` and SVG `fill: currentColor`.
|
|
144
147
|
|
|
145
148
|
Position the button absolutely so it overlays the content without pushing other elements out of place:
|
|
146
149
|
|
|
@@ -28,8 +28,14 @@ using CSS Modules `@value`, then consume with `var()`.
|
|
|
28
28
|
- Do not use `var(--wst-*)` directly; import the `@value` alias first.
|
|
29
29
|
- Do not pass a fallback as `var()`'s second argument
|
|
30
30
|
- Do not use `@import`; CSS Modules resolves theme aliases through `@value`.
|
|
31
|
-
- Do not use `wst-base-1-color` for text
|
|
32
|
-
|
|
31
|
+
- Do not use `wst-base-1-color` for text on a light surface. Prefer
|
|
32
|
+
heading/paragraph color tokens for body text.
|
|
33
|
+
- Use matching control tokens: pair `wst-button-primary-background-color` with
|
|
34
|
+
`wst-button-primary-color` for a primary CTA (or the secondary pair for a
|
|
35
|
+
secondary CTA). Do not mix `wst-links-and-actions-color` with
|
|
36
|
+
`wst-base-2-color` as button background and text: they are unrelated tokens
|
|
37
|
+
and may fail contrast. Check the rendered contrast of every state, and choose
|
|
38
|
+
a different token pair or design if it fails.
|
|
33
39
|
|
|
34
40
|
## Checklist
|
|
35
41
|
|
|
@@ -3,17 +3,6 @@
|
|
|
3
3
|
Use this reference when defining props, defaults, named-part wiring, complex data,
|
|
4
4
|
or internal file boundaries.
|
|
5
5
|
|
|
6
|
-
## Contents
|
|
7
|
-
|
|
8
|
-
- [Public Props Contract](#public-props-contract)
|
|
9
|
-
- [Numeric Range Constraints](#numeric-range-constraints)
|
|
10
|
-
- [Named Parts and `elementProps`](#named-parts-and-elementprops)
|
|
11
|
-
- [Content and Data](#content-and-data)
|
|
12
|
-
- [Active-Item Components](#active-item-components)
|
|
13
|
-
- [Defaults and Resources](#defaults-and-resources)
|
|
14
|
-
- [Internal File Splitting](#internal-file-splitting)
|
|
15
|
-
- [Checklist](#checklist)
|
|
16
|
-
|
|
17
6
|
## Public Props Contract
|
|
18
7
|
|
|
19
8
|
Keep identity and platform contracts together with component-specific data and
|
|
@@ -54,6 +43,9 @@ Rules:
|
|
|
54
43
|
- Default to common optional SDK callbacks by capability; add specialized ones
|
|
55
44
|
when requested. Keep implementation handlers internal.
|
|
56
45
|
- Use `Array<T>`, not `T[]`, for exported arrays.
|
|
46
|
+
- A CTA with a real destination is a native link with that `href`. If it only
|
|
47
|
+
performs an action, use a native button. Never use `href="#"` as a fallback;
|
|
48
|
+
it creates a focusable link without a meaningful destination.
|
|
57
49
|
|
|
58
50
|
## Numeric Range Constraints
|
|
59
51
|
|
|
@@ -153,6 +145,7 @@ slides, steps). Skip for always-visible lists, multi-select, or multi-expand.
|
|
|
153
145
|
`@wix/react-component-utils`. The type argument must match the array prop name
|
|
154
146
|
exactly, and `defaultProps` must set the index to `0`.
|
|
155
147
|
- Render all bodies with `.map()`. Active body gets --active; inactive bodies get functional CSS visibility, aria-hidden, and inert.
|
|
148
|
+
- With React 18 types, spread `...(!isActive ? { inert: 'true' } : {})` onto an inactive body; this emits the boolean HTML attribute without a TypeScript prop error. Use the app's typecheck instead of a scratch TypeScript project.
|
|
156
149
|
- Provide keyboard navigation and the matching ARIA pattern.
|
|
157
150
|
|
|
158
151
|
```ts
|
|
@@ -184,11 +177,16 @@ media type, whether it is a top-level prop or a field in an array item. Name
|
|
|
184
177
|
the field for the media itself (`image`, `video`, `audio`, and so on), not for
|
|
185
178
|
one representation of it.
|
|
186
179
|
|
|
180
|
+
Common fields in the installed types: `Image` has required `url: string` and
|
|
181
|
+
optional `uri`, `alt`, `width`, `height`; `Link` has optional `href`, `target`
|
|
182
|
+
(`'_self' | '_blank'`), and `rel`. Use `image.url` for `<img src>`,
|
|
183
|
+
`image.alt` for its alternative text, and `link.href` for `<a href>`.
|
|
184
|
+
|
|
187
185
|
Do not represent media as a URL/source string or split its metadata across
|
|
188
186
|
primitive props. Preserve the media object through the public contract so the
|
|
189
|
-
component can consume all of its supported data.
|
|
190
|
-
|
|
191
|
-
|
|
187
|
+
component can consume all of its supported data. Inspect the installed media
|
|
188
|
+
type declaration only if a needed field is not covered here or a typecheck
|
|
189
|
+
reports an error.
|
|
192
190
|
|
|
193
191
|
## Defaults and Resources
|
|
194
192
|
|
|
@@ -56,6 +56,7 @@ that semantic element is the root. Do not wrap it just to host root props.
|
|
|
56
56
|
|
|
57
57
|
Use flat, top-level selectors. Each selector must target one class plus an
|
|
58
58
|
optional state pseudo-class or global state modifier.
|
|
59
|
+
Put state overrides before bare classes so the manifest keeps resting defaults.
|
|
59
60
|
|
|
60
61
|
```css
|
|
61
62
|
.heading {
|
|
@@ -103,7 +104,7 @@ Choose the simplest root shape that fits the component:
|
|
|
103
104
|
|
|
104
105
|
- column: `--display: flex; flex-direction: column`
|
|
105
106
|
- row: `--display: flex; flex-direction: row`
|
|
106
|
-
- split layout: `--display: grid; grid-template-columns:
|
|
107
|
+
- split layout: `--display: grid; grid-template-columns: repeat(2, minmax(0, 1fr))`
|
|
107
108
|
- responsive collection: `--display: grid; grid-template-columns: repeat(auto-fit, minmax(...))`
|
|
108
109
|
|
|
109
110
|
Do not hardcode the root's pixel dimensions. Installation defaults belong in
|
|
@@ -136,7 +137,7 @@ the extension file.
|
|
|
136
137
|
## Responsiveness and Direction
|
|
137
138
|
|
|
138
139
|
Respond to the component container, not the browser viewport. Prefer intrinsic
|
|
139
|
-
flex/grid sizing
|
|
140
|
+
flex/grid sizing and tracks that can shrink below content size. Do not add
|
|
140
141
|
viewport `@media` rules; Wix owns page breakpoints.
|
|
141
142
|
|
|
142
143
|
Use logical inline-axis properties so layout flips automatically in RTL:
|
|
@@ -171,7 +172,7 @@ Use this pattern:
|
|
|
171
172
|
|
|
172
173
|
.grid {
|
|
173
174
|
--columns: 3;
|
|
174
|
-
grid-template-columns: repeat(var(--columns), 1fr);
|
|
175
|
+
grid-template-columns: repeat(var(--columns), minmax(0, 1fr));
|
|
175
176
|
}
|
|
176
177
|
```
|
|
177
178
|
|
|
@@ -13,6 +13,7 @@ in the component's `.tsx` and `.module.css`.
|
|
|
13
13
|
- [Author CSS](#3-author-css)
|
|
14
14
|
- [Wire React](#4-wire-react)
|
|
15
15
|
- [Use Prop-Triggered States on the Root Only](#5-use-prop-triggered-states-on-the-root-only)
|
|
16
|
+
- [Expose Open/Collapsed Toggles](#6-expose-opencollapsed-toggles)
|
|
16
17
|
- [Checklist](#checklist)
|
|
17
18
|
|
|
18
19
|
## 1. Choose Supported States
|
|
@@ -24,6 +25,7 @@ in the component's `.tsx` and `.module.css`.
|
|
|
24
25
|
| Other interactive element whose editable focus appearance the user explicitly requests | `focus` |
|
|
25
26
|
| Disableable — `button`/`input`/`select`/`textarea`/`fieldset` or a disableable role | `disabled` (+ `invalid` for `input`/`select`/`textarea`) |
|
|
26
27
|
| Has a selectable/variant value in its data — `selected`/`active`/`current`/`open`/`expanded`/`checked`/`featured` | that custom state |
|
|
28
|
+
| Whole component opens/collapses (expandable panel, disclosure, dropdown, drawer), even when a click toggles it | root `isOpen` prop state — see §6 |
|
|
27
29
|
| None of the above | no states — resting style only |
|
|
28
30
|
|
|
29
31
|
An explicit `role` overrides the tag's implicit semantics: `<input role="button">`
|
|
@@ -51,7 +53,10 @@ nested (`card__row--selected`).
|
|
|
51
53
|
## 3. Author CSS
|
|
52
54
|
|
|
53
55
|
Put the resting value in the bare class; put only the state override in the
|
|
54
|
-
state selector.
|
|
56
|
+
state selector. When both set the same property, write the state selector
|
|
57
|
+
**before** the bare class. Manifest generation can otherwise record the state
|
|
58
|
+
value as the part's resting `defaultValue`, even though runtime CSS renders
|
|
59
|
+
correctly. The state selector still wins at runtime through its specificity.
|
|
55
60
|
|
|
56
61
|
- **Native design state** — pair the pseudo-class with the `:global` modifier.
|
|
57
62
|
Every exposed native state needs both selectors in the same rule; do not
|
|
@@ -63,17 +68,22 @@ state selector.
|
|
|
63
68
|
The bare selector is the short **module** class (`.cta`); the `:global(...)`
|
|
64
69
|
state class is the **prefixed** global one.
|
|
65
70
|
|
|
71
|
+
Check text contrast against every background it appears on, including resting,
|
|
72
|
+
hover, and selected states. Normal text needs at least 4.5:1; large text needs
|
|
73
|
+
3:1. Pale gray small text on white or a tinted selected row commonly fails.
|
|
74
|
+
The local static accessibility scan cannot measure rendered color contrast.
|
|
75
|
+
|
|
66
76
|
```css
|
|
77
|
+
.cta:global(.pricing-card-cta--hover),
|
|
78
|
+
.cta:hover {
|
|
79
|
+
background: #4f46e5;
|
|
80
|
+
}
|
|
67
81
|
.cta {
|
|
68
82
|
background: #6366f1;
|
|
69
83
|
font-family: 'Inter', sans-serif;
|
|
70
84
|
font-size: 14px;
|
|
71
85
|
color: #ffffff;
|
|
72
86
|
} /* resting */
|
|
73
|
-
.cta:global(.pricing-card-cta--hover),
|
|
74
|
-
.cta:hover {
|
|
75
|
-
background: #4f46e5;
|
|
76
|
-
}
|
|
77
87
|
.cta:global(.pricing-card-cta--disabled),
|
|
78
88
|
.cta:disabled {
|
|
79
89
|
opacity: 0.5;
|
|
@@ -91,7 +101,9 @@ state class is the **prefixed** global one.
|
|
|
91
101
|
- **Native** — render the correct interactive element (`<button>`, an
|
|
92
102
|
interactive `role`, or a handler). No custom state class is needed, but the
|
|
93
103
|
element must still satisfy the accessibility contract for its semantics.
|
|
94
|
-
- **Custom** — toggle the global state class from the element's data.
|
|
104
|
+
- **Custom** — toggle the global state class from the element's data. Every
|
|
105
|
+
state class toggled in TSX needs a matching `:global()` rule in §3; without
|
|
106
|
+
one the manifest generator silently drops the state.
|
|
95
107
|
- **Inner elements** — every named inner element gets an `elementProps` entry;
|
|
96
108
|
spread it so editor-driven states reach it. On a raw HTML element also merge
|
|
97
109
|
`elementProps?.<key>.className` inline; on a skill-built sub-component the
|
|
@@ -155,8 +167,9 @@ Rules:
|
|
|
155
167
|
`props: { isFeatured: true }` as the trigger.
|
|
156
168
|
- To give the state styling, pair the root's **module** class with a prefixed
|
|
157
169
|
`:global(.<component-name>--<state>)` rule. With a matching class the manifest
|
|
158
|
-
entry carries that `className
|
|
159
|
-
|
|
170
|
+
entry carries that `className` and the editor lists it with the design-panel
|
|
171
|
+
states; with none it is props-only and appears in the on-stage state picker,
|
|
172
|
+
which sets the prop. An open/collapsed toggle must stay props-only (§6).
|
|
160
173
|
|
|
161
174
|
```css
|
|
162
175
|
.pricingCard:global(.pricing-card--is-featured) {
|
|
@@ -166,7 +179,48 @@ Rules:
|
|
|
166
179
|
|
|
167
180
|
Prefer a native state (interactive markup) or a class trigger (per-item data
|
|
168
181
|
such as `row.selected`) whenever one fits — those are the common cases and work
|
|
169
|
-
at any depth. Reach for a prop trigger only for a root-level boolean switch
|
|
182
|
+
at any depth. Reach for a prop trigger only for a root-level boolean switch
|
|
183
|
+
or an open/collapsed toggle (§6).
|
|
184
|
+
|
|
185
|
+
## 6. Expose Open/Collapsed Toggles
|
|
186
|
+
|
|
187
|
+
For a component that opens or collapses, expose its state to the editor even
|
|
188
|
+
when a click toggles it. `useState` alone gives the manifest no state picker.
|
|
189
|
+
For one-of-many item bodies, use the active-item contract instead.
|
|
190
|
+
|
|
191
|
+
- Add `isOpen?: ElementState<boolean>` and set `isOpen: false` in
|
|
192
|
+
`defaultProps`.
|
|
193
|
+
- Seed and resync internal state from the prop; clicks update internal state.
|
|
194
|
+
- Always render the collapsible content; hide it with CSS plus `aria-hidden`
|
|
195
|
+
and `inert` when closed. Never mount it with `open && …`.
|
|
196
|
+
- Style the open state with inner-part classes
|
|
197
|
+
(`<component-name>-content--open`) and matching `:global()` rules, not only
|
|
198
|
+
inline styles or refs measured during render.
|
|
199
|
+
- Keep the root state props-only for the on-stage picker (§5).
|
|
200
|
+
|
|
201
|
+
```tsx
|
|
202
|
+
const [open, setOpen] = React.useState(Boolean(isOpen));
|
|
203
|
+
React.useEffect(() => setOpen(Boolean(isOpen)), [isOpen]);
|
|
204
|
+
|
|
205
|
+
<div
|
|
206
|
+
{...elementProps?.content}
|
|
207
|
+
aria-hidden={!open}
|
|
208
|
+
{...(!open && { inert: '' })}
|
|
209
|
+
className={classNames(
|
|
210
|
+
'info-panel-content',
|
|
211
|
+
styles.content,
|
|
212
|
+
open && 'info-panel-content--open',
|
|
213
|
+
elementProps?.content?.className,
|
|
214
|
+
)}
|
|
215
|
+
>
|
|
216
|
+
<p>{text}</p>
|
|
217
|
+
</div>
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
```css
|
|
221
|
+
.content { display: none; }
|
|
222
|
+
.content:global(.info-panel-content--open) { display: block; }
|
|
223
|
+
```
|
|
170
224
|
|
|
171
225
|
## Checklist
|
|
172
226
|
|
|
@@ -176,4 +230,7 @@ at any depth. Reach for a prop trigger only for a root-level boolean switch.
|
|
|
176
230
|
- [ ] Non-input controls retain a standalone `:focus-visible` keyboard indicator.
|
|
177
231
|
- [ ] Custom state classes are flat, global, and prefixed by component and part.
|
|
178
232
|
- [ ] Named inner parts spread and merge their `elementProps` entry.
|
|
233
|
+
- [ ] Every state class toggled in TSX has a matching `:global()` CSS rule.
|
|
179
234
|
- [ ] `ElementState<boolean>` is used only for a component-level root state.
|
|
235
|
+
- [ ] An open/collapsed component exposes a props-only `isOpen` root state,
|
|
236
|
+
syncs internal state from it, and always renders its content.
|
|
@@ -9,12 +9,17 @@ generation rewrites
|
|
|
9
9
|
For a new component, complete the scaffolded installation and layout fields.
|
|
10
10
|
For an existing component, change only the sizing, installation, or manifest
|
|
11
11
|
behavior requested by the user; preserve every other extension field.
|
|
12
|
+
Use the current scaffold's field shape and the values below. Inspect installed
|
|
13
|
+
`@wix/astro` or schema types only if a related typecheck or build error requires it.
|
|
14
|
+
Normal component setup needs no `ELEMENT_TYPE` or `DATA_TYPE` lookup: the
|
|
15
|
+
generated `editorElement` and props manifest supply those details.
|
|
12
16
|
|
|
13
17
|
## Contents
|
|
14
18
|
|
|
15
19
|
- [Preserve the Extension Shape](#preserve-the-extension-shape)
|
|
16
20
|
- [Choose Initial Height](#choose-initial-height)
|
|
17
21
|
- [Choose Resize Direction](#choose-resize-direction)
|
|
22
|
+
- [Values](#values)
|
|
18
23
|
- [Checklist](#checklist)
|
|
19
24
|
|
|
20
25
|
## Preserve the Extension Shape
|
|
@@ -53,6 +58,12 @@ should fit content, use `content`.
|
|
|
53
58
|
|
|
54
59
|
Allow an axis only when dragging it produces a meaningful result.
|
|
55
60
|
|
|
61
|
+
For each allowed axis, implement what happens when content no longer fits.
|
|
62
|
+
Content height must grow after wrapping or changing items. A bounded height
|
|
63
|
+
needs a fitting layout or a deliberate accessible scroll region. Installation
|
|
64
|
+
defaults alone do not prevent overflow after resizing. Do not rely on native
|
|
65
|
+
container overflow controls for a custom component's internal DOM.
|
|
66
|
+
|
|
56
67
|
| Value | Use when |
|
|
57
68
|
| --- | --- |
|
|
58
69
|
| `horizontalAndVertical` | Content meaningfully fills both axes; default for framed visuals and most layouts |
|
|
@@ -61,11 +72,25 @@ Allow an axis only when dragging it produces a meaningful result.
|
|
|
61
72
|
| `aspectRatio` | Distortion would break the component's identity |
|
|
62
73
|
| `none` | A parent fully owns size; do not use for a top-level component |
|
|
63
74
|
|
|
75
|
+
## Values
|
|
76
|
+
|
|
77
|
+
Every value the scaffold uses comes from `LAYOUT` in
|
|
78
|
+
`@wix/react-component-schema`; do not search `node_modules` for them.
|
|
79
|
+
|
|
80
|
+
| Field | Values |
|
|
81
|
+
| --- | --- |
|
|
82
|
+
| `layout.resizeDirection` (`LAYOUT.RESIZE_DIRECTION`) | `horizontal`, `vertical`, `horizontalAndVertical`, `aspectRatio`, `none` |
|
|
83
|
+
| `layout.contentResizeDirection` (`LAYOUT.CONTENT_RESIZE_DIRECTION`) | `horizontal`, `vertical`, `horizontalAndVertical`, `none`: the axes along which content growth resizes the component |
|
|
84
|
+
| `initialSize.{width,height}.sizingType` (`LAYOUT.SIZING_TYPE`) | `content`, `pixels`, `stretched` |
|
|
85
|
+
| `installation.staticContainer` | `'HOMEPAGE'`, `'GLOBAL_PAGE'` |
|
|
86
|
+
|
|
64
87
|
Edit the scaffolded `layout`, `installation`, and `resources` fields in place;
|
|
65
88
|
do not reconstruct the extension from an example. For a new component, add
|
|
66
89
|
`staticContainer: 'HOMEPAGE'`. For an existing component, preserve its current
|
|
67
90
|
`staticContainer` value unless the request explicitly changes installation
|
|
68
91
|
behavior.
|
|
92
|
+
The scaffold's `installation` object accepts `staticContainer` next to
|
|
93
|
+
`initialSize`; add the literal above without searching `@wix/astro` types.
|
|
69
94
|
|
|
70
95
|
## Checklist
|
|
71
96
|
|