关于 add-hook
面向 shadcn-hooks 贡献者的新增 Hook 指南,按步骤覆盖注册、实现、文档和测试。它明确区分源码与自动生成目录,并要求把同步留给用户处理。
主要功能
- 01创建 Hook 实现与依赖清单
- 02编写交互式演示和文档
- 03更新注册表与介绍页
- 04添加参考文档和函数表条目
- 05运行 lint 与测试验证
- 06禁止编辑生成目录或执行同步
适用场景
- 01为 shadcn-hooks 添加新 Hook
- 02按项目规范补齐 Hook 文件
- 03验证 Hook 文档与测试
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ debbl/ shadcn-hooks --skill add-hook安装后在 Claude Code 中输入/add-hook确认已加载。
详细介绍
添加 Hook
向 shadcn-hooks 项目添加新 Hook 的指南。唯一可信来源是 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 — Hook 实现
规则:
- 使用
@/registry/hooks/...和@/registry/lib/...导入别名 - 命名导出:
export function use<Name>(...) - 在同一文件中导出所有公共类型
- 使用严格的 TypeScript,不得使用
any - 尽可能复用现有 Hook(例如
useBoolean、useEventListener、useMemoizedFn)
参考示例——简单的 Hook:
// 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
}
参考示例——组合其他 Hook 的 Hook:
// 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"
]
}
- 列出此 Hook 所依赖的所有 Hook/库,并为其添加
@shadcnhooks/前缀 - 如果没有依赖项:
{ "registryDependencies": [] }
1c. demo/demo-01.tsx — 演示组件
'use client'
import { use<Name> } from '..'
export function Demo01() {
// Interactive demo showcasing the hook
}
规则:
- 必须是客户端组件(
'use client') - 从
'..'(父目录)导入 Hook - 使用来自
~/components/ui/...的 shadcn UI 组件(例如Button、Card、Input) - 演示应具有交互性,并清晰展示 Hook 的行为
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)
注意:
- 如果此 Hook 存在内部依赖项,请在 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 的 Hook,在
beforeEach中创建元素,并在afterEach中清理
第 2 步:在 meta.json 中注册
在 src/registry/hooks/meta.json 的相应类别下添加 "use-<name>":
---State---— 状态管理 Hook---Advanced---— 记忆化、引用、高级模式---Lifecycle---— Effect、计时器、挂载/卸载---Browser---— DOM、事件、浏览器 API---Dev---— 开发与调试工具---External---— 外部库的封装
第 3 步:更新介绍页面
在 content/docs/introduction.mdx 的相应类别下添加新 Hook:
- State Management — 状态管理 Hook
- Advanced — 记忆化、引用、高级模式
- Lifecycle & Effects — Effect、计时器、挂载/卸载
- 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 |
- 独立 Hook 使用
AUTO - 封装外部 npm 包的 Hook 使用
EXTERNAL
第 6 步:验证
- 运行代码检查工具:检查已编辑文件是否存在代码检查错误
- 运行测试:
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命令。用户会在检查更改后手动运行同步。 packages/shadcn-hooks/src/index.ts中的导出也由自动流程管理,无需手动编辑。
评论
支持 Markdown