Build an Editor React Component in Studio Two

An Editor React Component (ERC) is built component first. You write the React code, the prop types, and the CSS, and then you regenerate the editorElement portion of the manifest from those three files. What a Wix user can select, edit, and style in the editor follows from how you write them.

This article walks through that loop end to end, from a scaffolded component to one with its own panels, presets, and states. The examples build a testimonial card with a quote and an author name.

Follow the instructions below to:

  1. Scaffold the component.
  2. Build the component UI.
  3. Set props and defaults.
  4. Style the component.
  5. Regenerate and check the manifest.
  6. Refine the manifest.
  7. Add presets and states.
  8. Check the component in the editor.

Step 1 | Scaffold the component

Start from a generated ERC rather than an empty folder, so the file structure and registration are already in place. For the procedure, see Add an Editor React Component Extension in Studio Two.

You can find the new files under src/extensions/site/components/<component-folder>/. You spend most of this article in these files:

  • <component-folder>.tsx
  • <component-folder>.props.ts
  • <component-folder>.module.css
  • <component-folder>.extension.ts

You also update component.preview.tsx once, in Step 3. Leave component.tsx as generated. For what every file in the folder is for, see Editor React Component Extension Files and Code.

To save a file, press Control+S (or Command+S on macOS). A circle on a file's tab means the file has unsaved edits. When the status bar shows Synced, the editor has your saved changes.

Tip: If the status bar shows that the sync failed, click it to retry. If it keeps syncing for a long time, reload the editor.

Step 2 | Build the component UI

Write your JSX in <component-folder>.tsx. Two rules govern how the editor sees it.

First, the root element carries the id and className props Wix passes in, plus a plain string class that the manifest selector matches. Without both the id and a matching class, the component renders but a Wix user can't select it or open its panels. Name the root class after the component so it doesn't collide with anything else on the page.

Second, every element you want the editor to target needs a plain string class alongside its CSS Module class. CSS Modules rewrite class names at build time, so a module class alone never matches a manifest selector. Give structural wrappers a module class only, and the editor leaves them alone.

For the example, .testimonial-card is the root selector, and .testimonial-quote and .testimonial-author mark the inner elements. The scaffold uses clsx to combine class names, so the example does too:

Copy

For the full DOM contract, including selector length limits and the props Wix provides, see Component Requirements and Runtime Props Reference.

Step 3 | Set props and defaults

Declare your props type and a defaultProps constant in <component-folder>.props.ts. Each prop you declare becomes editable content in the editor, and the value a Wix user sets arrives back on the component as that same prop at runtime.

Set each default once, in this file. It feeds both the rendered component and the editor panels, so the controls open on the same values a Wix user sees on the canvas. A copy of the component that's already on a page keeps the values it was added with, so a changed default shows only on copies added after you save. Leave id and className out of defaultProps, because Wix always supplies them.

For the example, the props replace the scaffold's image, title, description, and direction:

Copy

Update the preview's required fields

When you rename or replace props, update component.preview.tsx to match. That file is what the editor canvas loads. The scaffold wraps the component in withFallbackPlaceholder with a requiredDataFields list that names the scaffold's title and description props. If a field in that list is missing from the component's props, the canvas shows a placeholder instead of the component.

List your own content props in requiredDataFields, not id or className. For the example:

Copy

Step 4 | Style the component

Write default styles in <component-folder>.module.css. CSS Modules scope the class names to your component, so they can't collide with other components on the page.

The CSS properties you set here are what the editor turns into design controls. A property you never style isn't offered to Wix users.

For the example:

Copy

These scoped class names aren't what the manifest matches. Keep the plain string classes from Step 2 on every element the editor targets.

Step 5 | Regenerate and check the manifest

The editorElement in <component-folder>.generated.ts is the part of the manifest that declares editable data, inner elements, CSS properties, presets, states, and layout. The editor builds its panels from it. After you change the component, its props, or its CSS, regenerate the manifest.

To regenerate the manifest:

  1. In the Code tab, open the terminal. Press Control+J (or Command+J on macOS).

  2. Run:

    Copy

Then open <component-folder>.generated.ts and read it as a report on what you wrote:

  • Each prop becomes an entry under data. A Wix user edits text props in the component's Edit Text panel.
  • Each element with a plain string class becomes an entry under elements. Generated entries set inlineElement.behaviors.selectable to false, so a Wix user can't select those elements on their own. Step 6 covers changing that.
  • Each CSS property you styled becomes a cssProperties entry that the editor can offer as a design control.

If something you expected is missing, fix it in the source files and regenerate. A control that doesn't appear usually means a prop wasn't declared or a property was never styled. An element missing from elements usually has a module class but no plain string class.

Don't edit <component-folder>.generated.ts. Your changes are overwritten the next time you regenerate the manifest.

For what each manifest property controls in the editor, see About Auto Panels for Editor React Components.

Step 6 | Refine the manifest

<component-folder>.extension.ts is the manifest you own. Regenerating never overwrites it, so this is where you adjust anything the generated editorElement got wrong or left bare.

The scaffold merges your overrides onto the generated editorElement with deepmerge. Add each override to the second object, which already holds the scaffold's layout settings. You only write the values you change:

Copy

Common refinements:

  • Label controls. Set displayName on data items, CSS properties, and elements so panels read in your words instead of your variable names.
  • Make inner elements selectable. Under elements, use the element's key from the generated file and set inlineElement.behaviors.selectable to true. The element then gets its own action bar and panels. For every element field, see Elements.
  • Group controls. Use displayGroups to collect related properties into named sections inside a panel.
  • Show controls conditionally. Use displayFilters to hide a control unless another data item, preset, or state calls for it.
  • Set sizing behavior. Use layout for resize and stretch behavior, and installation.initialSize for the size the component takes when a Wix user first adds it to a page.

This file also holds the component's identity and its resources. For every field, see About the Editor React Component Manifest.

Important: Some type properties are immutable once the manifest is saved for the first time, including dataType on a data item and elementType on an element. Changing one later fails validation and blocks deployment. To use a different type, add a new variable with the type you want instead of editing the existing one.

Step 7 | Add presets and states

Presets and states are the two things a Wix user gets that don't come from your base declarations. You declare both in editorElement, inside the object you pass to deepmerge() in <component-folder>.extension.ts, as in Step 6, so regenerating the manifest never overwrites them. Each one also needs a small change in the component and its CSS. The sections below show what to add to which file.

Presets

A preset is a named visual variation of your component, such as a card layout and a minimal layout. Declaring presets gives the component an Explore Designs panel, where switching variation is a single click. To open it, select the component on the canvas and click the Explore Designs icon in the bottom action bar, to the left of the state selector.

1. <component-folder>.tsx: Wrap the root element in a container and spread wix.presetsWrapperProps onto it. Keep id and className on the inner element, not on the wrapper.

Copy

2. <component-folder>.extension.ts: Add presets inside the object you pass to deepmerge(), and set installation.presets to choose the starting preset at each breakpoint. Each preset needs a thumbnailUrl for the panel and a presetCssUrl for the CSS the editor applies when it's selected.

Copy

Replace the example URLs with your own. The thumbnail and CSS URLs must be publicly reachable.

To change a value when a Wix user picks a preset, use one of two fields. Use presetDefaults for the values that apply when a Wix user switches to the preset, such as layout behavior, CSS property defaults, and nested element defaults. Use styleOverrides when a value has to change by breakpoint or by state, such as a smaller font size on mobile. In the example, selecting Minimal in Explore Designs changes the card's background to #fff3cd.

Important: Every CSS property or element key you reference in presetDefaults or styleOverrides must already exist in the component's editorElement. If one doesn't, the editor reports "One or more referenced keys do not exist" under Site code errors, and the component stops loading on the canvas. Check the key names in <component-folder>.generated.ts first. For example, a background-color declaration in your CSS appears there as background, so backgroundColor isn't a valid key.

For every preset field and worked examples, see Presets.

States

A state is a condition a Wix user styles separately, such as hover or loading. Declaring states adds a state selector to the bottom action bar. To find it, select the component on the canvas. The selector is the drop-down that reads Regular, next to Edit Text. Choosing a state, such as Hover, shows the component in that state on the canvas, and the design controls you change apply to that state.

1. <component-folder>.extension.ts: Add states inside the object you pass to deepmerge(). How you declare each state depends on where it comes from:

  • Use pseudoClass for states the browser handles on the live site, such as hover or disabled. Set it to a NATIVE_STATE_TYPE value, imported from @wix/react-component-schema. A plain string such as 'hover' fails type checking.
  • Use className for custom states with no pseudo-class equivalent, such as loading or selected. The editor applies this class to the component while the state is selected.
  • Use props to put the component into that state on the editor canvas, so a Wix user can see what they're styling.
Copy

2. <component-folder>.module.css: Write the styles for the state. Target both the pseudo-class, for the live site, and the state's class, for the editor canvas. Because CSS Modules rewrite class names, wrap the state class in :global().

Copy

3. (Optional) <component-folder>.extension.ts, on a CSS property: To give a property a different default under a state, add statesDefaultValues to that property in the object you pass to deepmerge(). Use the property's key from <component-folder>.generated.ts, and key each value by the state's name.

Copy

When a Wix user selects Hover in the state selector, the background control then starts from #e8f0fe instead of the regular value.

For every state field and worked examples, see States.

Step 8 | Check the component in the editor

To check your component:

  1. Switch to the Design tab.
  2. Navigate to Add Elements > AI Generated.
  3. Select your component to place it on the page. If it isn't listed, ask Aria, Wix's AI assistant, to place it for you. For how to work with Aria, see Working with Aria. Add a fresh copy after each round of changes, because a copy placed earlier keeps the prop values it was added with.
  4. Confirm that the component shows your default prop values. If the canvas shows a placeholder instead, check the requiredDataFields list from Step 3, then regenerate the manifest as in Step 5.
  5. Select the component and open each control on its action bar. Confirm that Edit Text lists each text prop with its default value.
  6. If you made inner elements selectable in Step 6, click each one and confirm it has its own action bar.
  7. (Optional) Click Preview to view the page outside edit mode.

Panels that don't look right point back to a specific file. Missing or misnamed controls are a manifest matter, so return to Step 5 or Step 6. Controls that exist but don't change anything on the canvas usually mean a selector doesn't match a class the component renders, so return to Step 2.

When the component behaves the way you want, click Publish to ship it with the site.

See also

Last updated: 2 November 2026

Did this help?