mirror of
https://github.com/ant-design/ant-design.git
synced 2025-01-18 14:13:37 +08:00
Merge pull request #474 from ant-design/feature-placement
feat: support more placement for popover
This commit is contained in:
commit
3659d8ab8e
@ -2,7 +2,9 @@
|
||||
"extends": ["eslint-config-airbnb"],
|
||||
"env": {
|
||||
"browser": true,
|
||||
"node": true
|
||||
"node": true,
|
||||
"mocha": true,
|
||||
"jest": true
|
||||
},
|
||||
"ecmaFeatures": {
|
||||
"jsx": true
|
||||
|
@ -7,7 +7,7 @@
|
||||
---
|
||||
|
||||
````jsx
|
||||
import { Popconfirm, message } from 'antd';
|
||||
import { Popconfirm, message, Button } from 'antd';
|
||||
|
||||
const text = '确定要删除这个任务吗?';
|
||||
|
||||
@ -16,17 +16,44 @@ function confirm() {
|
||||
}
|
||||
|
||||
ReactDOM.render(<div>
|
||||
<Popconfirm placement="leftTop" title={text} onConfirm={confirm}>
|
||||
<Button>左上</Button>
|
||||
</Popconfirm>
|
||||
<Popconfirm placement="left" title={text} onConfirm={confirm}>
|
||||
<a href="javascript:;">左边</a>
|
||||
<Button>左</Button>
|
||||
</Popconfirm>
|
||||
<Popconfirm placement="leftBottom" title={text} onConfirm={confirm}>
|
||||
<Button>左下</Button>
|
||||
</Popconfirm>
|
||||
<br/>
|
||||
<Popconfirm placement="topLeft" title={text} onConfirm={confirm}>
|
||||
<Button>上左</Button>
|
||||
</Popconfirm>
|
||||
<Popconfirm placement="top" title={text} onConfirm={confirm}>
|
||||
<a href="javascript:;">上边</a>
|
||||
<Button>上</Button>
|
||||
</Popconfirm>
|
||||
<Popconfirm placement="topRight" title={text} onConfirm={confirm}>
|
||||
<Button>上右</Button>
|
||||
</Popconfirm>
|
||||
<br/>
|
||||
<Popconfirm placement="bottomLeft" title={text} onConfirm={confirm}>
|
||||
<Button>下左</Button>
|
||||
</Popconfirm>
|
||||
<Popconfirm placement="bottom" title={text} onConfirm={confirm}>
|
||||
<a href="javascript:;">下边</a>
|
||||
<Button>下</Button>
|
||||
</Popconfirm>
|
||||
<Popconfirm placement="bottomRight" title={text} onConfirm={confirm}>
|
||||
<Button>下右</Button>
|
||||
</Popconfirm>
|
||||
<br/>
|
||||
<Popconfirm placement="rightTop" title={text} onConfirm={confirm}>
|
||||
<Button>右上</Button>
|
||||
</Popconfirm>
|
||||
<Popconfirm placement="right" title={text} onConfirm={confirm}>
|
||||
<a href="javascript:;">右边</a>
|
||||
<Button>右</Button>
|
||||
</Popconfirm>
|
||||
<Popconfirm placement="rightBottom" title={text} onConfirm={confirm}>
|
||||
<Button>右下</Button>
|
||||
</Popconfirm>
|
||||
</div>, document.getElementById('components-popconfirm-demo-placement'));
|
||||
````
|
||||
@ -35,4 +62,8 @@ ReactDOM.render(<div>
|
||||
.code-box-demo .ant-popover-wrap > a {
|
||||
margin-right: 1em;
|
||||
}
|
||||
.code-box-demo .ant-btn {
|
||||
margin-right: 1em;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
</style>
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
- order: 1
|
||||
|
||||
位置有四个方向。
|
||||
位置有十二个方向。
|
||||
|
||||
---
|
||||
|
||||
@ -16,23 +16,51 @@ const content = <div>
|
||||
</div>;
|
||||
|
||||
ReactDOM.render(<div>
|
||||
<Popover placement="left" title={text} overlay={content}>
|
||||
<Popover placement="leftTop" title={text} overlay={content} trigger="click">
|
||||
<Button>左上</Button>
|
||||
</Popover>
|
||||
<Popover placement="left" title={text} overlay={content} trigger="click">
|
||||
<Button>左</Button>
|
||||
</Popover>
|
||||
<Popover placement="top" title={text} overlay={content}>
|
||||
<Popover placement="leftBottom" title={text} overlay={content} trigger="click">
|
||||
<Button>左下</Button>
|
||||
</Popover>
|
||||
<br/>
|
||||
<Popover placement="topLeft" title={text} overlay={content} trigger="click">
|
||||
<Button>上左</Button>
|
||||
</Popover>
|
||||
<Popover placement="top" title={text} overlay={content} trigger="click">
|
||||
<Button>上</Button>
|
||||
</Popover>
|
||||
<Popover placement="bottom" title={text} overlay={content}>
|
||||
<Popover placement="topRight" title={text} overlay={content} trigger="click">
|
||||
<Button>上右</Button>
|
||||
</Popover>
|
||||
<br/>
|
||||
<Popover placement="bottomLeft" title={text} overlay={content} trigger="click">
|
||||
<Button>下左</Button>
|
||||
</Popover>
|
||||
<Popover placement="bottom" title={text} overlay={content} trigger="click">
|
||||
<Button>下</Button>
|
||||
</Popover>
|
||||
<Popover placement="right" title={text} overlay={content}>
|
||||
<Popover placement="bottomRight" title={text} overlay={content} trigger="click">
|
||||
<Button>下右</Button>
|
||||
</Popover>
|
||||
<br/>
|
||||
<Popover placement="rightTop" title={text} overlay={content} trigger="click">
|
||||
<Button>右上</Button>
|
||||
</Popover>
|
||||
<Popover placement="right" title={text} overlay={content} trigger="click">
|
||||
<Button>右</Button>
|
||||
</Popover>
|
||||
<Popover placement="rightBottom" title={text} overlay={content} trigger="click">
|
||||
<Button>右下</Button>
|
||||
</Popover>
|
||||
</div>, document.getElementById('components-popover-demo-placement'));
|
||||
````
|
||||
|
||||
<style>
|
||||
.code-box-demo .ant-btn {
|
||||
margin-right: 1em;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
</style>
|
||||
|
@ -1,8 +1,9 @@
|
||||
import React from 'react';
|
||||
import Tooltip from 'rc-tooltip';
|
||||
|
||||
const prefixCls = 'ant-popover';
|
||||
|
||||
export default React.createClass({
|
||||
const Popover = React.createClass({
|
||||
getDefaultProps() {
|
||||
return {
|
||||
prefixCls: prefixCls,
|
||||
@ -13,8 +14,39 @@ export default React.createClass({
|
||||
overlayStyle: {}
|
||||
};
|
||||
},
|
||||
|
||||
render() {
|
||||
const overlay = <div>
|
||||
const transitionName = ({
|
||||
top: 'zoom-down',
|
||||
bottom: 'zoom-up',
|
||||
left: 'zoom-right',
|
||||
right: 'zoom-left',
|
||||
topLeft: 'zoom-down',
|
||||
bottomLeft: 'zoom-up',
|
||||
leftTop: 'zoom-right',
|
||||
rightTop: 'zoom-left',
|
||||
topRight: 'zoom-down',
|
||||
bottomRight: 'zoom-up',
|
||||
leftBottom: 'zoom-right',
|
||||
rightBottom: 'zoom-left',
|
||||
})[this.props.placement];
|
||||
|
||||
return (
|
||||
<Tooltip transitionName={transitionName}
|
||||
ref="tooltip"
|
||||
{...this.props}
|
||||
overlay={this.getOverlay()}>
|
||||
{this.props.children}
|
||||
</Tooltip>
|
||||
);
|
||||
},
|
||||
|
||||
getPopupDomNode() {
|
||||
return this.refs.tooltip.refs.trigger.popupDomNode;
|
||||
},
|
||||
|
||||
getOverlay() {
|
||||
return <div>
|
||||
<div className={prefixCls + '-title'}>
|
||||
{this.props.title}
|
||||
</div>
|
||||
@ -22,19 +54,7 @@ export default React.createClass({
|
||||
{this.props.overlay}
|
||||
</div>
|
||||
</div>;
|
||||
|
||||
const transitionName = ({
|
||||
top: 'zoom-down',
|
||||
bottom: 'zoom-up',
|
||||
left: 'zoom-right',
|
||||
right: 'zoom-left'
|
||||
})[this.props.placement];
|
||||
|
||||
return (
|
||||
<Tooltip transitionName={transitionName}
|
||||
{...this.props} overlay={overlay}>
|
||||
{this.props.children}
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
export default Popover;
|
||||
|
@ -22,5 +22,5 @@
|
||||
| trigger | 触发行为,可选 `hover/focus/click` | string | hover |
|
||||
| placement | 气泡框位置,可选 `top/left/right/bottom` | string | top |
|
||||
| title | 卡片标题 | React.Element | 无 |
|
||||
| content | 卡片内容 | React.Element | 无 |
|
||||
| overlayClassName | 浮层的类名 | string | 无 |
|
||||
| overlay | 卡片内容 | React.Element | 无 |
|
||||
| prefixCls | 浮层的类名 | string | 无 |
|
||||
|
@ -83,6 +83,7 @@
|
||||
"eslint-config-airbnb": "^0.1.0",
|
||||
"eslint-plugin-babel": "^2.1.1",
|
||||
"eslint-plugin-react": "^3.3.1",
|
||||
"expect.js": "~0.3.1",
|
||||
"extract-text-webpack-plugin": "^0.8.1",
|
||||
"gh-pages": "^0.3.1",
|
||||
"jest-cli": "~0.6.1",
|
||||
@ -105,7 +106,7 @@
|
||||
"clean": "rm -rf _site dist",
|
||||
"deploy": "rm -rf node_modules && node scripts/install.js && npm run just-deploy",
|
||||
"just-deploy": "npm run clean && webpack --config webpack.deploy.config.js && NODE_ENV=PRODUCTION nico build && node scripts/deploy.js",
|
||||
"lint": "eslint components index.js --ext '.js,.jsx'",
|
||||
"lint": "eslint components test index.js --ext '.js,.jsx'",
|
||||
"test": "npm run lint && webpack && npm run jest",
|
||||
"jest": "jest",
|
||||
"pub": "sh ./scripts/publish.sh",
|
||||
|
@ -54,7 +54,7 @@
|
||||
}
|
||||
|
||||
// Offset the popover to account for the popover arrow
|
||||
&-placement-top {
|
||||
&-placement-top, &-placement-topLeft, &-placement-topRight {
|
||||
margin-top: -@popover-arrow-width;
|
||||
padding-bottom: @popover-distance;
|
||||
&:after {
|
||||
@ -65,7 +65,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
&-placement-right {
|
||||
&-placement-right, &-placement-rightTop, &-placement-rightBottom {
|
||||
margin-left: @popover-arrow-width;
|
||||
padding-left: @popover-distance;
|
||||
&:after {
|
||||
@ -76,7 +76,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
&-placement-bottom {
|
||||
&-placement-bottom, &-placement-bottomLeft, &-placement-bottomRight {
|
||||
margin-top: @popover-arrow-width;
|
||||
padding-top: @popover-distance;
|
||||
&:after {
|
||||
@ -87,7 +87,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
&-placement-left {
|
||||
&-placement-left, &-placement-leftTop, &-placement-leftBottom {
|
||||
margin-left: -@popover-arrow-width;
|
||||
padding-right: @popover-distance;
|
||||
&:after {
|
||||
@ -165,7 +165,9 @@
|
||||
content: "";
|
||||
}
|
||||
|
||||
&-placement-top > &-arrow {
|
||||
&-placement-top > &-arrow,
|
||||
&-placement-topLeft > &-arrow,
|
||||
&-placement-topRight > &-arrow {
|
||||
left: 50%;
|
||||
margin-left: -@popover-arrow-outer-width;
|
||||
border-bottom-width: 0;
|
||||
@ -179,7 +181,16 @@
|
||||
border-top-color: @popover-arrow-color;
|
||||
}
|
||||
}
|
||||
&-placement-right > &-arrow {
|
||||
&-placement-topLeft > &-arrow {
|
||||
left: 15%;
|
||||
}
|
||||
&-placement-topRight > &-arrow {
|
||||
left: 85%;
|
||||
}
|
||||
|
||||
&-placement-right > &-arrow,
|
||||
&-placement-rightTop > &-arrow,
|
||||
&-placement-rightBottom > &-arrow {
|
||||
top: 50%;
|
||||
left: @popover-distance - @popover-arrow-outer-width + 1;
|
||||
margin-top: -@popover-arrow-outer-width;
|
||||
@ -193,7 +204,16 @@
|
||||
border-right-color: @popover-arrow-color;
|
||||
}
|
||||
}
|
||||
&-placement-bottom > &-arrow {
|
||||
&-placement-rightTop > &-arrow {
|
||||
top: 15%;
|
||||
}
|
||||
&-placement-rightBottom > &-arrow {
|
||||
top: 85%;
|
||||
}
|
||||
|
||||
&-placement-bottom > &-arrow,
|
||||
&-placement-bottomLeft > &-arrow,
|
||||
&-placement-bottomRight > &-arrow {
|
||||
left: 50%;
|
||||
margin-left: -@popover-arrow-outer-width;
|
||||
border-top-width: 0;
|
||||
@ -207,8 +227,16 @@
|
||||
border-bottom-color: @popover-arrow-color;
|
||||
}
|
||||
}
|
||||
&-placement-bottomLeft > &-arrow {
|
||||
left: 15%;
|
||||
}
|
||||
&-placement-bottomRight > &-arrow {
|
||||
left: 85%;
|
||||
}
|
||||
|
||||
&-placement-left > &-arrow {
|
||||
&-placement-left > &-arrow,
|
||||
&-placement-leftTop > &-arrow,
|
||||
&-placement-leftBottom > &-arrow {
|
||||
top: 50%;
|
||||
right: @popover-distance - @popover-arrow-outer-width + 1;
|
||||
margin-top: -@popover-arrow-outer-width;
|
||||
@ -222,4 +250,11 @@
|
||||
bottom: -@popover-arrow-width;
|
||||
}
|
||||
}
|
||||
&-placement-leftTop > &-arrow {
|
||||
top: 15%;
|
||||
}
|
||||
&-placement-leftBottom > &-arrow {
|
||||
top: 85%;
|
||||
}
|
||||
|
||||
}
|
||||
|
29
tests/popover.test.js
Normal file
29
tests/popover.test.js
Normal file
@ -0,0 +1,29 @@
|
||||
import React from 'react';
|
||||
import expect from 'expect.js';
|
||||
import TestUtils from 'react-addons-test-utils';
|
||||
|
||||
jest.dontMock('../components/popover/index');
|
||||
|
||||
const Popover = require('../components/popover/index');
|
||||
|
||||
describe('Popover', function() {
|
||||
it.only('should show overlay when trigger is clicked', () => {
|
||||
const popover = TestUtils.renderIntoDocument(
|
||||
<Popover overlay="console.log('hello world')" title="code" trigger="click">
|
||||
<a href="#">show me your code</a>
|
||||
</Popover>
|
||||
);
|
||||
|
||||
expect(popover.getPopupDomNode()).to.be(undefined);
|
||||
|
||||
TestUtils.Simulate.click(
|
||||
TestUtils.findRenderedDOMComponentWithTag(popover, 'a')
|
||||
);
|
||||
|
||||
const popup = popover.getPopupDomNode();
|
||||
expect(popup).not.to.be(undefined);
|
||||
expect(popup.className).to.contain('ant-popover-placement-top');
|
||||
expect(popup.innerHTML).to.match(/<div class="ant-popover-title".*?>code<\/div>/);
|
||||
expect(popup.innerHTML).to.match(/<div class="ant-popover-content".*?>console\.log\('hello world'\)<\/div>/);
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue
Block a user