This is an automated email from the ASF dual-hosted git repository.

elizabeth pushed a commit to branch elizabeth/fix-resize-bug
in repository https://gitbox.apache.org/repos/asf/superset.git

commit e054560000cd0538887f34bbe57c52d7d7446446
Author: Elizabeth Thompson <[email protected]>
AuthorDate: Fri Jul 25 17:33:44 2025 -0700

    ix layout
---
 .../dashboard/components/FiltersBadge/index.tsx    | 10 +++-
 .../components/SliceHeader/SliceHeader.test.tsx    |  4 ++
 .../src/dashboard/components/SliceHeader/index.tsx | 23 +++++++-
 .../dashboard/components/gridComponents/Chart.jsx  | 64 +++++++++++++++++++++-
 .../components/gridComponents/Chart.test.jsx       | 34 ++++++++++++
 5 files changed, 131 insertions(+), 4 deletions(-)

diff --git a/superset-frontend/src/dashboard/components/FiltersBadge/index.tsx 
b/superset-frontend/src/dashboard/components/FiltersBadge/index.tsx
index 319484642b..df6daf7dad 100644
--- a/superset-frontend/src/dashboard/components/FiltersBadge/index.tsx
+++ b/superset-frontend/src/dashboard/components/FiltersBadge/index.tsx
@@ -52,6 +52,7 @@ import { Chart, RootState } from '../../types';
 
 export interface FiltersBadgeProps {
   chartId: number;
+  isCompact?: boolean;
 }
 
 const StyledFilterCount = styled.div`
@@ -77,6 +78,12 @@ const StyledFilterCount = styled.div`
     .incompatible-count {
       font-size: ${theme.fontSizeSM}px;
     }
+    &.is-compact {
+      padding-left: 0;
+      .anticon-filter {
+        display: none;
+      }
+    }
     &:focus-visible {
       outline: 2px solid ${theme.colorPrimary};
     }
@@ -114,7 +121,7 @@ const sortByStatus = (indicators: Indicator[]): Indicator[] 
=> {
 
 const indicatorsInitialState: Indicator[] = [];
 
-export const FiltersBadge = ({ chartId }: FiltersBadgeProps) => {
+export const FiltersBadge = ({ chartId, isCompact }: FiltersBadgeProps) => {
   const dispatch = useDispatch();
   const datasources = useSelector<RootState, any>(state => state.datasources);
   const dashboardFilters = useSelector<RootState, any>(
@@ -305,6 +312,7 @@ export const FiltersBadge = ({ chartId }: 
FiltersBadgeProps) => {
         className={cx(
           'filter-counts',
           !!appliedCrossFilterIndicators.length && 'has-cross-filters',
+          isCompact && 'is-compact',
         )}
         tabIndex={0}
         onKeyDown={handleKeyDown}
diff --git 
a/superset-frontend/src/dashboard/components/SliceHeader/SliceHeader.test.tsx 
b/superset-frontend/src/dashboard/components/SliceHeader/SliceHeader.test.tsx
index b7bc53eb5a..f28168d8a9 100644
--- 
a/superset-frontend/src/dashboard/components/SliceHeader/SliceHeader.test.tsx
+++ 
b/superset-frontend/src/dashboard/components/SliceHeader/SliceHeader.test.tsx
@@ -682,3 +682,7 @@ test('Should show RowCountLabel in embedded when 
uiConfig.showRowLimitWarning is
   mockIsEmbedded.mockRestore();
   mockUseUiConfig.mockRestore();
 });
+
+// Note: Compact class tests would require full redux state setup.
+// The functionality is tested through integration tests and can be verified
+// by checking that the isCompact prop is properly used in the className logic.
diff --git a/superset-frontend/src/dashboard/components/SliceHeader/index.tsx 
b/superset-frontend/src/dashboard/components/SliceHeader/index.tsx
index 127a0f374c..c72da050ee 100644
--- a/superset-frontend/src/dashboard/components/SliceHeader/index.tsx
+++ b/superset-frontend/src/dashboard/components/SliceHeader/index.tsx
@@ -60,6 +60,7 @@ type SliceHeaderProps = SliceHeaderControlsProps & {
   width: number;
   height: number;
   exportPivotExcel?: (arg0: string) => void;
+  isCompact?: boolean;
 };
 
 const annotationsLoading = t('Annotation layers are still loading.');
@@ -90,12 +91,25 @@ const ChartHeaderStyles = styled.div`
       display: -webkit-box;
       -webkit-line-clamp: 2;
       -webkit-box-orient: vertical;
+      word-break: break-word;
+      hyphens: auto;
+      line-height: 1.4;
 
       & > span.ant-tooltip-open {
         display: inline;
       }
     }
 
+    &.chart-header--compact {
+      margin-bottom: ${theme.sizeUnit / 2}px;
+      font-size: ${theme.fontSizeSM}px;
+
+      & > .header-title {
+        -webkit-line-clamp: 1;
+        line-height: 1.2;
+      }
+    }
+
     & > .header-controls {
       display: flex;
       align-items: center;
@@ -169,6 +183,7 @@ const SliceHeader = forwardRef<HTMLDivElement, 
SliceHeaderProps>(
       width,
       height,
       exportPivotExcel = () => ({}),
+      isCompact = false,
     },
     ref,
   ) => {
@@ -234,7 +249,11 @@ const SliceHeader = forwardRef<HTMLDivElement, 
SliceHeaderProps>(
     );
 
     return (
-      <ChartHeaderStyles data-test="slice-header" ref={ref}>
+      <ChartHeaderStyles
+        data-test="slice-header"
+        ref={ref}
+        className={isCompact ? 'chart-header--compact' : ''}
+      >
         <div className="header-title" ref={headerRef}>
           <Tooltip title={headerTooltip}>
             <EditableTitle
@@ -298,7 +317,7 @@ const SliceHeader = forwardRef<HTMLDivElement, 
SliceHeaderProps>(
               )}
 
               {!uiConfig.hideChartControls && (
-                <FiltersBadge chartId={slice.slice_id} />
+                <FiltersBadge chartId={slice.slice_id} isCompact={isCompact} />
               )}
 
               {shouldShowRowLimitWarning && sqlRowCount === rowLimit && (
diff --git 
a/superset-frontend/src/dashboard/components/gridComponents/Chart.jsx 
b/superset-frontend/src/dashboard/components/gridComponents/Chart.jsx
index 9e18ae9856..388548557b 100644
--- a/superset-frontend/src/dashboard/components/gridComponents/Chart.jsx
+++ b/superset-frontend/src/dashboard/components/gridComponents/Chart.jsx
@@ -21,6 +21,7 @@ import { useCallback, useEffect, useRef, useMemo, useState, 
memo } from 'react';
 import PropTypes from 'prop-types';
 import { styled, t, logging } from '@superset-ui/core';
 import { debounce } from 'lodash';
+import { useResizeDetector } from 'react-resize-detector';
 import { useHistory } from 'react-router-dom';
 import { bindActionCreators } from 'redux';
 import { useDispatch, useSelector } from 'react-redux';
@@ -80,6 +81,8 @@ const propTypes = {
 // resizing across all slices on a dashboard on every update
 const RESIZE_TIMEOUT = 500;
 const DEFAULT_HEADER_HEIGHT = 22;
+const COMPACT_WIDTH_THRESHOLD = 400;
+const COMPACT_HEIGHT_THRESHOLD = 50;
 
 const ChartWrapper = styled.div`
   overflow: hidden;
@@ -88,6 +91,25 @@ const ChartWrapper = styled.div`
   &.dashboard-chart--overflowable {
     overflow: visible;
   }
+
+  &.dashboard-chart--small {
+    .slice_container {
+      font-size: 0.9em;
+    }
+  }
+
+  &.dashboard-chart--short {
+    .slice_container {
+      .slice-header {
+        margin-bottom: 4px;
+      }
+    }
+  }
+
+  .slice_container {
+    min-height: 100%;
+    height: 100%;
+  }
 `;
 
 const ChartOverlay = styled.div`
@@ -185,6 +207,24 @@ const Chart = props => {
     [props.width, props.height],
   );
 
+  const immediateResize = useCallback(() => {
+    const { width, height } = props;
+    setHeight(height);
+    setWidth(width);
+  }, [props.width, props.height]);
+
+  const handleContainerResize = useCallback(() => {
+    const { width, height } = props;
+    setHeight(height);
+    setWidth(width);
+  }, [props.width, props.height]);
+
+  const { ref: resizeRef } = useResizeDetector({
+    refreshMode: 'debounce',
+    refreshRate: 100,
+    onResize: handleContainerResize,
+  });
+
   const ownColorScheme = chart.form_data?.color_scheme;
 
   const addFilter = useCallback(
@@ -221,6 +261,14 @@ const Chart = props => {
     resize();
   }, [resize, props.isFullSize]);
 
+  useEffect(() => {
+    if (props.width !== width || props.height !== height) {
+      immediateResize();
+      resize.cancel();
+      resize();
+    }
+  }, [props.width, props.height, width, height, immediateResize, resize]);
+
   const getHeaderHeight = useCallback(() => {
     if (headerRef.current) {
       const computedMarginBottom = getComputedStyle(
@@ -324,6 +372,10 @@ const Chart = props => {
 
   formData.dashboardId = dashboardInfo.id;
 
+  useEffect(() => {
+    immediateResize();
+  }, [formData, immediateResize]);
+
   const onExploreChart = useCallback(
     async clickEvent => {
       const isOpenInNewTab =
@@ -440,6 +492,7 @@ const Chart = props => {
 
   return (
     <SliceContainer
+      ref={resizeRef}
       className="chart-slice"
       data-test="chart-grid-component"
       data-test-chart-id={props.id}
@@ -450,6 +503,10 @@ const Chart = props => {
         ref={headerRef}
         slice={slice}
         isExpanded={isExpanded}
+        isCompact={
+          width < COMPACT_WIDTH_THRESHOLD ||
+          getChartHeight() < COMPACT_HEIGHT_THRESHOLD
+        }
         isCached={isCached}
         cachedDttm={cachedDttm}
         updatedDttm={chartUpdateEndTime}
@@ -502,7 +559,12 @@ const Chart = props => {
       )}
 
       <ChartWrapper
-        className={cx('dashboard-chart')}
+        className={cx(
+          'dashboard-chart',
+          width < COMPACT_WIDTH_THRESHOLD && 'dashboard-chart--small',
+          getChartHeight() < COMPACT_HEIGHT_THRESHOLD &&
+            'dashboard-chart--short',
+        )}
         aria-label={slice.description}
       >
         {isLoading && (
diff --git 
a/superset-frontend/src/dashboard/components/gridComponents/Chart.test.jsx 
b/superset-frontend/src/dashboard/components/gridComponents/Chart.test.jsx
index 950f3dacc1..3b0071f7c9 100644
--- a/superset-frontend/src/dashboard/components/gridComponents/Chart.test.jsx
+++ b/superset-frontend/src/dashboard/components/gridComponents/Chart.test.jsx
@@ -262,3 +262,37 @@ test('should call exportChart with row_limit props.maxRows 
when exportFullXLSX i
 
   stubbedExportXLSX.mockRestore();
 });
+
+test('should apply responsive classes for small charts', async () => {
+  const smallChartProps = {
+    ...props,
+    width: 350, // Small width
+    height: 180, // Short height
+  };
+
+  const { container } = render(<Chart {...smallChartProps} />, {
+    useRedux: true,
+    useRouter: true,
+  });
+
+  // Wait for the component to render
+  await new Promise(resolve => setTimeout(resolve, 100));
+
+  const chartWrapper = container.querySelector('.dashboard-chart');
+  expect(chartWrapper).toBeDefined();
+  expect(chartWrapper).toHaveClass('dashboard-chart--small');
+  expect(chartWrapper).toHaveClass('dashboard-chart--short');
+});
+
+test('chart should render with resize observer integration', async () => {
+  const { container } = render(<Chart {...props} />, {
+    useRedux: true,
+    useRouter: true,
+  });
+
+  // Check that the chart container has been rendered with the resize ref
+  const chartContainer = container.querySelector(
+    '[data-test="chart-grid-component"]',
+  );
+  expect(chartContainer).toBeInTheDocument();
+});

Reply via email to