Power tools accrete features faster than they accrete affordances. Six months of shipping have given the csvdiff.app viewer per-column sort, value filters, pin, format, color rules, fill-down, image rendering, and hide — most controlled by tiny icons crammed into a 24-pixel-tall header row. The data was still there; the state of your view was not. This release fixes that with three changes that work together: an Active Filters strip that lists every applied modification as a removable pill, a ⌘K command palette for keyboard-first navigation, and a full dark mode pass across the product and marketing pages.
Everything below runs in your browser. No uploads, no account, no telemetry. Open any CSV or JSON file in the viewer to try the new controls.
The Active Filters Strip
Anyone who has spent ten minutes shaping a 50,000-row table knows the failure mode: you apply a sort, a couple of filters, pin a column, set a heatmap rule on the salary column, hide three columns you do not need, and then you go grab a coffee. When you come back, the table looks tidy — but you have no idea why it looks the way it does. Which columns were filtered? Was sort ascending or descending? Did you remember to unhide the three columns before exporting?
The Active Filters strip sits between the toolbar and the table and lists every applied modification as a small pill. Each pill is grouped by column: a column with three operations active (say a filter, a pin, and a Number format) shows up as a single bar with the column name on the left and the three operations after it. A small "×" next to each operation lifts that one modification — clicking the × on "format" leaves the filter and pin intact. Global modifications that do not belong to a single column — the row search, dedupe — appear as their own pills after the column groups.
A "Reset all" button on the right of the strip lifts every modification at once. It is the equivalent of closing and reopening the file, but without the round-trip through the upload page. The strip only renders when there is something to surface, so a freshly opened file does not waste vertical space.
What the Strip Tracks
- –Sort — direction (ascending or descending) and the sorted column.
- –Column value filters — count of selected values, e.g. "filter (3)".
- –Pinned columns — the columns frozen to the left edge.
- –Image rendering — columns flipped from URL text to inline images.
- –Color rules — heatmap, duplicates, empty, status colors, above/below average.
- –Column formats — number, currency, percent, date, text, scientific.
- –Fill-down — columns where blanks were filled from above.
- –Hidden columns — every column removed from view, with a one-click show.
- –Row search and dedupe — global modifications, listed as their own pills.
Every chip is keyboard-focusable and announces its action via an aria-label, so a screen reader on a column with a sort pill hears "Clear sort on email" instead of just "remove". For a table with twelve modifications applied, the strip becomes a one-line summary of "what you have done to this file."
A subtle ergonomic win: hidden columns used to be findable only through a dropdown buried in the toolbar. Now every hidden column shows up as an eye-off pill in the strip — one click brings it back. No more wondering whether the export will be missing a column you forgot you hid.
A Consolidated Column Overflow Menu
The strip works because the column header is no longer trying to be the source of truth. Sort and Filter — the two operations you reach for several times per session — stay as quick-action icons in the header. Everything else (Pin, Render as images, Format, Color rules, Fill-down, Hide column) folds into a single "⋯" overflow menu. When the column has nothing applied to it, the ⋯ is a single neutral icon. When it has anything applied, it grows into a small indigo badge with the active count — "⋯ 2" tells you at a glance that two of the secondary operations are active on this column.
The menu opens as a dropdown with the operations stacked vertically and the Format and Color rules sub-menus flying out to the right, Windows-style. Picking a format closes both menus and applies the change. The "wash" we used to paint across the entire header background when a column was "touched" is gone — the Active strip is now the canonical state view, so the header itself stays calm.
A ⌘K Command Palette
The viewer has accumulated enough controls that some of them are noticeably far from the keyboard. Toggling the dedupe popover, opening AI settings, exporting the current view, jumping to a column by name — each requires moving the mouse, finding an icon, and clicking. The command palette consolidates every action behind a single keyboard shortcut.
Hit ⌘K (or Ctrl-K on Windows and Linux) anywhere in the viewer and a search box opens in the center of the screen. Type a few letters to fuzzy-match against every action: "exp" surfaces Export CSV and Export JSON; "the" jumps to the theme toggle; "ded" opens dedupe. Each match shows the action name, a short description, and the keyboard shortcut if one exists. Enter runs the action; Escape closes the palette.
What the Palette Indexes
- –Every toolbar action — search, dedupe, AI summary, export, settings.
- –Every visible column — by name, so "salary" jumps the table to that column and pulses the header.
- –Every hidden column — so you can re-show a column without leaving the keyboard.
- –View-level toggles — theme, only-changed, view mode (A / B / diff).
- –Format and rule presets — "heatmap on salary", "currency on revenue".
- ActionsExport as CSVCurrent view, formatted⌘E
- Export as JSONCurrent view, raw values
- Explain changes with AISummarize what differs
- Columnsexpense_categoryJump to column
- Show "expires_at"Currently hidden
- ViewToggle themeLight / dark⌘T
The palette is the same primitive shipped behind the strip — both are reading the same column metadata and the same set of operations. Add a new column rule once and it shows up in both places at the same time.
Dark Mode
Dark mode was the most-requested feature of the last three months, and the one we sat on the longest because we wanted it to be more than an inverted color filter. The release switches every surface — diff, viewer, landing, blog, AI summary, settings modals — to a real dark palette driven by the same design tokens that produced the light theme. No "dark mode is just light mode with a blue tint" feel: status colors, added / removed / modified backgrounds, the indigo accent on the AI Summary button, the A and B side selections, and the color-rule swatches all have dedicated dark variants tuned to read at the same contrast level.
The toggle lives in the top-right of every page next to the GitHub link, and it also shows up in the command palette as "Toggle theme." Your choice is stored in localStorage so a refresh remembers it. On first visit the page renders in whichever theme matches your OS preference — the toggle is a flip, not a one-way trip.
| id | name | status | salary |
|---|---|---|---|
| 001 | Ayesha | active | $120,000 |
| 002 | Sara | on leave | $98,000 |
| 003 | John | active | $155,000 |
| 004 | Maya | pending | $142,000 |
| id | name | status | salary |
|---|---|---|---|
| 001 | Ayesha | active | $120,000 |
| 002 | Sara | on leave | $98,000 |
| 003 | John | active | $155,000 |
| 004 | Maya | pending | $142,000 |
A small but meaningful detail: the dark theme is applied before paint via an inline script in the document head, so opening the page in dark mode does not flash white for a frame before re-rendering. The same matters for screenshots and embedded demos in blog posts — they pick up the active theme automatically.
Column Stats Bar
The strip at the top tells you what you have done to the table. A new strip at the bottom tells you what is in it. Pick a column from the Σ dropdown in the footer and you get Count, Distinct, Blanks (when any are present), and — when the column is numeric — Sum, Avg, Min, Max, and Median, recomputed instantly as filters and dedupe change the visible row set. The viewer auto-selects the first majority-numeric column when you open a file, so opening a sales export already shows you the total without a click.
Each stat is a small icon tile next to a tabular-number value. Min stays red, Max stays green, Sum and Avg sit on indigo — the same accent the rest of the product uses. Blanks light up amber when a column has missing data so you can spot it without reading the number. The bar scrolls horizontally if the column has more stats than fit, so it never breaks the layout on narrow screens.
How They Work Together
The four features in this release are deliberately small individually and noticeably bigger together. The Active Filters strip removes the "what state is the table in" guessing game. The footer stats bar tells you what the data adds up to right now. The command palette removes the "where is that control" hunt. Dark mode means none of this leaves you squinting at midnight. Open any CSV or JSON file in the viewer — drag and drop on the landing page, or click View — and all four are visible immediately.
As always: every parser, every diff, every export runs in your browser. The CSV bytes you drop never touch our servers. AI summaries, if you turn them on, go directly from your tab to your OpenAI or Google key. The privacy promise is the deciding feature for regulated data — finance, health, PII — and it stays unchanged.