Engineering
Counting facets that do not collapse when you click them
A filter chip showing '0' the moment you select it is technically accurate and completely useless. The fix is one line, in the right place.
Engineering
Faceted filtering looks trivial until you count the facets. The naive implementation applies every active filter, then counts the values in what remains — which means selecting `status = active` makes every other status read zero.
The reader cannot tell whether 'paused: 0' means there are no paused rows or that they are currently filtered out.
Exclude a facet from its own filter
Each facet is counted against a pool with every filter applied except that facet's own. Selecting a status still shows the real counts for the other statuses, so the chips stay useful as navigation rather than becoming a readout of what you already clicked.
for (const field of config.filterFields) {
// Everything EXCEPT this field's own filter.
const pool = searched.filter((item) => matchesFilters(item, filters, String(field)));
facets[String(field)] = countValues(pool, field);
}Search is different
Free-text search applies to every stage including facet counting. A search narrows the universe under discussion; a filter narrows a view of it. Treating them the same produces counts that do not correspond to anything the reader can see.
Worth testing
This is exactly the behaviour that regresses silently during a refactor, because the page still renders and the numbers are still numbers. It is a three-line test and it has caught the regression more than once.
const { meta } = queryCollection(rows, { filters: { status: "active" } }, config);
expect(meta.facets.status).toEqual({ active: 3, paused: 1, draft: 1 });
expect(meta.facets.team).toEqual({ Platform: 1, Security: 1, Finance: 1 });