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

enzomartellucci pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/superset.git


The following commit(s) were added to refs/heads/master by this push:
     new 468bb5f47a refactor(Radio): Upgrade Radio Component to Ant Design 5 
(#32004)
468bb5f47a is described below

commit 468bb5f47a81f6b3773db2cd1a75f01ae9a32b5f
Author: Enzo Martellucci <[email protected]>
AuthorDate: Fri Jan 31 17:45:06 2025 +0100

    refactor(Radio): Upgrade Radio Component to Ant Design 5 (#32004)
---
 .../SqlLab/components/SaveDatasetModal/index.tsx   |   4 +-
 .../Chart/DrillBy/useDisplayModeToggle.tsx         |  28 ++--
 .../src/components/Radio/Radio.stories.tsx         | 149 +++++++++++++++++----
 superset-frontend/src/components/Radio/index.tsx   |  80 +++++------
 .../header-renderers/HeaderWithRadioGroup.tsx      |  20 ++-
 .../FiltersConfigForm/FiltersConfigForm.tsx        |  36 ++---
 .../explore/components/DataTableControl/index.tsx  |  22 ++-
 .../controls/DateFilterControl/DateFilterLabel.tsx |   6 -
 .../DateFilterControl/components/CalendarFrame.tsx |  18 +--
 .../DateFilterControl/components/CommonFrame.tsx   |  18 +--
 .../components/CurrentCalendarFrame.tsx            |  25 ++--
 .../DateFilterControl/components/CustomFrame.tsx   |  15 +--
 .../DateFilterControl/tests/CalendarFrame.test.tsx |   8 +-
 .../DateFilterControl/tests/CustomFrame.test.tsx   |   8 +-
 .../controls/DateFilterControl/utils/constants.ts  |  13 +-
 .../src/features/reports/ReportModal/index.tsx     |  40 +++---
 .../src/features/reports/ReportModal/styles.tsx    |   4 -
 17 files changed, 294 insertions(+), 200 deletions(-)

diff --git a/superset-frontend/src/SqlLab/components/SaveDatasetModal/index.tsx 
b/superset-frontend/src/SqlLab/components/SaveDatasetModal/index.tsx
index 5df4d0c304..379b0726ac 100644
--- a/superset-frontend/src/SqlLab/components/SaveDatasetModal/index.tsx
+++ b/superset-frontend/src/SqlLab/components/SaveDatasetModal/index.tsx
@@ -19,8 +19,8 @@
 
 import { useCallback, useState, FormEvent } from 'react';
 
-import { Radio } from 'src/components/Radio';
-import { RadioChangeEvent, AsyncSelect } from 'src/components';
+import { Radio, RadioChangeEvent } from 'src/components/Radio';
+import { AsyncSelect } from 'src/components';
 import { Input } from 'src/components/Input';
 import StyledModal from 'src/components/Modal';
 import Button from 'src/components/Button';
diff --git 
a/superset-frontend/src/components/Chart/DrillBy/useDisplayModeToggle.tsx 
b/superset-frontend/src/components/Chart/DrillBy/useDisplayModeToggle.tsx
index bd2729633e..12d186a25f 100644
--- a/superset-frontend/src/components/Chart/DrillBy/useDisplayModeToggle.tsx
+++ b/superset-frontend/src/components/Chart/DrillBy/useDisplayModeToggle.tsx
@@ -32,33 +32,21 @@ export const useDisplayModeToggle = () => {
       <div
         css={(theme: SupersetTheme) => css`
           margin-bottom: ${theme.gridUnit * 6}px;
-          .ant-radio-button-wrapper-checked:not(
-              .ant-radio-button-wrapper-disabled
-            ):focus-within {
-            box-shadow: none;
-          }
         `}
         data-test="drill-by-display-toggle"
       >
-        <Radio.Group
+        <Radio.GroupWrapper
           onChange={({ target: { value } }) => {
             setDrillByDisplayMode(value);
           }}
           defaultValue={DrillByType.Chart}
-        >
-          <Radio.Button
-            value={DrillByType.Chart}
-            data-test="drill-by-chart-radio"
-          >
-            {t('Chart')}
-          </Radio.Button>
-          <Radio.Button
-            value={DrillByType.Table}
-            data-test="drill-by-table-radio"
-          >
-            {t('Table')}
-          </Radio.Button>
-        </Radio.Group>
+          options={[
+            { label: t('Chart'), value: DrillByType.Chart },
+            { label: t('Table'), value: DrillByType.Table },
+          ]}
+          optionType="button"
+          buttonStyle="outline"
+        />
       </div>
     ),
     [],
diff --git a/superset-frontend/src/components/Radio/Radio.stories.tsx 
b/superset-frontend/src/components/Radio/Radio.stories.tsx
index e518e48baf..4329322b40 100644
--- a/superset-frontend/src/components/Radio/Radio.stories.tsx
+++ b/superset-frontend/src/components/Radio/Radio.stories.tsx
@@ -16,40 +16,139 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-import { useArgs } from '@storybook/preview-api';
-import { Radio } from './index';
+import { Space } from 'src/components/Space';
+import {
+  BarChartOutlined,
+  DotChartOutlined,
+  LineChartOutlined,
+  PieChartOutlined,
+} from '@ant-design/icons';
+import { Radio, RadioProps, RadioGroupWrapperProps } from './index';
 
 export default {
   title: 'Radio',
   component: Radio,
-  parameters: {
-    controls: { hideNoControlsWarning: true },
-  },
-  argTypes: {
-    theme: {
-      table: {
-        disable: true,
-      },
-    },
-    checked: { control: 'boolean' },
-    disabled: { control: 'boolean' },
+  tags: ['autodocs'],
+};
+
+const RadioArgsType = {
+  value: {
+    control: 'text',
+    description: 'The value of the radio button.',
+  },
+  disabled: {
+    control: 'boolean',
+    description: 'Whether the radio button is disabled or not.',
+  },
+  checked: {
+    control: 'boolean',
+    description: 'The checked state of the radio button.',
   },
 };
 
-export const SupersetRadio = () => {
-  const [{ checked, ...rest }, updateArgs] = useArgs();
-  return (
-    <Radio
-      checked={checked}
-      onChange={() => updateArgs({ checked: !checked })}
-      {...rest}
-    >
-      Example
-    </Radio>
-  );
+const radioGroupWrapperArgsType = {
+  onChange: { action: 'changed' },
+  disabled: { control: 'boolean' },
+  size: {
+    control: 'select',
+    options: ['small', 'middle', 'large'],
+  },
+  options: { control: 'object' },
+  'spaceConfig.direction': {
+    control: 'select',
+    options: ['horizontal', 'vertical'],
+    description: 'Direction of the Space layout',
+    if: { arg: 'enableSpaceConfig', truthy: true },
+  },
+  'spaceConfig.size': {
+    control: 'select',
+    options: ['small', 'middle', 'large'],
+    description: 'Layout size Space',
+    if: { arg: 'enableSpaceConfig', truthy: true },
+  },
+  'spaceConfig.align': {
+    control: 'select',
+    options: ['start', 'center', 'end'],
+    description: 'Alignment of the Space layout',
+    if: { arg: 'enableSpaceConfig', truthy: true },
+  },
+  'spaceConfig.wrap': {
+    control: 'boolean',
+    description:
+      'Controls whether the items inside the Space component should wrap to 
the next line when space is insufficient',
+    if: { arg: 'enableSpaceConfig', truthy: true },
+  },
 };
 
-SupersetRadio.args = {
+export const RadioStory = {
+  args: {
+    value: 'radio1',
+    disabled: false,
+    checked: false,
+    children: 'Radio',
+  },
+  argTypes: RadioArgsType,
+};
+
+export const RadioButtonStory = (args: RadioProps) => (
+  <Radio.Button {...args}>Radio Button</Radio.Button>
+);
+RadioButtonStory.args = {
+  value: 'button1',
+  disabled: false,
   checked: false,
+};
+RadioButtonStory.argTypes = RadioArgsType;
+
+export const RadioGroupWithOptionsStory = (args: RadioGroupWrapperProps) => (
+  <Radio.GroupWrapper {...args} />
+);
+RadioGroupWithOptionsStory.args = {
+  spaceConfig: {
+    direction: 'vertical',
+    size: 'middle',
+    align: 'center',
+    wrap: false,
+  },
+  size: 'middle',
+  options: [
+    {
+      value: 1,
+      label: (
+        <Space align="center" direction="vertical">
+          <LineChartOutlined style={{ fontSize: 18 }} />
+          LineChart
+        </Space>
+      ),
+    },
+    {
+      value: 2,
+      label: (
+        <Space align="center" direction="vertical">
+          <DotChartOutlined style={{ fontSize: 18 }} />
+          DotChart
+        </Space>
+      ),
+    },
+    {
+      value: 3,
+      label: (
+        <Space align="center" direction="vertical">
+          <BarChartOutlined style={{ fontSize: 18 }} />
+          BarChart
+        </Space>
+      ),
+    },
+    {
+      value: 4,
+      label: (
+        <Space align="center" direction="vertical">
+          <PieChartOutlined style={{ fontSize: 18 }} />
+          PieChart
+        </Space>
+      ),
+    },
+  ],
   disabled: false,
 };
+RadioGroupWithOptionsStory.argTypes = radioGroupWrapperArgsType;
diff --git a/superset-frontend/src/components/Radio/index.tsx 
b/superset-frontend/src/components/Radio/index.tsx
index f06392d278..9311cdde5a 100644
--- a/superset-frontend/src/components/Radio/index.tsx
+++ b/superset-frontend/src/components/Radio/index.tsx
@@ -16,46 +16,48 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-import { styled } from '@superset-ui/core';
-import { Radio as AntdRadio } from 'antd';
+import { Radio as Antd5Radio, CheckboxOptionType } from 'antd-v5';
+import type {
+  RadioChangeEvent,
+  RadioProps,
+  RadioGroupProps,
+} from 'antd-v5/lib/radio';
 
-const StyledRadio = styled(AntdRadio)`
-  .ant-radio-inner {
-    top: -1px;
-    left: 2px;
-    width: ${({ theme }) => theme.gridUnit * 4}px;
-    height: ${({ theme }) => theme.gridUnit * 4}px;
-    border-width: 2px;
-    border-color: ${({ theme }) => theme.colors.grayscale.light2};
-  }
+import { Space, SpaceProps } from 'src/components/Space';
 
-  .ant-radio.ant-radio-checked {
-    .ant-radio-inner {
-      border-width: ${({ theme }) => theme.gridUnit + 1}px;
-      border-color: ${({ theme }) => theme.colors.primary.base};
-    }
+export type RadioGroupWrapperProps = RadioGroupProps & {
+  spaceConfig?: {
+    direction?: SpaceProps['direction'];
+    size?: SpaceProps['size'];
+    align?: SpaceProps['align'];
+    wrap?: SpaceProps['wrap'];
+  };
+  options: CheckboxOptionType[];
+};
 
-    .ant-radio-inner::after {
-      background-color: ${({ theme }) => theme.colors.grayscale.light5};
-      top: 0;
-      left: 0;
-      width: ${({ theme }) => theme.gridUnit + 2}px;
-      height: ${({ theme }) => theme.gridUnit + 2}px;
-    }
-  }
-
-  .ant-radio:hover,
-  .ant-radio:focus {
-    .ant-radio-inner {
-      border-color: ${({ theme }) => theme.colors.primary.dark1};
-    }
-  }
-`;
-const StyledGroup = styled(AntdRadio.Group)`
-  font-size: inherit;
-`;
-
-export const Radio = Object.assign(StyledRadio, {
-  Group: StyledGroup,
-  Button: AntdRadio.Button,
+const RadioGroup = ({
+  spaceConfig,
+  options,
+  ...props
+}: RadioGroupWrapperProps) => {
+  const content = options.map((option: CheckboxOptionType) => (
+    <Radio key={option.value} value={option.value}>
+      {option.label}
+    </Radio>
+  ));
+  return (
+    <Radio.Group {...props}>
+      {spaceConfig ? <Space {...spaceConfig}>{content}</Space> : content}
+    </Radio.Group>
+  );
+};
+export type {
+  RadioChangeEvent,
+  RadioGroupProps,
+  RadioProps,
+  CheckboxOptionType,
+};
+export const Radio = Object.assign(Antd5Radio, {
+  GroupWrapper: RadioGroup,
+  Button: Antd5Radio.Button,
 });
diff --git 
a/superset-frontend/src/components/Table/header-renderers/HeaderWithRadioGroup.tsx
 
b/superset-frontend/src/components/Table/header-renderers/HeaderWithRadioGroup.tsx
index b80d5445f5..3aedff2b47 100644
--- 
a/superset-frontend/src/components/Table/header-renderers/HeaderWithRadioGroup.tsx
+++ 
b/superset-frontend/src/components/Table/header-renderers/HeaderWithRadioGroup.tsx
@@ -19,7 +19,6 @@
 import { useState } from 'react';
 import { css, useTheme } from '@superset-ui/core';
 import { Radio } from 'src/components/Radio';
-import { Space } from 'src/components/Space';
 import Icons from 'src/components/Icons';
 import Popover from 'src/components/Popover';
 
@@ -56,21 +55,20 @@ function HeaderWithRadioGroup(props: 
HeaderWithRadioGroupProps) {
             >
               {groupTitle}
             </div>
-            <Radio.Group
+            <Radio.GroupWrapper
+              spaceConfig={{
+                direction: 'vertical',
+                size: 4,
+                wrap: false,
+                align: 'start',
+              }}
               value={value}
               onChange={e => {
                 onChange(e.target.value);
                 setPopoverVisible(false);
               }}
-            >
-              <Space direction="vertical">
-                {groupOptions.map(option => (
-                  <Radio key={option.value} value={option.value}>
-                    {option.label}
-                  </Radio>
-                ))}
-              </Space>
-            </Radio.Group>
+              options={groupOptions}
+            />
           </div>
         }
         placement="bottomLeft"
diff --git 
a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FiltersConfigForm.tsx
 
b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FiltersConfigForm.tsx
index ccf763e393..5b843a370b 100644
--- 
a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FiltersConfigForm.tsx
+++ 
b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FiltersConfigForm.tsx
@@ -1106,15 +1106,16 @@ const FiltersConfigForm = (
                       initialValue={sort}
                       label={<StyledLabel>{t('Sort type')}</StyledLabel>}
                     >
-                      <Radio.Group
+                      <Radio.GroupWrapper
+                        options={[
+                          { value: true, label: t('Sort ascending') },
+                          { value: false, label: t('Sort descending') },
+                        ]}
                         onChange={value => {
                           onSortChanged(value.target.value);
                           formChanged();
                         }}
-                      >
-                        <Radio value>{t('Sort ascending')}</Radio>
-                        <Radio value={false}>{t('Sort descending')}</Radio>
-                      </Radio.Group>
+                      />
                     </StyledRowFormItem>
                     {hasMetrics && (
                       <StyledRowSubFormItem
@@ -1181,22 +1182,23 @@ const FiltersConfigForm = (
                         <StyledLabel>{t('Single value type')}</StyledLabel>
                       }
                     >
-                      <Radio.Group
+                      <Radio.GroupWrapper
                         onChange={value => {
                           onEnableSingleValueChanged(value.target.value);
                           formChanged();
                         }}
-                      >
-                        <Radio value={SingleValueType.Minimum}>
-                          {t('Minimum')}
-                        </Radio>
-                        <Radio value={SingleValueType.Exact}>
-                          {t('Exact')}
-                        </Radio>
-                        <Radio value={SingleValueType.Maximum}>
-                          {t('Maximum')}
-                        </Radio>
-                      </Radio.Group>
+                        options={[
+                          {
+                            label: t('Minimum'),
+                            value: SingleValueType.Minimum,
+                          },
+                          { label: t('Exact'), value: SingleValueType.Exact },
+                          {
+                            label: t('Maximum'),
+                            value: SingleValueType.Maximum,
+                          },
+                        ]}
+                      />
                     </StyledRowFormItem>
                   </CollapsibleControl>
                 </CleanFormItem>
diff --git 
a/superset-frontend/src/explore/components/DataTableControl/index.tsx 
b/superset-frontend/src/explore/components/DataTableControl/index.tsx
index 012b89e8da..20e2a4775a 100644
--- a/superset-frontend/src/explore/components/DataTableControl/index.tsx
+++ b/superset-frontend/src/explore/components/DataTableControl/index.tsx
@@ -30,7 +30,6 @@ import {
 import { Global } from '@emotion/react';
 import { Column } from 'react-table';
 import { debounce } from 'lodash';
-import { Space } from 'src/components/Space';
 import { Input } from 'src/components/Input';
 import {
   BOOL_FALSE_DISPLAY,
@@ -141,12 +140,21 @@ const FormatPicker = ({
   onChange: any;
   value: FormatPickerValue;
 }) => (
-  <Radio.Group value={value} onChange={onChange}>
-    <Space direction="vertical">
-      <Radio value={FormatPickerValue.Formatted}>{t('Formatted date')}</Radio>
-      <Radio value={FormatPickerValue.Original}>{t('Original value')}</Radio>
-    </Space>
-  </Radio.Group>
+  <Radio.GroupWrapper
+    spaceConfig={{
+      direction: 'vertical',
+      align: 'start',
+      size: 15,
+      wrap: false,
+    }}
+    size="large"
+    value={value}
+    onChange={onChange}
+    options={[
+      { label: t('Formatted date'), value: FormatPickerValue.Formatted },
+      { label: t('Original value'), value: FormatPickerValue.Original },
+    ]}
+  />
 );
 
 const FormatPickerContainer = styled.div`
diff --git 
a/superset-frontend/src/explore/components/controls/DateFilterControl/DateFilterLabel.tsx
 
b/superset-frontend/src/explore/components/controls/DateFilterControl/DateFilterLabel.tsx
index a4b0ca3a3e..dc4057f33b 100644
--- 
a/superset-frontend/src/explore/components/controls/DateFilterControl/DateFilterLabel.tsx
+++ 
b/superset-frontend/src/explore/components/controls/DateFilterControl/DateFilterLabel.tsx
@@ -87,12 +87,6 @@ const ContentStyleWrapper = styled.div`
       margin: 8px 0;
     }
 
-    .vertical-radio {
-      display: block;
-      height: 40px;
-      line-height: 40px;
-    }
-
     .section-title {
       font-style: normal;
       font-weight: ${theme.typography.weights.bold};
diff --git 
a/superset-frontend/src/explore/components/controls/DateFilterControl/components/CalendarFrame.tsx
 
b/superset-frontend/src/explore/components/controls/DateFilterControl/components/CalendarFrame.tsx
index 8900e213f4..4fb48cf52b 100644
--- 
a/superset-frontend/src/explore/components/controls/DateFilterControl/components/CalendarFrame.tsx
+++ 
b/superset-frontend/src/explore/components/controls/DateFilterControl/components/CalendarFrame.tsx
@@ -45,16 +45,18 @@ export function CalendarFrame({ onChange, value }: 
FrameComponentProps) {
       <div className="section-title">
         {t('Configure Time Range: Previous...')}
       </div>
-      <Radio.Group
+      <Radio.GroupWrapper
+        spaceConfig={{
+          direction: 'vertical',
+          size: 15,
+          align: 'start',
+          wrap: false,
+        }}
+        size="large"
         value={value}
         onChange={(e: any) => onChange(e.target.value)}
-      >
-        {CALENDAR_RANGE_OPTIONS.map(({ value, label }) => (
-          <Radio key={value} value={value} className="vertical-radio">
-            {label}
-          </Radio>
-        ))}
-      </Radio.Group>
+        options={CALENDAR_RANGE_OPTIONS}
+      />
     </>
   );
 }
diff --git 
a/superset-frontend/src/explore/components/controls/DateFilterControl/components/CommonFrame.tsx
 
b/superset-frontend/src/explore/components/controls/DateFilterControl/components/CommonFrame.tsx
index 30365ffc28..633066a4fd 100644
--- 
a/superset-frontend/src/explore/components/controls/DateFilterControl/components/CommonFrame.tsx
+++ 
b/superset-frontend/src/explore/components/controls/DateFilterControl/components/CommonFrame.tsx
@@ -41,16 +41,18 @@ export function CommonFrame(props: FrameComponentProps) {
       <div className="section-title" data-test={DateFilterTestKey.CommonFrame}>
         {t('Configure Time Range: Last...')}
       </div>
-      <Radio.Group
+      <Radio.GroupWrapper
+        spaceConfig={{
+          direction: 'vertical',
+          size: 15,
+          align: 'start',
+          wrap: false,
+        }}
+        size="large"
         value={commonRange}
         onChange={(e: any) => props.onChange(e.target.value)}
-      >
-        {COMMON_RANGE_OPTIONS.map(({ value, label }) => (
-          <Radio key={value} value={value} className="vertical-radio">
-            {label}
-          </Radio>
-        ))}
-      </Radio.Group>
+        options={COMMON_RANGE_OPTIONS}
+      />
     </>
   );
 }
diff --git 
a/superset-frontend/src/explore/components/controls/DateFilterControl/components/CurrentCalendarFrame.tsx
 
b/superset-frontend/src/explore/components/controls/DateFilterControl/components/CurrentCalendarFrame.tsx
index 7d1a3a7b78..27fc77818f 100644
--- 
a/superset-frontend/src/explore/components/controls/DateFilterControl/components/CurrentCalendarFrame.tsx
+++ 
b/superset-frontend/src/explore/components/controls/DateFilterControl/components/CurrentCalendarFrame.tsx
@@ -41,25 +41,22 @@ export function CurrentCalendarFrame({ onChange, value }: 
FrameComponentProps) {
       <div className="section-title">
         {t('Configure Time Range: Current...')}
       </div>
-      <Radio.Group
-        value={value}
+      <Radio.GroupWrapper
+        spaceConfig={{
+          direction: 'vertical',
+          size: 15,
+          align: 'start',
+          wrap: true,
+        }}
+        size="large"
         onChange={(e: any) => {
           let newValue = e.target.value;
-          // Sanitization: Trim whitespace
           newValue = newValue.trim();
-          // Validation: Check if the value is non-empty
-          if (newValue === '') {
-            return;
-          }
+          if (newValue === '') return;
           onChange(newValue);
         }}
-      >
-        {CURRENT_RANGE_OPTIONS.map(({ value, label }) => (
-          <Radio key={value} value={value} className="vertical-radio">
-            {label}
-          </Radio>
-        ))}
-      </Radio.Group>
+        options={CURRENT_RANGE_OPTIONS}
+      />
     </>
   );
 }
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 378956c645..969b46855e 100644
--- 
a/superset-frontend/src/explore/components/controls/DateFilterControl/components/CustomFrame.tsx
+++ 
b/superset-frontend/src/explore/components/controls/DateFilterControl/components/CustomFrame.tsx
@@ -238,18 +238,15 @@ export function CustomFrame(props: FrameComponentProps) {
             <div className="control-label">{t('Anchor to')}</div>
             <Row align="middle">
               <Col>
-                <Radio.Group
+                <Radio.GroupWrapper
+                  options={[
+                    { value: 'now', label: t('Now') },
+                    { value: 'specific', label: t('Date/Time') },
+                  ]}
                   onChange={onAnchorMode}
                   defaultValue="now"
                   value={anchorMode}
-                >
-                  <Radio key="now" value="now">
-                    {t('NOW')}
-                  </Radio>
-                  <Radio key="specific" value="specific">
-                    {t('Date/Time')}
-                  </Radio>
-                </Radio.Group>
+                />
               </Col>
               {anchorMode !== 'now' && (
                 <Col>
diff --git 
a/superset-frontend/src/explore/components/controls/DateFilterControl/tests/CalendarFrame.test.tsx
 
b/superset-frontend/src/explore/components/controls/DateFilterControl/tests/CalendarFrame.test.tsx
index 163ce4caf1..b859d737b5 100644
--- 
a/superset-frontend/src/explore/components/controls/DateFilterControl/tests/CalendarFrame.test.tsx
+++ 
b/superset-frontend/src/explore/components/controls/DateFilterControl/tests/CalendarFrame.test.tsx
@@ -42,7 +42,7 @@ describe('CalendarFrame', () => {
     const radios = screen.getAllByRole('radio');
     expect(radios).toHaveLength(CALENDAR_RANGE_OPTIONS.length);
     CALENDAR_RANGE_OPTIONS.forEach(option => {
-      expect(screen.getByText(option.label)).toBeInTheDocument();
+      expect(screen.getByText(option.label as string)).toBeInTheDocument();
     });
   });
 
@@ -56,7 +56,7 @@ describe('CalendarFrame', () => {
     );
 
     const secondOption = CALENDAR_RANGE_OPTIONS[1];
-    const radio = screen.getByLabelText(secondOption.label);
+    const radio = screen.getByLabelText(secondOption.label as string);
     fireEvent.click(radio);
 
     expect(mockOnChange).toHaveBeenCalledWith(secondOption.value);
@@ -85,6 +85,8 @@ describe('CalendarFrame', () => {
     const thirdOption = CALENDAR_RANGE_OPTIONS[2];
     expect(thirdOption.value).toBe(PreviousCalendarQuarter);
 
-    expect(screen.getByLabelText(thirdOption.label)).toBeInTheDocument();
+    expect(
+      screen.getByLabelText(thirdOption.label as string),
+    ).toBeInTheDocument();
   });
 });
diff --git 
a/superset-frontend/src/explore/components/controls/DateFilterControl/tests/CustomFrame.test.tsx
 
b/superset-frontend/src/explore/components/controls/DateFilterControl/tests/CustomFrame.test.tsx
index ab8fc5bb35..f8afe15998 100644
--- 
a/superset-frontend/src/explore/components/controls/DateFilterControl/tests/CustomFrame.test.tsx
+++ 
b/superset-frontend/src/explore/components/controls/DateFilterControl/tests/CustomFrame.test.tsx
@@ -167,8 +167,8 @@ test('renders anchor with now option', async () => {
   );
   await waitForElementToBeRemoved(() => screen.queryByLabelText('Loading'));
   expect(screen.getByText('Anchor to')).toBeInTheDocument();
-  expect(screen.getByRole('radio', { name: 'NOW' })).toBeInTheDocument();
-  expect(screen.getByRole('radio', { name: 'Date/Time' })).toBeInTheDocument();
+  expect(screen.getByLabelText('Now')).toBeInTheDocument();
+  expect(screen.getByLabelText('Date/Time')).toBeInTheDocument();
   expect(screen.queryByPlaceholderText('Select date')).not.toBeInTheDocument();
 });
 
@@ -180,8 +180,8 @@ test('renders anchor with date/time option', async () => {
   );
   await waitForElementToBeRemoved(() => screen.queryByLabelText('Loading'));
   expect(screen.getByText('Anchor to')).toBeInTheDocument();
-  expect(screen.getByRole('radio', { name: 'NOW' })).toBeInTheDocument();
-  expect(screen.getByRole('radio', { name: 'Date/Time' })).toBeInTheDocument();
+  expect(screen.getByLabelText('Now')).toBeInTheDocument();
+  expect(screen.getByLabelText('Date/Time')).toBeInTheDocument();
   expect(screen.getByPlaceholderText('Select date')).toBeInTheDocument();
 });
 
diff --git 
a/superset-frontend/src/explore/components/controls/DateFilterControl/utils/constants.ts
 
b/superset-frontend/src/explore/components/controls/DateFilterControl/utils/constants.ts
index 16b24d7a0b..e76b778fc6 100644
--- 
a/superset-frontend/src/explore/components/controls/DateFilterControl/utils/constants.ts
+++ 
b/superset-frontend/src/explore/components/controls/DateFilterControl/utils/constants.ts
@@ -32,6 +32,7 @@ import {
   CurrentQuarter,
   CurrentDay,
 } from 'src/explore/components/controls/DateFilterControl/types';
+import { CheckboxOptionType } from 'src/components/Radio';
 import { extendedDayjs } from 'src/utils/dates';
 
 export const FRAME_OPTIONS: SelectOptionType[] = [
@@ -43,7 +44,7 @@ export const FRAME_OPTIONS: SelectOptionType[] = [
   { value: 'No filter', label: t('No filter') },
 ];
 
-export const COMMON_RANGE_OPTIONS: SelectOptionType[] = [
+export const COMMON_RANGE_OPTIONS: CheckboxOptionType[] = [
   { value: 'Last day', label: t('Last day') },
   { value: 'Last week', label: t('Last week') },
   { value: 'Last month', label: t('Last month') },
@@ -51,20 +52,20 @@ export const COMMON_RANGE_OPTIONS: SelectOptionType[] = [
   { value: 'Last year', label: t('Last year') },
 ];
 export const COMMON_RANGE_VALUES_SET = new Set(
-  COMMON_RANGE_OPTIONS.map(({ value }) => value),
+  COMMON_RANGE_OPTIONS.map(value => value.value),
 );
 
-export const CALENDAR_RANGE_OPTIONS: SelectOptionType[] = [
+export const CALENDAR_RANGE_OPTIONS: CheckboxOptionType[] = [
   { value: PreviousCalendarWeek, label: t('previous calendar week') },
   { value: PreviousCalendarMonth, label: t('previous calendar month') },
   { value: PreviousCalendarQuarter, label: t('previous calendar quarter') },
   { value: PreviousCalendarYear, label: t('previous calendar year') },
 ];
 export const CALENDAR_RANGE_VALUES_SET = new Set(
-  CALENDAR_RANGE_OPTIONS.map(({ value }) => value),
+  CALENDAR_RANGE_OPTIONS.map(value => value.value),
 );
 
-export const CURRENT_RANGE_OPTIONS: SelectOptionType[] = [
+export const CURRENT_RANGE_OPTIONS: CheckboxOptionType[] = [
   { value: CurrentDay, label: t('Current day') },
   { value: CurrentWeek, label: t('Current week') },
   { value: CurrentMonth, label: t('Current month') },
@@ -72,7 +73,7 @@ export const CURRENT_RANGE_OPTIONS: SelectOptionType[] = [
   { value: CurrentYear, label: t('Current year') },
 ];
 export const CURRENT_RANGE_VALUES_SET = new Set(
-  CURRENT_RANGE_OPTIONS.map(({ value }) => value),
+  CURRENT_RANGE_OPTIONS.map(value => value.value),
 );
 
 const GRAIN_OPTIONS = [
diff --git a/superset-frontend/src/features/reports/ReportModal/index.tsx 
b/superset-frontend/src/features/reports/ReportModal/index.tsx
index 47f11dfa5b..59f9263a32 100644
--- a/superset-frontend/src/features/reports/ReportModal/index.tsx
+++ b/superset-frontend/src/features/reports/ReportModal/index.tsx
@@ -41,7 +41,7 @@ import TimezoneSelector from 
'src/components/TimezoneSelector';
 import LabeledErrorBoundInput from 
'src/components/Form/LabeledErrorBoundInput';
 import Icons from 'src/components/Icons';
 import { CronError } from 'src/components/CronPicker';
-import { RadioChangeEvent } from 'src/components';
+import { Radio, RadioChangeEvent } from 'src/components/Radio';
 import { Input } from 'src/components/Input';
 import withToasts from 'src/components/MessageToasts/withToasts';
 import { ChartState } from 'src/explore/types';
@@ -68,8 +68,6 @@ import {
   TimezoneHeaderStyle,
   SectionHeaderStyle,
   StyledMessageContentTitle,
-  StyledRadio,
-  StyledRadioGroup,
 } from './styles';
 
 interface ReportProps {
@@ -257,24 +255,32 @@ function ReportModal({
         <h4>{t('Message content')}</h4>
       </StyledMessageContentTitle>
       <div className="inline-container">
-        <StyledRadioGroup
+        <Radio.GroupWrapper
+          spaceConfig={{
+            direction: 'vertical',
+            size: 'middle',
+            align: 'start',
+            wrap: false,
+          }}
           onChange={(event: RadioChangeEvent) => {
             setCurrentReport({ report_format: event.target.value });
           }}
           value={currentReport.report_format || defaultNotificationFormat}
-        >
-          {isTextBasedChart && (
-            <StyledRadio value={NotificationFormats.Text}>
-              {t('Text embedded in email')}
-            </StyledRadio>
-          )}
-          <StyledRadio value={NotificationFormats.PNG}>
-            {t('Image (PNG) embedded in email')}
-          </StyledRadio>
-          <StyledRadio value={NotificationFormats.CSV}>
-            {t('Formatted CSV attached in email')}
-          </StyledRadio>
-        </StyledRadioGroup>
+          options={[
+            {
+              label: t('Text embedded in email'),
+              value: NotificationFormats.Text,
+            },
+            {
+              label: t('Image (PNG) embedded in email'),
+              value: NotificationFormats.PNG,
+            },
+            {
+              label: t('Formatted CSV attached in email'),
+              value: NotificationFormats.CSV,
+            },
+          ]}
+        />
       </div>
     </>
   );
diff --git a/superset-frontend/src/features/reports/ReportModal/styles.tsx 
b/superset-frontend/src/features/reports/ReportModal/styles.tsx
index ad30adce8f..0f5c12bd38 100644
--- a/superset-frontend/src/features/reports/ReportModal/styles.tsx
+++ b/superset-frontend/src/features/reports/ReportModal/styles.tsx
@@ -108,10 +108,6 @@ export const StyledRadio = styled(Radio)`
   line-height: ${({ theme }) => theme.gridUnit * 8}px;
 `;
 
-export const StyledRadioGroup = styled(Radio.Group)`
-  margin-left: ${({ theme }) => theme.gridUnit * 0.5}px;
-`;
-
 export const antDErrorAlertStyles = (theme: SupersetTheme) => css`
   margin: ${theme.gridUnit * 4}px;
   margin-top: 0;

Reply via email to