From e64f04cee55c484b192a43043bf63a0bc79d8ace Mon Sep 17 00:00:00 2001 From: Benjy Cui Date: Thu, 10 Nov 2016 11:14:03 +0800 Subject: [PATCH] feat: CheckableTag, close: #3560 --- components/tag/CheckableTag.tsx | 33 +++++++++++++++++++++++++ components/tag/demo/checkable.md | 39 ++++++++++++++++++++++++++++++ components/tag/demo/colorful.md | 2 +- components/tag/demo/control.md | 41 ++++++++++++++++---------------- components/tag/index.en-US.md | 9 +++++++ components/tag/index.tsx | 2 ++ components/tag/index.zh-CN.md | 9 +++++++ components/tag/style/index.less | 20 +++++++++++++++- 8 files changed, 133 insertions(+), 22 deletions(-) create mode 100644 components/tag/CheckableTag.tsx create mode 100644 components/tag/demo/checkable.md diff --git a/components/tag/CheckableTag.tsx b/components/tag/CheckableTag.tsx new file mode 100644 index 0000000000..ecf4ab88dd --- /dev/null +++ b/components/tag/CheckableTag.tsx @@ -0,0 +1,33 @@ +import React from 'react'; +import classNames from 'classnames'; +import splitObject from '../_util/splitObject'; + +export interface CheckableTagProps { + prefixCls?: string; + className?: string; + checked: boolean; + onChange?: (checked) => void; +} + +export default class CheckableTag extends React.Component { + handleClick = () => { + const { checked, onChange } = this.props; + if (onChange) { + onChange(!checked); + } + } + render() { + const [{ prefixCls = 'ant-tag', className = '', checked }, restProps ] = splitObject( + this.props, ['prefixCls', 'className', 'checked'] + ); + const cls = classNames({ + [`${prefixCls}`]: true, + [`${prefixCls}-checkable`]: true, + [`${prefixCls}-checkable-checked`]: checked, + [className]: className, + }); + + delete restProps.onChange; + return
; + } +} diff --git a/components/tag/demo/checkable.md b/components/tag/demo/checkable.md new file mode 100644 index 0000000000..cf0c07365c --- /dev/null +++ b/components/tag/demo/checkable.md @@ -0,0 +1,39 @@ +--- +order: 3 +title: + zh-CN: 可选择 + en-US: Checkable +--- + +## zh-CN + +可通过 Tag.CheckableTag 实现类似 Checkbox 的效果,该组件为完全受控组件,不支持非受控用法。 + +## en-US + +Tag.CheckableTag works like Checkbox, and it is an absolute controlled component and has no uncontrolled mode. + +````jsx +import { Tag } from 'antd'; +const CheckableTag = Tag.CheckableTag; + +class ControlledCheckableTag extends React.Component { + state = { checked: false }; + handleChange = (checked) => { + this.setState({ checked }); + } + + render() { + return ; + } +} + +ReactDOM.render( +
+ Unchecked + Checked + Controlled +
, + mountNode +); +```` diff --git a/components/tag/demo/colorful.md b/components/tag/demo/colorful.md index a7fb357db8..f9155eb1aa 100644 --- a/components/tag/demo/colorful.md +++ b/components/tag/demo/colorful.md @@ -1,7 +1,7 @@ --- order: 1 title: - zh-ch: 多彩标签 + zh-CN: 多彩标签 en-US: Colorful --- diff --git a/components/tag/demo/control.md b/components/tag/demo/control.md index 65fb320238..2bdd5497f7 100644 --- a/components/tag/demo/control.md +++ b/components/tag/demo/control.md @@ -1,5 +1,5 @@ --- -order: 3 +order: 2 title: zh-CN: 动态添加和删除 en-US: Add & Remove Dynamically @@ -18,27 +18,28 @@ It's based on `afterClose` event, which will be triggered while the close animat import { Tag, Button } from 'antd'; let index = 3; -const App = React.createClass({ - getInitialState() { - return { - tags: [ - { key: 1, name: 'Unremovable' }, - { key: 2, name: 'Tag 2' }, - { key: 3, name: 'Tag 3' }, - ], - }; - }, - handleClose(key) { +class EditableTagGroup extends React.Component { + state = { + tags: [ + { key: 1, name: 'Unremovable' }, + { key: 2, name: 'Tag 2' }, + { key: 3, name: 'Tag 3' }, + ], + }; + + handleClose = (key) => { const tags = [...this.state.tags].filter(tag => (tag.key !== key) && tag); console.log(tags); this.setState({ tags }); - }, - addTag() { - const tags = [...this.state.tags]; + } + + addTag = () => { index += 1; - tags.push({ key: index, name: `New tag ${index}` }); + const tags = [...this.state.tags, { key: index, name: `New tag ${index}` }]; + console.log(tags); this.setState({ tags }); - }, + } + render() { const { tags } = this.state; return ( @@ -51,8 +52,8 @@ const App = React.createClass({
); - }, -}); + } +} -ReactDOM.render(, mountNode); +ReactDOM.render(, mountNode); ```` diff --git a/components/tag/index.en-US.md b/components/tag/index.en-US.md index f6f828d7a9..decd0e910a 100644 --- a/components/tag/index.en-US.md +++ b/components/tag/index.en-US.md @@ -14,9 +14,18 @@ Tag for categorizing or markuping. ## API +### Tag + | Property | Description | Type | Default | |--------------|-----------------------|----------|--------------| | color | The background color of Tag | string | - | | closable | Tag can be closed. | boolean | false | | onClose | Callback when tag was closed | (e) => void| - | | afterClose | Callback when closed animation is complete | () => void | - | + +### Tag.CheckableTag + +| Property | Description | Type | Default | +|--------------|-----------------------|----------|--------------| +| checked | To set the checked status for Tag | boolean | false | +| onChange | A callback which will be called while Tag is clicked | (checked) => void | - | diff --git a/components/tag/index.tsx b/components/tag/index.tsx index 34a9cbba61..5371b717be 100644 --- a/components/tag/index.tsx +++ b/components/tag/index.tsx @@ -7,6 +7,7 @@ import assign from 'object-assign'; import Icon from '../icon'; import warning from '../_util/warning'; import splitObject from '../_util/splitObject'; +import CheckableTag from './CheckableTag'; export interface TagProps { color?: string; @@ -20,6 +21,7 @@ export interface TagProps { } export default class Tag extends React.Component { + static CheckableTag = CheckableTag; static defaultProps = { prefixCls: 'ant-tag', closable: false, diff --git a/components/tag/index.zh-CN.md b/components/tag/index.zh-CN.md index f487afc8e3..c311a7029d 100644 --- a/components/tag/index.zh-CN.md +++ b/components/tag/index.zh-CN.md @@ -14,9 +14,18 @@ title: Tag ## API +### Tag + | 参数 | 说明 | 类型 | 默认值 | |----------------|-------------------------------|------|--------| | color | 标签背景色 | string | - | | closable | 标签是否可以关闭 | boolean | false | | onClose | 关闭时的回调 | (e) => void | - | | afterClose | 关闭动画完成后的回调 | () => void | - | + +### Tag.CheckableTag + +| 参数 | 说明 | 类型 | 默认值 | +|----------------|-------------------------------|------|--------| +| checked | 设置标签的选中状态 | boolean | false | +| onChange | 点击标签时触发的回调 | (checked) => void | - | diff --git a/components/tag/style/index.less b/components/tag/style/index.less index 34af62f00a..0014a4a21d 100644 --- a/components/tag/style/index.less +++ b/components/tag/style/index.less @@ -16,7 +16,7 @@ vertical-align: middle; opacity: 1; overflow: hidden; - margin: 2px 4px 2px 0; + margin: 4px 8px 4px 0; cursor: pointer; &:hover { @@ -78,6 +78,24 @@ background: @error-color; } + &-checkable { + background-color: transparent; + border-color: transparent; + + &:hover, + &:active, + &-checked { + color: #fff; + } + &:hover { + background-color: tint(@primary-color, 20%); + } + &:active, + &-checked { + background-color: shade(@primary-color, 5%); + } + } + &-close { width: 0 !important; padding: 0;