# Popover 气泡卡片

- 来源：[E10 UI 组件库](https://www.e-cology.com.cn/ui/popover/freepass)
- 平台：PC
- 维护者：蒋贝贝
- Issue：http://gitlab.ecology10.cn/FRONTEND/weapp-ui/-/issues?state=all&search=[Popover]

## 代码演示

### 基础用法

直接引入组件进行使用

```jsx
import { Component } from 'react';
import { constants, Popover, PopoverProps, ColorPicker, Input, Button } from '@weapp/ui';

const prefixCls = `${constants.uiPcClsPrefix}-demo-popover`;

interface PopoverDemoState {
  visible?: boolean;
}

class PopoverDemo extends Component<PopoverProps, PopoverDemoState> {
  constructor(props: PopoverProps) {
    super(props);
    this.state = {
      visible: false,
    };
  }
  onVisibleChange = (visible?: boolean) => {
    console.info('visible', visible)
    this.setState({ visible });
  };
  getPopup = () => (
    <div className={`${prefixCls}-popoverContent`}>
      <div className={`${prefixCls}-popoverContent-content`}>PopoverContent</div>
      <div className={`${prefixCls}-colorpicker`}>
        <ColorPicker triggerProps={{ mask: false, maskClosable: false }} />
      </div>
    </div>
  );
  render() {
    const { visible } = this.state;
    const action = 'click';
    const popup = <div style={{ width: 200, height: 100 }}>PopoverContent</div>;
    const otherPopup = <div>this is popover</div>;
    return (
      <div className={prefixCls}>
        <h4>基本使用</h4>
        <Popover
         
          popup={popup}
          visible={visible}
          onVisibleChange={this.onVisibleChange}
          placement={'right'}
          popoverType="tooltip"
          className="testPopover"
          // showBorder
          // action={action}
          triggerProps={{
            popupClassName: 'textPopopverPopup',
          }}
        >
          <Input />
        </Popover>
        <h4>弹层类型</h4>
        <div className={`${prefixCls}-wrapper`}>
          <Popover popup={otherPopup} placement={'top'} popoverType="popover">
            <Button>popover</Button>
          </Popover>
          <Popover popup={otherPopup} placement={'top'} popoverType="tooltip">
            <Button>tooltip</Button>
          </Popover>
          <Popover
           
            popup={otherPopup}
            placement={'top'}
            popoverType="bottomPopup"
          >
            <Button>bottomPopup</Button>
          </Popover>
        </div>
        <h4>显示边框</h4>
        <Popover popup={otherPopup} placement={'top'} popoverType="popover" showBorder>
          <Button>popover</Button>
        </Popover>
      </div>
    );
  }
}

export default PopoverDemo;
```

### 多个弹层嵌套

多个弹层嵌套

```jsx
import { Component } from 'react';
import { constants, Popover, PopoverProps, ColorPicker } from '@weapp/ui';

const prefixCls = `${constants.uiPcClsPrefix}-demo-popover`;

interface PopoverDemoState {
  visible?: boolean;
}

class PopoverDemo extends Component<PopoverProps, PopoverDemoState> {
  constructor(props: PopoverProps) {
    super(props);
    this.state = {
      visible: false,
    }
  }
  onVisibleChange = (visible?: boolean) => this.setState({ visible })
  getPopup = () => (
    <div className={`${prefixCls}-colorpicker`} >
      <ColorPicker triggerProps={{ mask: false, maskClosable: false }} />
    </div>
  )
  render() {
    const { visible } = this.state;
    return (
      <div className={prefixCls}>
        <Popover
          action={['click']}
          popup={this.getPopup}
          visible={visible}
          onVisibleChange={this.onVisibleChange}
          placement={"bottom"}
          mask
          maskClosable
        >
          <div className={`${prefixCls}-tipcontainer`}>组件异步导致弹出层首次定位不准确，可通过给弹层添加最小宽度处理</div>
        </Popover>
        <div className={`${prefixCls}-tip`}>
          <div>注意：多个弹层嵌套的情况，外部的弹层需配置蒙层，最内部的可以不用</div>
          <div>以下案例： Popover需加上蒙层，ColorPicker可不需要</div>
          <div>Trigger组件多个弹层也可以参考本案例</div>
        </div>
      </div>
    );
  }
}

export default PopoverDemo;
```

### 多种触发方式

鼠标移入、点击(hover,click)

```jsx
import { Component } from 'react';
import { constants, Popover, PopoverProps, ColorPicker, Input, Button } from '@weapp/ui';

const prefixCls = `${constants.uiPcClsPrefix}-demo-popover`;

interface PopoverDemoState {
  visible?: boolean;
  visible1?:boolean
}

class PopoverDemo extends Component<PopoverProps, PopoverDemoState> {
  constructor(props: PopoverProps) {
    super(props);
    this.state = {
      visible: false,
      visible1:false
    };
  }
  onVisibleChange = () => {
    this.setState({ visible: !this.state.visible });
  };

  onVisibleChange1 = () => {
    this.setState({ visible1: !this.state.visible1 });
  };

  getPopup = () => (
    <div className={`${prefixCls}-popoverContent`}>
      <div className={`${prefixCls}-popoverContent-content`}>PopoverContent</div>
      <div className={`${prefixCls}-colorpicker`}>
        <ColorPicker triggerProps={{ mask: false, maskClosable: false }} />
      </div>
    </div>
  );
  render() {
    const { visible,visible1 } = this.state;
    const action = 'click';
    const popup = <div style={{ width: 80, height: 50 }}>Content</div>;
    const visiblePopup = (
      <div style={{ padding: '16px' }}>
        内容
        <div style={{ cursor: 'pointer', marginTop: '8px', color: '#1890ff' }} onClick={this.onVisibleChange}>
          Close
        </div>
      </div>
    );
    return (
      <div className={prefixCls}>
        <h4>触发方式</h4>
        <Popover
         
          popup={popup}
          placement={'top'}
          popoverType="tooltip"
          className="testPopover"
        >
          <Button
           
            style={{
              marginRight: '8px',
            }}
          >
            Hover me
          </Button>
        </Popover>
        <Popover
         
          popup={popup}
          placement={'top'}
          popoverType="tooltip"
          className="testPopover"
          action={action}
        >
          <Button>Click me</Button>
        </Popover>
        <h4>使用 visible 属性控制浮层显示,不跟随滚动。</h4>
        <Popover
         
          popup={visiblePopup}
          placement={'top'}
          popoverType="popover"
          className="testPopover"
          visible={visible}
        >
          <Button onClick={this.onVisibleChange}>
            Click me
          </Button>
        </Popover>
        <h4>使用 visible 属性控制浮层显示,跟随滚动</h4>
        <Popover
          popup={visiblePopup}
          placement={'top'}
          popoverType="popover"
          className="testPopover"
          visible={visible1}
          triggerProps={
            {followScroll:true}
          }
        >
          <Button onClick={this.onVisibleChange1}>
            Click me
          </Button>
        </Popover>
      </div>
    );
  }
}

export default PopoverDemo;
```

### 位置

```jsx
import { Component } from "react";
import {
  constants,
  Popover,
  PopoverProps,
  ColorPicker,
  Input,
  Button,
  utils,
  Switch,
} from "@weapp/ui";

const prefixCls = `${constants.uiPcClsPrefix}-demo-popover`;
const { needRTL } = utils;
interface PopoverDemoState {
  visible?: boolean;
  showBorder: boolean;
  popoverContentStyle: any;
  popoverArrowStyle: any;
  bubbleBorderColor: string;
  bubbleBgColor: string;
}

class PopoverDemo extends Component<PopoverProps, PopoverDemoState> {
  constructor(props: PopoverProps) {
    super(props);
    this.state = {
      visible: false,
      showBorder: false,
      popoverContentStyle: {},
      popoverArrowStyle: {},
      bubbleBorderColor: "transparent",
      bubbleBgColor: "transparent",
    };
  }

  handleChange = (showBorder: any) => {
    this.setState({
      showBorder,
    });
  };

  bubbleBorderChange = (value: string) => {
    const { popoverContentStyle } = this.state;
    this.setState({
      bubbleBorderColor: value,
      popoverArrowStyle: {
        borderColor: value,
      },
      popoverContentStyle: {
        ...popoverContentStyle,
        border: `1px solid ${value}`,
      },
    });
  };

  bubbleBgChange = (value: string) => {
    const { popoverContentStyle } = this.state;
    this.setState({
      bubbleBgColor: value,
      popoverContentStyle: {
        ...popoverContentStyle,
        background: value,
      },
    });
  };

  render() {
    const {
      showBorder,
      bubbleBorderColor,
      bubbleBgColor,
      popoverContentStyle,
      popoverArrowStyle,
    } = this.state;
    const popup = (
      <div style={{ height: "40px", lineHeight: "40px", padding: "0 6px" }}>
        PopoverContent
      </div>
    );
    return (
      <div className={prefixCls}>
        <div>
          <span>添加箭头边框：</span> &nbsp;
          <Switch
           
            value={showBorder}
            onChange={this.handleChange}
          ></Switch>
        </div>
        <br />
        <div>
          <span>气泡边框颜色：</span> &nbsp;
          <ColorPicker
           
            style={{ display: "inline-block" }}
            value={bubbleBorderColor}
            onChange={this.bubbleBorderChange}
          ></ColorPicker>
        </div>
        <br />
        <div>
          <span>气泡背景色：</span> &nbsp;
          <ColorPicker
           
            style={{ display: "inline-block" }}
            value={bubbleBgColor}
            onChange={this.bubbleBgChange}
          ></ColorPicker>
        </div>
        <br />
        <div className={`${prefixCls}-top`}>
          <Popover
           
            action={"click"}
            popup={popup}
            placement={"topRight"}
            popoverType="tooltip"
            className="testPopover"
            showBorder={showBorder}
            popoverArrowStyle={popoverArrowStyle}
            popoverContentStyle={popoverContentStyle}
          >
            <Button>TR</Button>
          </Popover>
          <Popover
           
            action={"click"}
            popup={popup}
            placement={"top"}
            popoverType="tooltip"
            className="testPopover"
            showBorder={showBorder}
            popoverArrowStyle={popoverArrowStyle}
            popoverContentStyle={popoverContentStyle}
          >
            <Button>Top</Button>
          </Popover>
          <Popover
           
            action={"click"}
            popup={popup}
            placement={"topLeft"}
            popoverType="tooltip"
            className="testPopover"
            showBorder={showBorder}
            popoverArrowStyle={popoverArrowStyle}
            popoverContentStyle={popoverContentStyle}
          >
            <Button>TL</Button>
          </Popover>
        </div>
        <div className={`${prefixCls}-content`}>
          {needRTL?.() ? (
            <>
              <div className={`${prefixCls}-content-left`}>
                <Popover
                 
                  action={"click"}
                  popup={popup}
                  placement={"rightTop"}
                  popoverType="tooltip"
                  className="testPopover"
                  showBorder={showBorder}
                  popoverArrowStyle={popoverArrowStyle}
                  popoverContentStyle={popoverContentStyle}
                >
                  <Button>RT</Button>
                </Popover>
                <Popover
                 
                  action={"click"}
                  popup={popup}
                  placement={"right"}
                  popoverType="tooltip"
                  className="testPopover"
                  showBorder={showBorder}
                  popoverArrowStyle={popoverArrowStyle}
                  popoverContentStyle={popoverContentStyle}
                >
                  <Button>
                    Right
                  </Button>
                </Popover>
                <Popover
                 
                  action={"click"}
                  popup={popup}
                  placement={"rightBottom"}
                  popoverType="tooltip"
                  className="testPopover"
                  showBorder={showBorder}
                  popoverArrowStyle={popoverArrowStyle}
                  popoverContentStyle={popoverContentStyle}
                >
                  <Button>RB</Button>
                </Popover>
              </div>
              <div className={`${prefixCls}-content-right`}>
                <Popover
                 
                  action={"click"}
                  popup={popup}
                  placement={"leftTop"}
                  popoverType="tooltip"
                  className="testPopover"
                  showBorder={showBorder}
                  popoverArrowStyle={popoverArrowStyle}
                  popoverContentStyle={popoverContentStyle}
                >
                  <Button>LT</Button>
                </Popover>
                <Popover
                 
                  action={"click"}
                  popup={popup}
                  placement={"left"}
                  popoverType="tooltip"
                  className="testPopover"
                  showBorder={showBorder}
                  popoverArrowStyle={popoverArrowStyle}
                  popoverContentStyle={popoverContentStyle}
                >
                  <Button>Left</Button>
                </Popover>
                <Popover
                 
                  action={"click"}
                  popup={popup}
                  placement={"leftBottom"}
                  popoverType="tooltip"
                  className="testPopover"
                  showBorder={showBorder}
                  popoverArrowStyle={popoverArrowStyle}
                  popoverContentStyle={popoverContentStyle}
                >
                  <Button>LB</Button>
                </Popover>
              </div>
            </>
          ) : (
            <>
              <div className={`${prefixCls}-content-left`}>
                <Popover
                 
                  action={"click"}
                  popup={popup}
                  placement={"leftTop"}
                  popoverType="tooltip"
                  className="testPopover"
                  showBorder={showBorder}
                  popoverArrowStyle={popoverArrowStyle}
                  popoverContentStyle={popoverContentStyle}
                >
                  <Button>LT</Button>
                </Popover>
                <Popover
                 
                  action={"click"}
                  popup={popup}
                  placement={"left"}
                  popoverType="tooltip"
                  className="testPopover"
                  showBorder={showBorder}
                  popoverArrowStyle={popoverArrowStyle}
                  popoverContentStyle={popoverContentStyle}
                >
                  <Button>Left</Button>
                </Popover>
                <Popover
                 
                  action={"click"}
                  popup={popup}
                  placement={"leftBottom"}
                  popoverType="tooltip"
                  className="testPopover"
                  showBorder={showBorder}
                  popoverArrowStyle={popoverArrowStyle}
                  popoverContentStyle={popoverContentStyle}
                >
                  <Button>LB</Button>
                </Popover>
              </div>
              <div className={`${prefixCls}-content-right`}>
                <Popover
                 
                  action={"click"}
                  popup={popup}
                  placement={"rightTop"}
                  popoverType="tooltip"
                  className="testPopover"
                  showBorder={showBorder}
                  popoverArrowStyle={popoverArrowStyle}
                  popoverContentStyle={popoverContentStyle}
                >
                  <Button>RT</Button>
                </Popover>
                <Popover
                 
                  action={"click"}
                  popup={popup}
                  placement={"right"}
                  popoverType="tooltip"
                  className="testPopover"
                  showBorder={showBorder}
                  popoverArrowStyle={popoverArrowStyle}
                  popoverContentStyle={popoverContentStyle}
                >
                  <Button>
                    Right
                  </Button>
                </Popover>
                <Popover
                 
                  action={"click"}
                  popup={popup}
                  placement={"rightBottom"}
                  popoverType="tooltip"
                  className="testPopover"
                  showBorder={showBorder}
                  popoverArrowStyle={popoverArrowStyle}
                  popoverContentStyle={popoverContentStyle}
                >
                  <Button>RB</Button>
                </Popover>
              </div>
            </>
          )}
        </div>
        <div className={`${prefixCls}-buttom`}>
          <Popover
           
            action={"click"}
            popup={popup}
            placement={"bottomRight"}
            popoverType="tooltip"
            className="testPopover"
            showBorder={showBorder}
            popoverArrowStyle={popoverArrowStyle}
            popoverContentStyle={popoverContentStyle}
          >
            <Button>BR</Button>
          </Popover>
          <Popover
           
            action={"click"}
            popup={popup}
            placement={"bottom"}
            popoverType="tooltip"
            className="testPopover"
            showBorder={showBorder}
            popoverArrowStyle={popoverArrowStyle}
            popoverContentStyle={popoverContentStyle}
          >
            <Button>Bottom</Button>
          </Popover>
          <Popover
           
            action={"click"}
            popup={popup}
            placement={"bottomLeft"}
            popoverType="tooltip"
            className="testPopover"
            showBorder={showBorder}
            popoverArrowStyle={popoverArrowStyle}
            popoverContentStyle={popoverContentStyle}
          >
            <Button>BL</Button>
          </Popover>
        </div>
      </div>
    );
  }
}

export default PopoverDemo;
```

### 多种触发方式

鼠标移入、点击(hover,click)

```jsx
import { Component } from 'react';
import { constants, Popover, PopoverProps, ColorPicker, Input, Button } from '@weapp/ui';

const prefixCls = `${constants.uiPcClsPrefix}-demo-popover`;

interface PopoverDemoState {
  visible?: boolean;
  visible1?:boolean
}

class PopoverDemo extends Component<PopoverProps, PopoverDemoState> {
  constructor(props: PopoverProps) {
    super(props);
    this.state = {
      visible: false,
      visible1:false
    };
  }
  onVisibleChange = () => {
    this.setState({ visible: !this.state.visible });
  };

  onVisibleChange1 = () => {
    this.setState({ visible1: !this.state.visible1 });
  };

  getPopup = () => (
    <div className={`${prefixCls}-popoverContent`}>
      <div className={`${prefixCls}-popoverContent-content`}>PopoverContent</div>
      <div className={`${prefixCls}-colorpicker`}>
        <ColorPicker triggerProps={{ mask: false, maskClosable: false }} />
      </div>
    </div>
  );
  render() {
    const { visible,visible1 } = this.state;
    const action = 'click';
    const popup = <div style={{ width: 80, height: 50 }}>Content</div>;
    const visiblePopup = (
      <div style={{ padding: '16px' }}>
        内容
        <div style={{ cursor: 'pointer', marginTop: '8px', color: '#1890ff' }} onClick={this.onVisibleChange}>
          Close
        </div>
      </div>
    );
    return (
      <div className={prefixCls}>
        <h4>触发方式</h4>
        <Popover
         
          popup={popup}
          placement={'top'}
          popoverType="tooltip"
          className="testPopover"
        >
          <Button
           
            style={{
              marginRight: '8px',
            }}
          >
            Hover me
          </Button>
        </Popover>
        <Popover
         
          popup={popup}
          placement={'top'}
          popoverType="tooltip"
          className="testPopover"
          action={action}
        >
          <Button>Click me</Button>
        </Popover>
        <h4>使用 visible 属性控制浮层显示,不跟随滚动。</h4>
        <Popover
         
          popup={visiblePopup}
          placement={'top'}
          popoverType="popover"
          className="testPopover"
          visible={visible}
        >
          <Button onClick={this.onVisibleChange}>
            Click me
          </Button>
        </Popover>
        <h4>使用 visible 属性控制浮层显示,跟随滚动</h4>
        <Popover
          popup={visiblePopup}
          placement={'top'}
          popoverType="popover"
          className="testPopover"
          visible={visible1}
          triggerProps={
            {followScroll:true}
          }
        >
          <Button onClick={this.onVisibleChange1}>
            Click me
          </Button>
        </Popover>
      </div>
    );
  }
}

export default PopoverDemo;
```

## API

### 参数说明如下：

| 参数 | 说明 | 类型 | 是否必填 | 默认值 |
| --- | --- | --- | --- | --- |
| action | 弹层动作(可设置 hover/click) | ActionType \| ActionType[] | 否 | - |
| getPopupContainer | 弹层容器定位 | () => HTMLElement/undefined; | 否 | - |
| mask | 是否展示遮罩 | boolean | 否 | - |
| maskClosable | 点击蒙层是否允许关闭 | boolean | 否 | - |
| maskStyle | 蒙层自定义样式 | CSSProperties | 否 | - |
| options | 选项配置，配置 popup 自定义弹层内容后，options 失效 | PopoverOptions[] | 否 | - |
| placement | 弹层位置 | PopupPlacement | 否 | - |
| popup | 弹层内容 | ReactNode  \| (() => ReactNode) | 否 | - |
| popoverType | 弹层类型 | PopoverType | 否 | - |
| showBorder | 是否显示边框 | boolean | 否 | - |
| triggerProps | 支持 Trigger 组件参数 | TriggerConfig | 否 | - |
| visible | 弹层显示/隐藏 | boolean | 否 | false |
| onVisibleChange | 弹层默认显示/隐藏事件 | (visible?: boolean) => void | 否 | - |
| hideArrow | 是否隐藏箭头 | boolean | 否 | - |
#### PopupPlacement 参数说明同 Trigger 组件

```js
type PopupPlacement 'left' | 'right' | 'top' | 'bottom' | 'topLeft' | 'topRight' | 'bottomRight' | 'bottomLeft' | 'leftTop' | 'rightTop' | 'leftBottom' | 'rightBottom'
```

#### PopoverType 参数说明如下：

```
  type PopoverType = "popover" | "tooltip" | "bottomPopup";
```

#### PopoverOptions 参数说明如下：

```
type DataType = {
  /* 数据的标示 */
  id: string;
  /* 数据显示内容 */
  content?: string;
  /* 多种数据类型的type */
  type?: string;
  /* 数据的提示 */
  title?: string;
  /* 是否是禁用项 */
  disabled?: boolean;
  /* 是否可选 */
  checkable?: boolean;
};

interface PopoverOptions extends DataType {
  onClick?: () => void, // 响应事件
  icon?: IconNames, // 图标名称
  iconProps?: IconProps, // 图标参数配置，继承Icon组件
  btnProps?: ButtonProps, // 按钮参数配置，继承Button组件
}
```
