创建新组件技能 new

端到端工作流程,用于从头开始构建新的Terrae组件,涵盖组件源代码、注册表、文档、示例等,是前端开发中构建地图相关组件的重要指南。

前端开发 0 次安装 0 次浏览 更新于 3/4/2026

创建新组件技能

从头开始构建新的Terrae组件的端到端工作流程。

涵盖所有8个输出:

  • 组件源代码
  • 注册表
  • 导出
  • 文档
  • 示例
  • 侧边栏
  • 组件页面
  • 更新日志

组件结构、模式、响应性和性能规则在.claude/rules/react/component.md中。

所有输出

# 输出 文件(s)
1 组件源文件 src/registry/map/{name}.tsx
2 桶导出 src/registry/map/index.tsx (更新)
3 注册表条目 registry.json (更新)
4 示例文件(s) src/app/docs/_components/examples/{name}-example.tsx
5 文档页面 src/app/docs/{slug}/page.tsx
6 侧边栏导航 src/app/docs/_components/docs-sidebar.tsx (更新)
7 组件列表 src/app/docs/components/page.tsx (更新)
8 更新日志条目 src/app/docs/changelog/page.tsx (更新)

说明

当开发人员请求新组件时:

第1步:收集需求

询问:

  • 组件名称(例如,MapHeatmapMapPolygon
  • 核心功能
  • 是否需要复合组件(如MarkerContentMarkerPopup
  • 类别:"core""features"(大多数组件是特性)
  • 侧边栏和组件页面的Lucide图标
  • 是否公开控制钩子(例如,useHeatmapControl

如果有多种有效的实现方法(例如,Mapbox图层与DOM覆盖,canvas与CSS动画,GeoJSON源与自定义渲染),呈现选项及其权衡,让开发人员在选择写代码之前做出选择。

第2步:创建组件文件和导出

按照.claude/rules/react/component.md中的地图组件规则,进行组件结构、模板、模式和桶导出。

  • 位置:src/registry/map/{component-name}.tsx
  • 文件名使用小写连字符(例如,heat-map.tsx
  • src/registry/map/index.tsx导出

第3步:添加注册表条目

通过向items数组添加条目来更新registry.json

按照此结构:

{
  "name": "heat-map",
  "type": "registry:ui",
  "title": "地图热力图",
  "description": "组件的简短描述。",
  "dependencies": ["mapbox-gl"],
  "devDependencies": ["@types/mapbox-gl"],
  "registryDependencies": ["https://www.terrae.dev/map.json"],
  "files": [
    {
      "path": "src/registry/map/heat-map.tsx",
      "type": "registry:ui",
      "target": "components/ui/map/heat-map.tsx"
    }
  ]
}
关键规则:
  • name使用小写连字符前缀(例如,heat-map
  • registryDependencies始终包括["https://www.terrae.dev/map.json"](所有其他组件依赖的核心Map组件)
  • 如果组件需要除mapbox-gl之外的包,则添加额外的dependencies
  • 不需要mapbox-gl的组件可以有空的dependencies(例如,水印)

第4步:创建示例文件(s)

位置:src/app/docs/_components/examples/{name}-example.tsx

文件名使用小写连字符。

基本示例应展示组件的最简单用法。

import { Map, MapHeatmap } from "@/registry/map"

export const HeatmapExample = () => {
  const accessToken = process.env.NEXT_PUBLIC_MAPBOX_ACCESS_TOKEN || ""

  return (
    <div className="h-full w-full">
      <Map accessToken={accessToken} center={[-74.006, 40.7128]} zoom={10}>
        <MapHeatmap id="heatmap-basic" {/* ...最小化属性 */} />
      </Map>
    </div>
  )
}
关键规则:
  • 仅当示例使用钩子、事件处理程序或浏览器API时添加"use client"——纯粹组合示例仅渲染地图组件不需要它
  • @/registry/map导入
  • 将地图包装在<div className="h-full w-full">
  • 传递process.env.NEXT_PUBLIC_MAPBOX_ACCESS_TOKEN || ""作为访问令牌——Map组件验证它并在缺失时显示错误,因此示例不需要自己的检查
  • 用描述性名称(PascalCase)导出组件
  • 为每种变体创建额外的示例文件(例如,heatmap-color-example.tsxheatmap-custom-example.tsx

第5步:创建文档页面

位置:src/app/docs/{slug}/page.tsx

使用lines-animated/page.tsx作为黄金标准参考。

slug应与侧边栏href匹配(例如,/docs/heatmapsrc/app/docs/heatmap/page.tsx)。

import { DocsLayout, DocsSection, DocsCode, DocsLink } from "../_components/docs"
import { ComponentPreview } from "../_components/component-preview"
import { CodeBlock } from "../_components/code-block"
import { HeatmapExample } from "../_components/examples/heatmap-example"
import { getExampleSource } from "@/lib/get-example-source"
import { Metadata } from "next"
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"

export const metadata: Metadata = {
  title: "热力图",
}

const HeatmapPage = () => {
  const basicSource = getExampleSource("heatmap-example.tsx")

  return (
    <DocsLayout
      title="热力图"
      description="组件的作用的简短描述。"
      prev={{ title: "前一个组件", href: "/docs/previous" }}
      next={{ title: "下一个组件", href: "/docs/next" }}
    >
      <DocsSection title="安装">
        <p>首先,确保你已经安装了基础地图组件:</p>
        <CodeBlock code={`npx shadcn@latest add https://www.terrae.dev/map.json`} language="bash" />
        <p className="mt-4">然后安装热力图组件:</p>
        <CodeBlock
          code={`npx shadcn@latest add https://www.terrae.dev/heat-map.json`}
          language="bash"
        />
      </DocsSection>

      <ComponentPreview code={basicSource}>
        <HeatmapExample />
      </ComponentPreview>

      {/* 附加部分,示例、属性表等。 */}
    </DocsLayout>
  )
}

export default HeatmapPage
关键规则:
  • 总是导出带有titlemetadata
  • 使用带有titledescriptionprevnext导航链接的DocsLayout
  • 第一节总是"安装",有两个CodeBlocks(基础地图+组件)
  • 基本ComponentPreview紧接在安装之后(没有节标题或描述,只有演示)
  • 使用ComponentPreview包装每个示例及其源代码
  • 使用getExampleSource("filename.tsx")加载示例源代码
  • 使用DocsCode进行描述中的内联代码引用
  • 使用带有titleDocsSection为每个部分
  • 当组件有许多可配置属性时,添加属性Table
  • 设置prev/next以匹配侧边栏导航中的相邻项

第6步:添加到侧边栏

更新src/app/docs/_components/docs-sidebar.tsx

  1. 在顶部导入Lucide图标(如果尚未导入)
  2. navigation数组的正确部分添加一个NavItem条目
  3. 添加badge: "new"
{ title: "热力图", href: "/docs/heatmap", icon: Flame, badge: "new" },

部分:

  • "Explore" — 故事,更新日志
  • "Get Started" — 介绍,安装,比较,组件,钩子,参考
  • "Core" — 地图,控件,指南针,标记,弹出窗口
  • "Features" — 其他所有内容

第7步:添加到组件页面

更新src/app/docs/components/page.tsx

  1. 在顶部导入Lucide图标(如果尚未导入)
  2. components数组添加一个ComponentItem条目
  3. 添加isNew: true
{
  title: "热力图",
  href: "/docs/heatmap",
  description: "与注册表描述相匹配的简短描述",
  icon: Flame,
  category: "features",
  installCommand: "npx shadcn@latest add https://www.terrae.dev/heat-map.json",
  isNew: true,
},
关键规则:
  • category"core""features"(必须与侧边栏部分匹配)
  • installCommand URL遵循模式https://www.terrae.dev/{registry-name}.json
  • 如果组件仅适用于Mapbox GL(而不是MapLibre),请添加mapboxOnly: true
  • 在数组中将条目放置在类似组件附近

第8步:更新更新日志

更新src/app/docs/changelog/page.tsx

changelogs数组中最顶部(最新)的ChangelogEntrycomponents数组中添加一个新条目:

{
  title: "热力图",
  description: (
    <>
      新的<code className="rounded bg-muted px-1 py-0.5 text-xs">MapHeatmap</code>组件用于在地图上可视化数据密度。支持自定义颜色坡道、半径控制和强度调整。
    </>
  ),
  href: "/docs/heatmap",
},
关键规则:
  • components下添加新组件,在features下添加新功能,在fixes下添加错误修复,在properties下添加新属性
  • description使用JSX内联<code>标签用于组件名称
  • 总是包含链接到文档页面的href

第9步:与用户审查

在最终确定之前,展示所有更改:

  • 组件源代码
  • 桶导出添加
  • 注册表条目
  • 示例文件(s)
  • 文档页面
  • 侧边栏条目
  • 组件页面条目
  • 更新日志条目