UpNext / Filters

Filters

<FilterPanel />Stable

The filter system, ported 1:1 from the shipped Search rail (UPN-2235…2243) and rebuilt on system primitives: the 296px FilterPanel chrome (header count, Clear all, collapse), plane labels, accordion zones with count chips, always-visible Clear, and collapsed-hover previews, labeled fields with scope/beta/info, the unified filter pill (soft gray → soft primary, weight never changes), toned pills wired to the system-label standard, tri-state Any / Is / Is-not flags, a cascading division tree with indeterminate rollup, an inline tag-input multi-select on Command, dual-thumb ranges with Any readouts, the Career/Season segmented, and the active-filter chip strip. Every color resolves through semantic + filter component tokens — dark mode included — heights ride the control scale, and motion rides the ease-swift signature; the only literals left are the documented tuned geometry (296px panel, 49px zones, 30px pills, 7/5/4px radii) called out in the component header.

import { FilterPanel, FilterRail, FilterSection, FilterField, ChipGroup, FilterTree, FilterTriState, FilterCombo, FilterRange, FilterSegmented, FilterChipStrip } from "@/components/upnext";

Search panel — live replica

The shipped Search panel, 1:1: the 296px chrome with header count and Clear all, the Your team plane above the Athlete facts plane, and all eight zones — recruit tags, position units, height/weight ranges, the division cascade with constrained conference and school combos, the Career/Season stat window, date presets with a custom range calendar, tri-state flags, and injury status. Hover a collapsed zone for its preview card; every control writes to the same state the counts, Clear actions, and the chip strip read from. This is ONE composition of the kit — other tabs assemble their own rails from the same zones and controls (see COMPOSING RAILS in components/upnext/filter.tsx).

Filters7
Your team

Athlete facts

Last 30 daysFBSQBWREliteHighscholarship

Pieces

Sections are one native trigger each — the Clear action rides above it as an overlay sibling (the MetricCard idiom), never nested. Selection never flips text weight: default pills answer with a soft primary fill, toned pills deepen their tint behind a soft outline, tree rows wash on a primary ladder, and the tri-state thumb stays surface-colored with the glyph carrying state. Hit targets stay at control heights, focus is always a visible ring, and every animation honors reduced motion.

Variant

State

Position

<FilterPanel count={chips.length} onClearAll={clearAll} onClose={close}>
<FilterPlaneLabel>Athlete facts</FilterPlaneLabel>
<FilterRail defaultOpen={["position"]}>
<FilterSection
first // skips its top hairline after a plane label
value="position"
title="Position"
icon="object.jersey" // Icon registry semantic
count={selected.length} // the `count` system label
onClear={() => setSelected([])} // ALWAYS-visible Clear when active
tooltip="Football positions, colored by unit."
preview={[ // collapsed-hover preview (dark card)
{ label: "Position", active: selected.length > 0 },
]}
>
<FilterField first label="Position">
<ChipGroup options={POSITIONS} value={selected} onToggle={toggle} />
</FilterField>
</FilterSection>
</FilterRail>
</FilterPanel>

Source

Built on the base Accordion, Badge (count chips + combo tags via the system-label standard), Button, Icon registry, Tooltip, Popover, and Command primitives. The decorative pill tones mirror lib/labels' categorical set so tags, badges, and chart series stay one visual family.