This is an automated email from the ASF dual-hosted git repository. sadpandajoe pushed a commit to branch fix-dashboard-filterbar-section-spacing in repository https://gitbox.apache.org/repos/asf/superset.git
commit ed770ace5518f6f22fc8cb5e7d1a07ad51377fe2 Author: sadpandajoe <[email protected]> AuthorDate: Sat Oct 3 17:41:03 2026 +0000 fix(dashboard): remove redundant margin causing extra space around filter bar out-of-scope section SectionContainer's margin-bottom stacked additively on top of FilterControlsWrapper's flex gap, doubling the vertical space before the "Filters out of scope" collapsible (and other sections) in the vertical filter bar. Spacing between sections is already handled by the wrapper's flex gap, so the extra margin is removed. Co-Authored-By: Claude Sonnet 5 <[email protected]> --- .../FilterControls/FilterControls.test.tsx | 62 ++++++++++++++++++++++ .../FilterBar/FilterControls/FilterControls.tsx | 12 ++--- 2 files changed, 66 insertions(+), 8 deletions(-) diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterControls.test.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterControls.test.tsx index 935928bada0..268129a7ee7 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterControls.test.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterControls.test.tsx @@ -26,6 +26,7 @@ import { ChartCustomizationType, ChartCustomizationDivider, } from '@superset-ui/core'; +import { styled } from '@apache-superset/core/theme'; import { FilterBarOrientation } from 'src/dashboard/types'; import FilterControls from './FilterControls'; @@ -422,3 +423,64 @@ test('FilterControls overflowedByIndex updates when filters change scope', () => expect(container).toBeInTheDocument(); }); + +// Mirrors FilterControlsWrapper in ../Vertical.tsx, which wraps FilterControls +// in production and supplies the flex `gap` between vertical sections. +const FilterControlsWrapper = styled.div` + display: flex; + flex-direction: column; + gap: ${({ theme }) => theme.sizeUnit * 2}px; +`; + +test('out-of-scope section does not add margin on top of the wrapper flex gap', () => { + const state = getDefaultState(FilterBarOrientation.Vertical); + state.dashboardLayout.present['CHART-1'].parents = [ + 'ROOT_ID', + 'TABS-1', + 'TAB-1', + ]; + state.dashboardLayout.present['CHART-2'].parents = [ + 'ROOT_ID', + 'TABS-1', + 'TAB-2', + ]; + state.nativeFilters.filters['filter-1'].chartsInScope = [1]; + state.nativeFilters.filters['filter-2'].chartsInScope = [1]; + // filter-3 lives under the inactive TAB-2, so it renders out of scope. + state.nativeFilters.filters['filter-3'].chartsInScope = [2]; + (state as any).dashboardInfo = { + ...state.dashboardInfo, + metadata: { + native_filter_configuration: Object.values(state.nativeFilters.filters), + }, + }; + + const { useSelector } = jest.requireMock('react-redux'); + useSelector.mockImplementation((selector: (s: typeof state) => unknown) => + selector(state), + ); + + const store = mockStore(state) as Store; + const { container } = render( + <Provider store={store}> + <FilterControlsWrapper> + <FilterControls + dataMaskSelected={{}} + onFilterSelectionChange={jest.fn()} + onPendingCustomizationDataMaskChange={jest.fn()} + chartCustomizationValues={[]} + /> + </FilterControlsWrapper> + </Provider>, + ); + + expect(screen.getByText('Filters out of scope (1)')).toBeInTheDocument(); + + // The "Filters" section is the out-of-scope collapsible's previous sibling + // inside the flex column. The parent already adds spacing via `gap`, so this + // section must not add its own margin-bottom on top of it. + const outOfScopeCollapse = container.querySelector('.ant-collapse'); + const filtersSection = outOfScopeCollapse?.previousElementSibling as Element; + const { marginBottom } = getComputedStyle(filtersSection); + expect(parseInt(marginBottom, 10) || 0).toBe(0); +}); diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterControls.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterControls.tsx index 2d5bc878768..ebf554d9390 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterControls.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterControls.tsx @@ -101,10 +101,6 @@ type FilterControlsProps = { hideHeader?: boolean; }; -const SectionContainer = styled.div` - margin-bottom: ${({ theme }) => theme.sizeUnit * 3}px; -`; - const SectionHeader = styled.button` appearance: none; border: none; @@ -321,7 +317,7 @@ const FilterControls: FC<FilterControlsProps> = ({ () => ( <> {filtersInScope.length > 0 && ( - <SectionContainer> + <div> {!hideHeader && ( <SectionHeader type="button" @@ -347,7 +343,7 @@ const FilterControls: FC<FilterControlsProps> = ({ <SectionContent>{filtersInScope.map(renderer)}</SectionContent> )} {(hideHeader || sectionsOpen.filters) && <StyledDivider />} - </SectionContainer> + </div> )} {showFiltersOutOfScope && ( @@ -359,7 +355,7 @@ const FilterControls: FC<FilterControlsProps> = ({ )} {customizationsInScope.length > 0 && ( - <SectionContainer> + <div> {!hideHeader && ( <SectionHeader type="button" @@ -396,7 +392,7 @@ const FilterControls: FC<FilterControlsProps> = ({ {(hideHeader || sectionsOpen.chartCustomization) && ( <StyledDivider /> )} - </SectionContainer> + </div> )} {showCustomizationCollapsePanel &&
