- Add 13 documentation pages under /docs (getting-started, concepts, SDK refs, integrations, API reference, self-hosting, OpenCode plugin) - Shared docs layout with collapsible sidebar navigation - Update model pricing across all SDKs: add GPT-5.x, GPT-4.1, o3/o4-mini, Claude 4.5 series, claude-opus-4-6 - Update trace-analytics context window lookup with current models
122 lines
3.5 KiB
TypeScript
122 lines
3.5 KiB
TypeScript
"use client";
|
|
|
|
import { useState } from "react";
|
|
|
|
interface NavItem {
|
|
title: string;
|
|
href: string;
|
|
}
|
|
|
|
interface NavSection {
|
|
heading: string;
|
|
items: NavItem[];
|
|
}
|
|
|
|
const navigation: NavSection[] = [
|
|
{
|
|
heading: "Overview",
|
|
items: [
|
|
{ title: "Introduction", href: "/docs" },
|
|
{ title: "Getting Started", href: "/docs/getting-started" },
|
|
{ title: "Core Concepts", href: "/docs/concepts" },
|
|
],
|
|
},
|
|
{
|
|
heading: "SDKs",
|
|
items: [
|
|
{ title: "Python SDK", href: "/docs/python-sdk" },
|
|
{ title: "TypeScript SDK", href: "/docs/typescript-sdk" },
|
|
],
|
|
},
|
|
{
|
|
heading: "Integrations",
|
|
items: [
|
|
{ title: "OpenAI", href: "/docs/integrations/openai" },
|
|
{ title: "Anthropic", href: "/docs/integrations/anthropic" },
|
|
{ title: "LangChain", href: "/docs/integrations/langchain" },
|
|
],
|
|
},
|
|
{
|
|
heading: "Tools",
|
|
items: [{ title: "OpenCode Plugin", href: "/docs/opencode-plugin" }],
|
|
},
|
|
{
|
|
heading: "Reference",
|
|
items: [
|
|
{ title: "REST API", href: "/docs/api-reference" },
|
|
{ title: "Self-Hosting", href: "/docs/self-hosting" },
|
|
],
|
|
},
|
|
];
|
|
|
|
function SidebarContent() {
|
|
return (
|
|
<nav className="space-y-6">
|
|
{navigation.map((section) => (
|
|
<div key={section.heading}>
|
|
<h4 className="text-xs font-semibold uppercase tracking-wider text-neutral-500 mb-2 px-3">
|
|
{section.heading}
|
|
</h4>
|
|
<ul className="space-y-0.5">
|
|
{section.items.map((item) => (
|
|
<li key={item.href}>
|
|
<a
|
|
href={item.href}
|
|
className="block px-3 py-1.5 text-sm text-neutral-400 hover:text-neutral-100 hover:bg-neutral-800/50 rounded-md transition-colors"
|
|
>
|
|
{item.title}
|
|
</a>
|
|
</li>
|
|
))}
|
|
</ul>
|
|
</div>
|
|
))}
|
|
</nav>
|
|
);
|
|
}
|
|
|
|
export function DocsSidebar() {
|
|
const [mobileOpen, setMobileOpen] = useState(false);
|
|
|
|
return (
|
|
<>
|
|
<button
|
|
type="button"
|
|
onClick={() => setMobileOpen(!mobileOpen)}
|
|
className="lg:hidden fixed bottom-4 right-4 z-50 w-12 h-12 rounded-full bg-emerald-500 text-neutral-950 shadow-lg shadow-emerald-500/25 flex items-center justify-center"
|
|
aria-label="Toggle navigation"
|
|
>
|
|
<svg className="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
|
|
{mobileOpen ? (
|
|
<path strokeLinecap="round" strokeLinejoin="round" d="M6 18L18 6M6 6l12 12" />
|
|
) : (
|
|
<path strokeLinecap="round" strokeLinejoin="round" d="M4 6h16M4 12h16M4 18h16" />
|
|
)}
|
|
</svg>
|
|
</button>
|
|
|
|
{mobileOpen && (
|
|
<div className="lg:hidden fixed inset-0 z-40">
|
|
<div
|
|
className="absolute inset-0 bg-neutral-950/80 backdrop-blur-sm"
|
|
onClick={() => setMobileOpen(false)}
|
|
onKeyDown={(e) => {
|
|
if (e.key === "Escape") setMobileOpen(false);
|
|
}}
|
|
role="button"
|
|
tabIndex={0}
|
|
aria-label="Close navigation"
|
|
/>
|
|
<div className="absolute left-0 top-14 bottom-0 w-72 bg-neutral-950 border-r border-neutral-800/50 p-6 overflow-y-auto">
|
|
<SidebarContent />
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
<aside className="hidden lg:block w-64 flex-shrink-0 border-r border-neutral-800/50 sticky top-14 h-[calc(100vh-3.5rem)] overflow-y-auto py-8 px-4">
|
|
<SidebarContent />
|
|
</aside>
|
|
</>
|
|
);
|
|
}
|