local-frontier / src /components /models /ModelDatabase.tsx
Onur Solmaz
feat: add gemma 3 4b gated profile
9efd956
Raw
History Blame Contribute Delete
3.81 kB
import * as React from "react";
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/table";
import type { ModelDatabaseRow } from "@/types/local-frontier";
export type ModelDatabaseProps = {
rows: readonly ModelDatabaseRow[];
};
function matchesSearch(row: ModelDatabaseRow, search: string): boolean {
const query = search.trim().toLowerCase();
return !query || row.searchText.includes(query);
}
function ModelRow({ row }: { row: ModelDatabaseRow }): React.JSX.Element {
return (
<TableRow>
<TableCell>
<a
className="font-semibold text-foreground underline-offset-2 hover:underline"
href={row.modelHref}
>
{row.id}
</a>
<span className="block text-muted-foreground">{row.name}</span>
<span className="mt-1 inline-flex border border-border px-2 py-0.5 text-xs text-muted-foreground">
{row.precision}
</span>
</TableCell>
<TableCell>{row.downloads}</TableCell>
<TableCell>
<span className="text-foreground">{row.architecture}</span>
{row.architectureDetail ? (
<span className="block">{row.architectureDetail}</span>
) : null}
<span className="mt-1 inline-flex border border-border px-2 py-0.5 text-xs">
{row.adapterKind}
</span>
</TableCell>
<TableCell>
<span>{row.totalParams} total</span>
<span className="block">{row.activeParams} active</span>
</TableCell>
<TableCell>
<span>{row.residentFootprint}</span>
<span className="block">
{row.activeTrafficFloor} active traffic floor
</span>
</TableCell>
<TableCell>{row.context}</TableCell>
<TableCell>
<Button asChild size="sm" variant="outline">
<a href={row.compareHref}>Compare</a>
</Button>
</TableCell>
</TableRow>
);
}
function ModelTable({
rows,
}: {
rows: readonly ModelDatabaseRow[];
}): React.JSX.Element {
if (!rows.length) {
return (
<div className="p-8 text-muted-foreground">
No models match the current filters.
</div>
);
}
return (
<Table className="min-w-[1060px]">
<TableHeader>
<TableRow>
<TableHead>HF model</TableHead>
<TableHead>Downloads</TableHead>
<TableHead>Architecture</TableHead>
<TableHead>Parameters</TableHead>
<TableHead>Resident footprint</TableHead>
<TableHead>Context</TableHead>
<TableHead>Calculator</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{rows.map((row) => (
<ModelRow key={row.id} row={row} />
))}
</TableBody>
</Table>
);
}
export function ModelDatabase({ rows }: ModelDatabaseProps): React.JSX.Element {
const [search, setSearch] = React.useState("");
const filteredRows = rows.filter((row) => matchesSearch(row, search));
return (
<Card>
<CardHeader>
<CardTitle>Model Database</CardTitle>
</CardHeader>
<CardContent className="grid gap-4">
<label className="grid gap-1.5">
<span className="text-xs font-semibold text-muted-foreground">
Search
</span>
<Input
placeholder="Qwen/Qwen3.6-35B-A3B, MoE, 32B"
type="search"
value={search}
onChange={(event) => {
setSearch(event.currentTarget.value);
}}
/>
</label>
<ModelTable rows={filteredRows} />
</CardContent>
</Card>
);
}