mcpField
C
create-element

create-element

github.com/crafter-stationデザイン・UI52671 回インストール11 週間前に更新
リポジトリ

create-element について

Elements registry向けにコンポーネントやブロックを作成する開発者向けスキルです。スキャフォールド、実装、ドキュメント、登録を案内し、Context7で依存ライブラリの最新資料を確認します。

主な機能

  1. 01registry要素のスキャフォールド生成
  2. 02コンポーネントの実装パターン
  3. 03Context7による依存資料の検索
  4. 04registryとプロバイダーメタデータの設定
  5. 05要素のビルドと検証

活用シーン

  1. 01UIプリミティブやブロックの作成
  2. 02コンポーネント例の追加
  3. 03新カテゴリのドキュメント作成
  4. 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.md
documentation.md
registry-schema.md
scripts/
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-authorityCVA バリアントのパターン
embla-carousel-reactカルーセルの実装
lucide-reactアイコンの使用パターン

要素の種類

種類例用途
registry:uibutton、card、input基本的な UI プリミティブ
registry:blocktheme-switcher、polar-checkout機能がそろったブロック
registry:examplebutton-demo使用例

参考資料

作業内容に応じて、以下をお読みください。

ディレクトリ構成

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"斜線パターンの色
既存のプロバイダー(参考)
プロバイダーキー表示名カテゴリー
clerkClerkUSER MGMT
polarPolarMONETIZATION
themeTheme SwitcherUI
logosBrand LogosBRAND
uploadthingUploadThingFILES
tinteTinteTHEMING
chartsChartsDATA VIZ
命名規則

デフォルトの抽出では、ハイフンより前の最初の部分を使用します。

  • clerk-sign-in → clerk
  • polar-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

コメント