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

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


The following commit(s) were added to refs/heads/master by this push:
     new 3b4df51  style: new toast design closer to SIP-34 (#10178)
3b4df51 is described below

commit 3b4df51848f1ff3b4f22771eacdd49e77077125d
Author: Lily Kuang <l...@preset.io>
AuthorDate: Fri Jul 10 14:58:59 2020 -0700

    style: new toast design closer to SIP-34 (#10178)
---
 superset-frontend/images/icons/check.svg           |  22 +++++
 superset-frontend/images/icons/error.svg           |  22 +++++
 .../dashboard/components/DashboardBuilder_spec.jsx |   5 +
 .../components/ToastPresenter_spec.jsx             |   4 +-
 .../messageToasts/components/Toast_spec.jsx        |  24 ++---
 .../javascripts/sqllab/TabbedSqlEditors_spec.jsx   |   7 ++
 superset-frontend/src/components/Icon.tsx          |   6 ++
 .../src/messageToasts/components/Toast.jsx         | 109 ---------------------
 .../src/messageToasts/components/Toast.tsx         |  93 ++++++++++++++++++
 .../messageToasts/components/ToastPresenter.jsx    |  56 -----------
 .../messageToasts/components/ToastPresenter.tsx    |  91 +++++++++++++++++
 .../src/messageToasts/stylesheets/toast.less       |  78 ---------------
 superset-frontend/src/messageToasts/types.ts       |  24 +++++
 13 files changed, 285 insertions(+), 256 deletions(-)

diff --git a/superset-frontend/images/icons/check.svg 
b/superset-frontend/images/icons/check.svg
new file mode 100644
index 0000000..7f6fd6e
--- /dev/null
+++ b/superset-frontend/images/icons/check.svg
@@ -0,0 +1,22 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+ 
+    http://www.apache.org/licenses/LICENSE-2.0
+ 
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+<svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor" 
xmlns="http://www.w3.org/2000/svg";>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M12 2C6.47715 2 2 6.47715 2 
12C2 17.5228 6.47715 22 12 22C17.5228 22 22 17.5228 22 12C22 9.34784 20.9464 
6.8043 19.0711 4.92893C17.1957 3.05357 14.6522 2 12 2Z" fill="currentColor"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M14.7191 8.79L10.4291 
13.09L8.77911 11.44C8.53472 11.1546 8.15099 11.0303 7.78569 11.1182C7.42039 
11.2061 7.13517 11.4913 7.0473 11.8566C6.95942 12.2219 7.08373 12.6056 7.36911 
12.85L9.71911 15.21C9.90783 15.3972 10.1633 15.5015 10.4291 15.5C10.6914 
15.4989 10.9428 15.3947 11.1291 15.21L16.1291 10.21C16.3184 10.0222 16.4249 
9.76664 16.4249 9.5C16.4249 9.23336 16.3184 8.97777 16.1291 8.79C15.7391 
8.40228 15.1091 8.40228 14.7191 8.79Z" fill= [...]
+</svg>
diff --git a/superset-frontend/images/icons/error.svg 
b/superset-frontend/images/icons/error.svg
new file mode 100644
index 0000000..03c1962
--- /dev/null
+++ b/superset-frontend/images/icons/error.svg
@@ -0,0 +1,22 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+ 
+    http://www.apache.org/licenses/LICENSE-2.0
+ 
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+<svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor" 
xmlns="http://www.w3.org/2000/svg";>
+<path id="Shape" fill-rule="evenodd" clip-rule="evenodd" d="M21.71 7.56L16.44 
2.29C16.2484 2.10727 15.9948 2.00368 15.73 2H8.27C8.00523 2.00368 7.75163 
2.10727 7.56 2.29L2.29 7.56C2.10727 7.75163 2.00368 8.00523 2 
8.27V15.73C2.00368 15.9948 2.10727 16.2484 2.29 16.44L7.56 21.71C7.75163 
21.8927 8.00523 21.9963 8.27 22H15.73C15.9948 21.9963 16.2484 21.8927 16.44 
21.71L21.71 16.44C21.8927 16.2484 21.9963 15.9948 22 15.73V8.27C21.9963 8.00523 
21.8927 7.75163 21.71 7.56Z" fill="currentColor"/>
+<path id="Combined Shape" fill-rule="evenodd" clip-rule="evenodd" d="M11 8C11 
7.44772 11.4477 7 12 7C12.5523 7 13 7.44772 13 8V12C13 12.5523 12.5523 13 12 
13C11.4477 13 11 12.5523 11 12V8ZM11 16C11 15.4477 11.4477 15 12 15C12.5523 15 
13 15.4477 13 16C13 16.5523 12.5523 17 12 17C11.4477 17 11 16.5523 11 16Z" 
fill="white"/>
+</svg>
diff --git 
a/superset-frontend/spec/javascripts/dashboard/components/DashboardBuilder_spec.jsx
 
b/superset-frontend/spec/javascripts/dashboard/components/DashboardBuilder_spec.jsx
index dbdee6a..04d885e 100644
--- 
a/superset-frontend/spec/javascripts/dashboard/components/DashboardBuilder_spec.jsx
+++ 
b/superset-frontend/spec/javascripts/dashboard/components/DashboardBuilder_spec.jsx
@@ -22,6 +22,7 @@ import { shallow, mount } from 'enzyme';
 import sinon from 'sinon';
 
 import { ParentSize } from '@vx/responsive';
+import { supersetTheme, ThemeProvider } from '@superset-ui/style';
 import { Sticky, StickyContainer } from 'react-sticky';
 import { TabContainer, TabContent, TabPane } from 'react-bootstrap';
 
@@ -77,6 +78,10 @@ describe('DashboardBuilder', () => {
           <Provider store={store}>
             <WithDragDropContext>{builder}</WithDragDropContext>
           </Provider>,
+          {
+            wrappingComponent: ThemeProvider,
+            wrappingComponentProps: { theme: supersetTheme },
+          },
         )
       : shallow(builder);
   }
diff --git 
a/superset-frontend/spec/javascripts/messageToasts/components/ToastPresenter_spec.jsx
 
b/superset-frontend/spec/javascripts/messageToasts/components/ToastPresenter_spec.jsx
index d888dad..9b3e4a0 100644
--- 
a/superset-frontend/spec/javascripts/messageToasts/components/ToastPresenter_spec.jsx
+++ 
b/superset-frontend/spec/javascripts/messageToasts/components/ToastPresenter_spec.jsx
@@ -34,9 +34,9 @@ describe('ToastPresenter', () => {
     return wrapper;
   }
 
-  it('should render a div with class toast-presenter', () => {
+  it('should render a div with id toast-presenter', () => {
     const wrapper = setup();
-    expect(wrapper.find('.toast-presenter')).toHaveLength(1);
+    expect(wrapper.find('#toast-presenter')).toHaveLength(1);
   });
 
   it('should render a Toast for each toast object', () => {
diff --git 
a/superset-frontend/spec/javascripts/messageToasts/components/Toast_spec.jsx 
b/superset-frontend/spec/javascripts/messageToasts/components/Toast_spec.jsx
index a37b834..d411093 100644
--- a/superset-frontend/spec/javascripts/messageToasts/components/Toast_spec.jsx
+++ b/superset-frontend/spec/javascripts/messageToasts/components/Toast_spec.jsx
@@ -19,21 +19,19 @@
 import { Alert } from 'react-bootstrap';
 import React from 'react';
 import { mount } from 'enzyme';
+import { act } from 'react-dom/test-utils';
 import Toast from 'src/messageToasts/components/Toast';
 
 import mockMessageToasts from '../mockMessageToasts';
 
-describe('Toast', () => {
-  const props = {
-    toast: mockMessageToasts[0],
-    onCloseToast() {},
-  };
+const props = {
+  toast: mockMessageToasts[0],
+  onCloseToast() {},
+};
 
-  function setup(overrideProps) {
-    const wrapper = mount(<Toast {...props} {...overrideProps} />);
-    return wrapper;
-  }
+const setup = overrideProps => mount(<Toast {...props} {...overrideProps} />);
 
+describe('Toast', () => {
   it('should render an Alert', () => {
     const wrapper = setup();
     expect(wrapper.find(Alert)).toHaveLength(1);
@@ -52,9 +50,13 @@ describe('Toast', () => {
         expect(id).toBe(props.toast.id);
         done();
       };
+
       const wrapper = setup({ onCloseToast });
-      const handleClosePress = wrapper.instance().handleClosePress;
-      expect(wrapper.find(Alert).prop('onDismiss')).toBe(handleClosePress);
+      const handleClosePress = wrapper.find('[label="Close alert"]').props()
+        .onClick;
+
+      const alertProps = wrapper.find(Alert).props();
+      expect(alertProps.onDismiss).toBe(handleClosePress);
       handleClosePress(); // there is a timeout for onCloseToast to be called
     });
   });
diff --git 
a/superset-frontend/spec/javascripts/sqllab/TabbedSqlEditors_spec.jsx 
b/superset-frontend/spec/javascripts/sqllab/TabbedSqlEditors_spec.jsx
index 2d09f36..f7db508 100644
--- a/superset-frontend/spec/javascripts/sqllab/TabbedSqlEditors_spec.jsx
+++ b/superset-frontend/spec/javascripts/sqllab/TabbedSqlEditors_spec.jsx
@@ -23,6 +23,7 @@ import URI from 'urijs';
 import { Tab } from 'react-bootstrap';
 import { shallow, mount } from 'enzyme';
 import sinon from 'sinon';
+import { supersetTheme, ThemeProvider } from '@superset-ui/style';
 import TabbedSqlEditors from 'src/SqlLab/components/TabbedSqlEditors';
 import SqlEditor from 'src/SqlLab/components/SqlEditor';
 
@@ -98,6 +99,8 @@ describe('TabbedSqlEditors', () => {
       uriStub.returns({ id: 1 });
       wrapper = mount(<TabbedSqlEditors {...mockedProps} />, {
         context: { store },
+        wrappingComponent: ThemeProvider,
+        wrappingComponentProps: { theme: supersetTheme },
       });
       expect(TabbedSqlEditors.prototype.componentDidMount.calledOnce).toBe(
         true,
@@ -110,6 +113,8 @@ describe('TabbedSqlEditors', () => {
       uriStub.returns({ savedQueryId: 1 });
       wrapper = mount(<TabbedSqlEditors {...mockedProps} />, {
         context: { store },
+        wrappingComponent: ThemeProvider,
+        wrappingComponentProps: { theme: supersetTheme },
       });
       expect(TabbedSqlEditors.prototype.componentDidMount.calledOnce).toBe(
         true,
@@ -122,6 +127,8 @@ describe('TabbedSqlEditors', () => {
       uriStub.returns({ sql: 1, dbid: 1 });
       wrapper = mount(<TabbedSqlEditors {...mockedProps} />, {
         context: { store },
+        wrappingComponent: ThemeProvider,
+        wrappingComponentProps: { theme: supersetTheme },
       });
       expect(TabbedSqlEditors.prototype.componentDidMount.calledOnce).toBe(
         true,
diff --git a/superset-frontend/src/components/Icon.tsx 
b/superset-frontend/src/components/Icon.tsx
index 9040ca7..e7dfe8d 100644
--- a/superset-frontend/src/components/Icon.tsx
+++ b/superset-frontend/src/components/Icon.tsx
@@ -19,12 +19,14 @@
 import React, { SVGProps } from 'react';
 import styled from '@superset-ui/style';
 import { ReactComponent as CancelXIcon } from 'images/icons/cancel-x.svg';
+import { ReactComponent as CheckIcon } from 'images/icons/check.svg';
 import { ReactComponent as CheckboxHalfIcon } from 
'images/icons/checkbox-half.svg';
 import { ReactComponent as CheckboxOffIcon } from 
'images/icons/checkbox-off.svg';
 import { ReactComponent as CheckboxOnIcon } from 
'images/icons/checkbox-on.svg';
 import { ReactComponent as CompassIcon } from 'images/icons/compass.svg';
 import { ReactComponent as DatasetPhysicalIcon } from 
'images/icons/dataset_physical.svg';
 import { ReactComponent as DatasetVirtualIcon } from 
'images/icons/dataset_virtual.svg';
+import { ReactComponent as ErrorIcon } from 'images/icons/error.svg';
 import { ReactComponent as PencilIcon } from 'images/icons/pencil.svg';
 import { ReactComponent as SearchIcon } from 'images/icons/search.svg';
 import { ReactComponent as SortAscIcon } from 'images/icons/sort-asc.svg';
@@ -35,12 +37,14 @@ import { ReactComponent as WarningIcon } from 
'images/icons/warning.svg';
 
 type Icon =
   | 'cancel-x'
+  | 'check'
   | 'checkbox-half'
   | 'checkbox-off'
   | 'checkbox-on'
   | 'compass'
   | 'dataset-physical'
   | 'dataset-virtual'
+  | 'error'
   | 'pencil'
   | 'search'
   | 'sort'
@@ -58,7 +62,9 @@ const iconsRegistry: { [key in Icon]: React.ComponentType } = 
{
   'dataset-virtual': DatasetVirtualIcon,
   'sort-asc': SortAscIcon,
   'sort-desc': SortDescIcon,
+  check: CheckIcon,
   compass: CompassIcon,
+  error: ErrorIcon,
   pencil: PencilIcon,
   search: SearchIcon,
   sort: SortIcon,
diff --git a/superset-frontend/src/messageToasts/components/Toast.jsx 
b/superset-frontend/src/messageToasts/components/Toast.jsx
deleted file mode 100644
index bbce2e9..0000000
--- a/superset-frontend/src/messageToasts/components/Toast.jsx
+++ /dev/null
@@ -1,109 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-import { Alert } from 'react-bootstrap';
-import cx from 'classnames';
-import Interweave from 'interweave';
-import PropTypes from 'prop-types';
-import React from 'react';
-
-import { toastShape } from '../propShapes';
-
-import {
-  INFO_TOAST,
-  SUCCESS_TOAST,
-  WARNING_TOAST,
-  DANGER_TOAST,
-} from '../constants';
-
-const propTypes = {
-  toast: toastShape.isRequired,
-  onCloseToast: PropTypes.func.isRequired,
-};
-
-const defaultProps = {};
-
-class Toast extends React.Component {
-  constructor(props) {
-    super(props);
-    this.state = {
-      visible: false,
-    };
-
-    this.showToast = this.showToast.bind(this);
-    this.handleClosePress = this.handleClosePress.bind(this);
-  }
-
-  componentDidMount() {
-    const { toast } = this.props;
-
-    setTimeout(this.showToast);
-
-    if (toast.duration > 0) {
-      this.hideTimer = setTimeout(this.handleClosePress, toast.duration);
-    }
-  }
-
-  componentWillUnmount() {
-    clearTimeout(this.hideTimer);
-  }
-
-  showToast() {
-    this.setState({ visible: true });
-  }
-
-  handleClosePress() {
-    clearTimeout(this.hideTimer);
-
-    this.setState({ visible: false }, () => {
-      // Wait for the transition
-      setTimeout(() => {
-        this.props.onCloseToast(this.props.toast.id);
-      }, 150);
-    });
-  }
-
-  render() {
-    const { visible } = this.state;
-    const {
-      toast: { toastType, text },
-    } = this.props;
-
-    return (
-      <Alert
-        onDismiss={this.handleClosePress}
-        bsClass={cx(
-          'alert',
-          'toast',
-          visible && 'toast--visible',
-          toastType === INFO_TOAST && 'toast--info',
-          toastType === SUCCESS_TOAST && 'toast--success',
-          toastType === WARNING_TOAST && 'toast--warning',
-          toastType === DANGER_TOAST && 'toast--danger',
-        )}
-      >
-        <Interweave content={text} />
-      </Alert>
-    );
-  }
-}
-
-Toast.propTypes = propTypes;
-Toast.defaultProps = defaultProps;
-
-export default Toast;
diff --git a/superset-frontend/src/messageToasts/components/Toast.tsx 
b/superset-frontend/src/messageToasts/components/Toast.tsx
new file mode 100644
index 0000000..87fba13
--- /dev/null
+++ b/superset-frontend/src/messageToasts/components/Toast.tsx
@@ -0,0 +1,93 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+import { Alert } from 'react-bootstrap';
+import styled from '@superset-ui/style';
+import cx from 'classnames';
+import Interweave from 'interweave';
+import React, { useEffect, useState } from 'react';
+import Icon from 'src/components/Icon';
+import { ToastType } from 'src/messageToasts/types';
+
+import { SUCCESS_TOAST, WARNING_TOAST, DANGER_TOAST } from '../constants';
+
+const ToastContianer = styled.div`
+  display: flex;
+  justify-content: center;
+  align-items: center;
+
+  span {
+    padding: 0 11px;
+  }
+`;
+
+interface ToastPresenterProps {
+  toast: { id: string; toastType: ToastType; text: string; duration: number };
+  onCloseToast: (id: string) => void;
+}
+
+export default function Toast({ toast, onCloseToast }: ToastPresenterProps) {
+  let hideTimer: ReturnType<typeof setTimeout>;
+  const [visible, setVisible] = useState(false);
+  const showToast = () => {
+    setVisible(true);
+  };
+
+  const handleClosePress = () => {
+    clearTimeout(hideTimer);
+    // Wait for the transition
+    setVisible(() => {
+      setTimeout(() => {
+        onCloseToast(toast.id);
+      }, 150);
+      return false;
+    });
+  };
+
+  useEffect(() => {
+    setTimeout(showToast);
+
+    if (toast.duration > 0) {
+      hideTimer = setTimeout(handleClosePress, toast.duration);
+    }
+    return () => {
+      clearTimeout(hideTimer);
+    };
+  }, []);
+
+  return (
+    <Alert
+      onDismiss={handleClosePress}
+      bsClass={cx(
+        'alert',
+        'toast',
+        visible && 'toast--visible',
+        toast.toastType === SUCCESS_TOAST && 'toast--success',
+        toast.toastType === WARNING_TOAST && 'toast--warning',
+        toast.toastType === DANGER_TOAST && 'toast--danger',
+      )}
+    >
+      <ToastContianer>
+        {toast.toastType === SUCCESS_TOAST && <Icon name="check" />}
+        {toast.toastType === WARNING_TOAST ||
+          (toast.toastType === DANGER_TOAST && <Icon name="error" />)}
+        <Interweave content={toast.text} />
+      </ToastContianer>
+    </Alert>
+  );
+}
diff --git a/superset-frontend/src/messageToasts/components/ToastPresenter.jsx 
b/superset-frontend/src/messageToasts/components/ToastPresenter.jsx
deleted file mode 100644
index 69fa144..0000000
--- a/superset-frontend/src/messageToasts/components/ToastPresenter.jsx
+++ /dev/null
@@ -1,56 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-import PropTypes from 'prop-types';
-import React from 'react';
-
-import Toast from './Toast';
-import { toastShape } from '../propShapes';
-
-import '../stylesheets/toast.less';
-
-const propTypes = {
-  toasts: PropTypes.arrayOf(toastShape),
-  removeToast: PropTypes.func.isRequired,
-};
-
-const defaultProps = {
-  toasts: [],
-};
-
-// eslint-disable-next-line react/prefer-stateless-function
-class ToastPresenter extends React.Component {
-  render() {
-    const { toasts, removeToast } = this.props;
-
-    return (
-      toasts.length > 0 && (
-        <div className="toast-presenter">
-          {toasts.map(toast => (
-            <Toast key={toast.id} toast={toast} onCloseToast={removeToast} />
-          ))}
-        </div>
-      )
-    );
-  }
-}
-
-ToastPresenter.propTypes = propTypes;
-ToastPresenter.defaultProps = defaultProps;
-
-export default ToastPresenter;
diff --git a/superset-frontend/src/messageToasts/components/ToastPresenter.tsx 
b/superset-frontend/src/messageToasts/components/ToastPresenter.tsx
new file mode 100644
index 0000000..5455735
--- /dev/null
+++ b/superset-frontend/src/messageToasts/components/ToastPresenter.tsx
@@ -0,0 +1,91 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+import React from 'react';
+import styled from '@superset-ui/style';
+import { ToastType } from 'src/messageToasts/types';
+import Toast from './Toast';
+
+const StyledToastPresenter = styled.div`
+  max-width: 600px;
+  position: fixed;
+  bottom: 0px;
+  right: -110px;
+  transform: translate(-50%, 0);
+  z-index: ${({ theme }) => theme.zIndex.max};
+
+  .toast {
+    background: ${({ theme }) => theme.colors.grayscale.dark1};
+    border-radius: ${({ theme }) => theme.borderRadius};
+    box-shadow: 0 2px 4px 0
+      fade(
+        ${({ theme }) => theme.colors.grayscale.dark2},
+        ${({ theme }) => theme.opacity.mediumLight}
+      );
+    color: ${({ theme }) => theme.colors.grayscale.light5};
+    opacity: 0;
+    position: relative;
+    transform: translateY(-100%);
+    white-space: pre-line;
+    will-change: transform, opacity;
+    transition: transform ${({ theme }) => theme.transitionTiming}s,
+      opacity ${({ theme }) => theme.transitionTiming}s;
+
+    &:after {
+      content: '';
+      position: absolute;
+      top: 0;
+      left: 0;
+      width: 6px;
+      height: 100%;
+    }
+  }
+
+  .toast > button {
+    color: ${({ theme }) => theme.colors.grayscale.light5};
+    opacity: 1;
+  }
+
+  .toast--visible {
+    opacity: 1;
+    transform: translateY(0);
+  }
+`;
+
+type ToastShape = {
+  id: string;
+  toastType: ToastType;
+  text: string;
+  duration: number;
+};
+
+interface ToastPresenterProps {
+  toasts: Array<ToastShape>;
+  removeToast: () => void;
+}
+
+const ToastPresenter = ({ toasts, removeToast }: ToastPresenterProps) =>
+  toasts.length > 0 && (
+    <StyledToastPresenter id="toast-presenter">
+      {toasts.map(toast => (
+        <Toast key={toast.id} toast={toast} onCloseToast={removeToast} />
+      ))}
+    </StyledToastPresenter>
+  );
+
+export default ToastPresenter;
diff --git a/superset-frontend/src/messageToasts/stylesheets/toast.less 
b/superset-frontend/src/messageToasts/stylesheets/toast.less
deleted file mode 100644
index 7221e9f..0000000
--- a/superset-frontend/src/messageToasts/stylesheets/toast.less
+++ /dev/null
@@ -1,78 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-@import '../../../stylesheets/less/variables.less';
-
-.toast-presenter {
-  position: fixed;
-  bottom: 16px;
-  left: 50%;
-  transform: translate(-50%, 0);
-  width: 600px;
-  z-index: @z-index-max;
-}
-
-.toast {
-  background: @lightest;
-  color: @almost-black;
-  opacity: 0;
-  position: relative;
-  white-space: pre-line;
-  box-shadow: 0 2px 4px 0 fade(@darkest, @opacity-medium-light);
-  will-change: transform, opacity;
-  transform: translateY(-100%);
-  transition: transform @timing-normal, opacity @timing-normal;
-
-  &:after {
-    content: '';
-    position: absolute;
-    top: 0;
-    left: 0;
-    width: 6px;
-    height: 100%;
-  }
-}
-
-.toast > button {
-  color: @almost-black;
-
-  &:hover {
-    color: @gray-dark;
-  }
-}
-
-.toast--visible {
-  transform: translateY(0);
-  opacity: 1;
-}
-
-.toast--info:after {
-  background: @info;
-}
-
-.toast--success:after {
-  background: @success;
-}
-
-.toast--warning:after {
-  background: @warning;
-}
-
-.toast--danger:after {
-  background: @danger;
-}
diff --git a/superset-frontend/src/messageToasts/types.ts 
b/superset-frontend/src/messageToasts/types.ts
new file mode 100644
index 0000000..471a3a0
--- /dev/null
+++ b/superset-frontend/src/messageToasts/types.ts
@@ -0,0 +1,24 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+export type ToastType =
+  | 'INFO_TOAST'
+  | 'SUCCESS_TOAST'
+  | 'WARNING_TOAST'
+  | 'DANGER_TOAST';

Reply via email to