From d8fd66992fdfe53745fb43d9e27bffd025b8fdb0 Mon Sep 17 00:00:00 2001 From: pingan1927 Date: Wed, 22 Mar 2017 23:59:30 +0800 Subject: [PATCH] add material-design for list.item --- components/list/ListItem.web.tsx | 67 +++++++++++++++++++++++++++++++- components/list/PropsType.tsx | 1 + components/list/demo/basic.md | 15 ++++++- components/list/index.en-US.md | 1 + components/list/index.zh-CN.md | 1 + components/list/style/index.less | 20 ++++++++++ 6 files changed, 102 insertions(+), 3 deletions(-) diff --git a/components/list/ListItem.web.tsx b/components/list/ListItem.web.tsx index 8fc70ed4dd..dc23ad768d 100644 --- a/components/list/ListItem.web.tsx +++ b/components/list/ListItem.web.tsx @@ -19,16 +19,70 @@ class ListItem extends React.Component { error: false, multipleLine: false, wrap: false, + material: false, }; static Brief = Brief; + debounceTimeout: any; + + constructor(props) { + super(props); + this.state = { + coverRipleStyle: {}, + RipleClicked: false, + }; + } + + componentWillUnmount() { + if (this.debounceTimeout) { + clearTimeout(this.debounceTimeout); + this.debounceTimeout = null; + } + } + + onClick = (ev) => { + const { onClick, material } = this.props; + if (!!navigator.userAgent.match(/Android/i) && !!onClick && material) { + if (this.debounceTimeout) { + clearTimeout(this.debounceTimeout); + this.debounceTimeout = null; + } + let Item = ev.currentTarget; + let RipleWidth = Math.max(Item.offsetHeight, Item.offsetWidth); + const ClientRect = ev.currentTarget.getBoundingClientRect(); + let pointX = ev.clientX - ClientRect.left - Item.offsetWidth / 2; + let pointY = ev.clientY - ClientRect.top - Item.offsetWidth / 2; + const coverRipleStyle = { + width: `${RipleWidth}px`, + height: `${RipleWidth}px`, + left: `${pointX}px`, + top: `${pointY}px`, + }; + this.setState({ + coverRipleStyle, + RipleClicked: true, + }, () => { + this.debounceTimeout = setTimeout(() => { + this.setState({ + coverRipleStyle: {}, + RipleClicked: false, + }); + }, 1000); + }); + } + + if (onClick) { + onClick(ev); + } + } render() { const { prefixCls, className, activeStyle, error, align, wrap, disabled, - children, multipleLine, thumb, extra, arrow, ...restProps} = this.props; + children, multipleLine, thumb, extra, arrow, onClick, ...restProps} = this.props; + const { coverRipleStyle, RipleClicked } = this.state; const wrapCls = { [className as string]: className, [`${prefixCls}-item`]: true, @@ -39,6 +93,11 @@ class ListItem extends React.Component { [`${prefixCls}-item-bottom`]: align === 'bottom', }; + const ripleCls = classNames({ + [`${prefixCls}-riple`]: true, + [`${prefixCls}-riple-animate`]: RipleClicked, + }); + const lineCls = classNames({ [`${prefixCls}-line`]: true, [`${prefixCls}-line-multiple`]: multipleLine, @@ -54,6 +113,9 @@ class ListItem extends React.Component { const content =
{ + this.onClick(ev); + }} className={classNames(wrapCls)} > {thumb ?
@@ -64,11 +126,12 @@ class ListItem extends React.Component { {extra !== undefined &&
{extra}
} {arrow &&
}
+
; return ( diff --git a/components/list/PropsType.tsx b/components/list/PropsType.tsx index e1d4ce5fe2..c66b10daee 100644 --- a/components/list/PropsType.tsx +++ b/components/list/PropsType.tsx @@ -36,6 +36,7 @@ export interface ListItemProps { styles?: any; onPressIn?: (e?: any) => void; onPressOut?: (e?: any) => void; + material?: boolean; } export interface BriefProps { diff --git a/components/list/demo/basic.md b/components/list/demo/basic.md index 1932a6f399..e1c67e793f 100644 --- a/components/list/demo/basic.md +++ b/components/list/demo/basic.md @@ -25,7 +25,20 @@ class ListExample extends React.Component { 标题文字 副标题 - + {}} + material + > + 开启material点击效果仅Android有效且设置了Click事件 + + {}} + > 标题文字 副标题 diff --git a/components/list/index.en-US.md b/components/list/index.en-US.md index 9b6f89324d..d75779ca5f 100644 --- a/components/list/index.en-US.md +++ b/components/list/index.en-US.md @@ -36,6 +36,7 @@ Properties | Descrition | Type | Default | multipleLine | 多行 | Boolean | `false` | | wrap | 是否换行,默认情况下,文字超长会被隐藏, | Boolean | `false` | | activeStyle(`web only`) | 自定义active的样式 | Object | | +| material(`web only`) | 开启material design点击效果(水波) | Boolean | `false` | ### List.Item.Brief diff --git a/components/list/index.zh-CN.md b/components/list/index.zh-CN.md index 9dce7f765c..4ea8ab4b37 100644 --- a/components/list/index.zh-CN.md +++ b/components/list/index.zh-CN.md @@ -37,6 +37,7 @@ subtitle: 列表 | multipleLine | 多行 | Boolean | `false` | | wrap | 是否换行,默认情况下,文字超长会被隐藏, | Boolean | `false` | | activeStyle(`web only`) | 自定义active的样式 | Object | | +| material(`web only`) | 开启material design点击效果(水波) | Boolean | false | ### List.Item.Brief diff --git a/components/list/style/index.less b/components/list/style/index.less index 29250a6924..f2ce3b7230 100644 --- a/components/list/style/index.less +++ b/components/list/style/index.less @@ -48,6 +48,22 @@ overflow: hidden; .box-align; transition: background-color 200ms; + .@{listPrefixCls}-riple { + position: absolute; + background: transparent; + display: inline-block; + overflow: hidden; + will-change: box-shadow,transform; + transition: box-shadow .2s cubic-bezier(.4,0,1,1), background-color .2s cubic-bezier(.4,0,.2,1), color .2s cubic-bezier(.4,0,.2,1); + outline: none; + cursor: pointer; + border-radius: 100%; + transform: scale(0); + &.@{listPrefixCls}-riple-animate { + background-color: hsla(0, 0%, 62%, .2); + animation: ripple 1s linear; + } + } &.@{listPrefixCls}-item-top { .@{listPrefixCls}-line { .box-align(flex-start); @@ -198,3 +214,7 @@ background-color: transparent; } } + +@keyframes ripple { + 100% {opacity: 0; transform: scale(2.5);} +}