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
11 changes: 6 additions & 5 deletions src/app.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { Byline } from '@kevinschaich/components'
import { BENCH, MODELS } from '@site/data'
import { BENCH, MODELS, TABS } from '@site/data'
import { ModelPage } from '@site/pages/model'
import { Overview } from '@site/pages/overview'
import { Overview, tabFromPath } from '@site/pages/overview'

/** The page for a path under BENCH.path: the overview, or one model's page. */
/** The page for a path under BENCH.path: an overview tab, or one model's page. */
export function App({ path }: { path: string }) {
const id = path.replace(BENCH.path, '').replace(/\/$/, '')
const model = id ? MODELS.find(candidate => candidate.id === id) : undefined
const tab = tabFromPath(path)
const model = tab ? undefined : id ? MODELS.find(candidate => candidate.id === id) : undefined
return (
<div className="mx-auto flex min-h-svh max-w-6xl flex-col gap-8 px-4 py-8 sm:px-6 sm:py-10">
<header className="flex flex-wrap items-end justify-between gap-3">
Expand All @@ -18,7 +19,7 @@ export function App({ path }: { path: string }) {
</div>
<Byline repo={BENCH.repository} />
</header>
{model ? <ModelPage model={model} /> : <Overview />}
{model ? <ModelPage model={model} /> : <Overview initialTab={tab ?? TABS[0].id} />}
</div>
)
}
13 changes: 12 additions & 1 deletion src/data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,14 @@ export const BENCH = {
origin: 'https://darkgrade.com',
}

/** The overview's tabs; each after the first is its own page at BENCH.path + id. */
export const TABS = [
{ id: 'results', label: 'Results' },
{ id: 'tradeoff', label: 'Accuracy vs. speed' },
{ id: 'method', label: 'How we test' },
{ id: 'script', label: 'The script' },
]

export interface Reason {
area: string
weight: number
Expand Down Expand Up @@ -162,5 +170,8 @@ export function routes(): Route[] {
},
})
)
return [overview, ...models]
const tabs = TABS.slice(1).map(
(tab): Route => ({ ...overview, path: `${tab.id}/`, title: `${tab.label} | ${BENCH.name} by Darkgrade` })
)
return [overview, ...tabs, ...models]
}
38 changes: 19 additions & 19 deletions src/pages/overview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,11 @@ import {
TabsTrigger,
TradeoffChart,
} from '@kevinschaich/components'
import { BENCH, FILTERS, MODELS, type ModelSummary, RUN, percent, sampleSentence, seconds } from '@site/data'
import { BENCH, FILTERS, TABS, MODELS, type ModelSummary, RUN, percent, sampleSentence, seconds } from '@site/data'
import { Method } from '@site/pages/method'
import { Script } from '@site/pages/script'
import { useEffect, useState } from 'react'

const TABS = [
{ id: 'results', label: 'Results' },
{ id: 'tradeoff', label: 'Accuracy vs. speed' },
{ id: 'method', label: 'How we test' },
{ id: 'script', label: 'The script' },
]

const COLUMNS: LeaderboardColumn<ModelSummary>[] = [
{
key: 'model',
Expand Down Expand Up @@ -52,12 +45,15 @@ const COLUMNS: LeaderboardColumn<ModelSummary>[] = [
},
]

function tabFromHash(): string {
if (typeof location === 'undefined') return TABS[0].id
const id = location.hash.replace(/^#/, '')
return TABS.some(tab => tab.id === id) ? id : TABS[0].id
/** The tab a path under BENCH.path names; the first tab is the bench's root. */
export function tabFromPath(path: string): string | undefined {
const id = path.replace(BENCH.path, '').replace(/\/$/, '')
if (!id) return TABS[0].id
return TABS.some(tab => tab.id === id) ? id : undefined
}

const tabPath = (id: string): string => (id === TABS[0].id ? BENCH.path : `${BENCH.path}${id}/`)

/** One row of filters per category, each a one-of-a-few choice. */
function Filters({ chosen, choose }: { chosen: Record<string, string>; choose: (filter: string, option: string) => void }) {
return (
Expand All @@ -77,20 +73,24 @@ function Filters({ chosen, choose }: { chosen: Record<string, string>; choose: (
)
}

export function Overview() {
const [tab, setTab] = useState(TABS[0].id)
export function Overview({ initialTab }: { initialTab: string }) {
const [tab, setTab] = useState(initialTab)
const [chosen, setChosen] = useState<Record<string, string>>(Object.fromEntries(FILTERS.map(filter => [filter.id, 'all'])))
const shown = MODELS.filter(model => FILTERS.every(filter => filter.options.find(option => option.id === chosen[filter.id])!.matches(model)))
const choose = (filter: string, option: string) => setChosen(previous => ({ ...previous, [filter]: option }))
useEffect(() => {
setTab(tabFromHash())
const onHash = () => setTab(tabFromHash())
window.addEventListener('hashchange', onHash)
return () => window.removeEventListener('hashchange', onHash)
const legacy = location.hash.replace(/^#/, '')
if (TABS.some(item => item.id === legacy)) {
history.replaceState(null, '', tabPath(legacy))
setTab(legacy)
}
const onPop = () => setTab(tabFromPath(location.pathname) ?? TABS[0].id)
window.addEventListener('popstate', onPop)
return () => window.removeEventListener('popstate', onPop)
}, [])
const select = (id: string) => {
setTab(id)
history.replaceState(null, '', `#${id}`)
history.pushState(null, '', tabPath(id))
}

return (
Expand Down
3 changes: 2 additions & 1 deletion vercel.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,6 @@
"destination": "/toolbench/",
"permanent": false
}
]
],
"trailingSlash": true
}
Loading