Commit 8e80ada9 authored by Rayron Victor's avatar Rayron Victor Committed by 陈帅

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
parent 4e392e43
import React, { PureComponent } from 'react'; import React, { PureComponent } from 'react';
import { FormattedMessage, formatMessage } from 'umi/locale'; 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 moment from 'moment';
import groupBy from 'lodash/groupBy'; import groupBy from 'lodash/groupBy';
import NoticeIcon from '../NoticeIcon'; import NoticeIcon from '../NoticeIcon';
import HeaderSearch from '../HeaderSearch'; import HeaderSearch from '../HeaderSearch';
import HeaderDropdown from '../HeaderDropdown';
import SelectLang from '../SelectLang'; import SelectLang from '../SelectLang';
import styles from './index.less'; import styles from './index.less';
...@@ -139,7 +140,6 @@ export default class GlobalHeaderRight extends PureComponent { ...@@ -139,7 +140,6 @@ export default class GlobalHeaderRight extends PureComponent {
onClear={onNoticeClear} onClear={onNoticeClear}
onPopupVisibleChange={onNoticeVisibleChange} onPopupVisibleChange={onNoticeVisibleChange}
loading={fetchingNotices} loading={fetchingNotices}
popupAlign={{ offset: [20, -16] }}
clearClose clearClose
> >
<NoticeIcon.Tab <NoticeIcon.Tab
...@@ -168,7 +168,7 @@ export default class GlobalHeaderRight extends PureComponent { ...@@ -168,7 +168,7 @@ export default class GlobalHeaderRight extends PureComponent {
/> />
</NoticeIcon> </NoticeIcon>
{currentUser.name ? ( {currentUser.name ? (
<Dropdown overlay={menu}> <HeaderDropdown overlay={menu}>
<span className={`${styles.action} ${styles.account}`}> <span className={`${styles.action} ${styles.account}`}>
<Avatar <Avatar
size="small" size="small"
...@@ -178,7 +178,7 @@ export default class GlobalHeaderRight extends PureComponent { ...@@ -178,7 +178,7 @@ export default class GlobalHeaderRight extends PureComponent {
/> />
<span className={styles.name}>{currentUser.name}</span> <span className={styles.name}>{currentUser.name}</span>
</span> </span>
</Dropdown> </HeaderDropdown>
) : ( ) : (
<Spin size="small" style={{ marginLeft: 8, marginRight: 8 }} /> <Spin size="small" style={{ marginLeft: 8, marginRight: 8 }} />
)} )}
......
...@@ -61,7 +61,7 @@ ...@@ -61,7 +61,7 @@
&:hover { &:hover {
background: @pro-header-hover-bg; background: @pro-header-hover-bg;
} }
:global(&.ant-popover-open) { &:global(.opened) {
background: @pro-header-hover-bg; background: @pro-header-hover-bg;
} }
} }
...@@ -90,7 +90,7 @@ ...@@ -90,7 +90,7 @@
color: rgba(255, 255, 255, 0.85); color: rgba(255, 255, 255, 0.85);
} }
&:hover, &:hover,
&:global(.ant-popover-open) { &:global(.opened) {
background: @primary-color; background: @primary-color;
} }
:global(.ant-badge) { :global(.ant-badge) {
......
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} />
);
}
}
@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;
}
}
...@@ -149,7 +149,6 @@ ReactDOM.render( ...@@ -149,7 +149,6 @@ ReactDOM.render(
count={5} count={5}
onItemClick={onItemClick} onItemClick={onItemClick}
onClear={onClear} onClear={onClear}
popupAlign={{ offset: [20, -16] }}
> >
<NoticeIcon.Tab <NoticeIcon.Tab
list={noticeData['通知']} list={noticeData['通知']}
......
...@@ -9,15 +9,6 @@ export interface INoticeIconProps { ...@@ -9,15 +9,6 @@ export interface INoticeIconProps {
onClear?: (tabName: string) => void; onClear?: (tabName: string) => void;
onItemClick?: (item: INoticeIconData, tabProps: INoticeIconProps) => void; onItemClick?: (item: INoticeIconData, tabProps: INoticeIconProps) => void;
onTabChange?: (tabTile: string) => 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; style?: React.CSSProperties;
onPopupVisibleChange?: (visible: boolean) => void; onPopupVisibleChange?: (visible: boolean) => void;
popupVisible?: boolean; popupVisible?: boolean;
......
...@@ -17,7 +17,6 @@ loading | Popup card loading status | boolean | false ...@@ -17,7 +17,6 @@ loading | Popup card loading status | boolean | false
onClear | Click to clear button the callback | function(tabName) | - onClear | Click to clear button the callback | function(tabName) | -
onItemClick | Click on the list item's callback | function(item, tabProps) | - onItemClick | Click on the list item's callback | function(item, tabProps) | -
onTabChange | Switching callbacks for tabs | function(tabTitle) | - 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) | - onPopupVisibleChange | Popup Card Showing or Hiding Callbacks | function(visible) | -
popupVisible | Popup card display state | boolean | - popupVisible | Popup card display state | boolean | -
locale | Default message text | Object | `{ emptyText: '暂无数据', clear: '清空' }` locale | Default message text | Object | `{ emptyText: '暂无数据', clear: '清空' }`
......
import React, { PureComponent } from 'react'; import React, { PureComponent, Fragment } from 'react';
import ReactDOM from 'react-dom'; 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 classNames from 'classnames';
import HeaderDropdown from '../HeaderDropdown';
import List from './NoticeList'; import List from './NoticeList';
import styles from './index.less'; import styles from './index.less';
...@@ -24,6 +25,10 @@ export default class NoticeIcon extends PureComponent { ...@@ -24,6 +25,10 @@ export default class NoticeIcon extends PureComponent {
emptyImage: 'https://gw.alipayobjects.com/zos/rmsportal/wAhyIChODzsoKIOBHcBk.svg', emptyImage: 'https://gw.alipayobjects.com/zos/rmsportal/wAhyIChODzsoKIOBHcBk.svg',
}; };
state = {
visible: false,
};
onItemClick = (item, tabProps) => { onItemClick = (item, tabProps) => {
const { onItemClick } = this.props; const { onItemClick } = this.props;
const { clickClose } = item; const { clickClose } = item;
...@@ -70,21 +75,30 @@ export default class NoticeIcon extends PureComponent { ...@@ -70,21 +75,30 @@ export default class NoticeIcon extends PureComponent {
); );
}); });
return ( return (
<Fragment>
<Spin spinning={loading} delay={0}> <Spin spinning={loading} delay={0}>
<Tabs className={styles.tabs} onChange={this.onTabChange}> <Tabs className={styles.tabs} onChange={this.onTabChange}>
{panes} {panes}
</Tabs> </Tabs>
</Spin> </Spin>
</Fragment>
); );
} }
handleVisibleChange = visible => {
const { onPopupVisibleChange } = this.props;
this.setState({ visible });
onPopupVisibleChange(visible);
};
render() { 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 noticeButtonClass = classNames(className, styles.noticeButton);
const notificationBox = this.getNotificationBox(); const notificationBox = this.getNotificationBox();
const NoticeBellIcon = bell || <Icon type="bell" className={styles.icon} />; const NoticeBellIcon = bell || <Icon type="bell" className={styles.icon} />;
const trigger = ( const trigger = (
<span className={noticeButtonClass}> <span className={classNames(noticeButtonClass, { opened: visible })}>
<Badge count={count} style={{ boxShadow: 'none' }} className={styles.badge}> <Badge count={count} style={{ boxShadow: 'none' }} className={styles.badge}>
{NoticeBellIcon} {NoticeBellIcon}
</Badge> </Badge>
...@@ -98,19 +112,18 @@ export default class NoticeIcon extends PureComponent { ...@@ -98,19 +112,18 @@ export default class NoticeIcon extends PureComponent {
popoverProps.visible = popupVisible; popoverProps.visible = popupVisible;
} }
return ( return (
<Popover <HeaderDropdown
placement="bottomRight" placement="bottomRight"
content={notificationBox} overlay={notificationBox}
popupClassName={styles.popover} overlayClassName={styles.popover}
trigger="click" trigger={['click']}
arrowPointAtCenter visible={visible}
popupAlign={popupAlign} onVisibleChange={this.handleVisibleChange}
onVisibleChange={onPopupVisibleChange}
{...popoverProps} {...popoverProps}
ref={node => (this.popover = ReactDOM.findDOMNode(node))} // eslint-disable-line ref={node => (this.popover = ReactDOM.findDOMNode(node))} // eslint-disable-line
> >
{trigger} {trigger}
</Popover> </HeaderDropdown>
); );
} }
} }
...@@ -2,9 +2,6 @@ ...@@ -2,9 +2,6 @@
.popover { .popover {
width: 336px; width: 336px;
:global(.ant-popover-inner-content) {
padding: 0;
}
} }
.noticeButton { .noticeButton {
......
...@@ -17,7 +17,6 @@ loading | 弹出卡片加载状态 | boolean | false ...@@ -17,7 +17,6 @@ loading | 弹出卡片加载状态 | boolean | false
onClear | 点击清空按钮的回调 | function(tabName) | - onClear | 点击清空按钮的回调 | function(tabName) | -
onItemClick | 点击列表项的回调 | function(item, tabProps) | - onItemClick | 点击列表项的回调 | function(item, tabProps) | -
onTabChange | 切换页签的回调 | function(tabTitle) | - onTabChange | 切换页签的回调 | function(tabTitle) | -
popupAlign | 弹出卡片的位置配置 | Object [alignConfig](https://github.com/yiminghe/dom-align#alignconfig-object-details) | -
onPopupVisibleChange | 弹出卡片显隐的回调 | function(visible) | - onPopupVisibleChange | 弹出卡片显隐的回调 | function(visible) | -
popupVisible | 控制弹层显隐 | boolean | - popupVisible | 控制弹层显隐 | boolean | -
locale | 默认文案 | Object | `{ emptyText: '暂无数据', clear: '清空' }` locale | 默认文案 | Object | `{ emptyText: '暂无数据', clear: '清空' }`
......
import React, { PureComponent } from 'react'; import React, { PureComponent } from 'react';
import { formatMessage, setLocale, getLocale } from 'umi/locale'; import { formatMessage, setLocale, getLocale } from 'umi/locale';
import { Menu, Icon, Dropdown } from 'antd'; import { Menu, Icon } from 'antd';
import classNames from 'classnames'; import classNames from 'classnames';
import HeaderDropdown from '../HeaderDropdown';
import styles from './index.less'; import styles from './index.less';
export default class SelectLang extends PureComponent { export default class SelectLang extends PureComponent {
...@@ -41,11 +42,11 @@ export default class SelectLang extends PureComponent { ...@@ -41,11 +42,11 @@ export default class SelectLang extends PureComponent {
</Menu> </Menu>
); );
return ( return (
<Dropdown overlay={langMenu} placement="bottomRight"> <HeaderDropdown overlay={langMenu} placement="bottomRight">
<span className={classNames(styles.dropDown, className)}> <span className={classNames(styles.dropDown, className)}>
<Icon type="global" title={formatMessage({ id: 'navBar.lang' })} /> <Icon type="global" title={formatMessage({ id: 'navBar.lang' })} />
</span> </span>
</Dropdown> </HeaderDropdown>
); );
} }
} }
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
margin-right: 8px; margin-right: 8px;
} }
:global(.ant-dropdown-menu-item) { :global(.ant-dropdown-menu-item) {
width: 160px; min-width: 160px;
} }
} }
......
...@@ -98,13 +98,11 @@ class HeaderView extends PureComponent { ...@@ -98,13 +98,11 @@ class HeaderView extends PureComponent {
this.setState({ this.setState({
visible: true, visible: true,
}); });
} } else if (scrollTop > 300 && visible) {
else if (scrollTop > 300 && visible) {
this.setState({ this.setState({
visible: false, visible: false,
}); });
} } else if (scrollTop < 300 && !visible) {
else if (scrollTop < 300 && !visible) {
this.setState({ this.setState({
visible: true, visible: true,
}); });
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment