提交 fdf07618 编写于 作者: Y Ymm0008

feat: fixednav 开发

上级 f3a1e83f
......@@ -296,6 +296,16 @@
"sort": 4,
"show": true,
"author": "songsong"
},
{
"version": "1.0.0",
"name": "FixedNav",
"type": "component",
"cName": "悬浮导航",
"desc": "悬浮收齐体验交互,用于快捷导航",
"sort": 5,
"show": true,
"author": "Ymm0008"
}
]
},
......@@ -370,4 +380,4 @@
]
}
]
}
}
\ No newline at end of file
import React, { useState, MouseEvent } from 'react'
import { Icon } from '../icon/icon'
import { FixedNav } from './fixednav'
const FixedNavDemo = () => {
const navList = [
{
id: 1,
text: '首页',
icon: 'https://img11.360buyimg.com/imagetools/jfs/t1/117646/2/11112/1297/5ef83e95E81d77f05/daf8e3b1c81e3c98.png',
},
{
id: 2,
text: '分类',
icon: 'https://img12.360buyimg.com/imagetools/jfs/t1/119490/8/9568/1798/5ef83e95E968c69a6/dd029326f7d5042e.png',
},
{
id: 3,
text: '购物车',
num: 2,
icon: 'https://img14.360buyimg.com/imagetools/jfs/t1/130725/4/3157/1704/5ef83e95Eb976644f/b36c6cfc1cc1a99d.png',
},
{
id: 4,
text: '我的',
icon: 'https://img12.360buyimg.com/imagetools/jfs/t1/147573/29/1603/1721/5ef83e94E1393a678/5ddf1695ec989373.png',
},
]
const [visible1, setVisible1] = useState(false)
const [visible2, setVisible2] = useState(false)
const [visible3, setVisible3] = useState(false)
const [visible4, setVisible4] = useState(false)
const change1 = (value: boolean) => {
setVisible1(value)
}
const selected1 = (item: any, event: MouseEvent) => {
console.log(item, event)
}
const change2 = (value: boolean) => {
setVisible2(value)
}
const selected2 = (item: any, event: MouseEvent) => {
console.log(item, event)
}
const change3 = (value: boolean) => {
setVisible3(value)
}
const selected3 = (item: any, event: MouseEvent) => {
console.log(item, event)
}
const change4 = (value: boolean) => {
setVisible4(value)
}
const selected4 = (item: any, event: MouseEvent) => {
console.log(item, event)
}
return (
<>
<div className="demo">
<FixedNav
navList={navList}
activeText="基础用法"
overlay={true}
position={{ top: '70px' }}
change={change1}
visible={visible1}
selected={selected1}
/>
<FixedNav
navList={navList}
type={'left'}
position={{ top: '140px' }}
visible={visible2}
activeText={'左侧收起'}
unActiveText={'左侧展开'}
change={change2}
selected={selected2}
/>
<FixedNav
navList={navList}
position={{ top: '210px' }}
overlay={false}
visible={visible3}
change={change3}
selected={selected3}
/>
<FixedNav
position={{ top: '280px' }}
type={'left'}
visible={visible4}
change={change4}
selected={selected4}
slotList={
<ul className="nut-fixednav__list" slot={'list'}>
<li className="nut-fixednav__list-item">1</li>
<li className="nut-fixednav__list-item">2</li>
<li className="nut-fixednav__list-item">3</li>
<li className="nut-fixednav__list-item">4</li>
<li className="nut-fixednav__list-item">5</li>
</ul>
}
slotBtn={
<>
<Icon name="retweet" color="#fff">
{' '}
</Icon>
<span className="text">{visible4 ? '自定义开' : '自定义关'}</span>
</>
}
/>
</div>
</>
)
}
export default FixedNavDemo
# FixedNav 悬浮导航
### 介绍
悬浮收齐体验交互,用于快捷导航
### 安装
``` javascript
import { FixedNav } from '@nutui/nutui-react';
```
### 基础用法
``` tsx
<FixedNav
navList={navList}
activeText="基础用法"
overlay={true}
position={{ top: '70px' }}
change={change}
visible={visible}
selected={selected}
>
```
``` tsx
const navList = [
{
id: 1,
text: '首页',
icon: 'https://img11.360buyimg.com/imagetools/jfs/t1/117646/2/11112/1297/5ef83e95E81d77f05/daf8e3b1c81e3c98.png'
},
{
id: 2,
text: '分类',
icon: 'https://img12.360buyimg.com/imagetools/jfs/t1/119490/8/9568/1798/5ef83e95E968c69a6/dd029326f7d5042e.png'
},
{
id: 3,
text: '购物车',
num: 2,
icon: 'https://img14.360buyimg.com/imagetools/jfs/t1/130725/4/3157/1704/5ef83e95Eb976644f/b36c6cfc1cc1a99d.png'
},
{
id: 4,
text: '我的',
icon: 'https://img12.360buyimg.com/imagetools/jfs/t1/147573/29/1603/1721/5ef83e94E1393a678/5ddf1695ec989373.png'
}
];
const [visible, setVisible] = useState(false);
const change = (value: boolean) => {
setVisible(value);
};
const selected = (item: any, event: MouseEvent) => {
console.log(item, event);
};
```
### 左侧效果
``` tsx
<FixedNav
navList={navList}
type={"left"}
position={{ top: '140px' }}
visible={visible}
activeText={"左侧收起"}
unActiveText={"左侧展开"}
change={change}
selected={selected}
/>
```
### 取消背景遮罩
``` tsx
<FixedNav
navList={navList}
position={{ top: '210px' }}
overlay={false}
visible={visible}
change={change}
selected={selected}
/>
```
### 自定义使用
``` tsx
<FixedNav
position={{ top: '280px' }}
type={"left"}
visible={visible}
change={change}
selected={selected}
slotList={
<ul className="nut-fixednav__list" slot={"list"}>
<li className="nut-fixednav__list-item">1</li>
<li className="nut-fixednav__list-item">2</li>
<li className="nut-fixednav__list-item">3</li>
<li className="nut-fixednav__list-item">4</li>
<li className="nut-fixednav__list-item">5</li>
</ul>
}
slotBtn={
<>
<Icon name="retweet" color="#fff"> </Icon>
<span className="text">{ visible ? '自定义开' : '自定义关' }</span>
</>
}
/>
```
### Prop
| 字段 | 说明 | 类型 | 默认值 |
|:---------------|:---------------------------|:--------|:-----------------------------|
| visible | 是否打开 | Boolean | false |
| navList | 悬浮列表内容数据 | Array | [] |
| activeText | 收起列表按钮文案 | String | 收起导航 |
| unActiveText | 展开列表按钮文案 | String | 快速导航 |
| type | 导航方向,可选值 left right | String | right |
| overlay | 展开时是否显示遮罩 | Boolean | true |
| position | fixed 垂直位置 | Object | {top: 'auto',bottom: 'auto'} |
| slotList | 自定义展开列表内容 | HTMLElement | - |
| slotBtn | 自定义按钮 | HTMLElement | - |
### Event
| 字段 | 说明 | 回调参数 |
|----------|--------------|--------------------------|
| change | 展开收起按钮回调 | {value:boolean} |
| selected | 选择之后触发 | {item:item, event:MouseEvent} |
\ No newline at end of file
.nut-fixednav {
position: fixed;
z-index: $fixednav-index;
display: inline-block;
height: 50px;
right: 0;
&.active {
.nut-icon {
transform: rotate(180deg);
}
.nut-fixednav__list {
transform: translateX(0%) !important;
}
&.left {
.nut-icon {
transform: rotate(0deg) !important;
}
}
}
&__btn {
box-sizing: border-box;
position: absolute;
right: 0;
z-index: $fixednav-index + 1;
width: 80px;
padding-left: 12px;
height: 100%;
background: $fixednav-btn-bg;
border-radius: 45px 0px 0px 45px;
box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.2);
display: flex;
align-items: center;
justify-content: center;
.text {
width: 24px;
line-height: 13px;
font-size: 10px;
color: $fixednav-bg-color;
flex-shrink: 0;
}
.nut-icon {
margin-right: 5px;
transition: all 0.3s;
transform: rotate(0deg);
transition: all 0.3s;
}
}
&__list {
position: absolute;
right: 0;
transform: translateX(100%);
transition: all 0.5s;
z-index: $fixednav-index;
flex-shrink: 0;
height: 100%;
background: $fixednav-bg-color;
display: flex;
justify-content: space-between;
border-radius: 25px 0px 0px 25px;
box-shadow: 2px 2px 8px 0px rgba(0, 0, 0, 0.2);
padding: {
left: 20px;
right: 80px;
}
&-item {
position: relative;
flex: 1;
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
min-width: 50px;
flex-shrink: 0;
img {
width: 20px;
height: 20px;
margin-bottom: 2px;
}
.span {
font-size: 10px;
color: $fixednav-font-color;
}
.b {
position: absolute;
right: 0;
top: 1px;
height: 14px;
line-height: 14px;
font-size: 10px;
padding: 0 3px;
color: white;
background: $primary-color;
border-radius: 7px;
text-align: center;
min-width: 12px;
}
}
}
&.left {
right: auto;
left: 0;
.nut-fixednav__btn {
flex-direction: row-reverse;
right: auto;
left: 0;
border-radius: 0 45px 45px 0;
.nut-icon {
transform: rotate(180deg);
}
}
.nut-fixednav__list {
transform: translateX(-100%);
right: auto;
border-radius: 0px 25px 25px 0px;
padding: {
left: 80px;
right: 20px;
}
}
}
}
import React, { FunctionComponent, useState, useEffect, MouseEvent, HTMLProps } from 'react'
import { Icon } from '../icon/icon'
import { Overlay } from '../overlay/overlay'
import classNames from 'classnames'
import './fixednav.scss'
export interface FixedNavProps {
prefixCls: string
visible: boolean
overlay: boolean
navList: Array<object>
activeText: string
unActiveText: string
position: object
type: string
change: Function
selected: Function
slotList: HTMLProps<HTMLElement>
slotBtn: HTMLProps<HTMLElement>
}
const defaultProps = {
prefixCls: 'nut-fixednav',
activeText: '收起导航',
unActiveText: '快速导航',
position: {
top: 'auto',
bottom: 'auto',
},
type: 'right',
} as FixedNavProps
export const FixedNav: FunctionComponent<
Partial<FixedNavProps> & React.HTMLAttributes<HTMLDivElement>
> = (props) => {
const {
prefixCls,
children,
overlay,
visible,
navList,
activeText,
unActiveText,
position,
change,
selected,
type,
slotList,
slotBtn,
} = { ...defaultProps, ...props }
const selectCb = (event: MouseEvent, item: any) => {
selected(item, event)
}
const updateValue = (value: boolean = !visible) => {
change(value)
}
const [classNames, setClassNames] = useState('')
const classes = () => {
return `${prefixCls} ${type} ${visible ? 'active' : ''}`
}
useEffect(() => {
setClassNames(classes())
}, [visible])
return (
<div className={`${classNames}`} style={position}>
{overlay && (
<Overlay visible={visible} zIndex={200} onClick={() => updateValue(false)}></Overlay>
)}
<div className="list">
{slotList ? (
slotList
) : (
<div className="nut-fixednav__list">
{navList.map((item: any, index) => {
return (
<div
className="nut-fixednav__list-item"
onClick={(event) => selectCb(event, item)}
key={item.id || index}
>
<img src={item.icon} />
<div className="span">{item.text}</div>
{item.num && <div className="b">{item.num}</div>}
</div>
)
})}
</div>
)}
</div>
<div className="nut-fixednav__btn" onClick={() => updateValue()}>
{slotBtn ? (
slotBtn
) : (
<>
<Icon name="left" color="#fff" />
<div className="text">{visible ? activeText : unActiveText}</div>
</>
)}
</div>
</div>
)
}
FixedNav.defaultProps = defaultProps
FixedNav.displayName = 'NutFixedNav'
import { FixedNav } from './fixednav'
export default FixedNav
import Avatar from './avatar'
import Button from './button'
import Cell from './cell'
import Icon from './icon'
import Price from './price'
import Overlay from './overlay'
import Divider from './divider'
import Drag from './drag'
import Collapse from './collapse'
import Toast from './toast'
import BackTop from './backtop'
import Range from './range'
import Infiniteloading from './infiniteloading'
import Steps from './steps'
import CircleProgress from './circleprogress'
import NavBar from './navbar'
import Tabbar from './tabbar'
import InputNumber from './inputnumber'
import Elevator from './elevator'
import FixedNav from './fixednav'
import Rate from './rate'
import Uploader from './uploader'
import Input from './input'
import TextArea from './textarea'
import CheckBox from './checkbox'
import Signature from './signature'
export {
Avatar,
Button,
Cell,
Icon,
Price,
Overlay,
Divider,
Drag,
Collapse,
Toast,
BackTop,
Range,
Infiniteloading,
Steps,
CircleProgress,
NavBar,
Tabbar,
InputNumber,
Elevator,
FixedNav,
Rate,
Uploader,
Input,
TextArea,
CheckBox,
Signature,
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册