Browse Source

NoticeIcon: using Dropdown instead of Popover. (#3057)

* NoticeIcon: using Dropdown instead of Popover.

* NoticeIcon: using 100% width on mobile

* New component `HeaderDropdown`

* Using PureComponent because of refs
Rayron Victor 7 years atrás
parent
commit
8e80ada985

+ 4 - 4
src/components/GlobalHeader/RightContent.js

@@ -1,10 +1,11 @@
 import React, { PureComponent } from 'react';
 import { FormattedMessage, formatMessage } from 'umi/locale';
-import { Spin, Tag, Menu, Icon, Dropdown, Avatar, Tooltip } from 'antd';
+import { Spin, Tag, Menu, Icon, Avatar, Tooltip } from 'antd';
 import moment from 'moment';
 import groupBy from 'lodash/groupBy';
 import NoticeIcon from '../NoticeIcon';
 import HeaderSearch from '../HeaderSearch';
+import HeaderDropdown from '../HeaderDropdown';
 import SelectLang from '../SelectLang';
 import styles from './index.less';
 
@@ -139,7 +140,6 @@ export default class GlobalHeaderRight extends PureComponent {
           onClear={onNoticeClear}
           onPopupVisibleChange={onNoticeVisibleChange}
           loading={fetchingNotices}
-          popupAlign={{ offset: [20, -16] }}
           clearClose
         >
           <NoticeIcon.Tab
@@ -168,7 +168,7 @@ export default class GlobalHeaderRight extends PureComponent {
           />
         </NoticeIcon>
         {currentUser.name ? (
-          <Dropdown overlay={menu}>
+          <HeaderDropdown overlay={menu}>
             <span className={`${styles.action} ${styles.account}`}>
               <Avatar
                 size="small"
@@ -178,7 +178,7 @@ export default class GlobalHeaderRight extends PureComponent {
               />
               <span className={styles.name}>{currentUser.name}</span>
             </span>
-          </Dropdown>
+          </HeaderDropdown>
         ) : (
           <Spin size="small" style={{ marginLeft: 8, marginRight: 8 }} />
         )}

+ 2 - 2
src/components/GlobalHeader/index.less

@@ -61,7 +61,7 @@
     &:hover {
       background: @pro-header-hover-bg;
     }
-    :global(&.ant-popover-open) {
+    &:global(.opened) {
       background: @pro-header-hover-bg;
     }
   }
@@ -90,7 +90,7 @@
       color: rgba(255, 255, 255, 0.85);
     }
     &:hover,
-    &:global(.ant-popover-open) {
+    &:global(.opened) {
       background: @primary-color;
     }
     :global(.ant-badge) {

+ 13 - 0
src/components/HeaderDropdown/index.js

@@ -0,0 +1,13 @@
+import React, { PureComponent } from 'react';
+import { Dropdown } from 'antd';
+import classNames from 'classnames';
+import styles from './index.less';
+
+export default class HeaderDropdown extends PureComponent {
+  render() {
+    const { overlayClassName, ...props } = this.props;
+    return (
+      <Dropdown overlayClassName={classNames(styles.container, overlayClassName)} {...props} />
+    );
+  }
+}

+ 16 - 0
src/components/HeaderDropdown/index.less

@@ -0,0 +1,16 @@
+@import '~antd/lib/style/themes/default.less';
+
+.container > *:global(:not(.ant-dropdown-menu)) {
+  background-color: #fff;
+  box-shadow: @shadow-1-down;
+  border-radius: 4px;
+}
+
+@media screen and (max-width: @screen-xs) {
+  .container {
+    width: 100% !important;
+  }
+  .container > * {
+    border-radius: 0 !important;
+  }
+}

+ 0 - 1
src/components/NoticeIcon/demo/popover.md

@@ -149,7 +149,6 @@ ReactDOM.render(
       count={5}
       onItemClick={onItemClick}
       onClear={onClear}
-      popupAlign={{ offset: [20, -16] }}
     >
       <NoticeIcon.Tab
         list={noticeData['通知']}

+ 0 - 9
src/components/NoticeIcon/index.d.ts

@@ -9,15 +9,6 @@ export interface INoticeIconProps {
   onClear?: (tabName: string) => void;
   onItemClick?: (item: INoticeIconData, tabProps: INoticeIconProps) => void;
   onTabChange?: (tabTile: string) => void;
-  popupAlign?: {
-    points?: [string, string];
-    offset?: [number, number];
-    targetOffset?: [number, number];
-    overflow?: any;
-    useCssRight?: boolean;
-    useCssBottom?: boolean;
-    useCssTransform?: boolean;
-  };
   style?: React.CSSProperties;
   onPopupVisibleChange?: (visible: boolean) => void;
   popupVisible?: boolean;

+ 0 - 1
src/components/NoticeIcon/index.en-US.md

@@ -17,7 +17,6 @@ loading | Popup card loading status | boolean | false
 onClear | Click to clear button the callback  | function(tabName) | -
 onItemClick | Click on the list item's callback | function(item, tabProps) | -
 onTabChange | Switching callbacks for tabs | function(tabTitle) | -
-popupAlign | Popup card location configuration | Object [alignConfig](https://github.com/yiminghe/dom-align#alignconfig-object-details) | -
 onPopupVisibleChange | Popup Card Showing or Hiding Callbacks | function(visible) | -
 popupVisible | Popup card display state | boolean | -
 locale | Default message text | Object | `{ emptyText: '暂无数据', clear: '清空' }`

+ 30 - 17
src/components/NoticeIcon/index.js

@@ -1,7 +1,8 @@
-import React, { PureComponent } from 'react';
+import React, { PureComponent, Fragment } from 'react';
 import ReactDOM from 'react-dom';
-import { Popover, Icon, Tabs, Badge, Spin } from 'antd';
+import { Icon, Tabs, Badge, Spin } from 'antd';
 import classNames from 'classnames';
+import HeaderDropdown from '../HeaderDropdown';
 import List from './NoticeList';
 import styles from './index.less';
 
@@ -24,6 +25,10 @@ export default class NoticeIcon extends PureComponent {
     emptyImage: 'https://gw.alipayobjects.com/zos/rmsportal/wAhyIChODzsoKIOBHcBk.svg',
   };
 
+  state = {
+    visible: false,
+  };
+
   onItemClick = (item, tabProps) => {
     const { onItemClick } = this.props;
     const { clickClose } = item;
@@ -70,21 +75,30 @@ export default class NoticeIcon extends PureComponent {
       );
     });
     return (
-      <Spin spinning={loading} delay={0}>
-        <Tabs className={styles.tabs} onChange={this.onTabChange}>
-          {panes}
-        </Tabs>
-      </Spin>
+      <Fragment>
+        <Spin spinning={loading} delay={0}>
+          <Tabs className={styles.tabs} onChange={this.onTabChange}>
+            {panes}
+          </Tabs>
+        </Spin>
+      </Fragment>
     );
   }
 
+  handleVisibleChange = visible => {
+    const { onPopupVisibleChange } = this.props;
+    this.setState({ visible });
+    onPopupVisibleChange(visible);
+  };
+
   render() {
-    const { className, count, popupAlign, popupVisible, onPopupVisibleChange, bell } = this.props;
+    const { className, count, popupVisible, bell } = this.props;
+    const { visible } = this.state;
     const noticeButtonClass = classNames(className, styles.noticeButton);
     const notificationBox = this.getNotificationBox();
     const NoticeBellIcon = bell || <Icon type="bell" className={styles.icon} />;
     const trigger = (
-      <span className={noticeButtonClass}>
+      <span className={classNames(noticeButtonClass, { opened: visible })}>
         <Badge count={count} style={{ boxShadow: 'none' }} className={styles.badge}>
           {NoticeBellIcon}
         </Badge>
@@ -98,19 +112,18 @@ export default class NoticeIcon extends PureComponent {
       popoverProps.visible = popupVisible;
     }
     return (
-      <Popover
+      <HeaderDropdown
         placement="bottomRight"
-        content={notificationBox}
-        popupClassName={styles.popover}
-        trigger="click"
-        arrowPointAtCenter
-        popupAlign={popupAlign}
-        onVisibleChange={onPopupVisibleChange}
+        overlay={notificationBox}
+        overlayClassName={styles.popover}
+        trigger={['click']}
+        visible={visible}
+        onVisibleChange={this.handleVisibleChange}
         {...popoverProps}
         ref={node => (this.popover = ReactDOM.findDOMNode(node))} // eslint-disable-line
       >
         {trigger}
-      </Popover>
+      </HeaderDropdown>
     );
   }
 }

+ 0 - 3
src/components/NoticeIcon/index.less

@@ -2,9 +2,6 @@
 
 .popover {
   width: 336px;
-  :global(.ant-popover-inner-content) {
-    padding: 0;
-  }
 }
 
 .noticeButton {

+ 0 - 1
src/components/NoticeIcon/index.zh-CN.md

@@ -17,7 +17,6 @@ loading | 弹出卡片加载状态 | boolean | false
 onClear | 点击清空按钮的回调 | function(tabName) | -
 onItemClick | 点击列表项的回调 | function(item, tabProps) | -
 onTabChange | 切换页签的回调 | function(tabTitle) | -
-popupAlign | 弹出卡片的位置配置 | Object [alignConfig](https://github.com/yiminghe/dom-align#alignconfig-object-details) | -
 onPopupVisibleChange | 弹出卡片显隐的回调 | function(visible) | -
 popupVisible | 控制弹层显隐 | boolean | -
 locale | 默认文案 | Object | `{ emptyText: '暂无数据', clear: '清空' }`

+ 4 - 3
src/components/SelectLang/index.js

@@ -1,7 +1,8 @@
 import React, { PureComponent } from 'react';
 import { formatMessage, setLocale, getLocale } from 'umi/locale';
-import { Menu, Icon, Dropdown } from 'antd';
+import { Menu, Icon } from 'antd';
 import classNames from 'classnames';
+import HeaderDropdown from '../HeaderDropdown';
 import styles from './index.less';
 
 export default class SelectLang extends PureComponent {
@@ -41,11 +42,11 @@ export default class SelectLang extends PureComponent {
       </Menu>
     );
     return (
-      <Dropdown overlay={langMenu} placement="bottomRight">
+      <HeaderDropdown overlay={langMenu} placement="bottomRight">
         <span className={classNames(styles.dropDown, className)}>
           <Icon type="global" title={formatMessage({ id: 'navBar.lang' })} />
         </span>
-      </Dropdown>
+      </HeaderDropdown>
     );
   }
 }

+ 1 - 1
src/components/SelectLang/index.less

@@ -5,7 +5,7 @@
     margin-right: 8px;
   }
   :global(.ant-dropdown-menu-item) {
-    width: 160px;
+    min-width: 160px;
   }
 }
 

+ 2 - 4
src/layouts/Header.js

@@ -98,13 +98,11 @@ class HeaderView extends PureComponent {
           this.setState({
             visible: true,
           });
-        }
-        else if (scrollTop > 300 && visible) {
+        } else if (scrollTop > 300 && visible) {
           this.setState({
             visible: false,
           });
-        }
-        else if (scrollTop < 300 && !visible) {
+        } else if (scrollTop < 300 && !visible) {
           this.setState({
             visible: true,
           });