create-element について
Elements registry向けにコンポーネントやブロックを作成する開発者向けスキルです。スキャフォールド、実装、ドキュメント、登録を案内し、Context7で依存ライブラリの最新資料を確認します。
主な機能
- 01registry要素のスキャフォールド生成
- 02コンポーネントの実装パターン
- 03Context7による依存資料の検索
- 04registryとプロバイダーメタデータの設定
- 05要素のビルドと検証
活用シーン
- 01UIプリミティブやブロックの作成
- 02コンポーネント例の追加
- 03新カテゴリのドキュメント作成
- 04コンポーネントの登録と検証
MCP 対応
外部依存を使うコンポーネントの実装前に、Context7 MCPツールでライブラリIDを解決し、依存ライブラリのドキュメントを検索します。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ crafter-station/ elements --skill create-elementインストール後、Claude Code で/create-elementを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/component-patterns.mddocumentation.mdregistry-schema.mdscripts/scaffold-element.ts詳細
要素を作成する
Elements レジストリ(tryelements.dev)用の新しい要素を作成します。
クイックスタート
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
Context7 との統合(重要)
外部依存関係を含むコンポーネントを実装する前に、最新のドキュメントを取得してください。
ステップ 1:ライブラリ ID を解決する
mcp__context7__resolve-library-id
libraryName: "radix-ui"
query: "dialog component accessibility patterns"
ステップ 2:特定のドキュメントを照会する
mcp__context7__query-docs
libraryId: "/radix-ui/primitives"
query: "Dialog API controlled vs uncontrolled portal usage"
よく使用するライブラリ
| ライブラリ | 照会する内容 |
|---|---|
radix-ui | プリミティブ(Dialog、Dropdown、Tabs、Select) |
next-themes | テーマプロバイダー、useTheme フック、ハイドレーション |
cmdk | コマンドパレットのパターン |
class-variance-authority | CVA バリアントのパターン |
embla-carousel-react | カルーセルの実装 |
lucide-react | アイコンの使用パターン |
要素の種類
| 種類 | 例 | 用途 |
|---|---|---|
registry:ui | button、card、input | 基本的な UI プリミティブ |
registry:block | theme-switcher、polar-checkout | 機能がそろったブロック |
registry:example | button-demo | 使用例 |
参考資料
作業内容に応じて、以下をお読みください。
- references/registry-schema.md - registry-item.json を作成・編集するとき
- references/component-patterns.md - コンポーネントのコードを記述するとき(CVA、cn()、data-slot)
- references/documentation.md - MDX ドキュメントを作成するとき
ディレクトリ構成
registry/default/blocks/{category}/{component-name}/
├── registry-item.json # Metadata
├── components/
│ └── elements/
│ └── {component}.tsx # Main component
└── routes/ # Optional demo routes
├── layout.tsx
└── page.tsx
ワークフローの例:テーマ切り替えタブ
1. ひな形を作成する
bun run .claude/skills/create-element/scripts/scaffold-element.ts theme theme-switcher-tabs
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"
3. 実装する
registry/default/blocks/theme/theme-switcher-tabs/components/elements/theme-switcher-tabs.tsx を編集します。
"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>
);
}
4. registry-item.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. ビルドしてテストする
bun run build:registry
bun run dev
検証チェックリスト
- registry-item.json に必須フィールド($schema、name、type、title、description、files)がすべて含まれている
- コンポーネントが PascalCase の関数をエクスポートしている(例:
export function ThemeSwitcherTabs) - クラス名の結合に
cn()を使用している - ルート要素に
data-slot属性がある - クライアントコンポーネントに
"use client"ディレクティブがある - テーマ/クライアント状態を使用する場合、ハイドレーションに安全である
-
bun run build:registryが成功する - 開発環境でコンポーネントが正しくレンダリングされる
- 新しいカテゴリの場合:プロバイダーのグループ化が設定されている(「新しいカテゴリの作成」セクションを参照)
コマンド
# Scaffold new element
bun run .claude/skills/create-element/scripts/scaffold-element.ts <category> <name>
# Build registry
bun run build:registry
# Development server
bun run dev
# Lint/format
bun run lint
bun run format
よくあるパターン
シンプルなコンポーネント(依存関係なし)
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}
/>
);
}
CVA バリアントを使用する場合
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 };
外部依存関係(Radix)を使用する場合
"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} />;
}
避けるべき落とし穴
- フックを使用するコンポーネントでは
"use client"を忘れないでください - 色をハードコードせず、CSS 変数(
text-foreground、bg-background)を使用してください - テーマに依存するコンポーネントのハイドレーション処理を省略しないでください
any型を使用せず、props に適切な型を指定してください- 変更後は
build:registryを実行してください
新しいカテゴリの作成(プロバイダーのグループ化)
コンポーネントの新しいカテゴリを作成する場合(既存のカテゴリに新しいコンポーネントを追加するだけではない場合)、ランディングページに正しく表示するため、プロバイダーシステムを設定する必要があります。設定しないと、各コンポーネントが個別の「近日公開」カードとして表示されます。
該当するケース
- 新しい統合機能を作成する場合(例:
charts/、payments/、analytics/) - グループ化すべき関連コンポーネントを複数追加する場合
- 現在のプロバイダーリストにカテゴリが存在しない場合
必要な 2 ファイルの設定
1. src/lib/registry-loader.ts
getProviderFromName()(約 53 行目)にグループ化ロジックを追加します。
// Special case: chart components go to "charts" provider
if (
name === "area-chart" ||
name === "bar-chart-vertical" ||
name === "heatmap-grid" ||
name === "growth-stats"
) {
return "charts";
}
getProviderMetadata()(約 156 行目)にプロバイダーメタデータを追加します。
charts: {
displayName: "Charts",
description: "Data visualization primitives - area charts, heatmaps, bar charts",
category: "DATA VIZ",
brandColor: "#14B8A6",
},
2. src/lib/providers.tsx
providerConfig(約 46 行目)にプロバイダー設定を追加します。
charts: {
isEnabled: true,
displayName: "Charts",
description: "Data visualization primitives - area charts, heatmaps, bar charts",
category: "Data Viz",
},
ProviderIcon()(約 196 行目)にプロバイダーアイコンを追加します。
charts: <ChartIcon className="w-10 h-10" />,
必要に応じて、アイコンを src/components/icons/{provider}.tsx に作成します。
プロバイダーメタデータのフィールド
| フィールド | 例 | 目的 |
|---|---|---|
displayName | "Charts" | ランディングページのカードタイトル |
description | "Data visualization..." | カードの説明 |
category | "DATA VIZ" | カードに表示されるバッジ |
brandColor | "#14B8A6" | 斜線パターンの色 |
既存のプロバイダー(参考)
| プロバイダーキー | 表示名 | カテゴリー |
|---|---|---|
clerk | Clerk | USER MGMT |
polar | Polar | MONETIZATION |
theme | Theme Switcher | UI |
logos | Brand Logos | BRAND |
uploadthing | UploadThing | FILES |
tinte | Tinte | THEMING |
charts | Charts | DATA VIZ |
命名規則
デフォルトの抽出では、ハイフンより前の最初の部分を使用します。
clerk-sign-in→clerkpolar-checkout→polar
次の場合は、特別なケースを追加します。
- コンポーネントが同じカテゴリーを共有していても、異なるプレフィックスを持つ場合(例:
area-chart、heatmap-grid) - カスタムのプロバイダー名を付ける場合(例:
theme-switcher-*→theme)
MDX ドキュメントのセットアップ
新しいカテゴリーでは、ドキュメントページを正しく表示するために MDX ドキュメントファイルも必要です。
1. デモコンポーネントを作成する
各コンポーネントについて、/registry/default/examples/{component}-demo.tsx にデモを作成します。
"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. MDX コンポーネントに登録する
/src/mdx-components.tsx にインポートとマッピングを追加します。
// Add import
import MyComponentDemo from "@/registry/default/examples/my-component-demo";
// Add to getMDXComponents return object
MyComponent: MyComponentDemo,
3. プロバイダーの MDX を作成する
/src/content/providers/{provider}.mdx を作成します。
---
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>
4. コンポーネントの MDX ファイルを作成する
各コンポーネントについて、/src/content/components/{provider}/{component}.mdx を作成します。
---
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
## Features