mcpField
W
wix-cli-site-component

wix-cli-site-component

github.com/wix开发36288 次安装今天更新
代码仓库

关于 wix-cli-site-component

面向 Wix CLI 的技能,用于构建可在 Wix Editor 中自定义的 React 网站组件。它指导编写组件清单、React 实现、CSS、TypeScript 类型及必需的扩展注册。

主要功能

  1. 01编辑器组件清单设计
  2. 02带类型的 React 组件模式
  3. 03响应式 CSS 与 CSS 变量
  4. 04可配置内容与样式
  5. 05元素级编辑器配置
  6. 06必需的扩展注册

适用场景

  1. 01构建可自定义的个人资料卡
  2. 02创建内容可配置的主视觉区
  3. 03制作可编辑的功能列表
  4. 04为组件元素定义编辑器控件

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/wix/skills --skill wix-cli-site-component

安装后在 Claude Code 中输入/wix-cli-site-component确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
CSS_GUIDELINES.md
DESIGN_SYSTEM.md
EXAMPLE.md
MANIFEST_ADVANCED.md
MANIFEST_GUIDELINES.md
REACT_PATTERNS.md
TYPESCRIPT_QUALITY.md

详细介绍

Wix 网站组件构建器

为 Wix CLI 应用创建生产级 React 网站组件及编辑器清单。网站组件是与 Wix Editor 集成的 React 组件,允许网站所有者通过可视化界面自定义内容、样式和行为。

先决条件: 编写任何文件前,先将 @wix/editor-react-types 安装为开发依赖。

架构

网站组件由 四个必需文件 组成:

1. 组件清单(manifest.json)

定义 React 组件与 Wix 生态系统之间的契约:

  • editorElement:根元素配置(选择器、显示名称、原型、布局)
  • cssProperties:用于样式自定义的 CSS API
  • data:用于内容配置的数据 API
  • elements:用于精细编辑的嵌套元素定义
  • behaviors:编辑器交互行为
2. React 组件(component.tsx)

可用于生产环境的 React 函数组件:

  • 实现与清单数据结构匹配的 props 接口
  • 将 className 和 id 应用到根元素
  • 通过 wix.elementsRemovalState 处理元素移除状态
  • 对嵌套元素使用子组件模式
  • 包含正确的 TypeScript 类型和错误处理
3. CSS 样式(style.css)

采用现代 CSS 并支持响应式设计:

  • 选择器与清单及 React classNames 保持同步
  • 使用 CSS 变量实现动态样式
  • 无需媒体查询即可实现响应式设计(flexbox、grid、clamp)
  • 为编辑器元素启用指针事件
  • 静态值不使用内联样式
  • 每个选择器只出现一次,所有元素均设置 box-sizing: border-box
  • 不使用 transition: all,不使用媒体查询(prefers-reduced-motion 除外)
  • 根元素显示方式:声明 --display: [value] CSS 变量,然后在根元素上使用 display: var(--display)
4. TypeScript 类型(types.ts)

严格的类型定义:

  • 导入类型:import type { Wix, Link, Image, Text, NumberType, BooleanValue, WebUrl, Direction } from '@wix/editor-react-types' — 不要在本地定义这些类型(已在先决条件中安装)
  • 例外:RichText — 在本地定义为 type RichText = string(@wix/editor-react-types 中的版本是 { text, html, linkList },而非纯字符串)
  • 为所有组件定义 props 接口
  • 元素 props 结构使用可选链

组件清单结构

在实现网站组件前,必须阅读 MANIFEST_GUIDELINES.md。 其中包含完整的清单结构、所有数据类型、元素配置和必需模式。

清单使用以下关键部分定义编辑器契约:

installation(初始放置)
{
  "installation": {
    "staticContainer": "HOMEPAGE",
    "initialSize": {
      "width": { "sizingType": "pixels", "pixels": 400 },
      "height": { "sizingType": "pixels", "pixels": 300 }
    }
  }
}
  • staticContainer:使用 "HOMEPAGE",以便在 Harmony 编辑器中自动安装
  • initialSize:使用 sizingType 选项定义初始尺寸:
    • "content" - 根据内容自动调整尺寸
    • "stretched" - 填满可用空间
    • "pixels" - 固定像素尺寸(需要 pixels 属性)
editorElement(根配置)
{
  "selector": ".component-name",
  "displayName": "Component Name",
  "archetype": "Container",
  "layout": {
    "resizeDirection": "horizontalAndVertical",
    "contentResizeDirection": "horizontal"
  },
  "cssProperties": {
    "backgroundColor": {
      "displayName": "Background Color",
      "defaultValue": "#ffffff"
    }
  },
  "data": {
    "columns": {
      "dataType": "number",
      "displayName": "Number of Columns",
      "number": { "minimum": 1, "maximum": 4 }
    }
  },
  "elements": {
    "title": {
      "elementType": "inlineElement",
      "inlineElement": {
        "selector": ".component-name__title",
        "displayName": "Title",
        "data": {
          "titleText": {
            "dataType": "text",
            "displayName": "Title Text"
          }
        },
        "behaviors": {
          "selectable": true,
          "removable": true
        }
      }
    }
  }
}
数据类型参考

所有运行时类型均来自 @wix/editor-react-types。

Manifest dataTypeTypeScript 类型用途
textText名称、标题、描述
textEnumTextEnum预定义选项
numberNumberType数量、尺寸
booleanValueBooleanValue开关、标志
a11yA11y无障碍属性
linkLink导航链接
imageImage图片
videoVideo媒体内容
audioAudio音频内容
vectorArtVectorArt图标、图形
localDateLocalDate (string, YYYY-MM-DD)日期值
localTimeLocalTime (string, hh:mm[:ss][.sss])时间值
localDateTimeLocalDateTime (string, YYYY-MM-DDThh:mm[:ss][.sss])日期 + 时间值
webUrlWebUrl (string)外部 URL
richTextRichText (define locally as string)格式化内容
arrayItemsArrayItems集合、列表
directionDirectionHTML dir 属性
menuItemsMenuItems导航菜单
CSS 属性参考

用于样式自定义的常见 CSS 属性:

  • 布局:display、gap、padding、margin、width、height
  • 排版:font、fontSize、fontWeight、textAlign、color
  • 背景:backgroundColor、backgroundImage
  • 边框:border、borderRadius、boxShadow
  • 定位:alignItems、justifyContent、flexDirection

**完整 CSS 属性参考:**所有 CSS 属性、变量模式和样式最佳实践,请参阅 CSS_GUIDELINES.md。

React 组件模式

**对于使用钩子、效果或回调的组件:**请参阅 REACT_PATTERNS.md;当组件使用 useEffect、useCallback、复杂状态或异步操作时,请阅读此文档。文档包含钩子、数组、引用和 SSR 安全数据获取的完整模式。

Props 结构
import type { Wix, Link, Image } from '@wix/editor-react-types'; // also: Text, NumberType, BooleanValue, WebUrl, Direction

interface ComponentProps {
  // Standard props (always present)
  className: string;
  id: string;
  wix?: Wix;

  // Component-level data (from editorElement.data)
  columns?: number;
  layout?: string;

  // Element props (from elements definitions)
  elementProps?: {
    title?: {
      titleText?: string;
      wix?: Wix;
    };
    button?: {
      buttonText?: string;
      buttonLink?: Link;
      wix?: Wix;
    };
  };
}
子组件模式

将每个不同的 UI 元素提取为一个具名子组件。每个子组件都接收一个与 manifest 选择器匹配的 className 属性,以及自身的数据属性:

const Title: FC<{ titleText?: string; className: string }> = ({
  titleText = "Default Title", className
}) => <h2 className={className}>{titleText}</h2>;

const MyComponent: FC<MyComponentProps> = ({ className, id, elementProps, wix }) => {
  const removalState = wix?.elementsRemovalState || {};
  return (
    <div className={`my-component ${className}`} id={id}>
      {!removalState['title'] && <Title className="my-component__title" {...elementProps?.title} />}
    </div>
  );
};

有关完整的子组件架构、数组处理和 TypeScript 模式,请参阅 REACT_PATTERNS.md。

条件渲染

根据 wix.elementsRemovalState 条件渲染所有元素:{!removalState['elementKey'] && <Element />},其中 removalState = wix?.elementsRemovalState || {}。

CSS 指南

响应式设计策略

组件位于用户可调整大小(300-1200px)的容器中,且视口大小各不相同:

  • 根元素:width: 100%; height: 100%
  • 布局结构:使用 CSS Grid 和 Flexbox 实现流式响应布局
  • 排版:使用 clamp() 实现流式缩放
  • 间距:使用固定间距或变化范围较小的 clamp 间距(≤50%)
动态样式的 CSS 变量
.component {
  --display: block;
  --background-color: #ffffff;
  --text-color: #333333;

  display: var(--display);
  background-color: var(--background-color);
  color: var(--text-color);
  pointer-events: auto;
}
选择器同步

**重要:**CSS 选择器必须与 manifest 选择器和 React classNames 完全匹配:

  • React:className="profile-card__name"
  • CSS:.profile-card__name { ... }
  • Manifest:"selector": ".profile-card__name"

设计指南

**完整参考:**有关视觉设计原则、创意指南和美学最佳实践,请参阅 DESIGN_SYSTEM.md。

通过间距传达信息
关系数值用途
紧密(图标 + 标签)0.25-0.5rem (4-8px)将相关项目聚合在一起
同一类别1-1.5rem (16-24px)卡片分区、表单字段
不同分区2-3rem (32-48px)主要内容块
强调/戏剧效果4rem+ (64px+)主视觉内容、营造奢华感
视觉一致性
  • 圆角半径:所有相似元素使用相同的圆角半径(0-4px 为锐利,6-12px 为圆润)
  • 阴影级别:最多 3 个级别(静止、悬停、浮起)
  • 元素高度:相似元素使用一致的高度
  • 配色策略:有目的地使用完整调色板来呈现层级和区域
创意探索

突破显而易见的方案:

  • 卡片:非对称网格、重叠元素、粗重的强调边框
  • 列表:交替样式、聚焦图案、色彩节奏
  • 交互元素:分体式按钮、彩色图标圆圈、平滑过渡
  • 内容层级:用于统计数据的大号数字、引言式醒目提示、留白分隔线

组件元素指南

一个元素 = 一个清单条目

每个独立的视觉部分都需要单独的清单元素:

  • ✅ 3 个按钮 → 3 个独立元素
  • ✅ 图片 + 文本 → 2 个独立元素
  • ❌ 将多个项目合并为一个元素
数据作用域规则

editorElement.data - 仅用于整个组件的配置:

  • ✅ 布局枚举值、数字(列数:3,速度:500)
  • ❌ 文本、链接、图片(应归属于元素)
  • ❌ 显示/隐藏布尔值(改用 removable: true)

elements[key].data - 此特定元素的内容:

  • ✅ 元素专属内容(标题文本、按钮链接、图片)

资源要求

组件需要默认图片时,请使用此格式:

// Import in component
import { heroImage } from './assets/defaultImages';

// Usage
<img src={heroImage} alt="Hero" />

资源规范格式:

<imageUrlName>
{ "description": "Modern cityscape at sunset", "width": 1920, "height": 1088 }
</imageUrlName>

规则:

  • 从 './assets/defaultImages' 作为命名导出导入
  • 宽度/高度:必须是 64 的倍数,范围为 128-2048px
  • 绝不使用外部 URL

输出结构

src/extensions/site/components/
└── {component-name}/
    ├── manifest.json        # Component manifest
    ├── component.tsx        # React component
    ├── style.css           # CSS styles
    ├── types.ts            # TypeScript types
    └── assets/             # Optional assets
        └── defaultImages.ts

示例

完整可运行示例: 请参阅 EXAMPLE.md,其中包含带嵌套元素的个人资料卡、所有数据类型,以及三种组件类型(叶子、容器、根组件)。构建复杂的多元素组件时、需要确认所有模式是否正确时,或需要交叉参考时,请阅读此文档。对于包含 ≤5 个元素的组件,本文档中记录的模式已足够,无需阅读 EXAMPLE.md。

个人资料卡组件

请求:“创建一张团队成员个人资料卡,包含照片、姓名、工作经验和联系按钮”

输出:

  • 清单包含 8 个元素,采用 2 层嵌套(照片区域、信息区域)
  • React 组件包含叶子、容器和根子组件
  • CSS 包含响应式布局和悬停效果
  • 为所有属性和数据结构定义 TypeScript 类型
主视觉区域组件

请求:“构建一个主视觉区域,包含背景图片、标题、副标题和 CTA 按钮”

输出:

  • 清单包含背景图片 CSS 属性和 3 个文本元素
  • React 组件采用叠加式设计和排版层级
  • CSS 包含响应式文本缩放和醒目的间距
  • 默认主视觉图片的资源规范
功能列表组件

请求:“创建一个功能组件,支持配置项目数量”

输出:

  • 清单使用 arrayItems 数据类型来存放功能集合
  • React 组件遍历功能数组,并进行安全检查
  • CSS 使用可根据项目数量调整的灵活网格布局
  • 为功能图标、标题和描述提供子组件

扩展注册

扩展注册为强制要求,且必须完成两个步骤。

步骤 1:创建组件专属扩展文件

每个站点组件都需要在其文件夹中包含一个 extensions.ts 文件:

import { extensions } from "@wix/astro/builders";
import manifest from "./manifest.json";

export const sitecomponentMyComponent = extensions.siteComponent({
  ...manifest,
  id: "{{GENERATE_UUID}}",
  description: "My Component",
  type: "<CODE_IDENTIFIER>.MyComponent",
  resources: {
    client: {
      component: "./extensions/site/components/my-component/component.tsx",
      componentUrl: "./extensions/site/components/my-component/component.tsx",
    },
  },
});

重要:类型命名约定

type 字段采用 {CODE_IDENTIFIER}.{PascalCaseFolderName} 格式:

  • 文件夹 my-component → type: "<CODE_IDENTIFIER>.MyComponent"
  • 文件夹 profile-card → type: "<CODE_IDENTIFIER>.ProfileCard"
  • 文件夹 hero-section → type: "<CODE_IDENTIFIER>.HeroSection"

文件夹名称会转换为 PascalCase(移除连字符,并将每个单词的首字母大写)。

CODE_IDENTIFIER 要求: Code Identifier 是必填值,不能猜测。每个 Wix 应用都会自动获得一个。

如果提示词中提供了 Code Identifier:

  • 将其用作类型前缀:<actual-code-identifier>.ComponentName

如果提示词中未提供 Code Identifier:

  • 在 type 字段中使用占位符 <CODE_IDENTIFIER>:<CODE_IDENTIFIER>.ComponentName
  • 在“手动操作事项”中添加:“将 <CODE_IDENTIFIER> 替换为 Wix Dev Center 中的实际 Code Identifier”

重要:UUID 生成

id 必须是唯一且固定的 UUID v4 字符串。为每个扩展生成一个新的 UUID——不要使用 randomUUID(),也不要复制示例中的 UUID。

步骤 2:在主扩展文件中注册

**重要:**创建组件专属扩展文件后,必须阅读 wix-cli-extension-registration,并按照“应用注册”部分的说明更新 src/extensions.ts。

如果未完成步骤 2,该站点组件将无法在 Wix Editor 中使用。

代码质量要求

**完整参考:**严格的 TypeScript 配置和代码质量标准请参阅 TYPESCRIPT_QUALITY.md。

TypeScript 标准
  • 使用严格的 TypeScript,不得使用 any 类型
  • 所有数据属性都必须是可选的(使用 ?)
  • 所有函数都必须显式声明返回类型
  • 使用可选链正确处理 null/undefined
  • 不得使用 @ts-ignore 或 @ts-expect-error 注释
React 最佳实践
  • 兼容 React 16——不得使用 React 18+ 特性(useId、useDeferredValue、useTransition 等)
  • 使用带 hooks 的函数组件
  • 为 useEffect 设置正确的依赖数组
  • 组件必须响应属性变化
  • 代码必须兼容 SSR(模块作用域中不得使用浏览器 API)
ESLint 合规要求
  1. 不得有未使用的变量/参数/导入项(@typescript-eslint/no-unused-vars)
  2. 不得使用外部图片:img 的 src 不得为 https://...(允许本地导入、wixstatic.com、变量)
  3. 兼容 SSR:模块作用域/构造函数中不得使用 window/document;在 useEffect/处理函数中使用浏览器 API 时必须添加保护
  4. 不得使用 dangerouslySetInnerHTML 或内联 <style> 标签——动态值应使用 CSS 变量或内联 style 属性
  5. 不得使用 window.fetch(no-restricted-properties)
  6. Hooks 的 exhaustive-deps:在 useEffect/useCallback 中使用的组件作用域内所有值都必须列入依赖数组
  7. 使用 const/let(不得使用 var),不得使用未知的 JSX 属性

常见错误

错误失败原因修复方法
CSS 选择器与清单不匹配编辑器无法将样式应用到该元素确保清单中的 selector、React className 和 CSS 选择器完全一致
将内容文本放在 editorElement.data 中内容应属于特定元素,而非根元素将文本/图像/链接数据移到 elements[key].data 中
直接在根元素上使用 display: flex会破坏编辑器覆盖机制使用 --display: flex CSS 变量,然后设置 display: var(--display)
元素缺少 removable: true网站所有者无法隐藏该元素为所有元素添加 behaviors: { selectable: true, removable: true }
arrayItems 没有 data/dataItem/dynamicItems部署验证失败arrayItems 对象必须包含以下之一:data、dataItem 或 dynamicItems
在模块作用域使用 window/document构建期间 SSR 会失败在 useEffect 或事件处理程序中保护浏览器 API 调用
从 @wix/design-system 导入网站组件无法使用仅使用纯 HTML/CSS 或自定义组件
import { FC } from 'react'Astro tsconfig 中的 verbatimModuleSyntax 要求仅导入类型使用 import { type FC } 或从 React 导入 import type { FC }

硬性约束

  • 不要虚构或假定新的类型、模块、函数、属性、事件或导入
  • 仅使用提供的参考资料中明确列出的实体,或本项目已使用的标准库
  • 不要添加依赖;不要使用 @wix/design-system 或 @wix/wix-ui-icons-common
  • 所有面向用户的内容都必须来自属性(不得硬编码文本)
  • 链接/媒体只能来自清单,绝不能硬编码 URL
  • 绝不要在任何代码中使用模拟内容、占位符或 TODO
  • 始终实现完整且可用于生产环境的功能

参考文档

文件阅读时机
MANIFEST_GUIDELINES.md始终阅读——清单结构、元素规则、CSS 属性、同步
MANIFEST_ADVANCED.md使用 arrayItems、链接约束、richText 功能或非默认安装尺寸时
REACT_PATTERNS.md使用钩子(useEffect、useCallback)、复杂状态或数组时
EXAMPLE.md构建复杂(5 个以上元素)组件时,或用于核对所有模式
CSS_GUIDELINES.md需要高级 CSS 模式或动画时
DESIGN_SYSTEM.md构建视觉丰富或具有品牌特色的组件时
TYPESCRIPT_QUALITY.md需要严格的 TypeScript 配置和属性接口模式时

评论

支持 Markdown