create-element
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseCreate Element
创建元素
Creates new elements for the Elements registry (tryelements.dev).
为Elements注册表(tryelements.dev)创建新元素。
Quick Start
快速开始
Step 1: Scaffold
bun run .claude/skills/create-element/scripts/scaffold-element.ts <category> <name>
Step 2: Implement
Edit component following patterns in references/component-patterns.md
Step 3: Register
bun run build:registry && bun run dev步骤1:脚手架初始化
bun run .claude/skills/create-element/scripts/scaffold-element.ts <category> <name>
步骤2:实现组件
参考references/component-patterns.md中的设计模式编辑组件
步骤3:注册组件
bun run build:registry && bun run devContext7 Integration (CRITICAL)
Context7 集成(至关重要)
Before implementing any component with external dependencies, fetch the latest documentation:
在实现任何带有外部依赖的组件之前,请获取最新文档:
Step 1: Resolve Library ID
步骤1:解析库ID
mcp__context7__resolve-library-id
libraryName: "radix-ui"
query: "dialog component accessibility patterns"mcp__context7__resolve-library-id
libraryName: "radix-ui"
query: "dialog component accessibility patterns"Step 2: Query Specific Docs
步骤2:查询特定文档
mcp__context7__query-docs
libraryId: "/radix-ui/primitives"
query: "Dialog API controlled vs uncontrolled portal usage"mcp__context7__query-docs
libraryId: "/radix-ui/primitives"
query: "Dialog API controlled vs uncontrolled portal usage"Common Libraries
常用库
| Library | Query For |
|---|---|
| Primitives (Dialog, Dropdown, Tabs, Select) |
| Theme provider, useTheme hook, hydration |
| Command palette patterns |
| CVA variant patterns |
| Carousel implementation |
| Icon usage patterns |
| 库名称 | 查询方向 |
|---|---|
| 基础组件(Dialog、Dropdown、Tabs、Select) |
| 主题提供者、useTheme钩子、水合处理 |
| 命令面板设计模式 |
| CVA变体设计模式 |
| 轮播组件实现 |
| 图标使用模式 |
Element Types
元素类型
| Type | Example | When to Use |
|---|---|---|
| button, card, input | Base UI primitives |
| theme-switcher, polar-checkout | Feature-complete blocks |
| button-demo | Usage examples |
| 类型 | 示例 | 使用场景 |
|---|---|---|
| button、card、input | 基础UI原语 |
| theme-switcher、polar-checkout | 功能完整的区块组件 |
| button-demo | 使用示例 |
References
参考文档
Read these based on what you're doing:
- references/registry-schema.md - When creating/editing registry-item.json
- references/component-patterns.md - When writing component code (CVA, cn(), data-slot)
- references/documentation.md - When creating MDX documentation
根据你的操作场景阅读以下文档:
- references/registry-schema.md - 创建/编辑registry-item.json时参考
- references/component-patterns.md - 编写组件代码时参考(CVA、cn()、data-slot)
- references/documentation.md - 创建MDX文档时参考
Directory Structure
目录结构
registry/default/blocks/{category}/{component-name}/
├── registry-item.json # Metadata
├── components/
│ └── elements/
│ └── {component}.tsx # Main component
└── routes/ # Optional demo routes
├── layout.tsx
└── page.tsxregistry/default/blocks/{category}/{component-name}/
├── registry-item.json # 元数据
├── components/
│ └── elements/
│ └── {component}.tsx # 主组件
└── routes/ # 可选的演示路由
├── layout.tsx
└── page.tsxWorkflow Example: Theme Switcher Tabs
工作流示例:主题切换标签页
1. Scaffold
1. 脚手架初始化
bash
bun run .claude/skills/create-element/scripts/scaffold-element.ts theme theme-switcher-tabsbash
bun run .claude/skills/create-element/scripts/scaffold-element.ts theme theme-switcher-tabs2. Fetch Docs
2. 获取文档
mcp__context7__resolve-library-id
libraryName: "next-themes"
query: "useTheme hook theme switching"
mcp__context7__query-docs
libraryId: "/pacocoursey/next-themes"
query: "useTheme setTheme resolvedTheme hydration"mcp__context7__resolve-library-id
libraryName: "next-themes"
query: "useTheme hook theme switching"
mcp__context7__query-docs
libraryId: "/pacocoursey/next-themes"
query: "useTheme setTheme resolvedTheme hydration"3. Implement
3. 实现组件
Edit :
registry/default/blocks/theme/theme-switcher-tabs/components/elements/theme-switcher-tabs.tsxtsx
"use client";
import { useTheme } from "next-themes";
import { useEffect, useState } from "react";
import { cn } from "@/lib/utils";
export function ThemeSwitcherTabs({ className }: { className?: string }) {
const { theme, setTheme } = useTheme();
const [mounted, setMounted] = useState(false);
useEffect(() => { setMounted(true); }, []);
if (!mounted) return <div className="h-8 w-24 animate-pulse bg-muted rounded" />;
return (
<div data-slot="theme-switcher-tabs" className={cn("...", className)}>
{/* Implementation */}
</div>
);
}编辑 :
registry/default/blocks/theme/theme-switcher-tabs/components/elements/theme-switcher-tabs.tsxtsx
"use client";
import { useTheme } from "next-themes";
import { useEffect, useState } from "react";
import { cn } from "@/lib/utils";
export function ThemeSwitcherTabs({ className }: { className?: string }) {
const { theme, setTheme } = useTheme();
const [mounted, setMounted] = useState(false);
useEffect(() => { setMounted(true); }, []);
if (!mounted) return <div className="h-8 w-24 animate-pulse bg-muted rounded" />;
return (
<div data-slot="theme-switcher-tabs" className={cn("...", className)}>
{/* 实现代码 */}
</div>
);
}4. Update registry-item.json
4. 更新registry-item.json
json
{
"name": "theme-switcher-tabs",
"type": "registry:ui",
"title": "Theme Switcher Tabs",
"description": "Tab-based theme switcher with Light/Dark/System options",
"registryDependencies": [],
"dependencies": ["next-themes"],
"files": [...],
"docs": "Requires ThemeProvider. Tab-style theme switcher with system support."
}json
{
"name": "theme-switcher-tabs",
"type": "registry:ui",
"title": "Theme Switcher Tabs",
"description": "Tab-based theme switcher with Light/Dark/System options",
"registryDependencies": [],
"dependencies": ["next-themes"],
"files": [...],
"docs": "Requires ThemeProvider. Tab-style theme switcher with system support."
}5. Build & Test
5. 构建与测试
bash
bun run build:registry
bun run devbash
bun run build:registry
bun run devVerification Checklist
验证清单
- registry-item.json has all required fields ($schema, name, type, title, description, files)
- Component exports PascalCase function (e.g., )
export function ThemeSwitcherTabs - Uses for className merging
cn() - Has attribute on root element
data-slot - Client components have directive
"use client" - Hydration-safe if using theme/client state
- succeeds
bun run build:registry - Component renders correctly in dev
- If new category: Provider grouping configured (see "Creating New Categories" section)
- registry-item.json包含所有必填字段($schema、name、type、title、description、files)
- 组件导出使用大驼峰命名的函数(例如:)
export function ThemeSwitcherTabs - 使用合并className
cn() - 根元素带有属性
data-slot - 客户端组件带有指令
"use client" - 依赖主题/客户端状态的组件具备水合安全性
- 执行成功
bun run build:registry - 组件在开发环境中正确渲染
- 如果是新分类:已配置提供者分组(参考“创建新分类”章节)
Commands
命令
bash
undefinedbash
undefinedScaffold new element
初始化新元素
bun run .claude/skills/create-element/scripts/scaffold-element.ts <category> <name>
bun run .claude/skills/create-element/scripts/scaffold-element.ts <category> <name>
Build registry
构建注册表
bun run build:registry
bun run build:registry
Development server
开发服务器
bun run dev
bun run dev
Lint/format
代码检查/格式化
bun run lint
bun run format
undefinedbun run lint
bun run format
undefinedCommon Patterns
常见设计模式
Simple Component (No Dependencies)
简单组件(无依赖)
tsx
import { cn } from "@/lib/utils";
interface BadgeProps extends React.ComponentProps<"span"> {}
export function Badge({ className, ...props }: BadgeProps) {
return (
<span
data-slot="badge"
className={cn("inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-semibold", className)}
{...props}
/>
);
}tsx
import { cn } from "@/lib/utils";
interface BadgeProps extends React.ComponentProps<"span"> {}
export function Badge({ className, ...props }: BadgeProps) {
return (
<span
data-slot="badge"
className={cn("inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-semibold", className)}
{...props}
/>
);
}With CVA Variants
带有CVA变体的组件
tsx
import { cva, type VariantProps } from "class-variance-authority";
import { cn } from "@/lib/utils";
const badgeVariants = cva("inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-semibold", {
variants: {
variant: {
default: "bg-primary text-primary-foreground",
secondary: "bg-secondary text-secondary-foreground",
destructive: "bg-destructive text-white",
},
},
defaultVariants: {
variant: "default",
},
});
interface BadgeProps extends React.ComponentProps<"span">, VariantProps<typeof badgeVariants> {}
export function Badge({ className, variant, ...props }: BadgeProps) {
return (
<span
data-slot="badge"
className={cn(badgeVariants({ variant, className }))}
{...props}
/>
);
}
export { badgeVariants };tsx
import { cva, type VariantProps } from "class-variance-authority";
import { cn } from "@/lib/utils";
const badgeVariants = cva("inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-semibold", {
variants: {
variant: {
default: "bg-primary text-primary-foreground",
secondary: "bg-secondary text-secondary-foreground",
destructive: "bg-destructive text-white",
},
},
defaultVariants: {
variant: "default",
},
});
interface BadgeProps extends React.ComponentProps<"span">, VariantProps<typeof badgeVariants> {}
export function Badge({ className, variant, ...props }: BadgeProps) {
return (
<span
data-slot="badge"
className={cn(badgeVariants({ variant, className }))}
{...props}
/>
);
}
export { badgeVariants };With External Dependency (Radix)
带有外部依赖的组件(Radix)
tsx
"use client";
import * as DialogPrimitive from "@radix-ui/react-dialog";
import { cn } from "@/lib/utils";
export function Dialog({ children, ...props }: DialogPrimitive.DialogProps) {
return <DialogPrimitive.Root {...props}>{children}</DialogPrimitive.Root>;
}
export function DialogTrigger({ className, ...props }: DialogPrimitive.DialogTriggerProps) {
return <DialogPrimitive.Trigger data-slot="dialog-trigger" className={cn("", className)} {...props} />;
}tsx
"use client";
import * as DialogPrimitive from "@radix-ui/react-dialog";
import { cn } from "@/lib/utils";
export function Dialog({ children, ...props }: DialogPrimitive.DialogProps) {
return <DialogPrimitive.Root {...props}>{children}</DialogPrimitive.Root>;
}
export function DialogTrigger({ className, ...props }: DialogPrimitive.DialogTriggerProps) {
return <DialogPrimitive.Trigger data-slot="dialog-trigger" className={cn("", className)} {...props} />;
}Pitfalls to Avoid
注意事项
- Don't forget for components using hooks
"use client" - Don't hardcode colors - use CSS variables (,
text-foreground)bg-background - Don't skip hydration handling for theme-dependent components
- Don't use types - properly type props
any - Don't forget to run after changes
build:registry
- 不要忘记为使用钩子的组件添加指令
"use client" - 不要硬编码颜色 - 使用CSS变量(、
text-foreground)bg-background - 不要跳过依赖主题的组件的水合处理
- 不要使用类型 - 正确定义props类型
any - 不要忘记在修改后运行
build:registry
Creating New Categories (Provider Grouping)
创建新分类(提供者分组)
When creating a new category of components (not just a new component in an existing category), you must configure the provider system for proper landing page display. Otherwise, each component will appear as a separate "Coming Soon" card.
当创建新的组件分类(而不是现有分类中的新组件)时,必须配置提供者系统以确保落地页正确显示。否则,每个组件都会显示为单独的“即将推出”卡片。
When This Applies
适用场景
- Creating a new integration (e.g., ,
charts/,payments/)analytics/ - Adding multiple related components that should be grouped together
- The category doesn't exist in the current provider list
- 创建新的集成(例如:、
charts/、payments/)analytics/ - 添加多个相关组件并希望将它们分组展示
- 当前提供者列表中不存在该分类
Two-File Setup Required
需配置两个文件
1. src/lib/registry-loader.ts
src/lib/registry-loader.ts1. src/lib/registry-loader.ts
src/lib/registry-loader.tsAdd grouping logic in (~line 53):
getProviderFromName()typescript
// Special case: chart components go to "charts" provider
if (
name === "area-chart" ||
name === "bar-chart-vertical" ||
name === "heatmap-grid" ||
name === "growth-stats"
) {
return "charts";
}Add provider metadata in (~line 156):
getProviderMetadata()typescript
charts: {
displayName: "Charts",
description: "Data visualization primitives - area charts, heatmaps, bar charts",
category: "DATA VIZ",
brandColor: "#14B8A6",
},在中添加分组逻辑(约第53行):
getProviderFromName()typescript
// 特殊情况:图表组件归到"charts"提供者
if (
name === "area-chart" ||
name === "bar-chart-vertical" ||
name === "heatmap-grid" ||
name === "growth-stats"
) {
return "charts";
}在中添加提供者元数据(约第156行):
getProviderMetadata()typescript
charts: {
displayName: "Charts",
description: "Data visualization primitives - area charts, heatmaps, bar charts",
category: "DATA VIZ",
brandColor: "#14B8A6",
},2. src/lib/providers.tsx
src/lib/providers.tsx2. src/lib/providers.tsx
src/lib/providers.tsxAdd provider config in (~line 46):
providerConfigtypescript
charts: {
isEnabled: true,
displayName: "Charts",
description: "Data visualization primitives - area charts, heatmaps, bar charts",
category: "Data Viz",
},Add provider icon in (~line 196):
ProviderIcon()typescript
charts: <ChartIcon className="w-10 h-10" />,Create the icon at if needed.
src/components/icons/{provider}.tsx在中添加提供者配置(约第46行):
providerConfigtypescript
charts: {
isEnabled: true,
displayName: "Charts",
description: "Data visualization primitives - area charts, heatmaps, bar charts",
category: "Data Viz",
},在中添加提供者图标(约第196行):
ProviderIcon()typescript
charts: <ChartIcon className="w-10 h-10" />,如果需要,在中创建图标。
src/components/icons/{provider}.tsxProvider Metadata Fields
提供者元数据字段
| Field | Example | Purpose |
|---|---|---|
| "Charts" | Landing page card title |
| "Data visualization..." | Card description |
| "DATA VIZ" | Badge shown on card |
| "#14B8A6" | Diagonal hatch pattern color |
| 字段 | 示例 | 用途 |
|---|---|---|
| "Charts" | 落地页卡片标题 |
| "Data visualization..." | 卡片描述 |
| "DATA VIZ" | 卡片上显示的标签 |
| "#14B8A6" | 对角填充图案颜色 |
Existing Providers (Reference)
现有提供者(参考)
| Provider Key | Display Name | Category |
|---|---|---|
| Clerk | USER MGMT |
| Polar | MONETIZATION |
| Theme Switcher | UI |
| Brand Logos | BRAND |
| UploadThing | FILES |
| Tinte | THEMING |
| Charts | DATA VIZ |
| 提供者Key | 显示名称 | 分类 |
|---|---|---|
| Clerk | USER MGMT |
| Polar | MONETIZATION |
| Theme Switcher | UI |
| Brand Logos | BRAND |
| UploadThing | FILES |
| Tinte | THEMING |
| Charts | DATA VIZ |
Naming Convention
命名约定
The default extraction uses the first part before hyphen:
- →
clerk-sign-inclerk - →
polar-checkoutpolar
Add special cases when:
- Components share a category but have different prefixes (e.g., ,
area-chart)heatmap-grid - You want a custom provider name (e.g., →
theme-switcher-*)theme
默认提取连字符前的第一部分作为分组依据:
- →
clerk-sign-inclerk - →
polar-checkoutpolar
在以下情况添加特殊规则:
- 组件属于同一分类但前缀不同(例如:、
area-chart)heatmap-grid - 你需要自定义提供者名称(例如:→
theme-switcher-*)theme
MDX Documentation Setup
MDX文档设置
New categories also need MDX documentation files for the docs pages to render properly:
新分类还需要配置MDX文档文件,以便文档页正确渲染:
1. Create Demo Components
1. 创建演示组件
For each component, create a demo in :
/registry/default/examples/{component}-demo.tsxtsx
"use client";
import { MyComponent } from "@/registry/default/blocks/{category}/{component}/components/elements/{component}";
export default function MyComponentDemo() {
return (
<div className="flex items-center justify-center p-4">
<MyComponent />
</div>
);
}为每个组件在中创建演示:
/registry/default/examples/{component}-demo.tsxtsx
"use client";
import { MyComponent } from "@/registry/default/blocks/{category}/{component}/components/elements/{component}";
export default function MyComponentDemo() {
return (
<div className="flex items-center justify-center p-4">
<MyComponent />
</div>
);
}2. Register in MDX Components
2. 在MDX组件中注册
Add imports and mappings in :
/src/mdx-components.tsxtsx
// Add import
import MyComponentDemo from "@/registry/default/examples/my-component-demo";
// Add to getMDXComponents return object
MyComponent: MyComponentDemo,在中添加导入和映射:
/src/mdx-components.tsxtsx
// 添加导入
import MyComponentDemo from "@/registry/default/examples/my-component-demo";
// 添加到getMDXComponents返回对象
MyComponent: MyComponentDemo,3. Create Provider MDX
3. 创建提供者MDX文件
Create :
/src/content/providers/{provider}.mdxmdx
---
title: My Provider
description: Description of the category
category: CATEGORY TAG
brandColor: "#hexcolor"
---创建:
/src/content/providers/{provider}.mdxmdx
---
title: My Provider
description: Description of the category
category: CATEGORY TAG
brandColor: "#hexcolor"
---Overview
概述
Brief description.
简要描述。
Components
组件
Component Name
组件名称
<ComponentPreviewItem
componentKey="component-name"
installUrl="@elements/component-name"
category="Category"
name="Component Name"
<ComponentName /> </ComponentPreviewItem> ```
<ComponentPreviewItem
componentKey="component-name"
installUrl="@elements/component-name"
category="Category"
name="Component Name"
<ComponentName /> </ComponentPreviewItem> ```
4. Create Component MDX Files
4. 创建组件MDX文件
Create for each component:
/src/content/components/{provider}/{component}.mdxmdx
---
title: Component Name
description: Brief description
---
<ComponentPreviewItem
componentKey="component-name"
installUrl="@elements/component-name"
category="Category"
name="Component Name"
>
<ComponentName />
</ComponentPreviewItem>为每个组件创建:
/src/content/components/{provider}/{component}.mdxmdx
---
title: Component Name
description: Brief description
---
<ComponentPreviewItem
componentKey="component-name"
installUrl="@elements/component-name"
category="Category"
name="Component Name"
>
<ComponentName />
</ComponentPreviewItem>Overview
概述
Installation
安装
Usage
使用
Props
Props
Features
特性
undefinedundefined