Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

timeline 组件 #47

Open
wants to merge 25 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
0a8815f
feat: temp
MuYunyun Apr 2, 2019
7590e72
Merge remote-tracking branch 'remote/master'
MuYunyun Apr 4, 2019
0ac0403
feat: markdown 中可以展示组件
MuYunyun Apr 4, 2019
e8a187c
feat: snake-design 样式添加
MuYunyun Apr 4, 2019
30e942c
Merge remote-tracking branch 'remote/master'
MuYunyun Apr 5, 2019
d710669
fix: fix #14 fix #13
MuYunyun Apr 5, 2019
51c8607
Merge remote-tracking branch 'remote/master'
MuYunyun Apr 13, 2019
725bb11
Merge remote-tracking branch 'remote/master'
MuYunyun Apr 16, 2019
ac387ac
Merge remote-tracking branch 'remote/master'
MuYunyun Apr 20, 2019
9046d4b
Merge remote-tracking branch 'remote/master'
MuYunyun Apr 23, 2019
ea1045e
Merge remote-tracking branch 'remote/master'
MuYunyun Apr 25, 2019
a66fde1
Merge remote-tracking branch 'remote/master'
MuYunyun May 1, 2019
5097cb7
Merge remote-tracking branch 'remote/master'
MuYunyun May 3, 2019
2be1ade
Merge remote-tracking branch 'remote/master'
MuYunyun May 8, 2019
a2d8d37
fix: affix snapshot
MuYunyun May 8, 2019
740e45b
docs: update README
MuYunyun May 9, 2019
3fa4442
Merge remote-tracking branch 'remote/master'
MuYunyun May 10, 2019
31e1c0e
Merge remote-tracking branch 'remote/master'
MuYunyun May 13, 2019
125a2bf
Merge remote-tracking branch 'remote/master'
MuYunyun May 19, 2019
8f1bae8
Merge remote-tracking branch 'remote/master'
MuYunyun May 19, 2019
0242c83
feat: WIP timeline
MuYunyun May 20, 2019
4076654
feat: timeline 时间轴
MuYunyun May 21, 2019
4d2f259
feat: timeline 组件
MuYunyun May 21, 2019
61a2054
feat: timeline 组件加强
MuYunyun May 23, 2019
4a5dbf3
feat: timeline 组件加强
MuYunyun May 23, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
165 changes: 165 additions & 0 deletions components/Timeline/__test__/__snapshots__/index.test.tsx.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`renders correctly 1`] = `
<div>
<ul>
<li
class="snake-timeline-item"
>
<div
class="snake-timeline-item-tail"
/>
<div
class="snake-timeline-item-dot"
>
<div
class="snake-timeline-item-dot-default snake-timeline-item-dot-default-current"
style="background: rgb(44, 165, 241);"
/>
</div>
<div
class="snake-timeline-item-content snake-timeline-item-content-current"
style="color: rgb(44, 165, 241);"
>
<p>
收件人已签收,阿乙
</p>
<p>
2018-08-03 13:34:23
</p>
</div>
</li>
<li
class="snake-timeline-item"
>
<div
class="snake-timeline-item-tail"
/>
<div
class="snake-timeline-item-dot"
>
<div
class="snake-timeline-item-dot-default"
/>
</div>
<div
class="snake-timeline-item-content"
>
<p>
收件人已签收,阿乙
</p>
<p>
2018-08-03 13:34:23
</p>
</div>
</li>
<li
class="snake-timeline-item snake-timeline-item-last"
>
<div
class="snake-timeline-item-tail"
style="height: 0%;"
/>
<div
class="snake-timeline-item-dot"
>
<div
class="snake-timeline-item-dot-default"
/>
</div>
<div
class="snake-timeline-item-content"
>
<p>
收件人已签收,阿乙
</p>
<p>
2018-08-03 13:34:23
</p>
</div>
</li>
</ul>
</div>
`;

exports[`renders correctly 2`] = `
<div>
<ul>
<li
class="snake-timeline-item"
>
<div
class="snake-timeline-item-tail"
/>
<div
class="snake-timeline-item-dot"
>
<div
class="snake-timeline-item-dot-default snake-timeline-item-dot-default-current"
style="background: rgb(17, 153, 238);"
/>
</div>
<div
class="snake-timeline-item-content snake-timeline-item-content-current"
style="color: rgb(17, 153, 238);"
>
<p>
收件人已签收,阿乙
</p>
<p>
2018-08-03 13:34:23
</p>
</div>
</li>
<li
class="snake-timeline-item"
>
<div
class="snake-timeline-item-tail"
/>
<div
class="snake-timeline-item-dot"
>
<div
class="snake-timeline-item-dot-default"
/>
</div>
<div
class="snake-timeline-item-content"
>
<p>
收件人已签收,阿乙
</p>
<p>
2018-08-03 13:34:23
</p>
</div>
</li>
<li
class="snake-timeline-item snake-timeline-item-last"
>
<div
class="snake-timeline-item-tail"
style="height: 0%;"
/>
<div
class="snake-timeline-item-dot"
>
<div
class="snake-timeline-item-dot-default"
/>
</div>
<div
class="snake-timeline-item-content"
>
<p>
收件人已签收,阿乙
</p>
<p>
2018-08-03 13:34:23
</p>
</div>
</li>
</ul>
</div>
`;
55 changes: 55 additions & 0 deletions components/Timeline/__test__/index.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import * as React from 'react'
import { render } from 'react-testing-library'
import Timeline from '../index'

// how to remove any
const TimelineItem = (Timeline as any).Item

it('renders correctly', () => {
const options = [
{
content: (
<>
<p>收件人已签收,阿乙</p>
<p>2018-08-03 13:34:23</p>
</>
)
},
{
content: (
<>
<p>收件人已签收,阿乙</p>
<p>2018-08-03 13:34:23</p>
</>
)
},
{
content: (
<>
<p>收件人已签收,阿乙</p>
<p>2018-08-03 13:34:23</p>
</>
),
lineHeight: 0
}
]
const { container: Timeline1 } = render(<Timeline options={options} highlightColor="#2ca5f1" />)
expect(Timeline1).toMatchSnapshot()
const { container: Timeline2 } = render(
<Timeline>
<TimelineItem>
<p>收件人已签收,阿乙</p>
<p>2018-08-03 13:34:23</p>
</TimelineItem>
<TimelineItem>
<p>收件人已签收,阿乙</p>
<p>2018-08-03 13:34:23</p>
</TimelineItem>
<TimelineItem lineHeight={0}>
<p>收件人已签收,阿乙</p>
<p>2018-08-03 13:34:23</p>
</TimelineItem>
</Timeline>
)
expect(Timeline2).toMatchSnapshot()
})
50 changes: 50 additions & 0 deletions components/Timeline/index.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
@import '../styles/themes/default';

$timeline: 'snake-timeline';

.#{$timeline} {
&-item {
position: relative;
margin: 0;
padding: 0 0 20px;
font-size: 12px;
list-style: none;

&-last {
padding: initial;
}

&-tail {
position: absolute;
top: 0.75em;
left: 4px;
height: 100%;
border-left: 2px solid #e8e8e8;
}

&-dot {
position: absolute;

&-default {
width: 9px;
height: 9px;
border-radius: 100%;
background: #d8d8d8;

&-current {
background: #19e;
}
}
}

&-content {
position: relative;
margin: 0 0 0 18px;
top: -2px;

&-current {
color: #19e;
}
}
}
}
4 changes: 4 additions & 0 deletions components/Timeline/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import Timeline from './timeline'
import TimelineItem from './timelineItem'
;(Timeline as any).Item = TimelineItem
export default Timeline
53 changes: 53 additions & 0 deletions components/Timeline/timeline.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import * as React from 'react'
import cx from 'classnames'
import TimelineItem from './timelineItem'
import { TimelineProps } from 'types/timeline.d'
import './index.scss'

const defaultProps = {
prefixCls: 'snake-timeline',
current: 0,
highlightColor: '#1199EE'
}

// 此处因为使用 React.ref 进行包裹, 所以没办法直接直接将 Timeline.Item = TimelineItem
const Timeline: React.FC<TimelineProps> = (userProps, ref) => {
const props = {
...defaultProps,
...userProps
}

const { prefixCls, current, options, children, highlightColor } = props
function cloneElement(ele: any, index: number) {
const count = (options && options.length) || React.Children.count(children)
return React.cloneElement(ele, {
className: cx(`${prefixCls}-item`, {
[`${prefixCls}-item-last`]: count - 1 === index
}),
ifCurrent: current === index,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isCurrent?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isCurrent 作为 Timeline 组件到 Timeline.Item 组件的一个传参,表示当前时间轴哪个节点高亮。

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

我的意思是:你叫做ifCurrent,是不是isCurrent比较规范?

highlightColor
})
}

function renderTimeline() {
if (options && options.length) {
return options.map((child, index) => {
const { content, lineHeight, dot } = child
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lineHeight为啥单独暴露出来,
如果要支持不同尺寸,应该是大中小的size(fontSize 搭配 lineHeight)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lineHeight 表示线条的高度, 可能命名和 line-height 重名了。不知道有没有其它名字推荐。比如当 lineHeight 为 0 时,相应的时间轴就’消失‘了。

image

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lineHeight感觉不如lineStyle好,可以自定义宽度 高度 颜色啥的

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

主要是歧义比较严重

return cloneElement(
<TimelineItem dot={dot} lineHeight={lineHeight} key={index}>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

key=index不推荐?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

因为这里没有数组首位增删的操作, 所以不会造成 index 作为 key 造成的 bug, 不过还可以用什么作为 key 呢, 除了随机数。

{content}
</TimelineItem>,
index
)
})
}

return React.Children.map(children, (child: React.ReactNode, index: number) => {
return cloneElement(child, index)
})
}

return <ul ref={ref}>{renderTimeline()}</ul>
}

export default React.forwardRef(Timeline)
41 changes: 41 additions & 0 deletions components/Timeline/timelineItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import * as React from 'react'
import cx from 'classnames'
import { TimeLineItemProps } from 'types/timeline.d'
import './index.scss'

const defaultProps = {
prefixCls: 'snake-timeline-item'
}

function TimeLineItem(userProps: TimeLineItemProps) {
const props = {
...defaultProps,
...userProps
}
const { prefixCls, dot, children, ifCurrent, lineHeight, highlightColor, ...restProps } = props
return (
<li {...restProps}>
<div className={cx(`${prefixCls}-tail`)} style={{ height: `${lineHeight}%` }} />
<div className={cx(`${prefixCls}-dot`)}>
{dot ? (
dot
) : (
<div
className={cx(`${prefixCls}-dot-default`, {
[`${prefixCls}-dot-default-current`]: ifCurrent
})}
style={ifCurrent ? { background: highlightColor } : {}}
/>
)}
</div>
<div
className={cx(`${prefixCls}-content`, { [`${prefixCls}-content-current`]: ifCurrent })}
style={ifCurrent ? { color: highlightColor } : {}}
>
{children}
</div>
</li>
)
}

export default TimeLineItem
1 change: 1 addition & 0 deletions components/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ export { default as Dropdown } from './Dropdown/index'
export { default as BackTop } from './BackTop/index'
export { default as Popover } from './Popover/index'
export { default as Tooltip } from './Tooltip/index'
export { default as Timeline } from './Timeline/index'
Loading