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 的启发。