Add colorless filters, and make set listings filterable

Colorless

There was no way to ask for colorless cards — the colour toggles are a 5-bit
WUBRG mask where 0 already means "don't filter by colour", leaving nothing to
express "no colours at all". That's exactly what you need to find a colorless
commander's card pool.

Adds a "C" pip to both colour rows, matching how ColorPips already renders
colorless cards, backed by two explicit booleans rather than a sixth bit — a
filter mask and a card's real colour mask staying the same shape is worth
keeping. The two rows mean different things and both are useful: on the
commander row C filters colour *identity*, which is the Commander rule; on the
includes row it filters the card's own colours. A card printed colorless can
still carry a coloured identity through mana symbols in its text, and it's the
identity that bars it from a colorless commander's deck.

Set listings

News > Releases had its own card path and so couldn't be filtered. A new
set_code filter (matched against printings.set_code, already ingested) lets the
set browser run through search_reference instead, so every criterion works
there identically rather than being reimplemented over a live Scryfall
response.

That alone would have cost the ability to browse an upcoming set, since
search_reference only knows downloaded card data — and upcoming sets are half
the point of the tab. So the browser picks a source per set: downloaded data
where it exists, with the full filter panel; otherwise Scryfall directly, with
the panel hidden and a line explaining why. A panel that silently does nothing
would be worse than no panel.

The source is decided by an *unfiltered* probe. Keying off whether the current
criteria match anything would flip a properly indexed set to "live" the moment
a filter excluded everything, dropping the panel exactly when it was in use.
This commit is contained in:
2026-08-10 22:34:46 -05:00
parent dff52a9d83
commit dfba2403a8
7 changed files with 345 additions and 17 deletions

View File

@@ -1376,9 +1376,20 @@ export function CardTile({
export function ColorToggles({
value,
onChange,
colorless,
onColorlessChange,
colorlessTitle,
}: {
value: number;
onChange: (mask: number) => void;
/** Renders a "C" pip alongside the colours when provided.
*
* Colourlessness can't live in the bitmask: 0 there already means "don't
* filter by colour", so there'd be no way to say "no colours at all" — which
* is exactly what you need to find a colourless commander's card pool. */
colorless?: boolean;
onColorlessChange?: (v: boolean) => void;
colorlessTitle?: string;
}) {
return (
<span className="color-toggles">
@@ -1392,6 +1403,15 @@ export function ColorToggles({
{c.code}
</span>
))}
{onColorlessChange && (
<span
title={colorlessTitle ?? "Colorless"}
className={`pip C ${colorless ? "on" : ""}`}
onClick={() => onColorlessChange(!colorless)}
>
C
</span>
)}
</span>
);
}