CP Design
使用 React hooks Typescript 開發的一個 H5 移動端 組件庫


其中包括了下圖中的27個基礎組件:

CP Design Mobile

(github地址:https://github.com/10086XIAOZHANG/CP-DESIGN)
特性
- 基於 CP Design 移動設計規范。
- 規則化的視覺樣式配置,適應各類產品風格。
- 使用 TypeScript React hooks 開發,提供類型定義文件。
🖥 環境支持
| IE11, Edge | last 2 versions | last 2 versions | last 2 versions | last 2 versions |
📦 安裝
npm install cp-design --save
yarn add cp-design
✨ 注意
在組件庫中使用了 SASS,在安裝的時候記得安裝 node-sass
npm install node-sass --save-dev
yarn add node-sass -D
🔨 使用
import { Button } from 'cp-design'
const App = () => (
<>
<Button type="primary">PRESS ME</Button>
</>
)
組件
- [x] Icon,
- [x] Button,
- [x] Input,
- [x] Row,
- [x] Col,
- [x] Affix,
- [x] Avatar,
- [x] Badge,
- [x] Card,
- [x] CheckboxGroup,
- [x] Checkbox,
- [x] Accordion,
- [x] Divider,
- [x] Modal,
- [x] Overlay,
- [x] Pagination,
- [x] Progress,
- [x] Radio,
- [x] Slider,
- [x] Step,
- [x] Spin,
- [x] Switch,
- [x] Tabs,
- [x] Tag,
- [x] ImagePicker,
- [x] Toast,
- [x] ActionSheet,
- [x] TabBar,
- [x] PickerPanel,
- [x] Picker,
- [x] SegmentedControl,
- [x] Popover,
- [x] NoticeBar,
- [x] SwipeAction
- [x] ListView
部分組件使用
Button 按鈕
按鈕的展示
引入組件
import * as React from 'react'
import { Button, Row, Col } from 'cp-design'
Demo 代碼
export default function ButtonDemo() {
const onClick = () => {}
return (
<div>
<Row style={{ marginBottom: '1rem' }}>
<Col span={24}>
<Button onClick={onClick}>default</Button>
</Col>
</Row>
<Row style={{ marginBottom: '1rem' }}>
<Col span={24}>
<Button disabled>default disabled</Button>
</Col>
</Row>
<Row style={{ marginBottom: '1rem' }}>
<Col span={24}>
<Button type="primary" onClick={onClick}>
primary
</Button>
</Col>
</Row>
<Row style={{ marginBottom: '1rem' }}>
<Col span={24}>
<Button type="primary" onClick={onClick} disabled>
primary disabled
</Button>
</Col>
</Row>
<Row style={{ marginBottom: '1rem' }}>
<Col span={24}>
<Button onClick={onClick} type="warning">
warning
</Button>
</Col>
</Row>
<Row style={{ marginBottom: '1rem' }}>
<Col span={24}>
<Button onClick={onClick} type="warning" disabled>
warning disabled
</Button>
</Col>
</Row>
<Row style={{ marginBottom: '1rem' }}>
<Col span={24}>
<Button onClick={onClick} loading>
loading button
</Button>
</Col>
</Row>
<Row style={{ marginBottom: '1rem' }}>
<Col span={24}>
<Button>with icon</Button>
</Col>
</Row>
</div>
)
}
Badge 徽標數
徽標數的展示
引入組件
import * as React from 'react'
import { Badge, Row, Col } from 'cp-design'
Demo 代碼
export default function BadgeDemo() {
return (
<div>
<Row style={{ marginBottom: '1rem' }}>
<Col span={24}>
<Badge dot status="default">
<span
style={{ width: '26px', height: '26px', background: '#ddd', display: 'inline-block' }}
/>
</Badge>
<span
style={{
marginLeft: 12,
height: '26px',
lineHeight: '26px',
display: 'inline-block',
verticalAlign: 'top'
}}
>
Dot badge
</span>
</Col>
</Row>
<Row style={{ marginBottom: '1rem' }}>
<Col span={24}>
<Badge dot status="success">
<span
style={{ width: '26px', height: '26px', background: '#ddd', display: 'inline-block' }}
/>
</Badge>
<span
style={{
marginLeft: 12,
height: '26px',
lineHeight: '26px',
display: 'inline-block',
verticalAlign: 'top'
}}
>
Dot badge Success
</span>
</Col>
</Row>
<Row style={{ marginBottom: '1rem' }}>
<Col span={24}>
<Badge text={'券1'} overflowCount={121}></Badge>
<Badge
text={'NEW'}
overflowCount={121}
style={{
marginLeft: 12,
padding: '0 3px',
backgroundColor: '#21b68a',
borderRadius: 2
}}
></Badge>
<Badge
text="自動繳費"
style={{
marginLeft: 12,
padding: '0 3px',
backgroundColor: '#fff',
borderRadius: 2,
color: '#f19736',
border: '1px solid #f19736'
}}
/>
</Col>
</Row>
<Row style={{ marginBottom: '1rem' }}>
<Col
span={24}
style={{
border: '1px solid #999',
height: 42,
overflow: 'hidden'
}}
>
<Badge corner text={'促'} outStyle={{ height: 42, lineHeight: '42px' }}>
<span
style={{
marginLeft: 12,
display: 'inline-block'
}}
>
Dot badge Success
</span>
</Badge>
</Col>
</Row>
</div>
)
}
| 屬性 | 說明 | 類型 | 默認值 | 可選 |
|---|---|---|---|---|
| text | 展示的數字或文案,當為數字時候,大於 overflowCount 時顯示為 ${overflowCount}+,為 0 時隱藏 | string | -- | -- |
| corner | 置於角落 | boolean | -- | -- |
| disabled | 設置禁用 | boolean | -- | -- |
| dot | 不展示數字,只有一個小紅點 | string/React.Element | -- | -- |
| overflowCount | 展示封頂的數字值 | number | -- | -- |
| status | status 狀態點 這個值對 dot 生效 | 'success', 'default' , 'process' , 'warning' , 'error' | -- | -- |
| style | 自定義樣式(樣式) | Object | -- | -- |
| outStyle | 外圍自定義樣式(樣式) | Object | -- | -- |
| hot | 營銷樣式 | boolean | -- | -- |
Api
| 屬性 | 說明 | 類型 | 默認值 | 可選 |
|---|---|---|---|---|
| type | 按鈕類型,可選值為 primary/ghost/warning 或者不設 | string | -- | -- |
| size | 按鈕大小,可選值為 large、small | string | large | -- |
| disabled | 設置禁用 | boolean | -- | -- |
| icon | 可以是 Icon 組件里內置的某個 icon 的 type 值,也可以是任意合法的 ReactElement (注意: loading 設置后此項設置失效) | string/React.Element | -- | -- |
| prefixCls | class 前綴 默認 cp-ui-btn | string | -- | -- |
| className | 樣式類名 | fun():void | -- | -- |
| onClick | 點擊按鈕的點擊回調函數 | fun() : void | -- | -- |
| style | 自定義樣式 | Object | -- | -- |
| loading | 是否出現正在加載 | boolean | -- | -- |
Icon 圖標
圖標的展示
引入組件
import * as React from 'react'
import { Icon, Row, Col } from 'cp-design'
Demo 代碼
export default function IconDemo() {
const list = [
'check-circle',
'check',
'caret-up',
'delete',
'eye-close',
'eye',
'up',
'down',
'left',
'right',
'message-fill',
'link'
]
const data = list.map(item => ({
icon: <Icon type={item} />,
text: item
}))
return (
<div>
<h3>基本</h3>
{data.map((item, index) => {
if (index !== 0 && (index + 1) % 3 === 0) {
return (
<Row style={{ marginBottom: '1rem', textAlign: 'center' }} key={index}>
<Col span={8}>
{data[index - 2].icon}
<p>{data[index - 2].text}</p>
</Col>
<Col span={8}>
{data[index - 1].icon}
<p>{data[index - 1].text}</p>
</Col>
<Col span={8}>
{item.icon}
<p>{data[index].text}</p>
</Col>
</Row>
)
}
return null
})}
<h3>大小</h3>
<Row style={{ marginBottom: '1rem', textAlign: 'center' }}>
<Col span={8}>
<Icon type={'camera-retro'} size={8} />
</Col>
<Col span={8}>
<Icon type={'camera-retro'} size={16} />
</Col>
<Col span={8}>
<Icon type={'camera-retro'} size={24} />
</Col>
<Col span={8}>
<Icon type={'camera-retro'} size={32} />
</Col>
</Row>
<h3>顏色</h3>
<Row style={{ marginBottom: '1rem', textAlign: 'center' }}>
<Col span={8}>
<Icon type={'camera-retro'} color="rgb(44, 167, 241)" />
</Col>
<Col span={8}>
<Icon type={'camera-retro'} color="rgb(234, 32, 152)" />
</Col>
<Col span={8}>
<Icon type={'camera-retro'} color="rgb(21, 239, 218)" />
</Col>
<Col span={8}>
<Icon type={'camera-retro'} color="rgb(95, 25, 220)" />
</Col>
</Row>
</div>
)
}
Api
| 屬性 | 說明 | 類型 | 默認值 | 可選 |
|---|---|---|---|---|
| type | 內置 icon 名稱 | string | -- | -- |
| size | 圖標大小 | string,number | -- | -- |
| color | 圖標顏色 | Color | '#000' | -- |
| rotate | 是否旋轉 | boolean | -- | -- |
| rotateDegree | 和 rotate 一起配置生效 | 0 ,90 ,180, 270 , 360 | -- | -- |
| flip | 是否翻轉 | boolean | -- | -- |
| flipOrder | 和 flip 一起配置生效 | 'horizontal' , 'vertical' | -- | -- |
Modal 彈窗
彈窗的展示
引入組件
import * as React from 'react'
import { Modal, Button, Row, Col } from 'cp-design'
Demo 代碼
const { useState } = React
export default function ModalDemo() {
const [modal1, setModal1] = useState(false)
const [modal2, setModal2] = useState(false)
const showModal1 = (e: React.MouseEvent) => {
e.preventDefault()
setModal1(true)
}
const showModal2 = (e: React.MouseEvent) => {
e.preventDefault()
setModal2(true)
}
return (
<div>
<Modal
visible={modal1}
title="Title1"
closable={false}
cancelText={null}
onOk={() => {
setModal1(false)
}}
>
<div style={{ height: 100, overflowY: 'scroll' }}>
scoll content...
<br />
scoll content...
<br />
scoll content...
<br />
scoll content...
<br />
scoll content...
<br />
scoll content...
<br />
</div>
</Modal>
<Modal
visible={modal2}
title="Title2"
closable={false}
onCancel={() => {
setModal2(false)
}}
onOk={() => {
alert('afterOK')
setModal2(false)
}}
>
<div style={{ height: 100, overflowY: 'scroll' }}>
scoll content...
<br />
scoll content...
<br />
scoll content...
<br />
scoll content...
<br />
scoll content...
<br />
scoll content...
<br />
</div>
</Modal>
<h1>Modal 對話框</h1>
<h3>基本</h3>
<Row style={{ marginBottom: '1rem' }}>
<Col span={24}>
<Button onClick={showModal1}>basic</Button>
</Col>
</Row>
<Row style={{ marginBottom: '1rem' }}>
<Col span={24}>
<Button onClick={showModal2}>confirm</Button>
</Col>
</Row>
</div>
)
}
Api
| 屬性 | 說明 | 類型 | 默認值 | 可選 |
|---|---|---|---|---|
| cancelText | 取消按鈕自定義 | React.ReactNode,string | -- | -- |
| okText | 確定按鈕自定義 | React.ReactNode,string | large | -- |
| visible | 是否可見 | boolean | -- | -- |
| title | Modal 彈窗標題 | string/React.Element | -- | -- |
| children | Modal 自定義內容區域 | string/React.Element | -- | -- |
| prefixCls | class 前綴 默認 cp-ui-modal | string | -- | -- |
| className | 樣式類名 | fun():void | -- | -- |
| maskClassName | 彈出層樣式類名 | fun():void | -- | -- |
| onOk | 點擊確定回調函數 | fun() : void | -- | -- |
| onCancel | 點擊取消回調函數 | fun() : void | -- | -- |
| style | 自定義樣式 | Object | -- | -- |
| maskClosable | 點擊浮層是否允許關閉 | boolean | true | -- |
| closable | 是否顯示右上角關閉圖標 | boolean | true | -- |
| closeIcon | 自定義右上角關閉圖標 | React.ReactNode | -- | -- |
| destroy | 是否銷毀(關閉后自動銷毀) | boolean | true | -- |
| maskAnimationName | 彈出層動畫類名 | string | fade | -- |
說明
icon 圖標遵循fontawesome規則
Input 輸入框
輸入框的展示
引入組件
import * as React from 'react'
import { useForm, Controller } from 'react-hook-form'
import { Input, Button, Icon, Row, Col } from 'cp-design'
Demo 代碼
const { useRef } = React
export default function ButtonDemo() {
const inputRef = (useRef < HTMLInputElement) | (null > null)
const { handleSubmit, control, errors } = useForm() // initialise the hook
const onSubmit = (data: any) => {
console.log(data)
}
const getInputRef = (ele: HTMLInputElement) => {
inputRef.current = ele
}
const handleFocus = (e: React.MouseEvent) => {
e.preventDefault()
if (!!inputRef.current) inputRef.current.focus()
}
const btnStyle = {
background: 'linear-gradient(316deg, #f75cff 0%, rgb(236, 9, 51) 100%)',
opacity: 0.5,
display: 'block',
margin: '0 auto',
height: '2.8rem',
borderRadius: '0.6rem',
textAlign: 'center',
lineHeight: '2.8rem',
fontSize: '0.88rem',
color: '#fff'
}
return (
<div>
<h1>Input 輸入框</h1>
<h3>基本</h3>
<form onSubmit={handleSubmit(onSubmit)}>
<div style={{ color: '#777575', marginBottom: '0.01rem' }}>標題</div>
<Row style={{ marginBottom: '1rem' }}>
<Col span={24}>
<Controller
as={
<Input
clear
placeholder="auto focus"
style={{ height: '2.5rem' }}
error={errors.title0 && <span style={{ color: 'red' }}>This is required.</span>}
/>
}
name="title0"
control={control}
rules={{ required: true }}
/>
</Col>
</Row>
<div style={{ color: '#777575', marginBottom: '0.01rem' }}>標題</div>
<Row style={{ marginBottom: '1rem' }}>
<Col span={24}>
<Controller
as={
<Input
clear
addonBefore={
<div
style={{
width: '100%',
color: 'rgb(16, 142, 233)',
textAlign: 'center',
float: 'right',
height: '2.33rem'
}}
onClick={handleFocus}
>
click to focus
</div>
}
getInputRef={getInputRef}
placeholder="auto focus"
style={{ height: '2.5rem' }}
error={
errors.title1 && (
<span style={{ color: 'red', paddingLeft: '8rem' }}>This is required.</span>
)
}
/>
}
name="title1"
control={control}
rules={{ required: true }}
/>
</Col>
</Row>
<div style={{ color: '#777575', marginBottom: '0.01rem' }}>自定義前綴</div>
<Row style={{ marginBottom: '1rem' }}>
<Col span={24}>
<Controller
as={
<Input
clear
prefix={<Icon type={'user'} style={{ lineHeight: '2.5rem' }} />}
placeholder="auto focus"
style={{ height: '2.5rem' }}
error={
errors.title2 && (
<span style={{ color: 'red', paddingLeft: '1rem' }}>This is required.</span>
)
}
/>
}
name="title2"
control={control}
rules={{ required: true }}
/>
</Col>
</Row>
<div style={{ color: '#777575', marginBottom: '0.01rem' }}>自定義內部前綴</div>
<Row style={{ marginBottom: '1rem' }}>
<Col span={24}>
<Controller
as={
<Input
clear
inlinePrefix={<Icon type={'user'} style={{ lineHeight: '2.5rem' }} />}
placeholder="auto focus"
style={{ height: '2.5rem' }}
error={
errors.title3 && (
<span style={{ color: 'red', paddingLeft: '1.4rem' }}>This is required.</span>
)
}
/>
}
name="title3"
control={control}
rules={{ required: true }}
/>
</Col>
</Row>
<div style={{ color: '#777575', marginBottom: '0.01rem' }}>價格</div>
<Row style={{ marginBottom: '1rem' }}>
<Col span={24}>
<Controller
as={
<Input
inlineSuffix={<Icon type={'cny'} style={{ lineHeight: '2.5rem' }} />}
placeholder="0.00"
style={{ height: '2.5rem' }}
error={
errors.title4 && (
<span style={{ color: 'red', paddingLeft: '1.4rem' }}>This is required.</span>
)
}
/>
}
name="title4"
control={control}
rules={{ required: true }}
/>
</Col>
</Row>
<h3>Format</h3>
<div style={{ color: '#777575', marginBottom: '0.01rem' }}>銀行卡</div>
<Row style={{ marginBottom: '1rem' }}>
<Col span={24}>
<Controller
as={
<Input
clear
type="bankCard"
placeholder="請輸入銀行卡"
style={{ height: '2.5rem' }}
error={errors.bankCard && <span style={{ color: 'red' }}>This is required.</span>}
/>
}
name="bankCard"
control={control}
rules={{ required: true }}
/>
</Col>
</Row>
<div style={{ color: '#777575', marginBottom: '0.01rem' }}>手機號碼</div>
<Row style={{ marginBottom: '1rem' }}>
<Col span={24}>
<Controller
as={
<Input
clear
type="mobile"
placeholder="請輸入手機號碼"
style={{ height: '2.5rem' }}
error={errors.mobile && <span style={{ color: 'red' }}>This is required.</span>}
/>
}
name="mobile"
control={control}
rules={{ required: true }}
/>
</Col>
</Row>
<div style={{ color: '#777575', marginBottom: '0.01rem' }}>密碼</div>
<Row style={{ marginBottom: '1rem' }}>
<Col span={24}>
<Controller
as={
<Input
clear
type="password"
placeholder="請輸入密碼"
style={{ height: '2.5rem' }}
error={errors.password && <span style={{ color: 'red' }}>This is required.</span>}
/>
}
name="password"
control={control}
rules={{ required: true }}
/>
</Col>
</Row>
<div style={{ color: '#777575', marginBottom: '0.01rem' }}>數字鍵盤</div>
<Row style={{ marginBottom: '1rem' }}>
<Col span={24}>
<Controller
as={
<Input
clear
type="number"
placeholder="數字鍵盤"
style={{ height: '2.5rem' }}
error={errors.number && <span style={{ color: 'red' }}>This is required.</span>}
/>
}
name="number"
control={control}
rules={{ required: true }}
/>
</Col>
</Row>
<h3>禁用</h3>
<Row style={{ marginBottom: '1rem' }}>
<Col span={24}>
<Controller
as={<Input clear disabled placeholder="不能輸入" style={{ height: '2.5rem' }} />}
name="number"
control={control}
rules={{ required: true }}
/>
</Col>
</Row>
<Row justify={'center'}>
<Col span={18}>
<Button htmlType="submit" onClick={handleSubmit(onSubmit)} style={btnStyle}>
Submit
</Button>
</Col>
</Row>
</form>
</div>
)
}
Api
| 屬性 | 說明 | 類型 | 默認值 | 可選 |
|---|---|---|---|---|
| type | 可以是銀行卡 bankCard; 手機號 phone(此時最大長度固定為 11,maxLength 設置無效); 密碼 password;類型:InputType | string | "text" | -- |
| addonBefore | 前置點擊 | React.ReactNode | -- | -- |
| addonAfter | 后置點擊 | React.ReactNode | -- | -- |
| error | 錯誤提示 | string/React.Element | -- | -- |
| clear | 是否顯示清除 | boolean | false | -- |
| className | 樣式類名 | fun():void | -- | -- |
| getInputRef | 獲取元素組件的 ref | (ele: HTMLInputElement) => void | -- | -- |
| style | 自定義樣式 | Object | -- | -- |
| disabled | 是否禁用 | boolean | -- | -- |
| inlinePrefix | 內嵌 input 前綴 | React.ReactNode | -- | -- |
| inlineSuffix | 內嵌 input 前綴 | React.ReactNode | -- | -- |
| prefix | input 外前綴 | React.ReactNode | -- | -- |
| suffix | input 外后綴 | React.ReactNode | -- | -- |
| prefix | input 外前綴 | string | -- | -- |
| value | value 值(受控與否參考 react-hook-form) | string | -- | -- |
| defaultValue | 默認 value 值(受控與否參考 react-hook-form) | string | -- | -- |
InputType
('text' ,'number' , 'mobile' ,'bankCard' , 'password')
案例
mobile web demo

https://10086xiaozhang.github.io/CP-DESIGN
安裝與使用
瀏覽器支持
iOSAndroid 4.0+
鏈接
歡迎貢獻
有任何建議或意見您可以進行 提問。
作者🎮Email
fcj_zhang@163.com
