diff --git a/superset-frontend/.storybook/preview.jsx b/superset-frontend/.storybook/preview.jsx index fa0c90887..a83b6e102 100644 --- a/superset-frontend/.storybook/preview.jsx +++ b/superset-frontend/.storybook/preview.jsx @@ -26,6 +26,7 @@ import { combineReducers, createStore, applyMiddleware, compose } from 'redux'; import thunk from 'redux-thunk'; import { Provider } from 'react-redux'; import reducerIndex from 'spec/helpers/reducerIndex'; +import { GlobalStyles } from '../src/GlobalStyles'; import 'src/theme.ts'; import './storybook.css'; @@ -37,7 +38,12 @@ const store = createStore( ); const themeDecorator = Story => ( - {} + + <> + + + + ); const providerDecorator = Story => ( diff --git a/superset-frontend/src/GlobalStyles.tsx b/superset-frontend/src/GlobalStyles.tsx index 1e2cf449f..50f54ba88 100644 --- a/superset-frontend/src/GlobalStyles.tsx +++ b/superset-frontend/src/GlobalStyles.tsx @@ -19,6 +19,7 @@ import React from 'react'; import { css } from '@superset-ui/core'; import { Global } from '@emotion/react'; +import { mix } from 'polished'; export const GlobalStyles = () => ( ( th { font-weight: ${theme.typography.weights.bold}; } + // TODO: Remove when on Ant Design 5. + // Check src/components/Modal for more info. + .modal-functions-ok-button { + border-radius: ${theme.borderRadius}px; + background: ${theme.colors.primary.base}; + border: none; + text-transform: uppercase; + color: ${theme.colors.grayscale.light5}; + line-height: 1.5715; + font-size: ${theme.typography.sizes.s}px; + font-weight: ${theme.typography.weights.bold}; + &:hover { + background: ${theme.colors.primary.dark1}; + } + } + .modal-functions-cancel-button { + border-radius: ${theme.borderRadius}px; + background: ${theme.colors.primary.light4}; + border: none; + text-transform: uppercase; + color: ${theme.colors.primary.dark1}; + line-height: 1.5715; + font-size: ${theme.typography.sizes.s}px; + font-weight: ${theme.typography.weights.bold}; + &:hover { + background: ${mix( + 0.1, + theme.colors.primary.base, + theme.colors.primary.light4, + )}; + } + } `} /> ); diff --git a/superset-frontend/src/components/Modal/Modal.stories.tsx b/superset-frontend/src/components/Modal/Modal.stories.tsx index b3557c5a8..67b8837b0 100644 --- a/superset-frontend/src/components/Modal/Modal.stories.tsx +++ b/superset-frontend/src/components/Modal/Modal.stories.tsx @@ -16,8 +16,10 @@ * specific language governing permissions and limitations * under the License. */ +import { ModalFuncProps } from 'antd/lib/modal'; import React from 'react'; import Modal, { ModalProps } from '.'; +import Button from '../Button'; export default { title: 'Modal', @@ -50,3 +52,16 @@ InteractiveModal.story = { }, }, }; + +export const ModalFunctions = (props: ModalFuncProps) => ( +
+ + + +
+); + +ModalFunctions.args = { + title: 'Modal title', + content: 'Modal content', +}; diff --git a/superset-frontend/src/components/Modal/Modal.tsx b/superset-frontend/src/components/Modal/Modal.tsx index 608e8c559..d1e1affcf 100644 --- a/superset-frontend/src/components/Modal/Modal.tsx +++ b/superset-frontend/src/components/Modal/Modal.tsx @@ -18,6 +18,7 @@ */ import React, { useMemo, useRef, useState } from 'react'; import { isNil } from 'lodash'; +import { ModalFuncProps } from 'antd/lib/modal'; import { styled, t } from '@superset-ui/core'; import { css } from '@emotion/react'; import { AntdModal, AntdModalProps } from 'src/components'; @@ -363,13 +364,26 @@ const CustomModal = ({ }; CustomModal.displayName = 'Modal'; +// Ant Design 4 does not allow overriding Modal's buttons when +// using one of the pre-defined functions. Ant Design 5 Modal introduced +// the footer property that will allow that. Meanwhile, we're replicating +// Button style using global CSS in src/GlobalStyles.tsx. +// TODO: Replace this logic when on Ant Design 5. +const buttonProps = { + okButtonProps: { className: 'modal-functions-ok-button' }, + cancelButtonProps: { className: 'modal-functions-cancel-button' }, +}; + // TODO: in another PR, rename this to CompatabilityModal // and demote it as the default export. // We should start using AntD component interfaces going forward. const Modal = Object.assign(CustomModal, { - error: AntdModal.error, - warning: AntdModal.warning, - confirm: AntdModal.confirm, + error: (config: ModalFuncProps) => + AntdModal.error({ ...config, ...buttonProps }), + warning: (config: ModalFuncProps) => + AntdModal.warning({ ...config, ...buttonProps }), + confirm: (config: ModalFuncProps) => + AntdModal.confirm({ ...config, ...buttonProps }), useModal: AntdModal.useModal, });