Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions biome.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@
"recommended": true,
"style": {
"useNodejsImportProtocol": "off"
},
"a11y": {
"noSvgWithoutTitle": "off"
},
"suspicious": {
"noArrayIndexKey": "off"
}
}
},
Expand Down
3 changes: 3 additions & 0 deletions docs/src/app/MobileNav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ function MobileThemeToggle() {

return (
<button
type="button"
onClick={() => setTheme(isDark ? "light" : "dark")}
aria-label={`Switch to ${isDark ? "light" : "dark"} mode`}
style={{
Expand Down Expand Up @@ -82,6 +83,7 @@ export function MobileNav() {
const [isOpen, setIsOpen] = useState(false);
const pathname = usePathname();

// biome-ignore lint/correctness/useExhaustiveDependencies: close nav on route change
useEffect(() => {
setIsOpen(false);
}, [pathname]);
Expand Down Expand Up @@ -117,6 +119,7 @@ export function MobileNav() {
GitHub
</a>
<button
type="button"
className={`mobile-nav-toggle ${isOpen ? "open" : ""}`}
onClick={() => setIsOpen(!isOpen)}
aria-label="Toggle navigation"
Expand Down
10 changes: 5 additions & 5 deletions docs/src/app/SideNav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@

import Link from "next/link";
import { usePathname } from "next/navigation";
import { useEffect, useState, useRef, useCallback } from "react";
import { createPortal } from "react-dom";
import { useEffect, useState, useRef } from "react";
import { useTheme } from "next-themes";
import { motion } from "framer-motion";
import * as Motion from "../components/Motion";
Expand Down Expand Up @@ -167,6 +166,7 @@ function ThemePicker() {
const currentTheme = theme || "system";

return (
// biome-ignore lint/a11y/noStaticElementInteractions: hover expand for theme picker
<div
className="theme-picker-wrap"
onMouseEnter={() => setExpanded(true)}
Expand Down Expand Up @@ -195,6 +195,7 @@ function ThemePicker() {
)}
{themeOrder.map((t) => (
<button
type="button"
key={t}
className={`theme-picker-option ${currentTheme === t ? "active" : ""}`}
onClick={() => setTheme(t)}
Expand Down Expand Up @@ -262,7 +263,6 @@ export function SideNav() {
<div className="nav-links">
{links.map((link) => {
const isActive = pathname === link.href;
const hasItems = link.items && link.items.length > 0;

return (
<div key={link.href} className="nav-item-wrapper">
Expand All @@ -283,10 +283,10 @@ export function SideNav() {
}}
>
<Motion.Presence mode="sync">
{isActive && hasItems && (
{isActive && link.items && (
<Motion.Height>
<TOC
headings={link.items!.map((item) => ({
headings={link.items.map((item) => ({
id: item.id,
level: 1,
text: item.text,
Expand Down
2 changes: 2 additions & 0 deletions docs/src/app/components/CodeBlock.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ export function CopyButton({
}
};

// biome-ignore lint/correctness/useExhaustiveDependencies: animation refs are stable
useEffect(() => {
if (isFirstRender.current) {
isFirstRender.current = false;
Expand All @@ -135,6 +136,7 @@ export function CopyButton({

return (
<button
type="button"
onClick={handleCopy}
className={className ?? "copy-button"}
title="Copy to clipboard"
Expand Down
2 changes: 2 additions & 0 deletions docs/src/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ export default function Home() {
rel="noopener noreferrer"
className="tagline-brand"
>
{/* biome-ignore lint/performance/noImgElement: static export incompatible with next/image */}
<img
src="/claude-logo.jpg"
alt="Claude"
Expand All @@ -90,6 +91,7 @@ export default function Home() {
rel="noopener noreferrer"
className="tagline-brand"
>
{/* biome-ignore lint/performance/noImgElement: static export incompatible with next/image */}
<img
src="/vercel-logo.png"
alt="Vercel"
Expand Down
5 changes: 3 additions & 2 deletions docs/src/components/TOC.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,12 @@ export const TOC: React.FC<TableOfContentsProps> = ({
const ids = React.useMemo(() => headings.map((h) => h.id), [headings]);
const activeHeading = useActiveScrollElement(ids);

// biome-ignore lint/correctness/useExhaustiveDependencies: reads DOM measurements when active heading changes
React.useEffect(() => {
if (activeLink.current) {
setStyle({
top: activeLink.current.offsetTop + "px",
height: activeLink.current.offsetHeight + "px",
top: `${activeLink.current.offsetTop}px`,
height: `${activeLink.current.offsetHeight}px`,
});
}
}, [activeHeading]);
Expand Down
5 changes: 3 additions & 2 deletions docs/src/hooks/useActiveScrollElement.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ export const useActiveScrollElement = (
}
}, []);

// biome-ignore lint/correctness/useExhaustiveDependencies: updateActive is stable via ref
useEffect(() => {
if (typeof window === "undefined") return;

Expand Down Expand Up @@ -86,7 +87,7 @@ export const useActiveScrollElement = (
return;
}

const index = ids.findIndex((i) => i === id);
const index = ids.indexOf(id);
const previous = ids[Math.max(index - 1, 0)];
updateActive(previous);
}
Expand Down Expand Up @@ -149,7 +150,7 @@ export const useActiveScrollElement = (
handleResize();
if (window.scrollY > 0) handleScroll();

sections.forEach((heading) => scrollObserver.observe(heading));
for (const heading of sections) scrollObserver.observe(heading);
resizeObserver.observe(document.body);
document.addEventListener("click", handleHash);
window.addEventListener("scroll", handleScroll, { passive: true });
Expand Down
2 changes: 2 additions & 0 deletions tests/tools/budget-integration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,8 @@ describe("createAgentTools budget integration", () => {
expect(openRouterModels).toBeInstanceOf(Map);
expect(openRouterModels!.has("anthropic/claude-sonnet-4-5")).toBe(true);

if (!openRouterModels) throw new Error("expected openRouterModels");

const model = openRouterModels.get("anthropic/claude-sonnet-4-5")!;
expect(model.contextLength).toBe(200000);
expect(model.pricing.inputPerToken).toBe(0.000003);
Expand Down