From 97316a4bfd19a3ddc1f62d9e5336d69ed1795a61 Mon Sep 17 00:00:00 2001 From: ImJustAMan Date: Wed, 19 May 2021 19:19:07 +0800 Subject: [PATCH] feat(List): finish List component --- src/List/ListItem.tsx | 71 ++++++++++++++++++++++++++++++++++++++++ src/List/PropsType.ts | 75 +++++++++++++++++++++++++++++++++++++++++++ src/List/index.md | 64 ++++++++++++++++++++++++++++++++++++ src/List/index.scss | 64 ++++++++++++++++++++++++++++++++++++ src/List/index.tsx | 36 +++++++++++++++++++++ src/index.ts | 1 + 6 files changed, 311 insertions(+) create mode 100644 src/List/ListItem.tsx create mode 100644 src/List/PropsType.ts create mode 100644 src/List/index.md create mode 100644 src/List/index.scss create mode 100644 src/List/index.tsx diff --git a/src/List/ListItem.tsx b/src/List/ListItem.tsx new file mode 100644 index 0000000..ef62fcd --- /dev/null +++ b/src/List/ListItem.tsx @@ -0,0 +1,71 @@ +import React, { useState } from 'react'; +import { IListItemPropsType } from '@/List/PropsType'; +import Icon from '@/Icon'; +import Touchable from '@ant-design/mobile-touchable'; +import classNames from 'classnames'; + +const prefixCls = 'h-list-item'; + +const ListItem: React.FC = props => { + const { arrow, extra, thumb, subtitle, children, onPress } = props; + + const createThumb = (thumb: IListItemPropsType['thumb']) => { + if (!thumb) return null; + if (typeof thumb === 'string') { + return ( +
+ +
+ ); + } else { + return
{thumb}
; + } + }; + + const [active, setActive] = useState(false); + + const innerCls = classNames(prefixCls, { + [`${prefixCls}-active`]: active && arrow !== 'none', + }); + + return ( + { + setActive(true); + }} + onPress={onPress} + onPressOut={() => { + setActive(false); + }} + > +
+
+ {createThumb(thumb)} +
+
{children}
+ {subtitle ? ( +
{subtitle}
+ ) : null} +
+ {extra ?
{extra}
: null} + {arrow !== 'none' ? ( +
+ +
+ ) : null} +
+
+
+ ); +}; + +ListItem.defaultProps = { + subtitle: '', + extra: '', + showAll: false, + arrow: 'none', +}; + +export default ListItem; diff --git a/src/List/PropsType.ts b/src/List/PropsType.ts new file mode 100644 index 0000000..77bd4ce --- /dev/null +++ b/src/List/PropsType.ts @@ -0,0 +1,75 @@ +import { ReactElement, SyntheticEvent } from 'react'; + +type renderType = string | ReactElement; +type listRenderFn = () => renderType; +type listRender = listRenderFn | renderType; +type listItemArrowType = 'up' | 'down' | 'horizontal' | 'none'; + +/** + * List properties + */ +export interface IListPropsType { + /** + * @description 是否设置列表圆角 + * @default false + */ + radius?: boolean; + /** + * @description 列表头部内容 + * @default "" + * @type string | ReactElement | () => void | string | ReactElement + */ + renderHeader?: listRender; + /** + * @description 列表尾部内容 + * @default "" + * @type string | ReactElement | () => void | string | ReactElement + */ + renderFooter?: listRender; +} + +/** + * ListItem properties + */ +export interface IListItemPropsType { + /** + * @description 列表副标题 此属性会在原本列表信息下方以多行的形式展示 + * @default "" + * @type string | React.ReactElement + */ + subtitle?: renderType; + /** + * @description 列表额外内容 + * @default "" + * @type string | React.ReactElement + */ + extra?: renderType; + /** + * @description 列表额外内容是否换行显示全部内容 + * @default false + */ + showAll?: boolean; + /** + * @description 列表尾端箭头方向 设置none时不显示 + * @default "none" + * @type "up" | "down" | "horizontal" | "none" + */ + arrow?: listItemArrowType; + /** + * @description 缩略图 当传入字符串时需要 + * @default "" + * @type string | React.ReactElement + */ + thumb?: renderType; + /** + * @description 列表项点触事件 + * @default null + */ + onPress?: (e: SyntheticEvent) => void; +} + +const List = (props: IListPropsType) => {}; + +const ListItem = (props: IListItemPropsType) => {}; + +export { List, ListItem }; diff --git a/src/List/index.md b/src/List/index.md new file mode 100644 index 0000000..841653b --- /dev/null +++ b/src/List/index.md @@ -0,0 +1,64 @@ +--- +title: List +nav: + title: 组件 + path: /components +--- + +## 基础使用 + +### type + +通过 type 属性切换 Button 组件样式 + +```tsx +import React from 'react'; +import { List } from 'hugSun-UI'; + +const { Item } = List; + +export default () => { + return ( + <> + 'Basic Type'}> + Title + Title + + Title + + + Title + + + + 'Subtitle'}> + + Title + + + Title + + + Title + + + + ); +}; +``` + +## API + + diff --git a/src/List/index.scss b/src/List/index.scss new file mode 100644 index 0000000..8fa6eae --- /dev/null +++ b/src/List/index.scss @@ -0,0 +1,64 @@ +.h-list { + .h-list-header { + padding: 30 * $rpx; + color: #888; + font-size: 32 * $rpx; + } + .h-list-item { + min-height: 88 * $rpx; + padding: 0 30 * $rpx; + background-color: #fff; + transition: background-color .2s; + &.h-list-item-active { + background-color: #ddd; + } + .h-list-item-line { + min-height: 88 * $rpx; + border-bottom: 1px solid #ddd; + padding: 14 * $rpx 0; + display: flex; + align-items: center; + vertical-align: middle; + overflow: hidden; + } + .h-list-item-thumb { + line-height: 0; + img { + width: 44 * $rpx; + height: 44 * $rpx; + vertical-align: middle; + } + & + .h-list-item-wrap { + margin-left: 20 * $rpx; + } + } + .h-list-item-wrap { + font-size: 34 * $rpx; + flex-grow: 1; + .h-list-item-title { + line-height: 1.5; + } + .h-list-item-subtitle { + color: #888; + font-size: 30 * $rpx; + } + } + .h-list-item-extra { + font-size: 32 * $rpx; + width: auto; + color: #888; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + text-align: right; + flex-basis: 36%; + } + .h-list-item-arrow { + color: #ccc; + font-size: 50 * $rpx; + } + } + .h-list-item:nth-last-child(1) .h-list-item-line { + border: none; + } +} diff --git a/src/List/index.tsx b/src/List/index.tsx new file mode 100644 index 0000000..a897fbd --- /dev/null +++ b/src/List/index.tsx @@ -0,0 +1,36 @@ +import React from 'react'; +import { IListPropsType } from './PropsType'; +import ListItem from '@/List/ListItem'; +import './index.scss'; + +const prefixCls = 'h-list'; + +const List: React.FC & { Item: typeof ListItem } = props => { + const { renderHeader, renderFooter } = props; + return ( +
+
+ {renderHeader && ( +
+ {typeof renderHeader === 'function' ? renderHeader() : renderHeader} +
+ )} + {props.children} + {renderFooter && ( +
+ {typeof renderFooter === 'function' ? renderFooter() : renderFooter} +
+ )} +
+
+ ); +}; + +List.Item = ListItem; +List.defaultProps = { + radius: false, + renderHeader: '', + renderFooter: '', +}; + +export default List; diff --git a/src/index.ts b/src/index.ts index 8eb2b9b..92dbacd 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,2 +1,3 @@ export { default as Button } from './Button'; +export { default as List } from './List'; export { default as Icon } from './Icon';