SearchRow top padding was 0 while left/right was sizeUnit*2 (8px).
Make them equal so the search input has uniform breathing room.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace custom option rendering, debounced search, race-condition
guards, and loading states with Select/AsyncSelect from
@superset-ui/core/components. The trigger is hidden via a
zero-height wrapper; the dropdown renders inside a container div
via getPopupContainer, giving the same visual as Explore's select
dropdowns. Also exposes the 'open' prop in AntdExposedProps so
Select/AsyncSelect can be controlled externally.
Removes ~130 lines of reimplemented debounce/race-condition/
filter logic and eliminates the outline hover hack.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Wrap Input in SearchRow with horizontal padding instead of margins on
.ant-input-affix-wrapper. width:100% + margin overflowed the container;
padding on a wrapper div keeps the input fully inside. Restore
overflow:hidden (needed for borderRadiusLG clipping) — it no longer
clips the input since the wrapper contains it correctly.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
CompactSelectPanel: remove overflow:hidden from panel (was clipping search
input); remove min-height from OptionItem (5px padding alone gives the
correct 24px height matching AntD Select optionPadding, not 42px).
index.tsx: clearFilters/clearFilterById now call updateFilterValue directly
as a safety net so URL always updates even when filter refs are stale
(e.g. after page refresh where internalFilters is URL-hydrated).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Use exact visual pattern from @superset-ui/core Select:
- borderRadiusLG on container (was borderRadius)
- paddingXXS top/bottom on container (matches ant-select-dropdown)
- borderRadiusSM on each OptionItem (rounded highlight, not edge-to-edge)
- 5px vertical padding on items (matches optionPadding token default)
- outline: 2px solid colorPrimary on hover (Superset's own Select override)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Show 'No filters applied' tooltip on hover when the Clear all button
is disabled, so users understand why it is not interactive.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace fixed 176px width on the search filter container with flex:1
so it expands into the space not taken by the pill filters.
min-width: 160px prevents it collapsing on narrow screens.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Match Superset dashboard FilterBar pattern (isClearAllEnabled): always
render the button so users can discover it, just disable it when nothing
is selected. Prevents layout shift and builds muscle memory.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Show a 'Clear all' text button at the end of the filter pill row when
one or more filters are active. Disappears when all filters are inactive.
Matches dashboard native filter bar behaviour.
Also update ListView tests to use new compact-filter-pill buttons
instead of the old combobox queries.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Owner options have a styled ReactNode label — typeof checks fail and we
fell back to String(value) = "1". Instead, capture the rendered text via
e.currentTarget.textContent at click/keydown time (always the visible
string regardless of label type) and use it as the normalized label.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace full-width inline filter blocks with compact pill triggers across
all ListView CRUD views. Each non-search filter becomes a pill that opens
a focused dropdown on click. Async selects use a debounced options panel
matching the DrillBy submenu pattern. Date/range filters get an Apply
button. Active pills show colored border, dot indicator, hover tooltip
with selected value, and inline clear button.
- CompactFilterTrigger: pill + Ant Design Dropdown, injects isOpen/onClose
into panel children via cloneElement; Tooltip on pill for active state;
destroyPopupOnHide intentionally omitted to preserve filter refs
- CompactSelectPanel: options list with debounced async fetch, race-condition
guard, keyboard nav (Enter/Space), proper ARIA (listbox/option/aria-selected,
aria-label on listbox)
- FilterPopoverContent: Apply button wrapper for DateRange/NumericalRange;
inner label visually hidden but screen-reader accessible
- index: expose clearFilterById in ref type to match ListView contract
- Tests: CompactSelectPanel.test.tsx and FilterPopoverContent.test.tsx added;
datetime_range and numerical_range pill tests added to index.test.tsx;
tooltip test in CompactFilterTrigger.test.tsx made non-brittle
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
URL serialization via use-query-params strips the label from the selected
SelectOption, leaving only {value: 1}. Reading the label back from
internalFilters after hydration therefore gives undefined.
Cache the string label in tooltipLabels state at the moment of selection
(before URL round-trip). Clear on onClear, clearFilters, and clearFilterById.
tooltipTitle now reads from the cache instead of internalFilters.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Wrapping the Dropdown in an outer span+Tooltip caused Dropdown to absorb
mouse events before they reached the Tooltip. Move Tooltip to wrap
FilterPill directly inside the Dropdown — Ant Design supports Tooltip
as a Dropdown child and the pill receives hover events cleanly.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Normalize selected option to plain {label: string, value} before passing
to onSelect — matches original SelectFilter behaviour and prevents
'Converting circular structure to JSON' when emotion-styled ReactNode
labels are serialized to URL query params.
Style OptionItem to match AntD Select dropdown exactly: colorBgElevated
container, fontSize (not fontSizeSM), colorText always (not colorPrimary
on selected), colorFillTertiary hover, borderRadiusSM on items, 32px
height with sizeUnit padding.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add .catch() to the fetch effect so rejected promises (network errors,
auth failures) don't surface as unhandled rejections. Guard result.data
with ?? [] so null/undefined responses fall back to empty list. Filter
null entries from displayOptions before rendering.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The 21px margin-top on ViewModeContainer existed to visually align with
filter label text above each input. Labels are now hidden (pills have no
label), so the offset pushed the icons below the pill midline. Removing
it lets align-items: center on .header do the right thing.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add align-items: center to .header so the grid/list toggle and the
filter pills sit on the same midline.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
optionFilterProps, paginate, and popupStyle were destructured in the filter
map but are no longer used after SelectFilter was replaced with
CompactSelectPanel. Remove them to eliminate dead code.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- index.tsx: remove redundant filterValue variable (merged into initialValue),
remove no-op onClose={() => {}} from CompactSelectPanel (it's injected via
cloneElement, the explicit pass was misleading), fix `any` type in
clearFilters forEach, pass popupType="dialog" for datetime_range and
numerical_range triggers
- CompactFilterTrigger: replace as Record<string,unknown> cloneElement cast
with typed FilterPanelInjectedProps interface; add popupType prop (default
'listbox', 'dialog' for form panels) wired to aria-haspopup so screen readers
get the correct popup role per ARIA spec
- CompactSelectPanel: add cancelled flag to fetchSelects effect to prevent
stale-closure state updates when deps change mid-flight; add
debouncedSetSearch.cancel() cleanup on unmount; add role="listbox" to
OptionList and role="option" + aria-selected + tabIndex + onKeyDown(Enter/
Space) to OptionItem for keyboard navigation
- FilterPopoverContent: replace label { display: none } with visually-hidden
CSS (position:absolute + clip) so FormLabel remains accessible to screen
readers (datepicker/number inputs retain their accessible name context)
while still hidden visually
- Tests: add 6 new tests covering isOpen/onClose injection via cloneElement,
aria-haspopup default and dialog values, dropdown close aria-expanded reset,
select filter pill rendering, and active state when value is present
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Force search-filter-container to controlHeight so it aligns flush with
the pill buttons (same height, align-items: center on the controls row
then centers everything correctly).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Fix autoFocus stealing focus from search: inject isOpen via cloneElement,
use InputRef.input.focus pattern from DrillBySubmenu (100ms delay, preventScroll).
Debounce remote fetch triggers with Constants.FAST_DEBOUNCE. Reset panel
search on close.
Add FilterPopoverContent wrapper with Apply button for date/numerical range
filters so cloneElement-injected onClose closes the dropdown on submit.
Hides inner FormLabel via CSS since the pill already shows the label.
Match DrillBySubmenu styling: iconSize="l"/colorIcon for search prefix,
colorTextDisabled for empty state, min-height: 35px for option rows,
container padding replaces SearchRow border, .ant-input-affix-wrapper
margin-bottom for visual separation, min-width: 220px, box-shadow: none
on the input.
Pass external loading prop to CompactSelectPanel. Change .controls to
align-items: center and hide search-filter-container label via CSS.
Add aria-label to pill when label is a string.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Remove destroyPopupOnHide so CompactSelectPanel stays mounted when the
dropdown closes, keeping its ref live. Add updateFilterValue(index, undefined)
directly in all onClear handlers as a safety net so the ListView filter
state always resets even if the ref is stale.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Use theme.borderRadius and theme.controlHeight on filter pills to match
the Search input and Select controls on the same row. Replace the
Popover+SelectFilter approach with a new CompactSelectPanel that renders a
clean options list (search + checkmark) opened via Dropdown — no
intermediate widget. Add tooltipTitle prop to CompactFilterTrigger so
hovering a filled pill shows the selected value. Align .controls with
flex-end so pills sit flush with the bottom of the search input.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace full-width inline filter blocks with compact pill triggers that
open a Popover on click. Search filter stays inline. Adds active state
indicator (dot + border + weight) and inline clear button. Single new
component, no new deps. Controls gap tightened to 10px for pill rows.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>