Pivot 是一个现代化的 React UI 组件库,专门为 OpenAPI 规范设计。它提供了一套可复制粘贴的组件,帮助开发者快速构建美观、功能强大的 API 文档界面。
设计理念
我们相信优秀的设计是软件成功的关键因素之一。对于 API 文档来说,清晰、直观的界面设计能够显著提升开发者的使用体验,降低 API 的学习成本。
一些开发者在使用 API 文档时会考虑:
- "这个 API 文档是否清晰易懂?"
- "示例代码是否完整准确?"
- "我能否快速找到需要的信息?"
糟糕的文档设计会让开发者望而却步。混乱的布局、缺失的示例、复杂的导航都会影响开发者的使用体验。
优秀的文档设计表明团队对细节的关注。这让开发者相信:"如果他们对文档都如此用心,那么 API 的质量一定也很可靠!"
核心特性
🚀 丰富的组件库
- 89+ 专业组件 - 涵盖 OpenAPI 规范的各个方面
- 原子化设计 - 可组合的小组件,灵活构建复杂界面
- 类型安全 - 完整的 TypeScript 类型定义
🎨 现代化设计
- 暗色模式 - 完整的暗色主题支持
- 响应式 - 移动端友好的设计
- 可定制 - 基于 Tailwind CSS,易于定制和扩展
- 无障碍 - 遵循 WAI-ARIA 标准
🛠️ 完善的工具链
- 5+ 专业 Hooks - useOpenApi、useOpenApiLoader、useOpenApiCombined、useOperation、useSchema 等
- 智能工具函数 - resolveRef、generateExample、schema-utils、type-utils 等专业工具
- 国际化支持 - 内置中英文翻译,可扩展多语言
- 多语言代码生成 - 支持 cURL、Python、PHP、Laravel、TypeScript 等
📦 Registry 系统
- 按需安装 - 只安装需要的组件,减少包体积
- 源码透明 - 所有组件源码可见,方便定制
- 版本管理 - 通过 registry 系统管理组件版本
项目架构
Pivot 采用了与 shadcn/ui 类似的 registry 系统,但专为 OpenAPI 场景优化:
目录结构
pivot/
├── registry/ # 可分发组件库
│ └── default/
│ ├── ui/ # 89+ UI 组件(OpenAPI 专用)
│ ├── hooks/ # 5+ React Hooks
│ ├── lib/ # 工具函数和库
│ │ ├── i18n/ # 国际化系统
│ │ └── *.ts # 工具函数
│ └── example/ # 演示组件
├── components/ # 文档站点组件(不分发)
├── content/docs/ # MDX 文档内容
└── app/ # Next.js App Router 页面
组件分类
📊 状态与标识组件 (8个)
显示 API 状态、方法和重要标识:
status-code- HTTP 状态码显示method-label- HTTP 方法标签required-badge- 必填参数标识deprecated-badge- 废弃 API 标识format-badge- 数据格式标识style-badge- 样式类型标识required-marker- 简单的必填标记in-label- 参数位置标签
📋 数据展示组件 (15个)
展示和处理 OpenAPI 数据结构:
schema-display- OpenAPI Schema 数据展示schema-composition-display- 复合模式显示schema-with-example-viewer- 带示例的模式查看器parameter-item- API 参数条目parameter-group- 参数分组显示parameter-name- 参数名称显示parameter-description- 参数描述response-item- 响应条目response-group- 响应分组type-indicator- 数据类型指示器constraint-display- 约束条件显示default-value-display- 默认值显示const-value- 常量值显示enum-values-display- 枚举值显示media-type-display- 媒体类型显示
📄 内容展示组件 (9个)
用于展示文档内容、示例和描述:
example-display- 示例数据显示examples-display- 多个示例展示description-display- 描述信息展示enum-values- 枚举值显示code-markdown- Markdown 代码块external-docs-display- 外部文档展示license-display- 许可证显示contact-display- 联系信息显示value-display- 通用值显示
🔧 交互功能组件 (10个)
提供用户交互功能:
copy-button- 一键复制按钮expand-collapse- 展开/折叠切换language-switcher- 语言切换器media-type-selector- 媒体类型选择器try-it-out-panel- API 在线测试面板resizable-sidebar- 可调整大小的侧边栏component-tabs- 组件标签页component-items-list- 组件列表component-detail- 组件详情webhook-display- Webhook 显示
🏗️ 布局组件 (15个)
用于组织和布局的容器组件:
operation-detailed-layout- 操作详情布局operation-list-layout- 操作列表布局navigation-sidebar- 导航侧边栏operation-box- API 操作容器operation-detail- 操作详情容器operation-path- 操作路径path-segment- 路径片段section-title- 章节标题accordion-components-section- 手风琴组件章节info-section- API 基本信息components-section- 组件章节servers-section- 服务器章节server- 服务器定义server-display- 服务器信息显示server-variable- 服务器变量
🌍 API 结构组件 (20个)
处理各种文档结构和章节:
parameters-section- 参数章节request-body-section- 请求体章节responses-section- 响应章节response-content-section- 响应内容章节response-headers-table- 响应头表格headers-section- 请求头章节header-item- 头部条目links-section- 链接章节link-item- 链接条目callback-display- 回调函数显示security-section- 安全章节security-requirements-section- 安全要求章节security-scheme- 安全模式security-scheme-display- 安全模式显示security-requirement-item- 安全要求条目oauth-flow- OAuth 流程oauth-flow-details- OAuth 流程详情scheme-type- 模式类型webhook-label- Webhook 标签path-item-display- 路径项显示
💻 代码生成组件 (6个)
支持多种编程语言的代码生成:
codegen- 通用代码生成器curl-generator- cURL 命令生成python-generator- Python 代码生成php-generator- PHP 代码生成laravel-generator- Laravel 代码生成typescript-generator- TypeScript 代码生成
🔄 高级功能组件 (6个)
专业的高级功能组件:
terms-of-service- 服务条款faker-example- 虚拟数据示例生成pattern-display- 正则模式显示servers- 服务器列表security-schemes- 安全模式列表external-docs- 外部文档链接
工具库(registry/default/lib/)
🎣 React Hooks (5个)
import { useOpenApi } from "@/hooks/use-openapi";
import { useOpenApiLoader } from "@/hooks/use-openapi-loader";
import { useOpenApiCombined } from "@/hooks/use-openapi-combined";
import { useOperation } from "@/hooks/use-operation";
import { useSchema } from "@/hooks/use-schema";🛠️ 工具函数 (8个)
import { resolveRef } from "@/lib/resolve-ref";
import { generateExample } from "@/lib/generate-example";
import { isReferenceObject } from "@/lib/schema-utils";
import { getSchemaType } from "@/lib/type-utils";🌍 国际化系统
import { useI18n, I18nProvider } from "@/lib/i18n";
// 支持的语言
-中文(zh) - 英文(en);安装
快速开始
批量安装
# 安装所有 UI 组件
npx shadcn@latest add https://pivotkit.vercel.app/r/index.json
# 安装 Hooks
npx shadcn@latest add https://pivotkit.vercel.app/r/hooks.json
# 安装工具库
npx shadcn@latest add https://pivotkit.vercel.app/r/lib.json手动安装
使用示例
基础组件使用
import { StatusCode } from "@/components/ui/status-code";
import { MethodLabel } from "@/components/ui/method-label";
import { OperationDetail } from "@/components/ui/operation-detail";
export default function ApiEndpoint({ operation, path, method }) {
return (
<div className="space-y-4">
<div className="flex items-center gap-3">
<MethodLabel method={method} />
<code className="text-sm">{path}</code>
<StatusCode code={200} />
</div>
<OperationDetail
operation={operation}
path={path}
method={method}
components={spec.components}
/>
</div>
);
}使用 Hooks 处理 OpenAPI
import { useOpenApi } from "@/hooks/use-openapi";
import { useOpenApiLoader } from "@/hooks/use-openapi-loader";
export default function ApiExplorer({ url }) {
const { spec, loading, error } = useOpenApiLoader({
type: "url",
data: url,
});
const openApi = useOpenApi(spec);
const operations = openApi?.getOperationsByTag() || {};
if (loading) return <div>加载中...</div>;
if (error) return <div>加载失败: {error}</div>;
return (
<div>
{Object.entries(operations).map(([tag, ops]) => (
<div key={tag} className="mb-8">
<h2 className="text-2xl font-bold mb-4">{tag}</h2>
{ops.map((op) => (
<OperationBox
key={`${op.path}-${op.method}`}
operation={op.operation}
path={op.path}
method={op.method}
/>
))}
</div>
))}
</div>
);
}完整的布局组件
import { OperationDetailedLayout } from "@/components/ui/operation-detailed-layout";
export default function ApiDocsPage() {
return (
<OperationDetailedLayout
url="https://api.example.com/openapi.json"
selectedPath="/users/{id}"
selectedMethod="GET"
showCodegen={true}
showTryPanel={true}
onSelectOperation={(path, method, operation) => {
console.log("选中操作:", path, method);
}}
/>
);
}组件生态
🔧 工具 Hooks
// 强大的 OpenAPI 处理 hook
const openApi = useOpenApi(spec);
const operations = openApi.getOperationsByTag();
const resolved = openApi.resolve(reference);
// 数据加载 hook
const { spec, loading, error } = useOpenApiLoader({
type: "url",
data: "https://api.example.com/openapi.json",
});
// 结合加载和解析的 hook
const { spec, openApi, operations } = useOpenApiCombined({
type: "url",
data: "https://api.example.com/openapi.json",
});
// 操作专用 hook
const operation = useOperation(operationData, path, method);
const parameters = operation.getParameters();
// Schema 处理 hook
const schema = useSchema(schemaData, components);
const properties = schema.getProperties();🌍 国际化支持
import { useI18n } from "@/lib/i18n";
function MyComponent() {
const { t, locale, setLocale } = useI18n();
return (
<div>
<p>{t("operation.parameters")}</p>
<button onClick={() => setLocale("zh")}>中文</button>
<button onClick={() => setLocale("en")}>English</button>
</div>
);
}🎯 代码生成
import { generateExample } from "@/lib/generate-example";
// 根据 OpenAPI Schema 生成示例数据
const example = generateExample(schema, components, {
maxDepth: 3,
includeReadOnly: false,
});最佳实践
1. 遵循组件层次
- registry/default/ui 组件:使用
../lib/下的工具 - components 组件:使用
@/hooks/和@/lib/下的工具
2. 样式处理
import { cn } from "@/lib/utils";
// 正确使用 cn() 合并样式
<div className={cn("base-styles", "additional-styles", className)} />;3. 引用解析
import { resolveRef } from "@/lib/resolve-ref";
// 解析 OpenAPI 引用
const resolved = resolveRef(reference, components);4. 类型安全
import type { OpenAPIV3 } from "openapi-types";
interface MyComponentProps {
operation: OpenAPIV3.OperationObject;
components?: OpenAPIV3.ComponentsObject;
}开始使用
准备好开始了吗?查看我们的快速开始指南,或者直接在在线演示中体验 Pivot 的强大功能。
推荐阅读
- 📖 快速开始 - 5 分钟上手指南
- 🏗️ 架构设计 - 了解设计原理
- 🎯 组件总览 - 浏览所有可用组件
- 🔧 Hooks 和工具 - 深入了解工具链
- 🎨 模板示例 - 预制模板和布局
本项目深受 shadcn/ui 的启发。