add-hook について
shadcn-hooks にフックを追加するコントリビューター向けの手順ガイドです。実装、登録、ドキュメント、テストを扱い、生成物の編集や同期はユーザーに委ねます。
主な機能
- 01フック実装と依存関係リストの作成
- 02インタラクティブなデモと文書の作成
- 03レジストリと紹介ページの更新
- 04リファレンス文書と関数表の追加
- 05lint とテストによる検証
- 06生成物の編集と同期コマンドの禁止
活用シーン
- 01shadcn-hooks へのフック追加
- 02プロジェクト規約に沿ったファイル整備
- 03フックの文書とテストの検証
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ debbl/ shadcn-hooks --skill add-hookインストール後、Claude Code で/add-hookを入力して読み込まれたか確認します。
詳細
フックの追加
shadcn-hooks プロジェクトに新しいフックを追加するためのガイドです。信頼できる情報源は src/registry/hooks/ です。packages/shadcn-hooks/ ディレクトリは自動生成されるため、手動で編集してはいけません。このスキルの一環として sync コマンドを実行しないでください。必要なときにユーザーが手動で実行します。
チェックリスト
このチェックリストをコピーして、進捗を記録してください。
Add Hook: use-<name>
- [ ] Step 1: Create registry entry (src/registry/hooks/use-<name>/)
- [ ] Step 2: Register in meta.json
- [ ] Step 3: Update introduction.mdx
- [ ] Step 4: Create skill reference doc
- [ ] Step 5: Update skill SKILL.md function table
- [ ] Step 6: Verify (lint + test)
ステップ 1:レジストリエントリーを作成する
src/registry/hooks/use-<name>/ ディレクトリを作成し、5 つのファイルを追加します。
1a. index.ts — フックの実装
ルール:
@/registry/hooks/...と@/registry/lib/...のインポートエイリアスを使用します- 名前付きエクスポート:
export function use<Name>(...) - すべての公開型を同じファイルからエクスポートします
- TypeScript の strict モードを使用し、
anyは使いません - 可能な場合は既存のフックを再利用します(例:
useBoolean、useEventListener、useMemoizedFn)
参照例 — シンプルなフック:
// src/registry/hooks/use-previous/index.ts
import { useRef } from 'react'
export type ShouldUpdateFunc<T> = (prev?: T, next?: T) => boolean
const defaultShouldUpdate = <T>(a?: T, b?: T) => !Object.is(a, b)
export default function usePrevious<T>(
state: T,
shouldUpdate: ShouldUpdateFunc<T> = defaultShouldUpdate,
): T | undefined {
const prevRef = useRef<T>()
const curRef = useRef<T>()
if (shouldUpdate(curRef.current, state)) {
prevRef.current = curRef.current
curRef.current = state
}
return prevRef.current
}
参照例 — ほかのフックを組み合わせるフック:
// src/registry/hooks/use-hover/index.ts
import { useBoolean } from '@/registry/hooks/use-boolean'
import { useEventListener } from '@/registry/hooks/use-event-listener'
import type { BasicTarget } from '@/registry/lib/create-effect-with-target'
export interface UseHoverOptions {
onEnter?: () => void
onLeave?: () => void
onChange?: (isHovering: boolean) => void
}
export function useHover(
target: BasicTarget,
options?: UseHoverOptions,
): boolean {
const { onEnter, onLeave, onChange } = options || {}
const [state, { setTrue, setFalse }] = useBoolean(false)
useEventListener(
'mouseenter',
() => {
onEnter?.()
setTrue()
onChange?.(true)
},
{ target },
)
useEventListener(
'mouseleave',
() => {
onLeave?.()
setFalse()
onChange?.(false)
},
{ target },
)
return state
}
1b. registry-item.json — 依存関係
{
"registryDependencies": [
"@shadcnhooks/use-dependency-a",
"@shadcnhooks/use-dependency-b"
]
}
- このフックが依存するすべてのフック/ライブラリを、
@shadcnhooks/を前置して列挙します - 依存関係がない場合:
{ "registryDependencies": [] }
1c. demo/demo-01.tsx — デモコンポーネント
'use client'
import { use<Name> } from '..'
export function Demo01() {
// Interactive demo showcasing the hook
}
ルール:
- クライアントコンポーネント(
'use client')にします - フックは
'..'(親ディレクトリ)からインポートします ~/components/ui/...の shadcn UI コンポーネント(例:Button、Card、Input)を使用します- デモは対話的にし、フックの動作が明確にわかるようにします
1d. index.mdx — ドキュメントページ
---
title: use<Name>
description: A hook to <description>
---
import { Demo01 } from './demo/demo-01'
<Demo01 />
## Installation
<Tabs items={['CLI', 'Manual']}>
<Tab>
<InstallCLI value='use-<name>' />
</Tab>
<Tab>
Copy and paste the following code into your project.
<RegistrySourceCode value='use-<name>' />
</Tab>
</Tabs>
## API
\`\`\`ts
// Full type declarations here
\`\`\`
## Credits
- [use-<name>](credit-link)
注:
- フックに内部依存関係がある場合は、Manual タブの下に複数の
<RegistrySourceCode>エントリーを追加します(use-toggleを含むuse-booleanを参照) - API セクションには、完全な TypeScript 型宣言を含めます
1e. index.test.ts — テスト
import { act, renderHook } from '@testing-library/react'
import { describe, expect, it } from 'vitest'
import { use<Name> } from './index'
describe('use<Name>', () => {
it('should ...', () => {
const { result } = renderHook(() => use<Name>(...))
expect(result.current).toBe(...)
})
})
ルール:
vitestと@testing-library/reactを使用します'./index'からインポートします- デフォルトの動作、状態の変化、エッジケース、コールバックを網羅します
- DOM ベースのフックでは、
beforeEachで要素を作成し、afterEachでクリーンアップします
ステップ 2:meta.json に登録する
src/registry/hooks/meta.json の適切なカテゴリに "use-<name>" を追加します。
---State---— 状態管理フック---Advanced---— メモ化、参照、高度なパターン---Lifecycle---— エフェクト、タイマー、マウント/アンマウント---Browser---— DOM、イベント、ブラウザー API---Dev---— 開発/デバッグ用ユーティリティ---External---— 外部ライブラリのラッパー
ステップ 3:紹介ページを更新する
content/docs/introduction.mdx の適切なカテゴリセクションに、新しいフックを追加します。
- State Management — 状態管理フック
- Advanced — メモ化、参照、高度なパターン
- Lifecycle & Effects — エフェクト、タイマー、マウント/アンマウント
- Browser — DOM、イベント、ブラウザー API
- Dev — 開発/デバッグ用ユーティリティ
- External Libraries — 外部ライブラリのラッパー
カテゴリ内でアルファベット順になるように行を追加します。
- [`use<Name>`](/docs/hooks/use-<name>) - <Short description>
ステップ 4:スキルのリファレンスを作成する
skills/shadcn-hooks/references/use<Name>.md を作成します。
# use<Name>
<One-line description>.
## Usage
\`\`\`tsx
import { use<Name> } from '@/hooks/use-<name>'
function Component() {
// Minimal usage example
}
\`\`\`
## Type Declarations
\`\`\`ts
// Full type signatures
\`\`\`
## Parameters
| Parameter | Type | Default | Description |
| --------- | ---- | ------- | ----------- |
| ... | ... | ... | ... |
## Returns
| Type | Description |
| ---- | ----------- |
| ... | ... |
ステップ 5:スキルの関数テーブルを更新する
skills/shadcn-hooks/SKILL.md の適切なカテゴリテーブルにエントリーを追加します。
| [`use<Name>`](references/use<Name>.md) | <description> | AUTO |
- 単独で動作するフックには
AUTOを使用します - 外部 npm パッケージをラップするフックには
EXTERNALを使用します
ステップ 6:確認する
- リンターを実行します:編集したファイルに lint エラーがないか確認します
- テストを実行します:
pnpm test run src/registry/hooks/use-<name>/index.test.ts - 開発サーバーを実行中の場合、ドキュメントページが正しく表示されることを確認します
packages/shadcn-hooks/を変更せず、pnpm run syncやpnpm --dir packages/shadcn-hooks syncを実行しないでください。この手順はユーザーに任せます
注
packages/shadcn-hooks/は自動生成されます。このスキルの一環として、そのディレクトリ内のファイルを手動で編集しないでください。- このスキルから
syncコマンドを実行しないでください。変更内容を確認した後、ユーザーが手動で sync を実行します。 packages/shadcn-hooks/src/index.tsのエクスポートも自動管理されるため、手動で編集する必要はありません。
コメント
Markdown 対応