Skip to content

feat(filters)!: add explicit choice controls and typed predicates - #51

Merged
francoischalifour merged 12 commits into
mainfrom
fc/selection-menu-primitives
Oct 8, 2026
Merged

francoischalifour merged 12 commits into
mainfrom
fc/selection-menu-primitives

Conversation

@francoischalifour

@francoischalifour francoischalifour commented Oct 8, 2026 •

Copy link
Copy Markdown
Member

Why

Single-value filters used checkbox visuals that suggested multiple values could be selected. The available controls also left apps to assemble numeric predicates, selection menus, and clear actions themselves, producing inconsistent behavior and layout.

This branch makes selection intent explicit and provides composable filter contracts and controls with controlled values, direct callbacks, and shared URL state.

What changed

  • Add searchVariable(), choiceVariable(), and multiChoiceVariable() with labeled option IDs. Add typed numeric and boolean predicates, validation, and server parsers. Dimension filters support explicit selection cardinality, opt-in exclusion, and missing values.
  • Preserve filter selections through declared view input bindings. useAppVariables() owns URL updates, history, clearing to unrestricted values, and resetting to configured defaults.
  • Provide a styled <Select>, single/multiple <ChoicePicker>, radio and checkbox groups, <SegmentedControl>, numeric fields and ranges, and <NumberFilterPicker>. Numeric panels keep edits local until Apply; Cancel or dismissal discards the draft. Invalid intervals cannot be applied.
  • Add menu primitives for commands and selection menus, and compose export actions with them. Documentation distinguishes menus, fixed choices, and searchable pickers.
  • Give generated filter rows one Lucide FilterX clear action with a tooltip. Selected values remain visible in the controls; single categorical pickers expose All and multiple-choice panels retain Clear selection.
  • Standardize control heights, independent popup widths, option spacing, and scroll-edge padding. Inputs have a 16px minimum on mobile; focusing picker search keeps the divider stable. Apply uses a neutral primary button, with a compact Cancel–Apply gap. Segmented labels and numeric legends align with their controls, and period summaries use consistent typography.
  • Preview the controls and states in the gallery, demonstrate single-country selection in the playground, and update authoring guides and consumer examples.

Breaking API changes

Combobox becomes ChoicePicker, textVariable() becomes searchVariable(), and selectVariable() becomes choiceVariable() with required labeled options. Dimension filter selection becomes selectionMode. Existing categorical URL values remain readable.

Verification

Build, typecheck, lint, authored style checks, Markdown and local links, formatting, package checks, and starter checks pass. All 150 public API tests pass with two workers and a 30-second hook timeout.

Browser workflows cover selection semantics, keyboard navigation and dismissal, numeric Apply/Cancel and invalid drafts, exclusion and missing values, URL history, clearing, matching heights, and mobile typography. Desktop and mobile gallery panels were inspected, including scroll fades, neutral primary colors, and the final 5px action gap.

Render standalone checkmarks for single choices and checkbox marks only for multiple selections. Keep keyboard navigation separate from applying a searchable value.

Expose composable menu primitives for commands and selected choices, and use command semantics for CSV exports. Document when apps should use a picker or menu.

Keep picker search dividers stable and use the public control text-size token for editable text, with a 16px floor on narrow and touch viewports.

Verified with bun run check: 134 tests, package consumer checks, and the local starter build.
Use a typed dimension filter with readable country choices while mapping displayed selection to the existing country-code operation input. Replace free-text instructions so the playground exercises picker selection and reset.

Verified TypeScript and lint checks, and selected United Kingdom in the live Docker-backed playground: 43 orders and ,742.36 revenue.
Separate fixed choices from categorical, numeric, and boolean predicates. Require explicit single or multiple choice picker semantics, labeled options, and preserve filter values through view input mapping.

Compose generated rows with removable chips and one clear icon with tooltip. Keep controls at the shared height and enforce the mobile text-size minimum. Preview the new controls and menus in the gallery.

BREAKING CHANGE: replace Combobox with ChoicePicker, textVariable with searchVariable, and selectVariable with choiceVariable. Rename dimension selection to selectionMode. Existing dimension deep links remain readable.
Remove duplicate active-filter chips and their public API. Selected choice pickers expose a separate inline clear button with tooltip and restore focus to the picker after clearing. Keep FilterX as the collective clear action.

Update the gallery and authoring guidance. Verify URL history, direct clear behavior, keyboard focus, and all141 public API tests.
Replace browser-native select popups with a styled accessible listbox. Expose NumberFilterPicker to compose numeric field primitives in a dedicated Apply/Cancel panel, keeping draft edits out of URL and operation state until validated.

Remove picker trigger reset buttons. Give panels responsive widths independent of their triggers, small option gaps, and padding within scroll content. Align segmented labels, simplify period typography, and delegate Escape dismissal to the overlay rather than inspecting ancestor dialogs.

Verify keyboard selection, numeric correction and submission, invalid ranges, draft cancellation, URL history, mobile text sizing, panel geometry, and all141 public API tests. Inspect desktop and mobile gallery previews.

BREAKING CHANGE: Select uses explicit controlled props instead of native select attributes. ChoicePicker no longer accepts resetValue; categorical single selection uses All.
Use accent fill and on-accent text for primary actions, including hover and pressed states. Apply uses the primary variant in numeric panels and draft filter actions. Preview default, compact, and disabled primary buttons in the gallery.

Remove native legend padding so Bounds aligns exactly with its numeric input group. Verify typing, styles, filter workflows, and rendered panel geometry.
Use the theme foreground for the primary fill and the background for contrasting text. Keep hover and pressed states neutral instead of deriving primary actions from the accent color.
Name numeric draft fields by their purpose and keep static condition options outside rendering. Build missing-value choices in one place and bind generated search and choice controls directly so reset behavior belongs only to search.
Preserve the enriched commerce playground and composed chart exports while resolving filter branch conflicts. Use selectionMode for its country filter.
@francoischalifour
francoischalifour merged commit 4c950a7 into main Oct 8, 2026
8 of 9 checks passed
@francoischalifour
francoischalifour deleted the fc/selection-menu-primitives branch October 8, 2026 15:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants