feat: virtual scroll, fuzzy search, default columns, inline data#1041
Open
sunipan wants to merge 19 commits intoanomalyco:devfrom
Open
feat: virtual scroll, fuzzy search, default columns, inline data#1041sunipan wants to merge 19 commits intoanomalyco:devfrom
sunipan wants to merge 19 commits intoanomalyco:devfrom
Conversation
Replaces imperative sort/filter/render with declarative Tanstack Table (createTable, getCoreRowModel, getSortedRowModel, getFilteredRowModel) and virtual row rendering via Virtualizer class. Adds column picker dropdown, URL state sync (search/sort/order/cols), and keyboard shortcut Cmd+K to focus search. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…n-id to tds - Add #table-scroll-container with full-viewport scroll height - Make thead th sticky at top:0 within scroll container - Replace nth-child column selectors with data-column-id attribute selectors - Add column picker dropdown styles (.picker-group, .picker-item, etc.) - Add .provider-logo img style; remove stale .provider-cell svg rule - Add #table-loading style - Add data-column-id to each td in renderRows() Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
In vanilla JS, Virtualizer._willUpdate() must be called manually to initialize scroll element observation (frameworks call it automatically via lifecycle hooks like useLayoutEffect). Without it, scrollElement stays null, observers are never set up, and getVirtualItems() always returns an empty array. Also added /api.json route to the dev server so the client-side fetch succeeds in development mode. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Embed api.json directly into HTML as <script type="application/json"> at build time, eliminating the fetch round-trip and loading flash. - Add model-data script placeholder to index.html - Inject JSON data in build script after static HTML replacement - Remove loading div from render.tsx (data available immediately) - Update dev server to also inject JSON for local development - Keep _api.json output for external API consumers HTML: 4.7KB → 1.2MB raw / 110KB gzipped (vs original 12MB / 373KB)
Show 9 curated columns by default instead of all 25: Provider, Model, Family, Model ID, Tool Call, Reasoning, Input Cost, Output Cost, Context Limit. - Export DEFAULT_COLUMN_IDS from url-state.ts - parseUrlState() returns defaults when no cols param in URL - serializeUrlState() omits cols when matching defaults - Update existing tests and add new ones for column defaults
Replace brute-force String.includes() search with MiniSearch for fuzzy matching, prefix search, and relevance scoring. Fixes issue anomalyco#977 where searching matched cost values. - New search.ts module with buildSearchIndex() and searchRows() - Index only text fields: provider name, model name, model ID, family - Does NOT index cost values, booleans, or limits - Fuzzy matching: "claud" finds "claude", "gpt4" finds "gpt-4" - Comma-separated multi-term OR logic preserved - Add debounce utility with cancel() for Escape key handling - Add minisearch ^7 dependency
Wire together MiniSearch, debounce, localStorage column persistence, and inline JSON data loading in the main client entry point. - Replace TanStack globalFilterFn with MiniSearch pre-filtering - Remove getFilteredRowModel() (pre-filter rows before passing to TanStack) - Add 150ms debounced search input handler - Escape key cancels debounce and clears immediately - localStorage persistence for column visibility (models.dev:cols) - Priority: URL cols param > localStorage > DEFAULT_COLUMN_IDS - init() now synchronous (reads inline JSON, no fetch) - Build search index once on data load
Add 27 new tests (41 total, up from 14): - search.test.ts (14): index building, fuzzy matching, prefix search, field exclusion (costs/booleans not indexed), comma-separated OR - debounce.test.ts (4): delay timing, call coalescing, cancel behavior - columns.test.ts (9): DEFAULT_COLUMN_IDS validation, parseUrlState column override, invalid ID filtering
3c655bf to
3df9ad9
Compare
Compute per-column widths from rendered data so full cell text remains visible, including model IDs with persistent copy controls and a consistently visible copy button.
ca33147 to
86cf580
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Closes #977
Builds on the approach from #1016 by @gianpaj (TanStack Table + virtual scroll). This PR adds search overhaul, sensible defaults, and inline data to eliminate the loading flash.
Summary
String.includes()— supports typo tolerance ("claud" → "claude"), prefix matching, and relevance scoringapi.jsonembedded in HTML at build time — no fetch round-trip, no "Loading models…" flashCheck it out live at: https://models-dev.pages.dev
Performance
Files changed
Only
packages/web/modified — no changes toproviders/,packages/core/, orpackages/function/.New dependencies:
@tanstack/table-core,@tanstack/virtual-core,minisearchValidation
bun validate✅bun test✅ (41 pass, 0 fail)bun run build✅Credit
Foundation (TanStack Table + Virtual, column picker, URL state) by @gianpaj in #1016.