feat(stats): redesign model hero

This commit is contained in:
Adam 2026-07-02 14:41:22 -05:00
parent 7457139849
commit 299daa2815
No known key found for this signature in database
GPG key ID: 9CB48779AF150E75

View file

@ -27,6 +27,7 @@ import {
findModelCatalogEntry,
formatCatalogLabName,
getModelCatalog,
type ModelCatalog,
type ModelCatalogCost,
type ModelCatalogEntry,
} from "../model-catalog"
@ -174,7 +175,12 @@ export default function StatsModel() {
<Show when={catalogEntry() || stats() !== undefined} fallback={<ModelLoading />}>
<Show when={catalogEntry() || stats()} fallback={<ModelNotFound lab={labParam()} model={modelParam()} />}>
<>
<ModelHero data={stats() ?? null} catalog={catalogEntry() ?? null} labName={labName()} />
<ModelHero
data={stats() ?? null}
catalog={catalogEntry() ?? null}
catalogData={catalog() ?? null}
labName={labName()}
/>
<ModelOverview data={stats() ?? null} />
<ModelUsageSection data={stats()?.usage ?? []} />
<ModelUsersSection data={stats()?.usage ?? []} />
@ -249,116 +255,170 @@ function ModelNotFound(props: { lab: string; model: string }) {
)
}
function ModelHero(props: { data: StatsModelData | null; catalog: ModelCatalogEntry | null; labName: string }) {
function ModelHero(props: {
data: StatsModelData | null
catalog: ModelCatalogEntry | null
catalogData: ModelCatalog | null
labName: string
}) {
const i18n = useI18n()
const language = useLanguage()
const labId = () => props.catalog?.lab ?? props.data?.provider ?? props.labName
const modelId = () => props.catalog?.id ?? props.data?.model ?? i18n.t("model.fallback")
const modelName = () => props.catalog?.name ?? props.data?.model ?? i18n.t("model.fallback")
const weights = () => props.catalog?.weights[0]
const labs = () => props.catalogData?.labs ?? []
const labModels = () =>
props.catalogData?.labs.find((lab) => lab.id === providerSlug(labId()))?.models ?? (props.catalog ? [props.catalog] : [])
return (
<section id="overview" data-section="model-hero">
<a data-slot="model-back-link" href={language.route(import.meta.env.BASE_URL)}>
{i18n.t("footer.modelData")}
</a>
<div data-slot="model-hero-grid">
<div data-slot="model-hero-copy">
<div data-slot="model-hero-tags">
<a data-slot="hero-meta" href={language.route(`${import.meta.env.BASE_URL}${providerSlug(labId())}`)}>
<ProviderIcon aria-hidden="true" id={getProviderIconId(labId())} />
<nav data-component="model-hero-breadcrumb" aria-label="Data breadcrumb">
<a data-slot="model-hero-crumb" href={language.route(import.meta.env.BASE_URL)}>
Data
</a>
<span data-slot="model-hero-separator">/</span>
<Show
when={labs().length > 0}
fallback={
<span data-slot="model-hero-crumb" data-current="true">
<span>{props.labName}</span>
</a>
<span data-slot="model-id-tag">{modelId()}</span>
</div>
<h1>
<a data-slot="heading-link" href="#overview">
{props.catalog?.name ?? props.data?.model ?? i18n.t("model.fallback")}
</a>
</h1>
<Show when={props.data} fallback={<p>{i18n.t("model.catalogFallback")}</p>}>
{(data) => (
<p>
{data().rank === null ? i18n.t("model.unranked") : i18n.t("model.ranked", { rank: data().rank ?? "" })}{" "}
{i18n.t("model.observedVolume", { share: formatPercent(data().tokenShare) })}
</p>
)}
</Show>
<ChevronDownIcon />
</span>
}
>
<details data-component="model-hero-menu">
<summary data-slot="model-hero-crumb" data-current="true">
<span>{props.labName}</span>
<ChevronDownIcon />
</summary>
<div data-slot="model-hero-options">
<For each={labs()}>
{(lab) => (
<a
data-slot="model-hero-option"
data-current={lab.id === providerSlug(labId()) ? "true" : undefined}
href={language.route(`${import.meta.env.BASE_URL}${lab.id}`)}
>
{lab.name}
</a>
)}
</For>
</div>
</details>
</Show>
<span data-slot="model-hero-separator">/</span>
<Show
when={labModels().length > 0}
fallback={
<span data-slot="model-hero-crumb" data-current="true" aria-current="page">
<span>{modelName()}</span>
<ChevronDownIcon />
</span>
}
>
<details data-component="model-hero-menu">
<summary data-slot="model-hero-crumb" data-current="true" aria-current="page">
<span>{modelName()}</span>
<ChevronDownIcon />
</summary>
<div data-slot="model-hero-options">
<For each={labModels()}>
{(model) => (
<a
data-slot="model-hero-option"
data-current={model.id === props.catalog?.id ? "true" : undefined}
href={language.route(`${import.meta.env.BASE_URL}${model.id}`)}
>
{model.name}
</a>
)}
</For>
</div>
</details>
</Show>
</nav>
<div data-slot="model-hero-title-row">
<span data-slot="model-hero-avatar">
<ProviderIcon aria-hidden="true" id={getProviderIconId(labId())} />
</span>
<h1>{modelName()}</h1>
<div data-slot="model-hero-actions">
<Show when={props.catalog?.openWeights && weights()}>
{(weight) => (
<a data-slot="model-weight-link" href={weight().url} target="_blank" rel="noopener noreferrer">
{i18n.t("model.weights", { label: weight().label })}
<a data-slot="model-hero-action" href={weight().url} target="_blank" rel="noopener noreferrer">
<ModelHeroActionIcon kind="weights" />
<span>Model weights</span>
</a>
)}
</Show>
</div>
<Show when={props.data} fallback={<ModelCatalogCallout catalog={props.catalog} />}>
{(data) => (
<div data-component="model-rank-panel">
<span>{i18n.t("model.rank")}</span>
<strong>{data().rank === null ? "—" : `#${data().rank}`}</strong>
<p>{formatModelRankMoveLabel(data(), i18n)}</p>
</div>
)}
</Show>
</div>
<div data-slot="model-hero-pattern" aria-hidden="true" />
<Show when={props.catalog}>{(catalog) => <ModelCatalogPanel data={catalog()} />}</Show>
<Show
when={props.data}
fallback={
<p data-slot="model-hero-state">
<span>Listed</span>
<span>across the shared model catalog.</span>
</p>
}
>
{(data) => (
<p data-slot="model-hero-rankline">
<span>Ranked</span>
<span data-slot="model-hero-rank-group">
<span data-slot="model-hero-pill">{formatHeroRank(data().rank)}</span>
<ModelHeroSparkline data={data()} />
</span>
<span>across last week's</span>
<span data-slot="model-hero-pill">OpenCode Go</span>
<span>usage with</span>
<span data-slot="model-hero-pill">{formatPercent(data().tokenShare)}</span>
<span>of observed</span>
<span data-slot="model-hero-pill">2M</span>
<span>volume.</span>
</p>
)}
</Show>
</section>
)
}
function ModelCatalogCallout(props: { catalog: ModelCatalogEntry | null }) {
const i18n = useI18n()
const language = useLanguage()
function ModelHeroActionIcon(props: { kind: "weights" | "compare" }) {
if (props.kind === "weights")
return (
<svg data-slot="model-hero-action-icon" viewBox="0 0 16 16" aria-hidden="true" fill="none">
<path d="M5.5 4.5H4.5V11.5H11.5V10.5" stroke="currentColor" stroke-linecap="square" />
<path d="M8.5 4.5H11.5V7.5" stroke="currentColor" stroke-linecap="square" />
<path d="M11.25 4.75L7.25 8.75" stroke="currentColor" stroke-linecap="square" />
</svg>
)
return (
<div data-component="model-rank-panel">
<span>{i18n.t("model.profile")}</span>
<strong>
{props.catalog?.releaseDate
? formatCatalogDate(props.catalog.releaseDate, language.tag(language.locale()), i18n.t("home.unknown"))
: i18n.t("model.listed")}
</strong>
<p>{i18n.t("model.noCurrentUsage")}</p>
</div>
<svg data-slot="model-hero-action-icon" viewBox="0 0 16 16" aria-hidden="true" fill="none">
<rect x="3.5" y="3.5" width="3" height="3" stroke="currentColor" />
<rect x="9.5" y="3.5" width="3" height="3" stroke="currentColor" />
<rect x="3.5" y="9.5" width="3" height="3" stroke="currentColor" />
<rect x="9.5" y="9.5" width="3" height="3" stroke="currentColor" />
</svg>
)
}
function ModelCatalogPanel(props: { data: ModelCatalogEntry }) {
const i18n = useI18n()
const language = useLanguage()
function ModelHeroSparkline(props: { data: StatsModelData }) {
const values = () => props.data.usage.slice(-14).map((point) => point.tokens)
return (
<aside data-component="model-catalog" aria-label={i18n.t("model.facts")}>
<div data-slot="model-catalog-grid">
<CatalogDatum
label={i18n.t("model.context")}
value={formatCatalogLimit(props.data.limit?.context, i18n.t("home.unknown"))}
/>
<CatalogDatum
label={i18n.t("model.output")}
value={formatCatalogLimit(props.data.limit?.output, i18n.t("home.unknown"))}
/>
<CatalogDatum
label={i18n.t("model.knowledge")}
value={formatCatalogDate(props.data.knowledge, language.tag(language.locale()), i18n.t("home.unknown"))}
/>
<CatalogDatum
label={i18n.t("model.release")}
value={formatCatalogDate(props.data.releaseDate, language.tag(language.locale()), i18n.t("home.unknown"))}
/>
<CatalogDatum
label={i18n.t("model.inputs")}
value={formatCatalogModalities(props.data.modalities.input, i18n)}
/>
</div>
</aside>
<span data-slot="model-hero-sparkline" aria-hidden="true">
<svg viewBox="0 0 36 24" fill="none">
<path d={sparklineAreaPath(values())} fill="currentColor" opacity="0.14" />
<path d={sparklineLinePath(values())} stroke="currentColor" stroke-width="1.5" stroke-linejoin="round" />
</svg>
</span>
)
}
function CatalogDatum(props: { label: string; value: string }) {
function ChevronDownIcon() {
return (
<article data-component="model-catalog-datum">
<span>{props.label}</span>
<strong>{props.value}</strong>
</article>
<svg width="16" height="16" viewBox="0 0 16 16" aria-hidden="true" fill="none">
<path d="M4.75 6.25L8 9.5L11.25 6.25" stroke="currentColor" stroke-width="1.5" />
</svg>
)
}
@ -938,6 +998,38 @@ function formatRankMove(change: number) {
return `${change}`
}
function formatHeroRank(rank: number | null) {
if (rank === null) return "--"
return String(rank).padStart(2, "0")
}
function sparklineLinePath(values: number[]) {
return sparklinePoints(values)
.map((point, index) => `${index === 0 ? "M" : "L"}${formatSparklinePoint(point.x)} ${formatSparklinePoint(point.y)}`)
.join(" ")
}
function sparklineAreaPath(values: number[]) {
const points = sparklinePoints(values)
return `M${formatSparklinePoint(points[0].x)} 18 ${points
.map((point) => `L${formatSparklinePoint(point.x)} ${formatSparklinePoint(point.y)}`)
.join(" ")} L${formatSparklinePoint(points[points.length - 1].x)} 18 Z`
}
function sparklinePoints(values: number[]) {
const normalized = values.length > 1 ? values : [values[0] ?? 0, values[0] ?? 0]
const min = Math.min(...normalized)
const max = Math.max(...normalized)
return normalized.map((value, index) => ({
x: 8 + (index / Math.max(1, normalized.length - 1)) * 20,
y: min === max ? 12 : 18 - ((value - min) / (max - min)) * 12,
}))
}
function formatSparklinePoint(value: number) {
return Number(value.toFixed(2)).toString()
}
function formatModelRankMoveLabel(data: StatsModelData, i18n: ReturnType<typeof useI18n>) {
if (data.rank === null) return i18n.t("model.noUsageLastWeek")
if (data.previousRank === null) return i18n.t("model.newThisWeek")
@ -993,35 +1085,6 @@ function formatChange(value: number) {
return `${value}%`
}
function formatCatalogLimit(value: number | undefined, unknown: string) {
return value === undefined ? unknown : formatTokens(value)
}
function formatCatalogModalities(value: string[], i18n: ReturnType<typeof useI18n>) {
if (value.length === 0) return i18n.t("home.unknown")
return value.map((item) => formatCatalogModality(item, i18n)).join(", ")
}
function formatCatalogModality(value: string, i18n: ReturnType<typeof useI18n>) {
if (value === "pdf") return i18n.t("model.pdf")
return value.charAt(0).toUpperCase() + value.slice(1)
}
function formatCatalogDate(value: string | undefined, locale: string, unknown: string) {
if (!value) return unknown
const match = /^(\d{4})(?:-(\d{2}))?(?:-(\d{2}))?$/.exec(value)
if (!match) return value
const year = Number(match[1])
const month = match[2] ? Number(match[2]) - 1 : 0
const day = match[3] ? Number(match[3]) : 1
return new Intl.DateTimeFormat(locale, {
month: match[2] ? "short" : undefined,
day: match[3] ? "numeric" : undefined,
year: "numeric",
timeZone: "UTC",
}).format(new Date(Date.UTC(year, month, day)))
}
function trimNumber(value: number, digits: number) {
return Number(value.toFixed(digits)).toLocaleString("en")
}