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

enzomartellucci pushed a commit to branch enxdev/refactor/antd5/create-wrappers
in repository https://gitbox.apache.org/repos/asf/superset.git

commit 87ef71f9daa1be0d60b2c38c700e9d5e05c5a647
Author: Enzo Martellucci <[email protected]>
AuthorDate: Mon Mar 17 18:54:14 2025 +0100

    refactor(Layout): add wrapper, tests, and story for Ant Design 5 Layout 
component
---
 .../src/SqlLab/components/SaveQuery/index.tsx      |   2 +-
 .../components/ScheduleQueryButton/index.tsx       |   2 +-
 .../AutoComplete/AutoComplete.stories.tsx          | 195 +++++++++++++++------
 .../src/components/AutoComplete/index.tsx          |   2 +-
 .../components/ErrorMessage/ErrorAlert.stories.tsx |   4 +-
 superset-frontend/src/components/Grid/index.tsx    |   7 +-
 .../src/components/Layout/Layout.stories.tsx       | 153 ++++++++++++++++
 .../src/components/Layout/Layout.test.tsx          |  94 ++++++++++
 superset-frontend/src/components/Layout/index.tsx  |   5 +
 superset-frontend/src/components/index.ts          |  11 +-
 .../dashboard/components/PropertiesModal/index.tsx |   3 +-
 .../explore/components/PropertiesModal/index.tsx   |   3 +-
 .../FormattingPopoverContent.tsx                   |   2 +-
 .../ContourControl/ContourPopoverControl.tsx       |   2 +-
 .../DateFilterControl/components/CustomFrame.tsx   |   2 +-
 .../databases/DatabaseModal/SSHTunnelForm.tsx      |   3 +-
 .../features/databases/UploadDataModel/index.tsx   |  10 +-
 superset-frontend/src/features/home/Menu.tsx       |   2 +-
 superset-frontend/src/features/home/SubMenu.tsx    |   2 +-
 superset-frontend/src/views/App.tsx                |   2 +-
 20 files changed, 422 insertions(+), 84 deletions(-)

diff --git a/superset-frontend/src/SqlLab/components/SaveQuery/index.tsx 
b/superset-frontend/src/SqlLab/components/SaveQuery/index.tsx
index b5793f11d3..3857e89873 100644
--- a/superset-frontend/src/SqlLab/components/SaveQuery/index.tsx
+++ b/superset-frontend/src/SqlLab/components/SaveQuery/index.tsx
@@ -19,7 +19,7 @@
 import { useState, useEffect, useMemo, ChangeEvent } from 'react';
 
 import type { DatabaseObject } from 'src/features/databases/types';
-import { Row, Col } from 'src/components';
+import { Row, Col } from 'src/components/Grid';
 import { Input } from 'src/components/Input';
 import { t, styled } from '@superset-ui/core';
 import Button from 'src/components/Button';
diff --git 
a/superset-frontend/src/SqlLab/components/ScheduleQueryButton/index.tsx 
b/superset-frontend/src/SqlLab/components/ScheduleQueryButton/index.tsx
index 0a68ac3ce6..39c1f86133 100644
--- a/superset-frontend/src/SqlLab/components/ScheduleQueryButton/index.tsx
+++ b/superset-frontend/src/SqlLab/components/ScheduleQueryButton/index.tsx
@@ -21,7 +21,7 @@ import { FunctionComponent, useState, useRef, ChangeEvent } 
from 'react';
 import SchemaForm, { FormProps } from '@rjsf/core';
 import { FormValidation } from '@rjsf/utils';
 import validator from '@rjsf/validator-ajv8';
-import { Row, Col } from 'src/components';
+import { Row, Col } from 'src/components/Grid';
 import { Input } from 'src/components/Input';
 import { t, styled } from '@superset-ui/core';
 import { parseDate } from 'chrono-node';
diff --git 
a/superset-frontend/src/components/AutoComplete/AutoComplete.stories.tsx 
b/superset-frontend/src/components/AutoComplete/AutoComplete.stories.tsx
index 053e189b03..79b0b372cc 100644
--- a/superset-frontend/src/components/AutoComplete/AutoComplete.stories.tsx
+++ b/superset-frontend/src/components/AutoComplete/AutoComplete.stories.tsx
@@ -1,12 +1,131 @@
 import { useState } from 'react';
-import { StoryFn } from '@storybook/react';
-import AutoComplete, { AntAutoCompleteProps } from './index';
-import { Input } from '../Input';
+import { Meta, StoryFn } from '@storybook/react';
+import AutoComplete, {
+  AntAutoCompleteProps,
+} from 'src/components/AutoComplete';
 
 export default {
   title: 'Components/AutoComplete',
   component: AutoComplete,
-};
+  argTypes: {
+    style: {
+      control: 'object',
+      description: 'Custom styles for AutoComplete',
+    },
+    placeholder: {
+      control: 'text',
+      description: 'Placeholder text for AutoComplete',
+    },
+    disabled: {
+      control: 'boolean',
+      description: 'Disable the AutoComplete',
+      defaultValue: false,
+    },
+    popupMatchSelectWidth: {
+      control: 'number',
+      description: 'Width of the dropdown',
+      defaultValue: 252,
+    },
+    children: {
+      control: 'text',
+      description: 'Custom input inside AutoComplete',
+    },
+    allowClear: {
+      control: 'boolean',
+      description: 'Show clear button',
+      defaultValue: false,
+    },
+    autoFocus: {
+      control: 'boolean',
+      description: 'If get focus when component mounted',
+      defaultValue: false,
+    },
+    backfill: {
+      control: 'boolean',
+      description: 'If backfill selected item the input when using keyboard',
+      defaultValue: false,
+    },
+    childrenInput: {
+      control: 'text',
+      description: 'Customize input element',
+    },
+    defaultActiveFirstOption: {
+      control: 'boolean',
+      description: 'Whether active first option by default',
+      defaultValue: true,
+    },
+    defaultOpen: {
+      control: 'boolean',
+      description: 'Initial open state of dropdown',
+    },
+    defaultValue: {
+      control: 'text',
+      description: 'Initial selected option',
+    },
+    dropdownRender: {
+      control: false,
+      description: 'Customize dropdown content',
+    },
+    popupClassName: {
+      control: 'text',
+      description: 'The className of dropdown menu',
+    },
+    filterOption: {
+      control: 'boolean',
+      description: 'If true, filter options by input',
+      defaultValue: true,
+    },
+    getPopupContainer: {
+      control: false,
+      description: 'Parent node of the dropdown.',
+      defaultValue: () => document.body,
+    },
+    notFoundContent: {
+      control: 'text',
+      description: 'Specify content to show when no result matches',
+    },
+    open: {
+      control: 'boolean',
+      description: 'Controlled open state of dropdown',
+    },
+    options: {
+      control: 'object',
+      description: 'Select options. Will get better perf than JSX definition',
+    },
+    status: {
+      control: 'select',
+      options: ['error', 'warning'],
+      description: 'Set validation status',
+    },
+    size: {
+      control: 'select',
+      options: ['large', 'middle', 'small'],
+      description: 'The size of the input box',
+    },
+    value: {
+      control: 'text',
+      description: 'Selected option',
+    },
+    variant: {
+      control: 'select',
+      options: ['outlined', 'borderless', 'filled'],
+      description: 'Variants of input',
+      defaultValue: 'outlined',
+    },
+    virtual: {
+      control: 'boolean',
+      description: 'Disable virtual scroll when set to false',
+      defaultValue: true,
+    },
+  },
+  parameters: {
+    docs: {
+      description: {
+        component: 'AutoComplete component for search functionality.',
+      },
+    },
+  },
+} as Meta;
 
 const getRandomInt = (max: number, min = 0) =>
   Math.floor(Math.random() * (max - min + 1)) + min;
@@ -34,7 +153,7 @@ const searchResult = (query: string) =>
     };
   });
 
-const Template: StoryFn<AntAutoCompleteProps> = args => {
+const AutoCompleteWithOptions = (args: AntAutoCompleteProps) => {
   const [options, setOptions] = useState<AntAutoCompleteProps['options']>([]);
 
   const handleSearch = (value: string) => {
@@ -44,52 +163,26 @@ const Template: StoryFn<AntAutoCompleteProps> = args => {
   return <AutoComplete {...args} options={options} onSearch={handleSearch} />;
 };
 
-export const Default = Template.bind({});
-Default.args = {
-  style: { width: 300 },
-  placeholder: 'Type to search...',
-};
-
-export const WithInputSearch = () => {
-  const [options, setOptions] = useState<AntAutoCompleteProps['options']>([]);
+export const AutoCompleteStory: StoryFn<AntAutoCompleteProps> = args => (
+  <div style={{ margin: '20px' }}>
+    <AutoCompleteWithOptions {...args} />
+  </div>
+);
 
-  const handleSearch = (value: string) => {
-    setOptions(value ? searchResult(value) : []);
-  };
-
-  return (
-    <AutoComplete
-      popupMatchSelectWidth={252}
-      style={{ width: 300 }}
-      options={options}
-      onSearch={handleSearch}
-    >
-      <Input.Search size="large" placeholder="input here" enterButton />
-    </AutoComplete>
-  );
-};
-
-export const Disabled = Template.bind({});
-Disabled.args = {
+AutoCompleteStory.args = {
   style: { width: 300 },
-  placeholder: 'Disabled AutoComplete',
-  disabled: true,
-};
-
-export const CustomRender = () => {
-  const [options, setOptions] = useState<AntAutoCompleteProps['options']>([]);
-
-  const handleSearch = (value: string) => {
-    setOptions(value ? searchResult(value) : []);
-  };
-
-  return (
-    <AutoComplete
-      style={{ width: 300 }}
-      options={options}
-      onSearch={handleSearch}
-    >
-      <Input placeholder="Custom Render" />
-    </AutoComplete>
-  );
+  placeholder: 'Type to search...',
+  disabled: false,
+  allowClear: false,
+  autoFocus: false,
+  backfill: false,
+  defaultActiveFirstOption: true,
+  defaultOpen: false,
+  defaultValue: '',
+  filterOption: true,
+  notFoundContent: 'No results found',
+  open: false,
+  size: 'middle',
+  variant: 'outlined',
+  virtual: true,
 };
diff --git a/superset-frontend/src/components/AutoComplete/index.tsx 
b/superset-frontend/src/components/AutoComplete/index.tsx
index 708c0acccb..8db93ca105 100644
--- a/superset-frontend/src/components/AutoComplete/index.tsx
+++ b/superset-frontend/src/components/AutoComplete/index.tsx
@@ -18,7 +18,7 @@
  */
 import AutoComplete, {
   AutoCompleteProps as AntAutoCompleteProps,
-} from 'antd-v5';
+} from 'antd-v5/lib/auto-complete';
 
 export type { AntAutoCompleteProps };
 
diff --git 
a/superset-frontend/src/components/ErrorMessage/ErrorAlert.stories.tsx 
b/superset-frontend/src/components/ErrorMessage/ErrorAlert.stories.tsx
index b7595c00fa..4ae49ac22f 100644
--- a/superset-frontend/src/components/ErrorMessage/ErrorAlert.stories.tsx
+++ b/superset-frontend/src/components/ErrorMessage/ErrorAlert.stories.tsx
@@ -17,7 +17,9 @@
  * under the License.
  */
 import { Meta, StoryFn } from '@storybook/react';
-import { Layout, Row, Col, Card } from 'antd-v5';
+import Layout from 'src/components/Layout';
+import { Row, Col } from 'src/components/Grid';
+import Card from 'src/components/Card';
 import ErrorAlert from './ErrorAlert';
 
 const { Content } = Layout;
diff --git a/superset-frontend/src/components/Grid/index.tsx 
b/superset-frontend/src/components/Grid/index.tsx
index 21eb5b8f07..acd9f2d316 100644
--- a/superset-frontend/src/components/Grid/index.tsx
+++ b/superset-frontend/src/components/Grid/index.tsx
@@ -1,8 +1,11 @@
-import Grid, { Row, Col } from 'antd-v5';
+import { Row, Col } from 'antd-v5';
+import useBreakpoint from 'antd-v5/es/grid/hooks/useBreakpoint';
 import type { ColProps, ColSize } from 'antd-v5/es/col';
 import type { RowProps } from 'antd-v5/es/row';
 
 export type { ColProps, ColSize, RowProps };
 
-export default Grid;
 export { Row, Col };
+
+const Grid = { useBreakpoint };
+export default Grid;
diff --git a/superset-frontend/src/components/Layout/Layout.stories.tsx 
b/superset-frontend/src/components/Layout/Layout.stories.tsx
new file mode 100644
index 0000000000..2a5496d95c
--- /dev/null
+++ b/superset-frontend/src/components/Layout/Layout.stories.tsx
@@ -0,0 +1,153 @@
+import { useState } from 'react';
+import { Meta, StoryFn } from '@storybook/react';
+import Layout from 'src/components/Layout';
+import { Menu } from 'src/components/Menu';
+import { MenuFoldOutlined, MenuUnfoldOutlined } from '@ant-design/icons';
+
+const { Header, Footer, Sider, Content } = Layout;
+
+export default {
+  title: 'Components/Layout',
+  component: Layout,
+  subcomponents: { Header, Footer, Sider, Content },
+  argTypes: {
+    hasSider: {
+      control: 'boolean',
+      description: 'Include a sider',
+      defaultValue: false,
+    },
+    // Layout.Sider props
+    breakpoint: {
+      control: 'select',
+      options: ['xs', 'sm', 'md', 'lg', 'xl', 'xxl'],
+      description: 'Breakpoints of the responsive layout',
+    },
+    collapsed: {
+      control: 'boolean',
+      description: 'Set the current collapsed status',
+      defaultValue: false,
+    },
+    collapsedWidth: {
+      control: 'number',
+      description: 'Width of collapsed sidebar',
+      defaultValue: 80,
+    },
+    collapsible: {
+      control: 'boolean',
+      description: 'Whether the sidebar can be collapsed',
+      defaultValue: false,
+    },
+    defaultCollapsed: {
+      control: 'boolean',
+      description: 'Set the initial collapsed status',
+      defaultValue: false,
+    },
+    reverseArrow: {
+      control: 'boolean',
+      description: 'Reverse the direction of the collapse arrow',
+      defaultValue: false,
+    },
+    theme: {
+      control: 'select',
+      options: ['light', 'dark'],
+      description: 'Sidebar theme',
+      defaultValue: 'dark',
+    },
+    width: {
+      control: 'number',
+      description: 'Width of the sidebar',
+      defaultValue: 200,
+    },
+    headerVisible: {
+      control: 'boolean',
+      description: 'Show Header',
+      defaultValue: true,
+    },
+    footerVisible: {
+      control: 'boolean',
+      description: 'Show Footer',
+      defaultValue: true,
+    },
+  },
+  parameters: {
+    docs: {
+      description: {
+        component:
+          'Ant Design Layout component with configurable Sider, Header, 
Footer, and Content.',
+      },
+    },
+  },
+} as Meta;
+
+export const LayoutStory: StoryFn = args => {
+  const [collapsed, setCollapsed] = useState(false);
+  return (
+    <Layout style={{ minHeight: '100vh' }}>
+      {args.hasSider && (
+        <Sider
+          collapsible={args.collapsible}
+          collapsed={collapsed}
+          onCollapse={value => setCollapsed(value)}
+          theme={args.theme}
+          width={args.width}
+          collapsedWidth={args.collapsedWidth}
+        >
+          <div
+            className="logo"
+            style={{ height: '32px', margin: '16px', background: '#ffffff30' }}
+          />
+          <Menu theme={args.theme} defaultSelectedKeys={['1']} mode="inline">
+            <Menu.Item key="1" icon={<MenuUnfoldOutlined />}>
+              Option 1
+            </Menu.Item>
+            <Menu.Item key="2" icon={<MenuFoldOutlined />}>
+              Option 2
+            </Menu.Item>
+          </Menu>
+        </Sider>
+      )}
+      <Layout>
+        {args.headerVisible && (
+          <Header
+            style={{
+              background: '#fff',
+              padding: '0 16px',
+              textAlign: 'center',
+            }}
+          >
+            Header
+          </Header>
+        )}
+        <Content
+          style={{
+            margin: '16px',
+            padding: '24px',
+            background: '#fff',
+            textAlign: 'center',
+          }}
+        >
+          Content Area
+        </Content>
+        {args.footerVisible && (
+          <Footer style={{ textAlign: 'center' }}>
+            Ant Design Layout Footer
+          </Footer>
+        )}
+      </Layout>
+    </Layout>
+  );
+};
+
+LayoutStory.args = {
+  hasSider: true,
+  theme: 'dark',
+  collapsible: true,
+  collapsed: false,
+  defaultCollapsed: false,
+  collapsedWidth: 80,
+  width: 200,
+  reverseArrow: false,
+  breakpoint: 'md',
+  headerVisible: true,
+  footerVisible: true,
+};
diff --git a/superset-frontend/src/components/Layout/Layout.test.tsx 
b/superset-frontend/src/components/Layout/Layout.test.tsx
new file mode 100644
index 0000000000..c4c01e03a1
--- /dev/null
+++ b/superset-frontend/src/components/Layout/Layout.test.tsx
@@ -0,0 +1,94 @@
+import { useState, ReactElement } from 'react';
+import { render, screen, fireEvent } from '@testing-library/react';
+import '@testing-library/jest-dom';
+import Layout from 'src/components/Layout';
+import Button from 'src/components/Button';
+import { ThemeProvider, supersetTheme } from '@superset-ui/core';
+
+describe('Layout Component', () => {
+  const renderWithTheme = (ui: ReactElement) =>
+    render(<ThemeProvider theme={supersetTheme}>{ui}</ThemeProvider>);
+
+  test('renders Layout with Header, Content, and Footer', () => {
+    render(
+      <Layout hasSider={false}>
+        <Layout.Header>Header</Layout.Header>
+        <Layout.Content>Content Area</Layout.Content>
+        <Layout.Footer>Ant Design Layout Footer</Layout.Footer>
+      </Layout>,
+    );
+
+    expect(screen.getByText('Header')).toBeInTheDocument();
+    expect(screen.getByText('Content Area')).toBeInTheDocument();
+    expect(screen.getByText('Ant Design Layout Footer')).toBeInTheDocument();
+  });
+
+  test('renders Layout with Sider when hasSider is true', () => {
+    render(
+      <Layout hasSider>
+        <Layout.Sider>Sider Content</Layout.Sider>
+      </Layout>,
+    );
+
+    expect(screen.getByText('Sider Content')).toBeInTheDocument();
+  });
+
+  test('hides Header when headerVisible is false', () => {
+    render(
+      <Layout>
+        {false && <Layout.Header>Header</Layout.Header>}
+        <Layout.Content>Content Area</Layout.Content>
+        <Layout.Footer>Ant Design Layout Footer</Layout.Footer>
+      </Layout>,
+    );
+
+    expect(screen.queryByText('Header')).not.toBeInTheDocument();
+  });
+
+  test('hides Footer when footerVisible is false', () => {
+    render(
+      <Layout>
+        <Layout.Header>Header</Layout.Header>
+        <Layout.Content>Content Area</Layout.Content>
+        {false && <Layout.Footer>Ant Design Layout Footer</Layout.Footer>}
+      </Layout>,
+    );
+
+    expect(
+      screen.queryByText('Ant Design Layout Footer'),
+    ).not.toBeInTheDocument();
+  });
+  test('collapses Sider when clicked', () => {
+    const TestLayout = () => {
+      const [collapsed, setCollapsed] = useState(false);
+
+      return (
+        <Layout hasSider>
+          <Layout.Sider
+            collapsible
+            collapsed={collapsed}
+            collapsedWidth={80}
+            width={200}
+          >
+            <Button onClick={() => setCollapsed(!collapsed)}>Toggle</Button>
+            Sider Content
+          </Layout.Sider>
+        </Layout>
+      );
+    };
+
+    renderWithTheme(<TestLayout />);
+
+    const toggleButton = screen.getByRole('button', { name: 'Toggle' });
+
+    expect(screen.getByText('Sider Content').parentElement).toHaveStyle({
+      width: '200px',
+    });
+
+    fireEvent.click(toggleButton);
+
+    expect(screen.getByText('Sider Content').parentElement).toHaveStyle({
+      width: '80px',
+    });
+  });
+});
diff --git a/superset-frontend/src/components/Layout/index.tsx 
b/superset-frontend/src/components/Layout/index.tsx
new file mode 100644
index 0000000000..17f3746716
--- /dev/null
+++ b/superset-frontend/src/components/Layout/index.tsx
@@ -0,0 +1,5 @@
+import Layout from 'antd-v5/lib/layout';
+import type { LayoutProps, SiderProps } from 'antd-v5/lib/layout';
+
+export type { LayoutProps, SiderProps };
+export default Layout;
diff --git a/superset-frontend/src/components/index.ts 
b/superset-frontend/src/components/index.ts
index e2f5997a16..42f56cf6b6 100644
--- a/superset-frontend/src/components/index.ts
+++ b/superset-frontend/src/components/index.ts
@@ -28,16 +28,7 @@ export { default as Button } from './Button';
 export { default as Card } from './Card';
 
 // Vanilla Ant Design components from v5
-export {
-  Col,
-  Grid,
-  Layout,
-  Row,
-  Skeleton,
-  Tag,
-  TreeSelect,
-  Typography,
-} from 'antd-v5';
+export { Skeleton, Tag, TreeSelect, Typography } from 'antd-v5';
 
 // Vanilla Ant Design components from v4 that require migration
 export { Upload } from 'antd';
diff --git 
a/superset-frontend/src/dashboard/components/PropertiesModal/index.tsx 
b/superset-frontend/src/dashboard/components/PropertiesModal/index.tsx
index 4831ece8a5..8cbb4a1278 100644
--- a/superset-frontend/src/dashboard/components/PropertiesModal/index.tsx
+++ b/superset-frontend/src/dashboard/components/PropertiesModal/index.tsx
@@ -22,7 +22,8 @@ import { Input } from 'src/components/Input';
 import { FormItem } from 'src/components/Form';
 import jsonStringify from 'json-stringify-pretty-compact';
 import Button from 'src/components/Button';
-import { AntdForm, AsyncSelect, Col, Row } from 'src/components';
+import { AntdForm, AsyncSelect } from 'src/components';
+import { Row, Col } from 'src/components/Grid';
 import rison from 'rison';
 import {
   ensureIsArray,
diff --git a/superset-frontend/src/explore/components/PropertiesModal/index.tsx 
b/superset-frontend/src/explore/components/PropertiesModal/index.tsx
index b5c8cd8d64..4eb4537593 100644
--- a/superset-frontend/src/explore/components/PropertiesModal/index.tsx
+++ b/superset-frontend/src/explore/components/PropertiesModal/index.tsx
@@ -21,7 +21,8 @@ import { ChangeEvent, useMemo, useState, useCallback, 
useEffect } from 'react';
 import Modal from 'src/components/Modal';
 import { Input } from 'src/components/Input';
 import Button from 'src/components/Button';
-import { AsyncSelect, Row, Col, AntdForm } from 'src/components';
+import { AsyncSelect, AntdForm } from 'src/components';
+import { Row, Col } from 'src/components/Grid';
 import { SelectValue } from 'antd/lib/select';
 import rison from 'rison';
 import {
diff --git 
a/superset-frontend/src/explore/components/controls/ConditionalFormattingControl/FormattingPopoverContent.tsx
 
b/superset-frontend/src/explore/components/controls/ConditionalFormattingControl/FormattingPopoverContent.tsx
index 8e68bc0209..69ef6a661f 100644
--- 
a/superset-frontend/src/explore/components/controls/ConditionalFormattingControl/FormattingPopoverContent.tsx
+++ 
b/superset-frontend/src/explore/components/controls/ConditionalFormattingControl/FormattingPopoverContent.tsx
@@ -25,7 +25,7 @@ import {
 } from '@superset-ui/chart-controls';
 import { Form, FormItem, FormProps } from 'src/components/Form';
 import Select from 'src/components/Select/Select';
-import { Col, Row } from 'src/components';
+import { Col, Row } from 'src/components/Grid';
 import { InputNumber } from 'src/components/Input';
 import Button from 'src/components/Button';
 import { ConditionalFormattingConfig } from './types';
diff --git 
a/superset-frontend/src/explore/components/controls/ContourControl/ContourPopoverControl.tsx
 
b/superset-frontend/src/explore/components/controls/ContourControl/ContourPopoverControl.tsx
index fc9c1bfd78..17bd35011a 100644
--- 
a/superset-frontend/src/explore/components/controls/ContourControl/ContourPopoverControl.tsx
+++ 
b/superset-frontend/src/explore/components/controls/ContourControl/ContourPopoverControl.tsx
@@ -17,7 +17,7 @@
  * under the License.
  */
 import { useState, useEffect } from 'react';
-import { Row, Col } from 'src/components';
+import { Row, Col } from 'src/components/Grid';
 import Button from 'src/components/Button';
 import Tabs from 'src/components/Tabs';
 import { legacyValidateInteger, styled, t } from '@superset-ui/core';
diff --git 
a/superset-frontend/src/explore/components/controls/DateFilterControl/components/CustomFrame.tsx
 
b/superset-frontend/src/explore/components/controls/DateFilterControl/components/CustomFrame.tsx
index 969b46855e..1164d246fd 100644
--- 
a/superset-frontend/src/explore/components/controls/DateFilterControl/components/CustomFrame.tsx
+++ 
b/superset-frontend/src/explore/components/controls/DateFilterControl/components/CustomFrame.tsx
@@ -18,7 +18,7 @@
  */
 import { t, customTimeRangeDecode } from '@superset-ui/core';
 import { InfoTooltipWithTrigger } from '@superset-ui/chart-controls';
-import { Col, Row } from 'src/components';
+import { Col, Row } from 'src/components/Grid';
 import { InputNumber } from 'src/components/Input';
 import { DatePicker } from 'src/components/DatePicker';
 import { Radio } from 'src/components/Radio';
diff --git 
a/superset-frontend/src/features/databases/DatabaseModal/SSHTunnelForm.tsx 
b/superset-frontend/src/features/databases/DatabaseModal/SSHTunnelForm.tsx
index fd496b4026..96c4b78bca 100644
--- a/superset-frontend/src/features/databases/DatabaseModal/SSHTunnelForm.tsx
+++ b/superset-frontend/src/features/databases/DatabaseModal/SSHTunnelForm.tsx
@@ -18,7 +18,8 @@
  */
 import { useState } from 'react';
 import { t, styled } from '@superset-ui/core';
-import { AntdForm, Col, Row } from 'src/components';
+import { AntdForm } from 'src/components';
+import { Row, Col } from 'src/components/Grid';
 import { Form, FormLabel } from 'src/components/Form';
 import { Radio } from 'src/components/Radio';
 import { Input } from 'src/components/Input';
diff --git a/superset-frontend/src/features/databases/UploadDataModel/index.tsx 
b/superset-frontend/src/features/databases/UploadDataModel/index.tsx
index eccfe3da37..dc7e7fc599 100644
--- a/superset-frontend/src/features/databases/UploadDataModel/index.tsx
+++ b/superset-frontend/src/features/databases/UploadDataModel/index.tsx
@@ -35,14 +35,8 @@ import Modal from 'src/components/Modal';
 import Button from 'src/components/Button';
 import { Switch, SwitchProps } from 'src/components/Switch';
 import Collapse from 'src/components/Collapse';
-import {
-  AntdForm,
-  AsyncSelect,
-  Col,
-  Row,
-  Select,
-  Upload,
-} from 'src/components';
+import { AntdForm, AsyncSelect, Select, Upload } from 'src/components';
+import { Row, Col } from 'src/components/Grid';
 import { UploadOutlined } from '@ant-design/icons';
 import { Input, InputNumber } from 'src/components/Input';
 import rison from 'rison';
diff --git a/superset-frontend/src/features/home/Menu.tsx 
b/superset-frontend/src/features/home/Menu.tsx
index ebcff4a023..08ca7fe919 100644
--- a/superset-frontend/src/features/home/Menu.tsx
+++ b/superset-frontend/src/features/home/Menu.tsx
@@ -20,7 +20,7 @@ import { useState, useEffect } from 'react';
 import { styled } from '@superset-ui/core';
 import { debounce } from 'lodash';
 import { getUrlParam } from 'src/utils/urlUtils';
-import { Row, Col, Grid } from 'src/components';
+import Grid, { Row, Col } from 'src/components/Grid';
 import { MainNav, MenuMode } from 'src/components/Menu';
 import { Tooltip } from 'src/components/Tooltip';
 import { NavLink, useLocation } from 'react-router-dom';
diff --git a/superset-frontend/src/features/home/SubMenu.tsx 
b/superset-frontend/src/features/home/SubMenu.tsx
index af1df5a59a..c450271354 100644
--- a/superset-frontend/src/features/home/SubMenu.tsx
+++ b/superset-frontend/src/features/home/SubMenu.tsx
@@ -23,7 +23,7 @@ import { styled, SupersetTheme, css, t } from 
'@superset-ui/core';
 import cx from 'classnames';
 import { Tooltip } from 'src/components/Tooltip';
 import { debounce } from 'lodash';
-import { Row } from 'src/components';
+import { Row } from 'src/components/Grid';
 import { Menu, MenuMode, MainNav } from 'src/components/Menu';
 import Button, { OnClickHandler } from 'src/components/Button';
 import Icons from 'src/components/Icons';
diff --git a/superset-frontend/src/views/App.tsx 
b/superset-frontend/src/views/App.tsx
index 970ad95870..486b8548e5 100644
--- a/superset-frontend/src/views/App.tsx
+++ b/superset-frontend/src/views/App.tsx
@@ -29,7 +29,7 @@ import { css } from '@superset-ui/core';
 import { GlobalStyles } from 'src/GlobalStyles';
 import ErrorBoundary from 'src/components/ErrorBoundary';
 import Loading from 'src/components/Loading';
-import { Layout } from 'src/components';
+import Layout from 'src/components/Layout';
 import Menu from 'src/features/home/Menu';
 import getBootstrapData from 'src/utils/getBootstrapData';
 import ToastContainer from 'src/components/MessageToasts/ToastContainer';

Reply via email to