@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,519 +1,223 @@
|
|
|
1
|
-
# CSS
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
##
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
// ✅ Root: global string + module class + consumer className
|
|
37
|
-
// (a <div> here only because this component lays out several sibling parts)
|
|
38
|
-
<div className={classNames(className, 'profile-card', styles.root)} id={id}>
|
|
39
|
-
|
|
40
|
-
{/* ✅ Named part: prefixed global string + short module class */}
|
|
41
|
-
<h2 className={classNames('profile-card-heading', styles.heading)}>{heading}</h2>
|
|
42
|
-
|
|
43
|
-
{/* ✅ Named part: interactive elements always get both classes */}
|
|
44
|
-
<button type="button" className={classNames('profile-card-cta', styles.cta)}>
|
|
45
|
-
{ctaLabel}
|
|
46
|
-
</button>
|
|
47
|
-
|
|
48
|
-
{/* ✅ Non-part layout wrapper: module class only */}
|
|
49
|
-
<div className={styles.contentWrapper}>
|
|
50
|
-
<span className={classNames('profile-card-label', styles.label)}>{label}</span>
|
|
51
|
-
</div>
|
|
52
|
-
</div>
|
|
53
|
-
|
|
54
|
-
// ✅ Internal sub-components — same pattern on part slots
|
|
55
|
-
<CardHeader className={classNames('profile-card-header', styles.header)}>
|
|
56
|
-
<CardTitle className={classNames('profile-card-title', styles.title)}>{title}</CardTitle>
|
|
57
|
-
</CardHeader>
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
A component that reduces to one control is the other shape, and it has exactly one
|
|
61
|
-
part — its root ([`PARTS.md`](PARTS.md) Step 0). The text it renders and any decoration
|
|
62
|
-
stay inside that root, on module classes:
|
|
1
|
+
# CSS Guidelines
|
|
2
|
+
|
|
3
|
+
Use these rules for the scaffolded `<component-name>.module.css` file and any
|
|
4
|
+
colocated CSS Modules owned by internal sub-components. Keep existing visual
|
|
5
|
+
decisions outside the request unchanged. These rules keep the component
|
|
6
|
+
editable by zero config, responsive to its Wix-owned container, and safe in
|
|
7
|
+
both LTR and RTL layouts.
|
|
8
|
+
|
|
9
|
+
## Contents
|
|
10
|
+
|
|
11
|
+
- [Classes and Named Parts](#classes-and-named-parts)
|
|
12
|
+
- [Selector Rules](#selector-rules)
|
|
13
|
+
- [Root Layout](#root-layout)
|
|
14
|
+
- [Sizing Through the Tree](#sizing-through-the-tree)
|
|
15
|
+
- [Responsiveness and Direction](#responsiveness-and-direction)
|
|
16
|
+
- [Editable Values](#editable-values)
|
|
17
|
+
- [Interaction and Motion](#interaction-and-motion)
|
|
18
|
+
- [Default Visual Quality](#default-visual-quality)
|
|
19
|
+
- [Checklist](#checklist)
|
|
20
|
+
|
|
21
|
+
## Classes and Named Parts
|
|
22
|
+
|
|
23
|
+
Apply classes with `classnames`:
|
|
24
|
+
|
|
25
|
+
| Element | Classes |
|
|
26
|
+
| --- | --- |
|
|
27
|
+
| Elected root | `'<component-name>'`, `styles.root`, incoming `className`, fallback-direction class |
|
|
28
|
+
| Named inner part | `'<component-name>-<part-name>'`, its module class, injected `elementProps` class |
|
|
29
|
+
| Structural/decorative non-part | Module class only |
|
|
30
|
+
|
|
31
|
+
The global class lets zero config create an editor element. Prefix every inner
|
|
32
|
+
part with the component name to prevent collisions between components. The
|
|
33
|
+
module class carries the component's default CSS. Preserve the scaffolded root
|
|
34
|
+
pattern. For a new named part, add only the wiring the scaffold cannot infer:
|
|
35
|
+
spread its `elementProps` entry and merge the injected class.
|
|
63
36
|
|
|
64
37
|
```tsx
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
38
|
+
<h2
|
|
39
|
+
{...elementProps?.heading}
|
|
40
|
+
className={classNames(
|
|
41
|
+
'profile-card-heading',
|
|
42
|
+
styles.heading,
|
|
43
|
+
elementProps?.heading?.className,
|
|
44
|
+
)}
|
|
71
45
|
>
|
|
72
|
-
{
|
|
73
|
-
|
|
74
|
-
{/* ✅ Decoration: module class only, out of the a11y tree, not a part */}
|
|
75
|
-
<span className={styles.burst} aria-hidden="true" />
|
|
76
|
-
</button>
|
|
46
|
+
{heading}
|
|
47
|
+
</h2>
|
|
77
48
|
```
|
|
78
49
|
|
|
79
|
-
|
|
50
|
+
If a component reduces to one meaningful control, link, media surface, or list,
|
|
51
|
+
that semantic element is the root. Do not wrap it just to host root props.
|
|
80
52
|
|
|
81
|
-
|
|
82
|
-
rule. Compound selectors (`.a.b`), descendant
|
|
83
|
-
selectors (`.a .b`), child combinators (`.a > .b`), sibling
|
|
84
|
-
combinators (`.a + .b`), tag selectors, and CSS nesting (the `&`
|
|
85
|
-
syntax) are not permitted in component CSS.
|
|
53
|
+
## Selector Rules
|
|
86
54
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
either two elements share a rule or one element's appearance depends
|
|
90
|
-
on context — either way the editor cannot decide which rule to
|
|
91
|
-
modify when a user changes a property. CSS nesting compiles to
|
|
92
|
-
descendant selectors and has the same effect.
|
|
93
|
-
|
|
94
|
-
A state modifier on the element's own class (`.title:hover`,
|
|
95
|
-
`.title:global(.profile-card-title--featured)`) is allowed — see [`DESIGN-STATES.md`](DESIGN-STATES.md).
|
|
55
|
+
Use flat, top-level selectors. Each selector must target one class plus an
|
|
56
|
+
optional state pseudo-class or global state modifier.
|
|
96
57
|
|
|
97
58
|
```css
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
}
|
|
101
|
-
.title {
|
|
102
|
-
}
|
|
103
|
-
.content {
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
/* ❌ Compound selector — rule applies only when both classes match the same element */
|
|
107
|
-
.profile-card.featured {
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
/* ❌ Descendant selector — rule depends on ancestor structure */
|
|
111
|
-
.profile-card .title {
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
/* ❌ Child combinator — rule depends on direct parent */
|
|
115
|
-
.profile-card > .content {
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
/* ❌ Sibling combinator — rule depends on a sibling element */
|
|
119
|
-
.title + .subtitle {
|
|
59
|
+
.heading {
|
|
60
|
+
color: #1e293b;
|
|
120
61
|
}
|
|
121
62
|
|
|
122
|
-
|
|
123
|
-
.
|
|
124
|
-
|
|
125
|
-
color: black;
|
|
126
|
-
}
|
|
63
|
+
.cta:global(.profile-card-cta--hover),
|
|
64
|
+
.cta:hover {
|
|
65
|
+
background: #4f46e5;
|
|
127
66
|
}
|
|
128
67
|
```
|
|
129
68
|
|
|
130
|
-
|
|
69
|
+
Do not use compound selectors, tag selectors, child/sibling combinators, or CSS
|
|
70
|
+
nesting for editable styling. They make an element's editor surface depend on
|
|
71
|
+
DOM context.
|
|
131
72
|
|
|
132
|
-
|
|
73
|
+
Narrow exception: a relationship selector may control behavior-only visibility
|
|
74
|
+
when the behavior requires ancestor state and the rule does not define editable
|
|
75
|
+
appearance. A hover-revealed play/pause control is the canonical case. Keep all
|
|
76
|
+
of the control's size, color, border, typography, and state styling on its own
|
|
77
|
+
single-class rules.
|
|
133
78
|
|
|
134
|
-
|
|
135
|
-
`box-sizing: border-box`. The component never assumes a specific
|
|
136
|
-
pixel size for its outer box.
|
|
79
|
+
## Root Layout
|
|
137
80
|
|
|
138
|
-
|
|
139
|
-
dimensions aren't known at authoring time. A root with hardcoded
|
|
140
|
-
width or height overflows or leaves gaps inside its slot.
|
|
81
|
+
The root must fill the available inline size and use border-box sizing:
|
|
141
82
|
|
|
142
83
|
```css
|
|
143
|
-
|
|
144
|
-
|
|
84
|
+
.root {
|
|
85
|
+
--display: flex;
|
|
145
86
|
width: 100%;
|
|
146
|
-
height: 100%;
|
|
147
87
|
box-sizing: border-box;
|
|
148
88
|
}
|
|
149
89
|
```
|
|
150
90
|
|
|
151
|
-
|
|
91
|
+
Add `height: 100%` only when the editor extension gives the component a pixel
|
|
92
|
+
height or the requested behavior requires a bounded height. Omit it when the
|
|
93
|
+
extension uses `LAYOUT.SIZING_TYPE.content`; the component's content must then
|
|
94
|
+
establish its block size.
|
|
95
|
+
|
|
96
|
+
Set `--display` on the root; do not set root `display` directly. The platform
|
|
97
|
+
resolves and overrides this custom property. Inner elements use `display`
|
|
98
|
+
normally.
|
|
99
|
+
|
|
100
|
+
Choose the simplest root shape that fits the component:
|
|
101
|
+
|
|
102
|
+
- column: `--display: flex; flex-direction: column`
|
|
103
|
+
- row: `--display: flex; flex-direction: row`
|
|
104
|
+
- split layout: `--display: grid; grid-template-columns: 1fr 1fr`
|
|
105
|
+
- responsive collection: `--display: grid; grid-template-columns: repeat(auto-fit, minmax(...))`
|
|
152
106
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
wrapper collapses the entire subtree to intrinsic size.
|
|
107
|
+
Do not hardcode the root's pixel dimensions. Installation defaults belong in
|
|
108
|
+
the extension file.
|
|
156
109
|
|
|
157
|
-
|
|
158
|
-
on children that should grow, and `flex: 0 0 auto` on children that
|
|
159
|
-
should stay fixed-size.
|
|
110
|
+
## Sizing Through the Tree
|
|
160
111
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
112
|
+
- Put `box-sizing: border-box` on every component selector.
|
|
113
|
+
- In a bounded axis, use `flex: 1` with `min-width: 0` or `min-height: 0` for
|
|
114
|
+
children that grow.
|
|
115
|
+
- Use `flex: 0 0 auto` for controls that retain intrinsic size.
|
|
116
|
+
- Ensure every wrapper between the root and bounded growing content
|
|
117
|
+
participates in the sizing chain. Do not create a block-axis sizing chain for
|
|
118
|
+
a content-height component.
|
|
164
119
|
|
|
165
120
|
```css
|
|
166
|
-
|
|
167
|
-
|
|
121
|
+
.content {
|
|
122
|
+
box-sizing: border-box;
|
|
168
123
|
display: flex;
|
|
169
124
|
flex: 1;
|
|
170
125
|
min-width: 0;
|
|
171
126
|
}
|
|
172
127
|
|
|
173
|
-
/* ✅ Do: fixed child keeps intrinsic size */
|
|
174
128
|
.control {
|
|
175
|
-
flex: 0 0 auto;
|
|
176
|
-
}
|
|
177
|
-
```
|
|
178
|
-
|
|
179
|
-
### Set `box-sizing: border-box` on every selector
|
|
180
|
-
|
|
181
|
-
Apply `box-sizing: border-box` to every class in component CSS, not
|
|
182
|
-
just the root. The default `content-box` is never wanted in this
|
|
183
|
-
codebase.
|
|
184
|
-
|
|
185
|
-
**Why:** the editor exposes padding and border-width as live
|
|
186
|
-
controls. With `content-box`, increasing either grows the element's
|
|
187
|
-
outer box, which makes neighbouring elements visibly shift while the
|
|
188
|
-
user is dragging a slider — the component "shakes" in the editor.
|
|
189
|
-
`border-box` keeps the outer dimension stable; padding and border
|
|
190
|
-
eat into the existing box instead, so the layout stays still while
|
|
191
|
-
the user tunes values.
|
|
192
|
-
|
|
193
|
-
```css
|
|
194
|
-
/* ✅ Do: border-box — outer size stays stable while the editor tunes padding and border */
|
|
195
|
-
.profile-card,
|
|
196
|
-
.title,
|
|
197
|
-
.button {
|
|
198
129
|
box-sizing: border-box;
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
/* ❌ content-box — outer size grows when the editor adjusts padding or border */
|
|
202
|
-
.profile-card {
|
|
203
|
-
box-sizing: content-box; /* the default — don't rely on it */
|
|
130
|
+
flex: 0 0 auto;
|
|
204
131
|
}
|
|
205
132
|
```
|
|
206
133
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
Layout responds to the size of the component's parent, not to the
|
|
210
|
-
browser viewport. Use intrinsic flex/grid sizing (`auto-fit`,
|
|
211
|
-
`minmax(...)`, `1fr`) and `clamp()` for fluid scaling. `@media`
|
|
212
|
-
queries keyed on viewport dimensions (`width`, `height`,
|
|
213
|
-
`orientation`) are not permitted in component CSS.
|
|
214
|
-
|
|
215
|
-
**Why:** the Wix editor owns viewport-level breakpoints. A component
|
|
216
|
-
that branches on viewport width competes with the editor's
|
|
217
|
-
responsiveness model and renders the same container size differently
|
|
218
|
-
across viewports, breaking the editor's WYSIWYG contract.
|
|
219
|
-
|
|
220
|
-
```css
|
|
221
|
-
/* ✅ Do: Container-driven sizing — adapts to the slot, not the viewport */
|
|
222
|
-
.card-grid {
|
|
223
|
-
display: grid;
|
|
224
|
-
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
|
225
|
-
gap: clamp(1rem, 2.5vw, 2rem);
|
|
226
|
-
}
|
|
134
|
+
## Responsiveness and Direction
|
|
227
135
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
grid-template-columns: 1fr;
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
```
|
|
136
|
+
Respond to the component container, not the browser viewport. Prefer intrinsic
|
|
137
|
+
flex/grid sizing, `minmax()`, `auto-fit`, `1fr`, and `clamp()`. Do not add
|
|
138
|
+
viewport `@media` rules; Wix owns page breakpoints.
|
|
235
139
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
For any property that should flip between LTR and RTL — horizontal
|
|
239
|
-
margin, padding, border, positional offset — use logical properties
|
|
240
|
-
keyed on the inline axis: `margin-inline`, `margin-inline-start`,
|
|
241
|
-
`margin-inline-end`, `padding-inline`, `padding-inline-start`,
|
|
242
|
-
`padding-inline-end`, `border-inline-start`, `border-inline-end`,
|
|
243
|
-
`inset-inline-start`, `inset-inline-end`. Do not use `margin-left` /
|
|
244
|
-
`margin-right`, `padding-left` / `padding-right`, `border-left` /
|
|
245
|
-
`border-right`, `left`, or `right`.
|
|
246
|
-
|
|
247
|
-
Block-axis properties (`margin-top`, `margin-bottom`, `padding-top`,
|
|
248
|
-
`padding-bottom`, `border-top`, `border-bottom`, `top`, `bottom`)
|
|
249
|
-
stay as physical properties — they don't flip with text direction
|
|
250
|
-
in horizontal writing modes, which is what site components ship in.
|
|
251
|
-
|
|
252
|
-
**Why:** the Wix editor lets the site owner switch a site's text
|
|
253
|
-
direction between LTR and RTL. Logical inline properties flip
|
|
254
|
-
automatically with `direction: rtl` set by an ancestor, so one CSS
|
|
255
|
-
file produces correct layouts in both directions. Physical
|
|
256
|
-
left/right properties stay locked regardless of direction, which
|
|
257
|
-
breaks RTL layouts (icons end up on the wrong side of text, padding
|
|
258
|
-
piles up on the wrong edge, sticky offsets point the wrong way).
|
|
140
|
+
Use logical inline-axis properties so layout flips automatically in RTL:
|
|
259
141
|
|
|
260
142
|
```css
|
|
261
|
-
|
|
262
|
-
.profile-card {
|
|
143
|
+
.content {
|
|
263
144
|
padding-inline: 24px;
|
|
264
145
|
margin-inline-start: 8px;
|
|
265
|
-
border-inline-start:
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
/* ❌ Don't: Physical left/right — stays locked in RTL and breaks the layout */
|
|
269
|
-
.profile-card {
|
|
270
|
-
padding-left: 24px;
|
|
271
|
-
padding-right: 24px;
|
|
272
|
-
margin-left: 8px;
|
|
273
|
-
border-left: 4px solid currentColor;
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
/* ✅ Do: Block axis stays physical — top/bottom don't flip with direction */
|
|
277
|
-
.banner {
|
|
278
|
-
position: sticky;
|
|
279
|
-
top: 0;
|
|
280
|
-
padding-block: 12px;
|
|
281
|
-
}
|
|
282
|
-
```
|
|
283
|
-
|
|
284
|
-
### Set the root layout via `--display`, never `display`
|
|
285
|
-
|
|
286
|
-
The root rule declares `--display: <value>` and does not set
|
|
287
|
-
`display` itself. The platform reads `--display` and applies the
|
|
288
|
-
resolved `display` value at runtime. This rule applies to the root
|
|
289
|
-
selector only — inner element classes set `display` directly as
|
|
290
|
-
normal.
|
|
291
|
-
|
|
292
|
-
**Why:** the editor toggles a component's visibility (and other
|
|
293
|
-
display modes) by overriding the `--display` custom property on the
|
|
294
|
-
root. If the root rule also sets `display` directly, that
|
|
295
|
-
declaration wins over the platform's override and the editor has to
|
|
296
|
-
rewrite the rule to take effect, which is fragile. Inner elements
|
|
297
|
-
aren't toggled this way, so they use `display` normally.
|
|
298
|
-
|
|
299
|
-
```css
|
|
300
|
-
/* ✅ Do: Root declares --display only — platform applies it, editor can override */
|
|
301
|
-
.profile-card {
|
|
302
|
-
--display: flex;
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
/* ❌ Don't: Root sets display directly — competes with the platform override */
|
|
306
|
-
.profile-card {
|
|
307
|
-
--display: flex;
|
|
308
|
-
display: var(--display);
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
/* ✅ Do: Inner elements set display normally — the --display rule is root-only */
|
|
312
|
-
.header {
|
|
313
|
-
display: flex;
|
|
314
|
-
align-items: center;
|
|
315
|
-
}
|
|
316
|
-
```
|
|
317
|
-
|
|
318
|
-
### Choose one of four layout shapes for the component root
|
|
319
|
-
|
|
320
|
-
A component's root layout typically fits one of four shapes — reach
|
|
321
|
-
for the simplest one that satisfies the design.
|
|
322
|
-
|
|
323
|
-
**Why:** a small, shared vocabulary of layouts produces predictable
|
|
324
|
-
manifests and predictable editor behavior. The editor's
|
|
325
|
-
auto-generated controls (gap, padding, alignment) are tuned for
|
|
326
|
-
these shapes.
|
|
327
|
-
|
|
328
|
-
```css
|
|
329
|
-
/* ✅ Do: Single column — stacked content (profile card, pricing card, CTA block) */
|
|
330
|
-
.profile-card {
|
|
331
|
-
--display: flex;
|
|
332
|
-
flex-direction: column;
|
|
333
|
-
align-items: center;
|
|
334
|
-
text-align: center;
|
|
335
|
-
gap: 1rem;
|
|
336
|
-
padding: clamp(1rem, 3vw, 2rem);
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
/* ✅ Do: Two-column split — media + text pair (testimonial, feature row, media card) */
|
|
340
|
-
.media-card {
|
|
341
|
-
--display: grid;
|
|
342
|
-
grid-template-columns: 1fr 1fr;
|
|
343
|
-
gap: clamp(1rem, 3vw, 2rem);
|
|
344
|
-
align-items: center;
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
/* ✅ Do: Multi-column grid — list of children (product list, testimonial list, gallery) */
|
|
348
|
-
.testimonial-list {
|
|
349
|
-
--display: grid;
|
|
350
|
-
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
|
351
|
-
gap: clamp(1rem, 2.5vw, 2rem);
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
/* ✅ Do: Inline row — fixed controls on edges, growing center
|
|
355
|
-
(numeric stepper, search bar, toolbar, split button, pagination).
|
|
356
|
-
Pair with stretch-chain rules: controls flex: 0 0 auto,
|
|
357
|
-
center area flex: 1; min-width: 0. */
|
|
358
|
-
.numeric-stepper {
|
|
359
|
-
--display: flex;
|
|
360
|
-
flex-direction: row;
|
|
361
|
-
align-items: center;
|
|
146
|
+
border-inline-start: 1px solid currentColor;
|
|
147
|
+
inset-inline-end: 0;
|
|
362
148
|
}
|
|
363
149
|
```
|
|
364
150
|
|
|
365
|
-
|
|
151
|
+
Avoid `left`, `right`, `margin-left`, `padding-right`, and similar physical
|
|
152
|
+
inline-axis properties. Physical block-axis properties such as `top` and
|
|
153
|
+
`margin-bottom` are fine.
|
|
366
154
|
|
|
367
|
-
|
|
155
|
+
## Editable Values
|
|
368
156
|
|
|
369
|
-
|
|
370
|
-
when
|
|
371
|
-
|
|
372
|
-
inside `repeat()`, `calc()`, `min()`, `max()`, or `clamp()`. Do not
|
|
373
|
-
add a React prop for a value the user wouldn't meaningfully tune.
|
|
157
|
+
Keep static styling in the CSS Module, not JSX `style` objects. Use literal CSS
|
|
158
|
+
values when no interpolation is needed; do not create a React prop or CSS custom
|
|
159
|
+
property for routine values that zero config already surfaces.
|
|
374
160
|
|
|
375
|
-
|
|
376
|
-
control in the editor. Exposing routine values like `gap` or
|
|
377
|
-
`padding` as props clutters the editor UI, and the editor already
|
|
378
|
-
auto-surfaces those properties from the CSS rule itself —
|
|
379
|
-
duplicating them as props gives the user two competing controls for
|
|
380
|
-
the same thing.
|
|
161
|
+
Use this pattern:
|
|
381
162
|
|
|
382
163
|
```css
|
|
383
|
-
|
|
384
|
-
.profile-card {
|
|
385
|
-
--gap: 16px;
|
|
386
|
-
gap: var(--gap);
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
/* ✅ Do: Literal value — nothing to interpolate */
|
|
390
|
-
.profile-card {
|
|
164
|
+
.root {
|
|
391
165
|
gap: 16px;
|
|
166
|
+
padding: 24px;
|
|
167
|
+
background: #ffffff;
|
|
392
168
|
}
|
|
393
169
|
|
|
394
|
-
|
|
395
|
-
.card-grid {
|
|
170
|
+
.grid {
|
|
396
171
|
--columns: 3;
|
|
397
172
|
grid-template-columns: repeat(var(--columns), 1fr);
|
|
398
173
|
}
|
|
399
174
|
```
|
|
400
175
|
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
Static styling lives in the component's CSS. Do not use the JSX
|
|
406
|
-
`style={{ ... }}` attribute on rendered elements. Dynamic values
|
|
407
|
-
that genuinely vary per instance go through CSS custom properties
|
|
408
|
-
(see the rule above), still set in CSS.
|
|
409
|
-
|
|
410
|
-
**Why:** zeroConfig reads CSS rules to derive the editor's control
|
|
411
|
-
surface. An inline `style` attribute is invisible to the extractor,
|
|
412
|
-
so any value baked into JSX cannot be edited in the visual editor —
|
|
413
|
-
the user sees no control for it.
|
|
176
|
+
A dynamic runtime value that cannot be represented statically may use a narrowly
|
|
177
|
+
scoped CSS custom property set from JSX, but keep the actual style rule in CSS
|
|
178
|
+
and do not expose a visual prop solely for that purpose.
|
|
414
179
|
|
|
415
|
-
|
|
416
|
-
// ❌ Inline style — invisible to zeroConfig, no editor control
|
|
417
|
-
<div className="profile-card" style={{ padding: 20, borderRadius: 8 }} />
|
|
418
|
-
|
|
419
|
-
// ✅ Do: Defaults in CSS — surfaced to the editor as controls
|
|
420
|
-
<div className="profile-card" />
|
|
421
|
-
```
|
|
422
|
-
|
|
423
|
-
```css
|
|
424
|
-
/* ✅ Do: Defaults belong in CSS so the editor can surface them */
|
|
425
|
-
.profile-card {
|
|
426
|
-
padding: 20px;
|
|
427
|
-
border-radius: 8px;
|
|
428
|
-
background: #ffffff; /* Use `background`, never `background-color` — the schema key is "background"; zeroConfig can't match "background-color" so the default is lost in the design panel */
|
|
429
|
-
}
|
|
430
|
-
```
|
|
180
|
+
## Interaction and Motion
|
|
431
181
|
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
| Property | Guidance |
|
|
439
|
-
|---|---|
|
|
440
|
-
| `border-radius` | 8–12 px containers, `50%` for controls and interactive groups (buttons, pills, input rows) |
|
|
441
|
-
| `box-shadow` | Prefer soft, diffused shadows over hard borders (e.g. `0 2px 8px rgba(0,0,0,0.06), 0 0 1px rgba(0,0,0,0.08)`) |
|
|
442
|
-
| Spacing | 8–16 px inside controls, 16–32 px for containers. Avoid cramped layouts |
|
|
443
|
-
| Typography | Body ≥ 16 px, labels ≥ 14 px, headings larger. `font-weight: 500`–`600` |
|
|
444
|
-
| Palette | Root background transparent (blends with page). Use subtle fills (`#f1f5f9`/`#e2e8f0`) on *inner controls* only (buttons, input areas, pill containers). Text `#1e293b`/`#334155`, borders `#e2e8f0`. `#475569` for large/secondary text only |
|
|
445
|
-
| Accent | Use a muted accent color (e.g. `#6366f1`, `#7c83db`) sparingly on interactive icons, active indicators, and primary actions — just enough to signal interactivity without dominating |
|
|
446
|
-
| Contrast | WCAG AA minimum: 4.5:1 body text, 3:1 large text / UI controls |
|
|
447
|
-
| Hierarchy | Interactive elements visually distinct from static via weight, fill, or elevation |
|
|
448
|
-
| Touch targets | Interactive elements ≥ 44×44 px |
|
|
449
|
-
|
|
450
|
-
### Design states
|
|
451
|
-
|
|
452
|
-
Style interaction and selection states (`hover`, `focus`, `disabled`,
|
|
453
|
-
`selected`, …) per [`DESIGN-STATES.md`](DESIGN-STATES.md).
|
|
454
|
-
|
|
455
|
-
### Don't add transitions or animations unless functionally required
|
|
456
|
-
|
|
457
|
-
Component CSS does not declare `transition` or `animation` for
|
|
458
|
-
decorative purposes. Use them only when the motion is part of the
|
|
459
|
-
component's behavior (e.g. an accordion panel sliding open, a
|
|
460
|
-
carousel translating between slides). When transitions are required,
|
|
461
|
-
list the specific properties — never `transition: all`,
|
|
462
|
-
`transition-property: all`, or the implicit `all` of a duration-only
|
|
463
|
-
shorthand (`transition: 0.2s ease`).
|
|
464
|
-
|
|
465
|
-
**Why:** the editor mutates many CSS properties live as the user
|
|
466
|
-
configures the component — colors, font, padding, border width,
|
|
467
|
-
even layout properties on parent classes. Animating those mutations
|
|
468
|
-
makes the editor visibly laggy: values meant to update instantly
|
|
469
|
-
slide instead.
|
|
182
|
+
- Set `pointer-events: auto` on the root and each interactive element.
|
|
183
|
+
- Pair native interaction selectors with the matching editor-injected global
|
|
184
|
+
state modifier. Toggle custom state modifiers from component data.
|
|
185
|
+
- Do not add decorative transitions or animations.
|
|
186
|
+
- When motion is functionally required, list the exact transition properties;
|
|
187
|
+
never use `transition: all` or an implicit `all` shorthand.
|
|
470
188
|
|
|
471
189
|
```css
|
|
472
|
-
/* ❌ Don't: decorative transition with no functional reason */
|
|
473
|
-
.button {
|
|
474
|
-
transition: background-color 0.2s ease;
|
|
475
|
-
}
|
|
476
|
-
|
|
477
|
-
/* ❌ Don't: transition: all — animates every property the editor touches */
|
|
478
|
-
.button {
|
|
479
|
-
transition: all 0.2s ease;
|
|
480
|
-
}
|
|
481
|
-
|
|
482
|
-
/* ❌ Don't: implicit all — duration-only shorthand resolves to transition-property: all */
|
|
483
|
-
.button {
|
|
484
|
-
transition: 0.2s ease;
|
|
485
|
-
}
|
|
486
|
-
|
|
487
|
-
/* ✅ Do: Functional transition with specific properties named (e.g. accordion expand) */
|
|
488
190
|
.panel {
|
|
489
191
|
transition: height 0.2s ease;
|
|
490
192
|
}
|
|
491
193
|
```
|
|
492
194
|
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
.
|
|
514
|
-
.
|
|
515
|
-
.
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
195
|
+
## Default Visual Quality
|
|
196
|
+
|
|
197
|
+
When creating a component and the request has no visual direction, use a
|
|
198
|
+
restrained accessible default. When editing an existing component, preserve its
|
|
199
|
+
visual language unless the request changes it.
|
|
200
|
+
|
|
201
|
+
- body text at least 16px and labels at least 14px
|
|
202
|
+
- WCAG AA contrast (4.5:1 body text, 3:1 large text and UI controls)
|
|
203
|
+
- touch targets at least 44 by 44px
|
|
204
|
+
- clear hierarchy and visible focus states
|
|
205
|
+
- generous but consistent spacing
|
|
206
|
+
- transparent root backgrounds unless the design requires a surface
|
|
207
|
+
|
|
208
|
+
Avoid prescribing a brand palette in a generic component. Only when the prompt
|
|
209
|
+
explicitly requests branded or themed output, use its named brand tokens rather
|
|
210
|
+
than hardcoded generic color choices.
|
|
211
|
+
|
|
212
|
+
## Checklist
|
|
213
|
+
|
|
214
|
+
- [ ] The scaffolded component and each extracted internal sub-component own
|
|
215
|
+
their styles through colocated CSS Modules.
|
|
216
|
+
- [ ] Global classes exist only for the root and named inner parts.
|
|
217
|
+
- [ ] Selectors are flat except for a documented behavior-only exception.
|
|
218
|
+
- [ ] The root uses `--display`, fills the applicable configured axes, and uses
|
|
219
|
+
border-box sizing.
|
|
220
|
+
- [ ] A sizing chain exists only on bounded growing axes.
|
|
221
|
+
- [ ] Layout is container-driven and uses logical inline properties.
|
|
222
|
+
- [ ] Static styling stays in CSS; custom properties exist only when needed.
|
|
223
|
+
- [ ] Interactive elements expose pointer events and accessible design states.
|