-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
18 changed files
with
496 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
# NoticeBar 通知栏 | ||
|
||
<code hidden="hidden" src="./demos/demo.tsx"></code> | ||
|
||
## 介绍 | ||
适用于当前页面内信息的通知,是一种较醒目的页面内通知方式。 | ||
|
||
## 使用 | ||
|
||
```tsx | ||
import { NoticeBar } from 'aunt'; | ||
``` | ||
|
||
### 基本用法 | ||
默认用法,文字长度超出容器后会自动进行滚动。 | ||
<code src="./demos/demo-base.tsx"></code> | ||
|
||
### 自定义icon | ||
可以对左侧右侧进行一些自定义的操作。 | ||
<code src="./demos/demo-icon.tsx"></code> | ||
|
||
### 多行样式 | ||
可以通过`wrapable`属性进行多行展示,前提`scrollable`为`false`。 | ||
<code src="./demos/demo-wrapable.tsx"></code> | ||
|
||
### 滚动播放 | ||
文字长度超出后会自动进行滚动,也可将`scrollable`打开后多长都会进行滚动。 | ||
<code src="./demos/demo-scrollable.tsx"></code> | ||
|
||
### 自定义颜色 | ||
可以通过`background` `color`进行一些颜色的自定义。 | ||
<code src="./demos/demo-color.tsx"></code> | ||
|
||
|
||
## 参数 | ||
|
||
| 参数 | 说明 | 类型 | 默认值 | | ||
| ----------- | --------- | ------- | ----- | | ||
| closeable | 是否可关闭 | `boolean` | `false` | | ||
| closeIcon | 自定义关闭图标 | `React.ReactNode` | `<AuntIconX />` | | ||
| content | 通知文本内容 | `string \| React.ReactNode` | `-` | | ||
| color | 通知文本颜色 | `string` | `#FF7D00` | | ||
| background | 通知背景颜色 | `string` | `#FFF7E8` | | ||
| delay | 动画延迟时间 (ms) | `number` | `0` | | ||
| speed | 滚动速率 (px/s) | `number` | `1` | | ||
| scrollable | 是否开启滚动播放,内容长度溢出时默认开启 | `boolean` | `false` | | ||
| wrapable | 否开启文本换行,只在禁用滚动时生效 | `boolean` | `false` | | ||
| leftIcon | 自定义左侧图标 | `React.ReactNode` | `-` | | ||
| rightIcon | 自定义右侧图标 | `React.ReactNode` | `-` | | ||
| onClose | 闭通知栏时触发 | `(event: React.MouseEvent) => void;` | `-` | | ||
| onClick | 点击通知栏时触发 | `(event: React.MouseEvent) => void;` | `-` | | ||
| onReplay | 每当滚动栏重新开始滚动时触发 | `() => void;` | `-` | | ||
|
||
## 样式变量 | ||
|
||
| 属性名 | 说明 | 默认值 | | ||
| --------- | ---------- | ----------------- | | ||
| --aunt-notice-bar-background-color | 通知背景颜色 | `var(--aunt-orange-1);` | | ||
| --aunt-notice-bar-color | 通知内容文字颜色 | `var(--aunt-orange);` | | ||
| --aunt-notice-bar-font-size | 通知内容文字大小 | `var(--aunt-font-size-md);` | | ||
| --aunt-notice-bar-padding | 通知内边距 | `var(--aunt-padding-xs);` | | ||
| --aunt-notice-bar-item-margin | 左右两侧icon外边距 | `var(--aunt-padding-xs);` | | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
import React from 'react'; | ||
import { NoticeBar } from 'aunt'; | ||
|
||
export default () => <NoticeBar content='这是一种通知的方式~' />; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import React from 'react'; | ||
import { NoticeBar, AuntIconPocket } from 'aunt'; | ||
|
||
export default () => ( | ||
<NoticeBar | ||
color='rgb(0, 180, 42)' | ||
background='rgb(232, 255, 234)' | ||
leftIcon={<AuntIconPocket size={20} />} | ||
content='如果不喜欢这个颜色,自己还可以自定义下颜色。' | ||
closeable | ||
onClick={() => { | ||
console.log('点击了'); | ||
}} | ||
onClose={() => { | ||
console.log('关闭了'); | ||
}} | ||
onReplay={() => { | ||
console.log('进行重新开始了'); | ||
}} | ||
/> | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import React from 'react'; | ||
import { NoticeBar, Space, AuntIconBell, AuntIconXCircle, Toast } from 'aunt'; | ||
|
||
export default () => { | ||
return ( | ||
<Space direction='vertical' style={{ width: '100%' }}> | ||
<NoticeBar leftIcon={<AuntIconBell size={20} />} content='自定义了一下左侧的图标。' /> | ||
<NoticeBar closeable content='打开了右侧的关闭按钮。' /> | ||
<NoticeBar | ||
closeable | ||
closeIcon={<AuntIconXCircle size={20} />} | ||
content='自定义了一下右侧的关闭图标。' | ||
/> | ||
<NoticeBar | ||
rightIcon={ | ||
<div | ||
style={{ | ||
width: 50, | ||
height: 20, | ||
background: '#ff7d00', | ||
borderRadius: 20, | ||
color: '#ffffff', | ||
fontSize: 12, | ||
display: 'flex', | ||
alignItems: 'center', | ||
justifyContent: 'center', | ||
}} | ||
onClick={() => { | ||
Toast('点我干啥~'); | ||
}} | ||
> | ||
点我 | ||
</div> | ||
} | ||
content='自定义了一下右侧的图标。' | ||
/> | ||
</Space> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
import React from 'react'; | ||
import { NoticeBar } from 'aunt'; | ||
|
||
export default () => { | ||
return <NoticeBar content='这样文字如果够多的情况下,会自动开启滚动效果的。' closeable />; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import React from 'react'; | ||
import { NoticeBar } from 'aunt'; | ||
|
||
export default () => { | ||
return ( | ||
<NoticeBar | ||
wrapable | ||
content='如果文字比较多的情况下也可以开启多行样式这样不会进行滚动的~' | ||
closeable | ||
/> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import React from 'react'; | ||
import { DemoBlock } from 'demos'; | ||
import DemoBase from './demo-base'; | ||
import DemoIcon from './demo-icon'; | ||
import DemoWrapable from './demo-wrapable'; | ||
import DemoScrollable from './demo-scrollable'; | ||
import DemoColor from './demo-color'; | ||
import './index.less'; | ||
|
||
function Demo() { | ||
return ( | ||
<div className='demo'> | ||
<DemoBlock title='基础用法'> | ||
<DemoBase /> | ||
</DemoBlock> | ||
<DemoBlock title='自定义icon'> | ||
<DemoIcon /> | ||
</DemoBlock> | ||
<DemoBlock title='多行样式'> | ||
<DemoWrapable /> | ||
</DemoBlock> | ||
<DemoBlock title='滚动播放'> | ||
<DemoScrollable /> | ||
</DemoBlock> | ||
<DemoBlock title='自定义颜色'> | ||
<DemoColor /> | ||
</DemoBlock> | ||
</div> | ||
); | ||
} | ||
|
||
export default Demo; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
.demo { | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import './styles/index.less'; | ||
import { NoticeBar } from './notice-bar'; | ||
|
||
export type { NoticeBarProps } from './types'; | ||
|
||
export { NoticeBar }; | ||
export default NoticeBar; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
import React, { | ||
useMemo, | ||
useRef, | ||
FunctionComponent, | ||
useContext, | ||
useLayoutEffect, | ||
useCallback, | ||
useState, | ||
} from 'react'; | ||
import { AuntIconX } from '../icon/icons'; | ||
import ConfigProviderContext from '../config-provider/config-provider-context'; | ||
import { useNamespace, useTimeout } from '../../hooks'; | ||
import { joinTrim } from '../../utils'; | ||
import type { NoticeBarProps } from './types'; | ||
|
||
export const NoticeBar: FunctionComponent<NoticeBarProps> = props => { | ||
const { prefix } = useContext(ConfigProviderContext); | ||
const ns = useNamespace('notice-bar', prefix); | ||
|
||
const { startTimer } = useTimeout(); | ||
const animationTimer = useRef<number>(); | ||
|
||
const [visible, setVisible] = useState(true); | ||
|
||
const { content, speed = 1 } = props; | ||
|
||
const wrapRef = useRef<HTMLDivElement | null>(null); | ||
const contentRef = useRef<HTMLParagraphElement | null>(null); | ||
const elWidth = useRef({ | ||
wrap: 0, | ||
content: 0, | ||
}); | ||
|
||
const varStyles = useMemo(() => { | ||
const styles: React.CSSProperties = {}; | ||
if (props.color) styles.color = props.color; | ||
if (props.background) styles.backgroundColor = props.background; | ||
return { ...styles, ...props.style }; | ||
}, [props.color, props.background]); | ||
|
||
const renderLeft = () => { | ||
if (!React.isValidElement(props.leftIcon)) return null; | ||
return <div className={ns.m('left')}>{props.leftIcon}</div>; | ||
}; | ||
|
||
const renderRight = () => { | ||
const element = (e: React.ReactNode) => <div className={ns.m('right')}>{e}</div>; | ||
if (props.closeable) { | ||
const size = contentRef.current?.clientHeight || 20; | ||
const node = React.cloneElement( | ||
React.isValidElement(props.closeIcon) ? props.closeIcon : <AuntIconX size={size} />, | ||
{ | ||
onClick: (e: React.MouseEvent) => { | ||
e.stopPropagation(); | ||
setVisible(false); | ||
props.onClose?.(e); | ||
}, | ||
} | ||
); | ||
return element(node); | ||
} | ||
if (React.isValidElement(props.rightIcon)) return element(props.rightIcon); | ||
return null; | ||
}; | ||
|
||
// 判断是否可以进行滚动 | ||
const isScrollable = useCallback(() => { | ||
if (!wrapRef.current || !contentRef.current) return false; | ||
if (!props.scrollable && props.wrapable) return false; | ||
const is = wrapRef.current!.clientWidth >= contentRef.current!.clientWidth; | ||
if (!props.scrollable && is) return false; | ||
return true; | ||
}, [wrapRef, contentRef]); | ||
|
||
const getOffsetX = (ref: React.MutableRefObject<HTMLParagraphElement | null>) => { | ||
const { transform } = ref.current!.style; | ||
const ret = transform.split('px')[0].split('(')[1] || 0; | ||
return ret; | ||
}; | ||
|
||
const setOffsetX = ( | ||
num: string | number, | ||
ref: React.MutableRefObject<HTMLParagraphElement | null> | ||
) => { | ||
ref.current!.style.transform = `translateX(${num}px)`; | ||
}; | ||
|
||
// 清除动画 | ||
const clearAnimationFrame = () => { | ||
if (animationTimer.current) window.cancelAnimationFrame(animationTimer.current); | ||
}; | ||
|
||
// 移动方法 | ||
const move = (endPosition: number) => { | ||
const contentOffsetX = getOffsetX(contentRef); | ||
// 当移动到最左边后 把位置改到右边去 开启新一轮的循环 | ||
if (contentOffsetX <= endPosition) { | ||
props.onReplay?.(); | ||
clearAnimationFrame(); | ||
setOffsetX(elWidth.current.wrap, contentRef); | ||
move(endPosition); | ||
return; | ||
} | ||
setOffsetX(Number(contentOffsetX) - speed, contentRef); | ||
animationTimer.current = window.requestAnimationFrame(() => { | ||
move(endPosition); | ||
}); | ||
}; | ||
|
||
// 开始执行动画 | ||
const startMove = () => { | ||
elWidth.current = { | ||
wrap: wrapRef.current!.offsetWidth || 0, | ||
content: contentRef.current!.offsetWidth || 0, | ||
}; | ||
|
||
animationTimer.current = window.requestAnimationFrame(() => { | ||
move(-elWidth.current.content); | ||
}); | ||
}; | ||
|
||
useLayoutEffect(() => { | ||
if (isScrollable() && visible) startTimer(startMove, props.delay); | ||
return () => { | ||
clearAnimationFrame(); | ||
}; | ||
}, [props, wrapRef, contentRef, visible]); | ||
|
||
if (!visible) return null; | ||
|
||
return ( | ||
<div className={joinTrim([ns.b(), props.className])} style={varStyles} onClick={props.onClick}> | ||
{renderLeft()} | ||
<div | ||
className={ns.e('box')} | ||
ref={wrapRef} | ||
style={{ | ||
whiteSpace: !isScrollable() && props.wrapable ? 'normal' : 'nowrap', | ||
}} | ||
> | ||
<p ref={contentRef}>{content}</p> | ||
</div> | ||
{renderRight()} | ||
</div> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
@class-prefix: ~'aunt'; | ||
:root{ | ||
--aunt-notice-bar-background-color: var(--aunt-orange-1); | ||
--aunt-notice-bar-color: var(--aunt-orange); | ||
--aunt-notice-bar-font-size: var(--aunt-font-size-md); | ||
--aunt-notice-bar-padding: var(--aunt-padding-xs); | ||
--aunt-notice-bar-item-margin: var(--aunt-padding-xs); | ||
} | ||
|
||
.@{class-prefix}-notice-bar { | ||
padding: var(--aunt-notice-bar-padding); | ||
display: flex; | ||
align-items: flex-start; | ||
background-color: var(--aunt-notice-bar-background-color); | ||
color: var(--aunt-notice-bar-color); | ||
font-size: var(--aunt-notice-bar-font-size); | ||
|
||
&--left{ | ||
margin-right: var(--aunt-notice-bar-item-margin); | ||
} | ||
&--right{ | ||
margin-left: var(--aunt-notice-bar-item-margin); | ||
} | ||
&__box{ | ||
width: 100%; | ||
height: 100%; | ||
overflow: hidden; | ||
word-break: break-all; | ||
p{ | ||
display: inline-block; | ||
transition-timing-function: linear; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import '@testing-library/jest-dom'; | ||
import React from 'react'; | ||
import { render, screen } from '@testing-library/react'; | ||
|
||
describe('< />', () => {}); |
Oops, something went wrong.