Skip to content
Open
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
5 changes: 3 additions & 2 deletions app/about/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { Metadata } from 'next'
import { Github, ExternalLink, FileCode, Database, BarChart3, Cog, GitCommit } from 'lucide-react'
import Link from 'next/link'
import { TopBanner } from '@/components/top-banner'

export const metadata: Metadata = {
title: 'About PinchBench - Best Models for OpenClaw FAQ',
Expand Down Expand Up @@ -48,12 +49,12 @@ const faqJsonLd = {

export default function AboutPage() {
return (
<>
<div className="min-h-screen bg-background flex flex-col">
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(faqJsonLd) }}
/>
<main className="min-h-screen bg-background">
<TopBanner />
{/* Header */}
<header className="border-b border-border bg-card/50">
<div className="max-w-4xl mx-auto px-6 py-8">
Expand Down
2 changes: 2 additions & 0 deletions app/claim/error/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import Link from 'next/link'
import { Button } from '@/components/ui/button'
import { Card } from '@/components/ui/card'
import { XCircle } from 'lucide-react'
import { TopBanner } from '@/components/top-banner'

export const metadata: Metadata = {
title: 'Verification Failed — PinchBench',
Expand Down Expand Up @@ -42,6 +43,7 @@ export default async function ClaimErrorPage({ searchParams }: ClaimErrorPagePro

return (
<div className="min-h-screen bg-background flex flex-col">
<TopBanner />
{/* Header */}
<header className="border-b border-border">
<div className="max-w-4xl mx-auto px-6 py-6">
Expand Down
2 changes: 2 additions & 0 deletions app/claim/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import Link from 'next/link'
import { Github } from 'lucide-react'
import { Button } from '@/components/ui/button'
import { Card } from '@/components/ui/card'
import { TopBanner } from '@/components/top-banner'

export const metadata: Metadata = {
title: 'Claim Your PinchBench Submissions',
Expand All @@ -20,6 +21,7 @@ export default async function ClaimPage({ searchParams }: ClaimPageProps) {

return (
<div className="min-h-screen bg-background flex flex-col">
<TopBanner />
{/* Header */}
<header className="border-b border-border">
<div className="max-w-4xl mx-auto px-6 py-6">
Expand Down
2 changes: 2 additions & 0 deletions app/claim/success/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import Link from 'next/link'
import { Button } from '@/components/ui/button'
import { Card } from '@/components/ui/card'
import { CheckCircle2, Github, User } from 'lucide-react'
import { TopBanner } from '@/components/top-banner'

export const metadata: Metadata = {
title: 'Account Linked — PinchBench',
Expand All @@ -18,6 +19,7 @@ export default async function ClaimSuccessPage({ searchParams }: ClaimSuccessPag

return (
<div className="min-h-screen bg-background flex flex-col">
<TopBanner />
{/* Header */}
<header className="border-b border-border">
<div className="max-w-4xl mx-auto px-6 py-6">
Expand Down
1 change: 0 additions & 1 deletion app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,6 @@ export default function RootLayout({
<body className="font-sans antialiased">
<PostHogProvider>
<TooltipProvider delayDuration={300} disableHoverableContent>
<TopBanner />
{children}
<Footer />
</TooltipProvider>
Expand Down
2 changes: 2 additions & 0 deletions app/runs/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { PROVIDER_COLORS } from '@/lib/types'
import { fetchSubmissions, fetchBenchmarkVersions } from '@/lib/api'
import { normalizeProvider } from '@/lib/transforms'
import { formatDistanceToNow } from 'date-fns'
import { TopBanner } from '@/components/top-banner'

interface RunsPageProps {
searchParams: Promise<{ version?: string; official?: string }>
Expand Down Expand Up @@ -32,6 +33,7 @@ export default async function RunsPage({ searchParams }: RunsPageProps) {

return (
<div className="min-h-screen bg-background">
<TopBanner />
<header className="border-b border-border">
<div className="max-w-7xl mx-auto px-6 py-6">
<div className="flex items-center justify-between">
Expand Down
3 changes: 3 additions & 0 deletions app/submission/[id]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { PROVIDER_COLORS } from '@/lib/types'
import { formatDistanceToNow } from 'date-fns'
import { fetchSubmission } from '@/lib/api'
import { transformSubmission } from '@/lib/transforms'
import { TopBanner } from '@/components/top-banner'

interface SubmissionPageProps {
params: Promise<{ id: string }>
Expand All @@ -37,6 +38,7 @@ export default async function SubmissionPage({ params, searchParams }: Submissio
} catch (error) {
return (
<div className="min-h-screen bg-background">
<TopBanner />
<header className="border-b border-border">
<div className="max-w-7xl mx-auto px-6 py-6">
<div className="flex items-center justify-between">
Expand Down Expand Up @@ -89,6 +91,7 @@ export default async function SubmissionPage({ params, searchParams }: Submissio

return (
<div className="min-h-screen bg-background">
<TopBanner />
{/* Header */}
<header className="border-b border-border">
<div className="max-w-7xl mx-auto px-6 py-6">
Expand Down
2 changes: 2 additions & 0 deletions app/user/[github_username]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { fetchUserSubmissions } from '@/lib/api'
import { PROVIDER_COLORS } from '@/lib/types'
import { normalizeProvider } from '@/lib/transforms'
import { formatDistanceToNow } from 'date-fns'
import { TopBanner } from '@/components/top-banner'

interface UserPageProps {
params: Promise<{ github_username: string }>
Expand Down Expand Up @@ -51,6 +52,7 @@ export default async function UserPage({ params, searchParams }: UserPageProps)

return (
<div className="min-h-screen bg-background">
<TopBanner />
{/* Header */}
<header className="border-b border-border">
<div className="max-w-4xl mx-auto px-6 py-6">
Expand Down
261 changes: 261 additions & 0 deletions components/filter-sidebar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,261 @@
'use client'

import { useMemo, useState } from 'react'
import { Search, X, Filter, ChevronDown, ChevronRight } from 'lucide-react'
import type { LeaderboardEntry, BenchmarkVersion } from '@/lib/types'
import { PROVIDER_COLORS } from '@/lib/types'
import { VersionSelector } from '@/components/version-selector'
import { Checkbox } from '@/components/ui/checkbox'
import {
Sidebar,
SidebarContent,
SidebarHeader,
SidebarGroup,
SidebarGroupContent,
SidebarInput,
SidebarSeparator,
SidebarFooter,
} from '@/components/ui/sidebar'

interface FilterSidebarProps {
entries: LeaderboardEntry[]
versions: BenchmarkVersion[]
currentVersion: string | null
officialOnly: boolean
openWeightsOnly: boolean
providerFilters: string[]
lastUpdated: string
onOfficialOnlyChange: (officialOnly: boolean) => void
onOpenWeightsOnlyChange: (openWeightsOnly: boolean) => void
onProviderToggle: (provider: string) => void
onClearProviders: () => void
onClearAll: () => void
}

function CollapsibleGroup({
label,
defaultOpen = true,
children,
}: {
label: string
defaultOpen?: boolean
children: React.ReactNode
}) {
const [open, setOpen] = useState(defaultOpen)

return (
<SidebarGroup className="py-2">
<button
onClick={() => setOpen(!open)}
className="flex items-center gap-1.5 w-full px-2 py-1 text-xs font-medium text-sidebar-foreground/70 hover:text-sidebar-foreground transition-colors"
>
{open ? (
<ChevronDown className="h-3 w-3" />
) : (
<ChevronRight className="h-3 w-3" />
)}
{label}
</button>
{open && <SidebarGroupContent className="mt-1">{children}</SidebarGroupContent>}
</SidebarGroup>
)
}

export function FilterSidebar({
entries,
versions,
currentVersion,
officialOnly,
openWeightsOnly,
providerFilters,
lastUpdated,
onOfficialOnlyChange,
onOpenWeightsOnlyChange,
onProviderToggle,
onClearProviders,
onClearAll,
}: FilterSidebarProps) {
const [providerSearch, setProviderSearch] = useState('')

// Extract unique providers from entries, sorted by count
const providers = useMemo(() => {
const counts = new Map<string, number>()
for (const entry of entries) {
const p = entry.provider.toLowerCase()
counts.set(p, (counts.get(p) || 0) + 1)
}
return Array.from(counts.entries())
.sort((a, b) => b[1] - a[1])
.map(([name, count]) => ({ name, displayName: name.charAt(0).toUpperCase() + name.slice(1), count }))
}, [entries])

const filteredProviders = useMemo(() => {
if (!providerSearch) return providers
const q = providerSearch.toLowerCase()
return providers.filter((p) => p.name.includes(q))
}, [providers, providerSearch])

const activeFilterCount = useMemo(() => {
let count = 0
if (!officialOnly) count++
if (openWeightsOnly) count++
if (providerFilters.length > 0) count += providerFilters.length
return count
}, [officialOnly, openWeightsOnly, providerFilters])

return (
<Sidebar side="left" variant="sidebar" collapsible="offcanvas">
<SidebarHeader className="border-b border-sidebar-border px-3 py-3">
<div className="flex items-center justify-between">
<div className="flex items-center gap-2">
<Filter className="h-4 w-4 text-sidebar-foreground/70" />
<span className="text-sm font-semibold text-sidebar-foreground">Filters</span>
{activeFilterCount > 0 && (
<span className="inline-flex items-center justify-center h-5 min-w-5 px-1.5 rounded-full bg-primary text-primary-foreground text-[10px] font-bold">
{activeFilterCount}
</span>
)}
</div>
{activeFilterCount > 0 && (
<button
onClick={onClearAll}
className="text-[11px] text-sidebar-foreground/60 hover:text-sidebar-foreground transition-colors flex items-center gap-1"
>
<X className="h-3 w-3" />
Clear
</button>
)}
</div>
</SidebarHeader>

<SidebarContent className="px-0">
{/* Data Quality */}
<CollapsibleGroup label="Data Quality">
<div className="space-y-2.5 px-1">
<label className="flex items-center gap-2.5 text-xs text-sidebar-foreground/90 cursor-pointer hover:text-sidebar-foreground transition-colors pl-1">
<Checkbox
checked={!officialOnly}
onCheckedChange={(checked) => onOfficialOnlyChange(!checked)}
className="h-3.5 w-3.5 rounded border border-sidebar-border data-[state=checked]:bg-primary data-[state=checked]:border-primary"
/>
Include unofficial runs
</label>
<label className="flex items-center gap-2.5 text-xs text-sidebar-foreground/90 cursor-pointer hover:text-sidebar-foreground transition-colors pl-1">
<Checkbox
checked={openWeightsOnly}
onCheckedChange={(checked) => onOpenWeightsOnlyChange(!!checked)}
className="h-3.5 w-3.5 rounded border border-sidebar-border data-[state=checked]:bg-primary data-[state=checked]:border-primary"
/>
Open-weight only
</label>
</div>
</CollapsibleGroup>

<SidebarSeparator className="mx-3" />

{/* Version */}
<CollapsibleGroup label="Benchmark Version">
<div className="px-1">
<VersionSelector versions={versions} currentVersion={currentVersion} />
</div>
</CollapsibleGroup>

<SidebarSeparator className="mx-3" />

{/* Providers */}
<CollapsibleGroup label={`Providers (${providers.length})`}>
<div className="px-1 space-y-2">
{/* Search input */}
<div className="relative">
<Search className="absolute left-2 top-1/2 -translate-y-1/2 h-3.5 w-3.5 text-sidebar-foreground/50" />
<SidebarInput
placeholder="Search providers..."
value={providerSearch}
onChange={(e) => setProviderSearch(e.target.value)}
className="h-8 pl-7 pr-7 text-xs"
/>
{providerSearch && (
<button
onClick={() => setProviderSearch('')}
className="absolute right-2 top-1/2 -translate-y-1/2 text-sidebar-foreground/50 hover:text-sidebar-foreground"
>
<X className="h-3 w-3" />
</button>
)}
</div>

{/* Active provider filters badges */}
{providerFilters.length > 0 && (
<div className="flex flex-wrap gap-1 px-1 py-1">
{providerFilters.map((p) => {
const display = providers.find(pr => pr.name === p.toLowerCase())?.displayName || (p.charAt(0).toUpperCase() + p.slice(1))
return (
<div
key={p}
className="flex items-center gap-1 px-1.5 py-1 rounded-md bg-sidebar-accent text-[10px] font-medium text-sidebar-accent-foreground max-w-full"
>
<span
className="w-1.5 h-1.5 rounded-full flex-shrink-0"
style={{ backgroundColor: PROVIDER_COLORS[p.toLowerCase()] || '#666' }}
/>
<span className="truncate">{display}</span>
<button
onClick={() => onProviderToggle(p)}
className="text-sidebar-foreground/50 hover:text-sidebar-foreground"
>
<X className="h-2.5 w-2.5" />
</button>
</div>
)
})}
</div>
)}

{/* Provider checkbox list */}
<div className="space-y-0.5 max-h-[60vh] overflow-y-auto pr-1">
{filteredProviders.map((provider) => {
const isActive = providerFilters.some(p => p.toLowerCase() === provider.name)
const color = PROVIDER_COLORS[provider.name] || '#666'
return (
<label
key={provider.name}
className={`flex items-center gap-2.5 px-2 py-1.5 rounded-md text-xs cursor-pointer transition-colors ${
isActive
? 'bg-sidebar-accent text-sidebar-accent-foreground'
: 'text-sidebar-foreground/80 hover:bg-sidebar-accent/50 hover:text-sidebar-foreground'
}`}
>
<Checkbox
checked={isActive}
onCheckedChange={() => onProviderToggle(provider.name)}
className="h-3.5 w-3.5 rounded border border-sidebar-border data-[state=checked]:bg-primary data-[state=checked]:border-primary"
/>
<span
className="w-2 h-2 rounded-full flex-shrink-0"
style={{ backgroundColor: color }}
/>
<span className="flex-1 truncate">{provider.displayName}</span>
<span className="text-[10px] text-sidebar-foreground/50 tabular-nums">
{provider.count}
</span>
</label>
)
})}
{filteredProviders.length === 0 && (
<p className="text-xs text-sidebar-foreground/50 px-2 py-2 text-center">
No providers match "{providerSearch}"
</p>
)}
</div>
</div>
</CollapsibleGroup>
</SidebarContent>

<SidebarFooter className="border-t border-sidebar-border px-3 py-2">
<p className="text-[10px] text-sidebar-foreground/50">
Updated {lastUpdated}
</p>
</SidebarFooter>
</Sidebar>
)
}
Loading