Skip to content
This repository has been archived by the owner on Nov 14, 2023. It is now read-only.

Commit

Permalink
feat: Tooltip component and doc
Browse files Browse the repository at this point in the history
  • Loading branch information
wangkailang committed Jun 6, 2019
1 parent be6eeda commit 3c43293
Show file tree
Hide file tree
Showing 9 changed files with 261 additions and 13 deletions.
61 changes: 61 additions & 0 deletions docs/content/components/tooltip.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
---
title: Tooltip 文字提示
date: 2019-06-06
---
文字提示气泡框。

## 使用方式
鼠标移入显示提示,移出消失,气泡浮层不承载复杂文本和操作。

用来替换默认 `title` 提示,提供解释文案。

## 代码演示
### 文本提示
给文本提供说明文案。
```
<Tooltip label={<span>鼠标移入会展示提示。</span>}>
你好👋!
</Tooltip>
```
### 提示方向
- 可以指定提示展示的方向;
- 如果不指定,默认是朝上 `top` 展示;
- 不指定方向,根据 tooltip 在浏览器中的位置,在初次渲染时会调整展示方向,避免提示信息超出窗口,同时可能方便用户查看提示信息。
```
<div className="flex-between">
<Tooltip label={<Button>右 right</Button>} placement="right">
你好👋!
</Tooltip>
<Tooltip label={<Button>上 top</Button>} placement="top">
你好👋!
</Tooltip>
<Tooltip label={<Button>底 bottom</Button>} placement="bottom">
你好👋!
</Tooltip>
<Tooltip label={<Button>左 left</Button>} placement="left">
你好👋!
</Tooltip>
</div>
```

### 提示颜色
默认提示背景是黑色,文案是白色。可以使用 `contrast` 调换。白色背景、黑色文案。
```
<Tooltip contrast label={<Button>移入试试!</Button>}>
你好👋!
</Tooltip>
```
### 图标提示
部分场景布局紧凑,无法完全展示信息内容,这时可以配合图标给出提示文案。默认是`提示 info`图标。
```
<div>
<Tooltip>提示!</Tooltip>
<span style={{ paddingLeft: '40px' }} />
<Tooltip icon='help'>帮助!</Tooltip>
</div>
```

## API
```jsx previewOnly
<PropTable of="tooltip" />
```
2 changes: 1 addition & 1 deletion docs/src/components/Playground/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export default ({ isShow, children, previewOnly }) => {
</div>
<div className="Playground__View">
<LivePreview />
<Button bsStyle="link" onClick={toggle}>{show ? '隐藏代码' : '展开代码'}</Button>
<Button className="toggle-code" bsStyle="link" onClick={toggle}>{show ? '隐藏代码' : '展开代码'}</Button>
</div>
{show && <LiveEditor />}
</>
Expand Down
2 changes: 1 addition & 1 deletion docs/src/components/Playground/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ $w: 0.08333333333333333%;
> div {
width: 100%;
}
button {
button.toggle-code {
padding: 0;
opacity: 0;
max-height: 30px;
Expand Down
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,10 @@
"devDependencies": {
"@storybook/addon-options": "^5.0.11",
"@storybook/react": "^5.0.11",
"@types/classnames": "^2.2.8",
"@types/react-bootstrap": "^0.32.17",
"babel-loader": "^8.0.6",
"classnames": "^2.2.6",
"node-sass": "^4.12.0",
"raw-loader": "^2.0.0",
"react-syntax-highlighter": "^7.0.4"
Expand Down
32 changes: 22 additions & 10 deletions src/interface.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,27 @@
export interface BadgeProps {
count?: number | string;
showZero?: boolean;
dot?: boolean;
size?: string;
status?: string;
overflowCount?: number;
text?: string;
title?: string;
count?: number | string
showZero?: boolean
dot?: boolean
size?: string
status?: string
overflowCount?: number
text?: string
title?: string
}

export interface IconProps {
type: string,
className?: string,
type: string
className?: string
}

export interface TooltipProps {
iconClass?: string
icon?: string
iconAlign?: string
onClick?: any
label?: React.ReactNode,
contrast?: boolean
style?: string
placement?: string
children: React.ReactNode
}
128 changes: 128 additions & 0 deletions src/lib/Tooltip/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
import * as React from 'react';
import * as PropTypes from 'prop-types';
import cn from 'classnames';
import { Overlay, Tooltip as BaseTooltip } from 'react-bootstrap';
import { TooltipProps } from '../../interface';
import './style.scss';

const Tooltip: React.FC<TooltipProps> = props => {
const {
iconClass,
icon,
iconAlign,
onClick,
label,
contrast,
style,
children,
placement: defaultPlacement,
...extra
} = props;

const wrapper = React.useRef(null);
const [ placement, setPlacement ] = React.useState('top');
// 类似 componentDidMount。只会在 render 后执行一次
React.useEffect(() => {
const elem: any = wrapper.current;
let placement = 'top';
const docElem = document.documentElement;
const box = elem.getBoundingClientRect();
const elemOffsetLeft = box.left + docElem.scrollLeft;
const elemOffsetTop = box.top + docElem.scrollTop;
const pageWidth = document.documentElement.clientWidth;
const pageHeight = document.documentElement.clientHeight;
if (elemOffsetLeft > pageWidth * 0.8) {
placement = 'left';
}
if (elemOffsetLeft < pageWidth * 0.2) {
placement = 'right';
}
if (elemOffsetTop < pageHeight * 0.2) {
placement = 'bottom';
}
setPlacement(placement);
}, []);
const [ show, setShow ] = React.useState(false);
const handleShow = () => setShow(true);
const handleHide = () => setShow(false);

const placeholder = label ? (
label
) : icon ? (
<span
className={`Tooltip__icon icon icon-${icon} ${iconClass}`}
onClick={onClick}
style={{
verticalAlign: iconAlign,
}}
/>
) : (
undefined
);
return (
<div
ref={wrapper}
className="Tooltip"
onMouseEnter={handleShow}
onMouseLeave={handleHide}
>
{placeholder}
<Overlay
{...extra}
placement={defaultPlacement || placement}
target={wrapper.current || undefined}
show={show}
>
<BaseTooltip
id="tooltip"
style={Object.assign({}, { maxWidth: 280 }, style)}
className={cn({ contrast })}
onMouseEnter={handleShow}
onMouseLeave={handleHide}
>
{children}
</BaseTooltip>
</Overlay>
</div>
);
}

Tooltip.propTypes = {
/**
* 提示框的内容,子节点;
**/
children: PropTypes.node.isRequired,
/**
* 选定的元素
**/
label: PropTypes.element,
/**
* 当选定的特定元素是一个图标的时候传入的参数,具体详见 icomoon;
**/
icon: PropTypes.string,
/**
* 设置图标的垂直对齐方式,具体参见 vertical-align 的可选值;
**/
iconAlign: PropTypes.string,
/**
* 提示框的位置,可选'top','right','bottom','left'。
* 若不传入这一属性,会根据 OverlayTrigger 的位置,自适应选取提示框的位置;
**/
placement: PropTypes.string,
/**
* 提示框的颜色;
**/
contrast: PropTypes.bool,
/**
* 给图标传入的其他 class;
**/
iconClass: PropTypes.string,
};

Tooltip.defaultProps = {
icon: 'info',
iconAlign: 'text-bottom',
contrast: false,
};

export default Tooltip;
30 changes: 30 additions & 0 deletions src/lib/Tooltip/style.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
@import '../../style/variables.scss';

.Tooltip__icon {
font-size: 14px;
color: var(--light-steel-blue-normal);
}
.Tooltip {
display: inline-block;
}
.tooltip {
&.contrast {
&.top > .tooltip-arrow {
border-top-color: white;
}
&.right > .tooltip-arrow {
border-right-color: white;
}
&.bottom > .tooltip-arrow {
border-bottom-color: white;
}
&.left > .tooltip-arrow {
border-left-color: white;
}
.tooltip-inner {
color: black;
background-color: white;
box-shadow: 0 0 20px rgba(0,0,0,.3);
}
}
}
2 changes: 2 additions & 0 deletions src/lib/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import Badge from './Badge';
import Icon from './Icon';
import Tooltip from './Tooltip';

export {
Badge,
Icon,
Tooltip,
}
14 changes: 13 additions & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1818,6 +1818,11 @@
dependencies:
"@babel/types" "^7.3.0"

"@types/classnames@^2.2.8":
version "2.2.8"
resolved "https://registry.yarnpkg.com/@types/classnames/-/classnames-2.2.8.tgz#17139e1e1104203572caa4368f6796f6225b70b4"
integrity sha512-3UrLzPnz8u+MMXuJTF++389IfLSQUbl5F3ry9WCxva0BKG5H/oo5NuPRXk+HrpPU1+5pVHSWhnVWRzIaFQ7QuQ==

"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0":
version "2.0.1"
resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz#42995b446db9a48a11a07ec083499a860e9138ff"
Expand Down Expand Up @@ -1865,6 +1870,13 @@
resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.2.tgz#690a1475b84f2a884fd07cd797c00f5f31356ea8"
integrity sha512-ce5d3q03Ex0sy4R14722Rmt6MT07Ua+k4FwDfdcToYJcMKNtRVQvJ6JCAPdAmAnbRb6CsX6aYb9m96NGod9uTw==

"@types/react-bootstrap@^0.32.17":
version "0.32.17"
resolved "https://registry.yarnpkg.com/@types/react-bootstrap/-/react-bootstrap-0.32.17.tgz#62be3350734c7433683f54ec02afba69e7412427"
integrity sha512-w/Agv91PQ2q5w4MK+plWshyvLMFePxdl+b2KtlFHBSbr6FgaguIGEAdhA3l0hyKDmEj3VMHGFiBqwhsQJ2Rltg==
dependencies:
"@types/react" "*"

"@types/react-dom@16.8.4":
version "16.8.4"
resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-16.8.4.tgz#7fb7ba368857c7aa0f4e4511c4710ca2c5a12a88"
Expand Down Expand Up @@ -3489,7 +3501,7 @@ class-utils@^0.3.5:
isobject "^3.0.0"
static-extend "^0.1.1"

classnames@^2.2.5:
classnames@^2.2.5, classnames@^2.2.6:
version "2.2.6"
resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.6.tgz#43935bffdd291f326dad0a205309b38d00f650ce"
integrity sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q==
Expand Down

0 comments on commit 3c43293

Please sign in to comment.