diff --git a/site/mobile/mobile.config.js b/site/mobile/mobile.config.js index d5967f20..5268ecd2 100644 --- a/site/mobile/mobile.config.js +++ b/site/mobile/mobile.config.js @@ -220,7 +220,7 @@ export default { { title: 'NoticeBar 公告栏', name: 'notice-bar', - component: () => import('tdesign-mobile-react/notice-bar/_example/mobile.jsx'), + component: () => import('tdesign-mobile-react/notice-bar/_example/mobile.tsx'), }, { title: 'Result 结果', diff --git a/src/notice-bar/NoticeBar.tsx b/src/notice-bar/NoticeBar.tsx index 0db0c021..6f35814c 100644 --- a/src/notice-bar/NoticeBar.tsx +++ b/src/notice-bar/NoticeBar.tsx @@ -1,10 +1,18 @@ -import React, { useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react'; -import { InfoCircleFilledIcon, CheckCircleFilledIcon, CloseCircleFilledIcon } from 'tdesign-icons-react'; -import cls from 'classnames'; -import { ConfigContext } from '../config-provider'; +import React, { useEffect, useMemo, useRef, useState } from 'react'; +import { InfoCircleFilledIcon, CheckCircleFilledIcon } from 'tdesign-icons-react'; +import classNames from 'classnames'; +import isObject from 'lodash/isObject'; +import parseTNode from 'tdesign-mobile-react/_util/parseTNode'; +import isArray from 'lodash/isArray'; +import Swiper from 'tdesign-mobile-react/swiper'; +import SwiperItem from 'tdesign-mobile-react/swiper/SwiperItem'; +import { usePrefixClass } from 'tdesign-mobile-react/hooks/useClass'; import type { StyledProps } from '../common'; -import type { TdNoticeBarProps, NoticeBarTrigger } from './type'; +import type { TdNoticeBarProps, NoticeBarTrigger, NoticeBarMarquee } from './type'; import useDefault from '../_util/useDefault'; +import useDefaultProps from '../hooks/useDefaultProps'; +import { noticeBarDefaultProps } from './defaultProps'; +import noop from '../_util/noop'; export interface NoticeBarProps extends TdNoticeBarProps, StyledProps {} @@ -44,26 +52,15 @@ const defaultIcons: Record = { info: , success: , warning: , - error: , + error: , }; -function filterUndefinedValue>(obj: T): Partial { - const keys = Object.keys(obj); - const result = keys.reduce((prev, next: keyof T) => { - if (typeof obj[next] !== 'undefined') { - return { - ...prev, - [next]: obj[next], - }; - } - return prev; - }, {}); - - return result; -} - function useAnimationSettingValue() { - const animationSettingValue = useRef(defaultReduceState()); + const animationSettingValue = useRef(null); + if (!animationSettingValue.current) { + // 仅为null时进行初始化 + animationSettingValue.current = defaultReduceState(); + } const [, setState] = useState(0); function updateScroll(obj: Partial) { @@ -89,6 +86,7 @@ function useAnimationSettingValue() { animationSettingValue.current = obj || defaultReduceState(); setState(Math.random()); } + return { animationSettingValue, updateScroll, @@ -98,60 +96,51 @@ function useAnimationSettingValue() { } const NoticeBar: React.FC = (props) => { - const { classPrefix } = useContext(ConfigContext); const { content, - extra, + direction, marquee, + operation, prefixIcon, suffixIcon, theme = 'info', visible, defaultVisible, - onChange, onClick, - } = props; + } = useDefaultProps(props, noticeBarDefaultProps); - const { animationSettingValue, updateScroll, updateAnimationFrame } = useAnimationSettingValue(); - - const name = `${classPrefix}-notice-bar`; + const listDOM = useRef(null); + const itemDOM = useRef(null); + const hasBeenExecute = useRef(false); - const showExtraText = !!extra; - const rootClasses = useMemo(() => cls([name, `${name}--${theme}`]), [name, theme]); + const [isShow] = useDefault(visible, defaultVisible, noop); + const rootClassName = usePrefixClass('notice-bar'); + const containerClassName = classNames(rootClassName, `${rootClassName}--${theme}`); + const { animationSettingValue, updateScroll, updateAnimationFrame } = useAnimationSettingValue(); - const computedPrefixIcon: TdNoticeBarProps['prefixIcon'] | IconType | null = useMemo(() => { - let temp = null; - if (prefixIcon !== '') { - if (Object.keys(defaultIcons).includes(theme)) { - temp = defaultIcons[theme]; + useEffect(() => { + if (!hasBeenExecute.current) { + if (isShow) { + hasBeenExecute.current = true; + handleScrolling(); } - - return prefixIcon || temp || null; + return; } - return null; - }, [prefixIcon, theme]); - - const handleClick = useCallback( - (trigger: NoticeBarTrigger) => { - onClick?.(trigger); - }, - [onClick], - ); + const timer = setTimeout(() => { + if (isShow) { + updateAnimationFrame({ + offset: animationSettingValue.current.listWidth, + duration: 0, + }); + handleScrolling(); + } + }, 0); - const animateStyle = useMemo( - () => ({ - transform: animationSettingValue.current.offset ? `translateX(${animationSettingValue.current.offset}px)` : '', - transitionDuration: `${animationSettingValue.current.duration}s`, - transitionTimingFunction: 'linear', - }), + return () => { + clearTimeout(timer); + }; // eslint-disable-next-line react-hooks/exhaustive-deps - [animationSettingValue.current.offset, animationSettingValue.current.duration], - ); - - const listDOM = useRef(null); - const itemDOM = useRef(null); - - const [isShow] = useDefault(visible, defaultVisible, onChange); + }, [isShow]); function handleScrolling() { // 过滤 marquee 为 false @@ -170,13 +159,16 @@ const NoticeBar: React.FC = (props) => { updateScrollState = { ...animationSettingValue.current.scroll, ...defaultReduceState().scroll, - marquee: true, + marquee, }; - } else { + } + if (isObject(marquee)) { + const curMarquee = marquee as NoticeBarMarquee; updateScrollState = { - ...animationSettingValue.current.scroll, - ...filterUndefinedValue(marquee), marquee: true, + loop: typeof curMarquee?.loop === 'undefined' ? updateScrollState.loop : curMarquee.loop, + speed: curMarquee.speed ?? updateScrollState.speed, + delay: curMarquee.delay ?? updateScrollState.delay, }; } @@ -225,90 +217,103 @@ const NoticeBar: React.FC = (props) => { }, 0); } - const listScrollDomCls = cls(`${name}__list`, { - [`${name}__list--scrolling`]: animationSettingValue.current.scroll.marquee, - }); - - const listItemScrollDomCls = cls(`${name}__item`, { - [`${name}__item-detail`]: showExtraText, - }); - - const renderPrefixIcon = useMemo( - () => - computedPrefixIcon ? ( -
handleClick('prefix-icon')}> - {computedPrefixIcon} -
- ) : null, - [handleClick, name, computedPrefixIcon], + const handleClick = (trigger: NoticeBarTrigger) => { + onClick?.(trigger); + }; + // 动画 + const animateStyle = useMemo( + () => ({ + transform: animationSettingValue.current.offset ? `translateX(${animationSettingValue.current.offset}px)` : '', + transitionDuration: `${animationSettingValue.current.duration}s`, + transitionTimingFunction: 'linear', + }), + // eslint-disable-next-line react-hooks/exhaustive-deps + [animationSettingValue.current.offset, animationSettingValue.current.duration], ); - function onClickExtra(e: React.MouseEvent) { - e.stopPropagation(); - handleClick('extra'); - } - - const itemDomStyle = animationSettingValue.current.scroll.marquee ? animateStyle : {}; - - const hasBeenExecute = useRef(false); - - useEffect(() => { - if (!hasBeenExecute.current) { - if (isShow) { - hasBeenExecute.current = true; - handleScrolling(); - } - return; + const renderPrefixIcon = () => { + const prefixIconContent = prefixIcon ? parseTNode(prefixIcon) : defaultIcons[theme]; + if (prefixIcon !== null && prefixIconContent) { + return ( +
handleClick('prefix-icon')}> + {prefixIconContent} +
+ ); } - onChange?.(isShow); - setTimeout(() => { - if (isShow) { - updateAnimationFrame({ - offset: animationSettingValue.current.listWidth, - duration: 0, - }); - handleScrolling(); - } - }, 0); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [isShow]); - - if (!isShow) { return null; - } - - return ( -
-
- {renderPrefixIcon} -
-
-
- handleClick('content')}> - {content} - {showExtraText && ( - - {extra} - - )} - -
-
-
+ }; - {suffixIcon && ( -
handleClick('suffix-icon')}> - {suffixIcon} + const renderContent = () => { + const renderShowContent = () => parseTNode(content) || null; + const renderOperationContent = () => { + const operationContent = parseTNode(operation); + if (!operationContent) { + return null; + } + return ( + { + e.stopPropagation(); + handleClick('operation'); + }} + > + {operationContent} + + ); + }; + return ( +
handleClick('content')}> + {direction === 'vertical' && isArray(content) ? ( + + {content.map((item, index) => ( + +
{item}
+
+ ))} +
+ ) : ( +
+ {renderShowContent()} + {renderOperationContent()}
)}
+ ); + }; + + const renderSuffixIconContent = () => { + const suffixIconContent = parseTNode(suffixIcon); + if (!suffixIconContent) { + return null; + } + return ( +
handleClick('suffix-icon')}> + {suffixIconContent} +
+ ); + }; + return isShow ? ( +
+ {renderPrefixIcon()} + {renderContent()} + {renderSuffixIconContent()}
- ); + ) : null; }; NoticeBar.displayName = 'NoticeBar'; diff --git a/src/notice-bar/_example/base.tsx b/src/notice-bar/_example/base.tsx new file mode 100644 index 00000000..7631cf21 --- /dev/null +++ b/src/notice-bar/_example/base.tsx @@ -0,0 +1,6 @@ +import React from 'react'; +import { NoticeBar } from 'tdesign-mobile-react'; + +export default function Base() { + return ; +} diff --git a/src/notice-bar/_example/controller.jsx b/src/notice-bar/_example/controller.jsx deleted file mode 100644 index 6e1d9b4f..00000000 --- a/src/notice-bar/_example/controller.jsx +++ /dev/null @@ -1,30 +0,0 @@ -import React from 'react'; -import { ArrowRightIcon, AppIcon } from 'tdesign-icons-react'; -import { NoticeBar, Toast } from 'tdesign-mobile-react'; -import TDemoBlock from '../../../site/mobile/components/DemoBlock'; - -export default function ControllerDemo() { - const handleClick = (context) => { - Toast({ message: `click: ${context}` }); - }; - - return ( -
- - } - onClick={handleClick} - /> - } - onClick={handleClick} - /> - -
- ); -} diff --git a/src/notice-bar/_example/custom.tsx b/src/notice-bar/_example/custom.tsx new file mode 100644 index 00000000..d716fa16 --- /dev/null +++ b/src/notice-bar/_example/custom.tsx @@ -0,0 +1,16 @@ +import React from 'react'; +import { NoticeBar } from 'tdesign-mobile-react'; +import { ChevronRightIcon, SoundIcon } from 'tdesign-icons-react'; +import './style/index.less'; + +export default function Custom() { + return ( + } + suffixIcon={} + /> + ); +} diff --git a/src/notice-bar/_example/customization.tsx b/src/notice-bar/_example/customization.tsx new file mode 100644 index 00000000..4318b82b --- /dev/null +++ b/src/notice-bar/_example/customization.tsx @@ -0,0 +1,19 @@ +import React from 'react'; +import { Link, NoticeBar } from 'tdesign-mobile-react'; +import { CloseIcon } from 'tdesign-icons-react'; +import './style/index.less'; + +export default function Customization() { + return ( + + 详情 + + } + suffixIcon={} + /> + ); +} diff --git a/src/notice-bar/_example/event.jsx b/src/notice-bar/_example/event.jsx deleted file mode 100644 index 66ba54e9..00000000 --- a/src/notice-bar/_example/event.jsx +++ /dev/null @@ -1,34 +0,0 @@ -import React, { useState } from 'react'; -import { CloseIcon } from 'tdesign-icons-react'; -import { NoticeBar, Toast, Button } from 'tdesign-mobile-react'; -import TDemoBlock from '../../../site/mobile/components/DemoBlock'; - -export default function EventDemo() { - const [visible, setVisible] = useState(false); - const handleClick = (context) => { - Toast({ message: `click: ${context}` }); - }; - - const handleChange = () => { - setVisible((prev) => !prev); - }; - - const handleConsole = (value) => { - console.log(value); - }; - - return ( -
- - - } - /> - -
- ); -} diff --git a/src/notice-bar/_example/event.tsx b/src/notice-bar/_example/event.tsx new file mode 100644 index 00000000..b9c5c1cc --- /dev/null +++ b/src/notice-bar/_example/event.tsx @@ -0,0 +1,19 @@ +import React from 'react'; +import { NoticeBar, Toast } from 'tdesign-mobile-react'; +import { ChevronRightIcon } from 'tdesign-icons-react'; +import './style/index.less'; + +export default function Event() { + const handleClick = (context: string) => { + Toast({ message: `click:${context}` }); + }; + return ( + } + onClick={handleClick} + /> + ); +} diff --git a/src/notice-bar/_example/icon.jsx b/src/notice-bar/_example/icon.jsx deleted file mode 100644 index 7ab8a341..00000000 --- a/src/notice-bar/_example/icon.jsx +++ /dev/null @@ -1,13 +0,0 @@ -import React from 'react'; -import { NoticeBar } from 'tdesign-mobile-react'; -import TDemoBlock from '../../../site/mobile/components/DemoBlock'; - -export default function IconDemo() { - return ( -
- - - -
- ); -} diff --git a/src/notice-bar/_example/icon.tsx b/src/notice-bar/_example/icon.tsx new file mode 100644 index 00000000..b378cea1 --- /dev/null +++ b/src/notice-bar/_example/icon.tsx @@ -0,0 +1,6 @@ +import React from 'react'; +import { NoticeBar } from 'tdesign-mobile-react'; + +export default function IconDemo() { + return ; +} diff --git a/src/notice-bar/_example/mobile.jsx b/src/notice-bar/_example/mobile.jsx deleted file mode 100644 index 2761cfce..00000000 --- a/src/notice-bar/_example/mobile.jsx +++ /dev/null @@ -1,82 +0,0 @@ -import React, { useState } from 'react'; -import { CloseIcon, ChevronRightIcon } from 'tdesign-icons-react'; -import { NoticeBar, Toast } from 'tdesign-mobile-react'; -import TDemoBlock from '../../../site/mobile/components/DemoBlock'; - -function MobileDemo() { - const [visible] = useState(true); - const iconFunc = ; - const arrowRight = ; - const handleClick = (context) => { - Toast({ message: `click:${context}` }); - }; - - return ( -
- - - - - - - - - - - - - - - - - - - - - - - - - - - {' '} -
- ); -} - -export default MobileDemo; diff --git a/src/notice-bar/_example/mobile.tsx b/src/notice-bar/_example/mobile.tsx new file mode 100644 index 00000000..8f39a84d --- /dev/null +++ b/src/notice-bar/_example/mobile.tsx @@ -0,0 +1,48 @@ +import React from 'react'; +import BaseDemo from './base'; +import IconDemo from './icon'; +import SuffixIcon from './suffixIcon'; +import Event from './event'; +import CustomDemo from './custom'; +import Customization from './customization'; +import ThemeDemo from './theme'; +import ScrollDemo from './scrolling'; +import TDemoBlock from '../../../site/mobile/components/DemoBlock'; +import TDemoHeader from '../../../site/mobile/components/DemoHeader'; + +function MobileDemo() { + return ( +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ ); +} + +export default MobileDemo; diff --git a/src/notice-bar/_example/multi-line.jsx b/src/notice-bar/_example/multi-line.jsx deleted file mode 100644 index aa0de456..00000000 --- a/src/notice-bar/_example/multi-line.jsx +++ /dev/null @@ -1,43 +0,0 @@ -import React from 'react'; -import { ArrowRightIcon, CloseIcon } from 'tdesign-icons-react'; -import { NoticeBar, Toast } from 'tdesign-mobile-react'; -import TDemoBlock from '../../../site/mobile/components/DemoBlock'; - -export default function MultiLineDemo() { - const closeIcon = ; - const arrowRightIcon = ; - - const handleClick = (context) => { - Toast({ message: `click:${context}` }); - }; - - return ( -
- - - - - - -
- ); -} diff --git a/src/notice-bar/_example/scrolling.jsx b/src/notice-bar/_example/scrolling.jsx deleted file mode 100644 index 74a976b1..00000000 --- a/src/notice-bar/_example/scrolling.jsx +++ /dev/null @@ -1,21 +0,0 @@ -import React, { useState } from 'react'; -import { NoticeBar } from 'tdesign-mobile-react'; -import TDemoBlock from '../../../site/mobile/components/DemoBlock'; - -export default function ScrollingDemo() { - const [visible] = useState(true); - - return ( -
- - - - -
- ); -} diff --git a/src/notice-bar/_example/scrolling.tsx b/src/notice-bar/_example/scrolling.tsx new file mode 100644 index 00000000..074c9ce5 --- /dev/null +++ b/src/notice-bar/_example/scrolling.tsx @@ -0,0 +1,17 @@ +import React from 'react'; +import { NoticeBar } from 'tdesign-mobile-react'; +import './style/index.less'; +import { SoundIcon } from 'tdesign-icons-react'; + +export default function Scrolling() { + const content = '提示文字描述提示文字描述提示文字描述提示文字描述文'; + const content1 = ['君不见', '高堂明镜悲白发', '朝如青丝暮成雪', '人生得意须尽欢', '莫使金樽空对月']; + + return ( + <> + + + } /> + + ); +} diff --git a/src/notice-bar/_example/static.jsx b/src/notice-bar/_example/static.jsx deleted file mode 100644 index 96bf575a..00000000 --- a/src/notice-bar/_example/static.jsx +++ /dev/null @@ -1,15 +0,0 @@ -import React, { useState } from 'react'; -import { NoticeBar } from 'tdesign-mobile-react'; -import TDemoBlock from '../../../site/mobile/components/DemoBlock'; - -export default function StaticDemo() { - const [visible] = useState(true); - - return ( -
- - - -
- ); -} diff --git a/src/notice-bar/_example/style/index.less b/src/notice-bar/_example/style/index.less new file mode 100644 index 00000000..254f28bb --- /dev/null +++ b/src/notice-bar/_example/style/index.less @@ -0,0 +1,23 @@ +.cover-class { + background-color: var(--bg-color-demo, #fff); + + .t-icon { + color: var(--td-text-color-primary, rgba(0, 0, 0, 0.9)) !important; + } + + .t-notice-bar__text { + color: var(--bg-color-demo, #fff) !important; + } +} + +.custom-link { + margin-left: 2px; +} + +.notice-bar-demo-block { + margin-bottom: 16px; +} + +.tdesign-mobile-demo { + background-color: var(--bg-color-demo, #fff); +} diff --git a/src/notice-bar/_example/suffixIcon.tsx b/src/notice-bar/_example/suffixIcon.tsx new file mode 100644 index 00000000..c91af8c0 --- /dev/null +++ b/src/notice-bar/_example/suffixIcon.tsx @@ -0,0 +1,7 @@ +import React from 'react'; +import { NoticeBar } from 'tdesign-mobile-react'; +import { CloseIcon } from 'tdesign-icons-react'; + +export default function SuffixIcon() { + return } />; +} diff --git a/src/notice-bar/_example/theme.jsx b/src/notice-bar/_example/theme.jsx deleted file mode 100644 index 39b89f53..00000000 --- a/src/notice-bar/_example/theme.jsx +++ /dev/null @@ -1,16 +0,0 @@ -import React from 'react'; -import { NoticeBar } from 'tdesign-mobile-react'; -import TDemoBlock from '../../../site/mobile/components/DemoBlock'; - -export default function ThemeDemo() { - return ( -
- - - - - - -
- ); -} diff --git a/src/notice-bar/_example/theme.tsx b/src/notice-bar/_example/theme.tsx new file mode 100644 index 00000000..8129c096 --- /dev/null +++ b/src/notice-bar/_example/theme.tsx @@ -0,0 +1,14 @@ +import React from 'react'; +import { NoticeBar } from 'tdesign-mobile-react'; +import './style/index.less'; + +export default function ThemeDemo() { + return ( + <> + + + + + + ); +} diff --git a/src/notice-bar/defaultProps.ts b/src/notice-bar/defaultProps.ts index a40c4a2f..7653f552 100644 --- a/src/notice-bar/defaultProps.ts +++ b/src/notice-bar/defaultProps.ts @@ -4,4 +4,9 @@ import { TdNoticeBarProps } from './type'; -export const noticeBarDefaultProps: TdNoticeBarProps = { marquee: false, theme: 'info', defaultVisible: false }; +export const noticeBarDefaultProps: TdNoticeBarProps = { + direction: 'horizontal', + marquee: false, + theme: 'info', + defaultVisible: false, +}; diff --git a/src/notice-bar/notice-bar.en-US.md b/src/notice-bar/notice-bar.en-US.md new file mode 100644 index 00000000..8ad8a151 --- /dev/null +++ b/src/notice-bar/notice-bar.en-US.md @@ -0,0 +1,22 @@ +:: BASE_DOC :: + +## API + + +### NoticeBar Props + +name | type | default | description | required +-- | -- | -- | -- | -- +className | String | - | className of component | N +style | Object | - | CSS(Cascading Style Sheets),Typescript:`React.CSSProperties` | N +content | TNode | - | Typescript:`string \| string[] \| TNode`。[see more ts definition](https://github.com/Tencent/tdesign-mobile-react/blob/develop/src/common.ts) | N +direction | String | horizontal | options: horizontal/vertical | N +marquee | Boolean / Object | false | Typescript:`boolean \| NoticeBarMarquee` `interface NoticeBarMarquee { speed?: number; loop?: number; delay?: number }`。[see more ts definition](https://github.com/Tencent/tdesign-mobile-react/tree/develop/src/notice-bar/type.ts) | N +operation | TNode | - | Typescript:`string \| TNode`。[see more ts definition](https://github.com/Tencent/tdesign-mobile-react/blob/develop/src/common.ts) | N +prefixIcon | TElement | - | Typescript:`TNode`。[see more ts definition](https://github.com/Tencent/tdesign-mobile-react/blob/develop/src/common.ts) | N +suffixIcon | TElement | - | Typescript:`TNode`。[see more ts definition](https://github.com/Tencent/tdesign-mobile-react/blob/develop/src/common.ts) | N +theme | String | info | options: info/success/warning/error | N +visible | Boolean | false | \- | N +defaultVisible | Boolean | false | uncontrolled property | N +onChange | Function | | Typescript:`(value: boolean) => void`
`deprecated` | N +onClick | Function | | Typescript:`(trigger: NoticeBarTrigger) => void`
[see more ts definition](https://github.com/Tencent/tdesign-mobile-react/tree/develop/src/notice-bar/type.ts)。
`type NoticeBarTrigger = 'prefix-icon' \| 'content' \| 'operation' \| 'suffix-icon';`
| N diff --git a/src/notice-bar/notice-bar.md b/src/notice-bar/notice-bar.md index 16c6039c..a41b6a35 100644 --- a/src/notice-bar/notice-bar.md +++ b/src/notice-bar/notice-bar.md @@ -2,19 +2,21 @@ ## API + ### NoticeBar Props -名称 | 类型 | 默认值 | 说明 | 必传 +名称 | 类型 | 默认值 | 描述 | 必传 -- | -- | -- | -- | -- className | String | - | 类名 | N style | Object | - | 样式,TS 类型:`React.CSSProperties` | N -content | TNode | - | 文本内容。TS 类型:`string | TNode`。[通用类型定义](https://github.com/Tencent/tdesign-mobile-react/blob/develop/src/common.ts) | N -extra | TNode | - | 右侧额外信息。TS 类型:`string | TNode`。[通用类型定义](https://github.com/Tencent/tdesign-mobile-react/blob/develop/src/common.ts) | N -marquee | Boolean / Object | false | 跑马灯效果。speed 指速度控制;loop 指循环播放次数,值为 -1 表示循环播放,值为 0 表示不循环播放;delay 表示延迟多久开始播放。TS 类型:`boolean | DrawMarquee` `interface DrawMarquee { speed?: number; loop?: number; delay?: number }`。[详细类型定义](https://github.com/Tencent/tdesign-mobile-react/tree/develop/src/notice-bar/type.ts) | N -prefixIcon | TNode | - | 前缀图标。TS 类型:`string | TNode`。[通用类型定义](https://github.com/Tencent/tdesign-mobile-react/blob/develop/src/common.ts) | N +content | TNode | - | 文本内容。TS 类型:`string \| string[] \| TNode`。[通用类型定义](https://github.com/Tencent/tdesign-mobile-react/blob/develop/src/common.ts) | N +direction | String | horizontal | 滚动方向。可选项:horizontal/vertical | N +marquee | Boolean / Object | false | 跑马灯效果。speed 指速度控制;loop 指循环播放次数,值为 -1 表示循环播放,值为 0 表示不循环播放;delay 表示延迟多久开始播放。TS 类型:`boolean \| NoticeBarMarquee` `interface NoticeBarMarquee { speed?: number; loop?: number; delay?: number }`。[详细类型定义](https://github.com/Tencent/tdesign-mobile-react/tree/develop/src/notice-bar/type.ts) | N +operation | TNode | - | 右侧额外信息。TS 类型:`string \| TNode`。[通用类型定义](https://github.com/Tencent/tdesign-mobile-react/blob/develop/src/common.ts) | N +prefixIcon | TElement | - | 前缀图标。TS 类型:`TNode`。[通用类型定义](https://github.com/Tencent/tdesign-mobile-react/blob/develop/src/common.ts) | N suffixIcon | TElement | - | 后缀图标。TS 类型:`TNode`。[通用类型定义](https://github.com/Tencent/tdesign-mobile-react/blob/develop/src/common.ts) | N theme | String | info | 内置主题。可选项:info/success/warning/error | N visible | Boolean | false | 显示/隐藏 | N defaultVisible | Boolean | false | 显示/隐藏。非受控属性 | N -onChange | Function | | TS 类型:`(value: boolean) => void`
展示或关闭公告栏时触发。参数为true时,代表展示公告栏。参数为false时,代表关闭公告栏 | N -onClick | Function | | TS 类型:`(trigger: NoticeBarTrigger) => void`
点击事件。[详细类型定义](https://github.com/Tencent/tdesign-mobile-react/tree/develop/src/notice-bar/type.ts)。
`type NoticeBarTrigger = 'prefix-icon' | 'content' | 'extra' | 'suffix-icon';`
| N +onChange | Function | | TS 类型:`(value: boolean) => void`
已废弃。展示或关闭公告栏时触发。参数为true时,代表展示公告栏。参数为false时,代表关闭公告栏 | N +onClick | Function | | TS 类型:`(trigger: NoticeBarTrigger) => void`
点击事件。[详细类型定义](https://github.com/Tencent/tdesign-mobile-react/tree/develop/src/notice-bar/type.ts)。
`type NoticeBarTrigger = 'prefix-icon' \| 'content' \| 'operation' \| 'suffix-icon';`
| N diff --git a/src/notice-bar/style/index.js b/src/notice-bar/style/index.js index 9ce2be11..fc4c44cc 100644 --- a/src/notice-bar/style/index.js +++ b/src/notice-bar/style/index.js @@ -1 +1 @@ -import '../../_common/style/mobile/components/notice-bar/_index.less'; +import '../../_common/style/mobile/components/notice-bar/v2/_index.less'; diff --git a/src/notice-bar/type.ts b/src/notice-bar/type.ts index 3e347002..f073008f 100644 --- a/src/notice-bar/type.ts +++ b/src/notice-bar/type.ts @@ -10,20 +10,25 @@ export interface TdNoticeBarProps { /** * 文本内容 */ - content?: TNode; + content?: [] | TNode; /** - * 右侧额外信息 + * 滚动方向 + * @default horizontal */ - extra?: TNode; + direction?: 'horizontal' | 'vertical'; /** * 跑马灯效果。speed 指速度控制;loop 指循环播放次数,值为 -1 表示循环播放,值为 0 表示不循环播放;delay 表示延迟多久开始播放 * @default false */ - marquee?: boolean | DrawMarquee; + marquee?: boolean | NoticeBarMarquee; + /** + * 右侧额外信息 + */ + operation?: TNode; /** * 前缀图标 */ - prefixIcon?: TNode; + prefixIcon?: TElement; /** * 后缀图标 */ @@ -43,20 +48,16 @@ export interface TdNoticeBarProps { * @default false */ defaultVisible?: boolean; - /** - * 展示或关闭公告栏时触发。参数为true时,代表展示公告栏。参数为false时,代表关闭公告栏 - */ - onChange?: (value: boolean) => void; /** * 点击事件 */ onClick?: (trigger: NoticeBarTrigger) => void; } -export interface DrawMarquee { +export interface NoticeBarMarquee { speed?: number; loop?: number; delay?: number; } -export type NoticeBarTrigger = 'prefix-icon' | 'content' | 'extra' | 'suffix-icon'; +export type NoticeBarTrigger = 'prefix-icon' | 'content' | 'operation' | 'suffix-icon'; diff --git a/test/snap/__snapshots__/csr.test.jsx.snap b/test/snap/__snapshots__/csr.test.jsx.snap index d4c5db5b..73822122 100644 --- a/test/snap/__snapshots__/csr.test.jsx.snap +++ b/test/snap/__snapshots__/csr.test.jsx.snap @@ -20121,6 +20121,1218 @@ exports[`csr snapshot test > csr test src/navbar/_example/size.tsx 1`] = `
`; +exports[`csr snapshot test > csr test src/notice-bar/_example/base.tsx 1`] = ` +
+
+
+
+ 这是一条普通的通知消息 +
+
+
+
+`; + +exports[`csr snapshot test > csr test src/notice-bar/_example/custom.tsx 1`] = ` +
+
+
+ + + +
+
+
+ 提示文字描述提示文字描述提示文字描述 +
+
+
+ + + +
+
+
+`; + +exports[`csr snapshot test > csr test src/notice-bar/_example/customization.tsx 1`] = ` +
+
+
+ + + +
+
+
+ 提示文字描述提示文字描述提示文字描述提示文字描述提示文字描述提示文字描述 + + + + 详情 + + + +
+
+
+ + + +
+
+
+`; + +exports[`csr snapshot test > csr test src/notice-bar/_example/event.tsx 1`] = ` +
+
+
+ + + +
+
+
+ 这是一条普通的消息通知 +
+
+
+ + + +
+
+
+`; + +exports[`csr snapshot test > csr test src/notice-bar/_example/icon.tsx 1`] = ` +
+
+
+ + + +
+
+
+ 提示文字描述提示文字描述提示文字描述 +
+
+
+
+`; + +exports[`csr snapshot test > csr test src/notice-bar/_example/mobile.tsx 1`] = ` +
+
+
+

+ NoticeBar 公告栏 +

+

+ 在导航栏下方,用于给用户显示提示消息。 +

+
+
+
+

+ 01 组件类型 +

+

+ 纯文字的公告栏 +

+
+
+
+
+
+ 这是一条普通的通知消息 +
+
+
+
+
+
+
+

+ 带图标静态公告栏 +

+
+
+
+
+ + + +
+
+
+ 提示文字描述提示文字描述提示文字描述 +
+
+
+
+
+
+
+

+ 带关闭的公告栏 +

+
+
+
+
+ + + +
+
+
+ 这是一条普通的通知信息 +
+
+
+ + + +
+
+
+
+
+
+

+ 带入口的公告栏 +

+
+
+
+
+ + + +
+
+
+ 这是一条普通的消息通知 +
+
+
+ + + +
+
+
+
+
+
+

+ 自定样式的公告栏 +

+
+
+
+
+ + + +
+
+
+ 提示文字描述提示文字描述提示文字描述 +
+
+
+ + + +
+
+
+
+
+
+

+ 自定义内容的公告栏 +

+
+
+
+
+ + + +
+
+
+ 提示文字描述提示文字描述提示文字描述提示文字描述提示文字描述提示文字描述 + + + + 详情 + + + +
+
+
+ + + +
+
+
+
+
+
+

+ 02 组件状态 +

+

+ 公告栏类型有普通(info)、警示(warning)、成功(success)、错误(error) +

+
+
+
+
+ + + +
+
+
+ 默认状态公告栏默认状态公告栏 +
+
+
+
+
+ + + +
+
+
+ 成功状态公告栏成功状态公告栏 +
+
+
+
+
+ + + +
+
+
+ 警示状态公告栏警示状态公告栏 +
+
+
+
+
+ + + +
+
+
+ 错误状态公告栏错误状态公告栏 +
+
+
+
+
+
+
+

+ 03 可滚动的公告栏 +

+

+ 可滚动公告栏有水平 (horizontal) 和垂直 (vertical) +

+
+
+
+
+
+ 提示文字描述提示文字描述提示文字描述提示文字描述文 +
+
+
+
+
+ + + +
+
+
+ 提示文字描述提示文字描述提示文字描述提示文字描述文 +
+
+
+
+
+ + + +
+
+
+
+
+
+ 莫使金樽空对月 +
+
+
+
+ 君不见 +
+
+
+
+ 高堂明镜悲白发 +
+
+
+
+ 朝如青丝暮成雪 +
+
+
+
+ 人生得意须尽欢 +
+
+
+
+ 莫使金樽空对月 +
+
+
+
+ 君不见 +
+
+
+
+
+
+
+
+
+
+`; + +exports[`csr snapshot test > csr test src/notice-bar/_example/scrolling.tsx 1`] = ` +
+
+
+
+ 提示文字描述提示文字描述提示文字描述提示文字描述文 +
+
+
+
+
+ + + +
+
+
+ 提示文字描述提示文字描述提示文字描述提示文字描述文 +
+
+
+
+
+ + + +
+
+
+
+
+
+ 莫使金樽空对月 +
+
+
+
+ 君不见 +
+
+
+
+ 高堂明镜悲白发 +
+
+
+
+ 朝如青丝暮成雪 +
+
+
+
+ 人生得意须尽欢 +
+
+
+
+ 莫使金樽空对月 +
+
+
+
+ 君不见 +
+
+
+
+
+
+
+`; + +exports[`csr snapshot test > csr test src/notice-bar/_example/suffixIcon.tsx 1`] = ` +
+
+
+ + + +
+
+
+ 这是一条普通的通知信息 +
+
+
+ + + +
+
+
+`; + +exports[`csr snapshot test > csr test src/notice-bar/_example/theme.tsx 1`] = ` +
+
+
+ + + +
+
+
+ 默认状态公告栏默认状态公告栏 +
+
+
+
+
+ + + +
+
+
+ 成功状态公告栏成功状态公告栏 +
+
+
+
+
+ + + +
+
+
+ 警示状态公告栏警示状态公告栏 +
+
+
+
+
+ + + +
+
+
+ 错误状态公告栏错误状态公告栏 +
+
+
+
+`; + exports[`csr snapshot test > csr test src/overlay/_example/base.tsx 1`] = `
@@ -25194,6 +26406,24 @@ exports[`ssr snapshot test > ssr test src/navbar/_example/search.tsx 1`] = `" ssr test src/navbar/_example/size.tsx 1`] = `"
标题文字
标题左对齐
大尺寸标题
"`; +exports[`ssr snapshot test > ssr test src/notice-bar/_example/base.tsx 1`] = `"
这是一条普通的通知消息
"`; + +exports[`ssr snapshot test > ssr test src/notice-bar/_example/custom.tsx 1`] = `"
提示文字描述提示文字描述提示文字描述
"`; + +exports[`ssr snapshot test > ssr test src/notice-bar/_example/customization.tsx 1`] = `"
提示文字描述提示文字描述提示文字描述提示文字描述提示文字描述提示文字描述详情
"`; + +exports[`ssr snapshot test > ssr test src/notice-bar/_example/event.tsx 1`] = `"
这是一条普通的消息通知
"`; + +exports[`ssr snapshot test > ssr test src/notice-bar/_example/icon.tsx 1`] = `"
提示文字描述提示文字描述提示文字描述
"`; + +exports[`ssr snapshot test > ssr test src/notice-bar/_example/mobile.tsx 1`] = `"

NoticeBar 公告栏

在导航栏下方,用于给用户显示提示消息。

01 组件类型

纯文字的公告栏

这是一条普通的通知消息

带图标静态公告栏

提示文字描述提示文字描述提示文字描述

带关闭的公告栏

这是一条普通的通知信息

带入口的公告栏

这是一条普通的消息通知

自定样式的公告栏

提示文字描述提示文字描述提示文字描述

自定义内容的公告栏

提示文字描述提示文字描述提示文字描述提示文字描述提示文字描述提示文字描述详情

02 组件状态

公告栏类型有普通(info)、警示(warning)、成功(success)、错误(error)

默认状态公告栏默认状态公告栏
成功状态公告栏成功状态公告栏
警示状态公告栏警示状态公告栏
错误状态公告栏错误状态公告栏

03 可滚动的公告栏

可滚动公告栏有水平 (horizontal) 和垂直 (vertical)

提示文字描述提示文字描述提示文字描述提示文字描述文
提示文字描述提示文字描述提示文字描述提示文字描述文
莫使金樽空对月
君不见
高堂明镜悲白发
朝如青丝暮成雪
人生得意须尽欢
莫使金樽空对月
君不见
"`; + +exports[`ssr snapshot test > ssr test src/notice-bar/_example/scrolling.tsx 1`] = `"
提示文字描述提示文字描述提示文字描述提示文字描述文
提示文字描述提示文字描述提示文字描述提示文字描述文
莫使金樽空对月
君不见
高堂明镜悲白发
朝如青丝暮成雪
人生得意须尽欢
莫使金樽空对月
君不见
"`; + +exports[`ssr snapshot test > ssr test src/notice-bar/_example/suffixIcon.tsx 1`] = `"
这是一条普通的通知信息
"`; + +exports[`ssr snapshot test > ssr test src/notice-bar/_example/theme.tsx 1`] = `"
默认状态公告栏默认状态公告栏
成功状态公告栏成功状态公告栏
警示状态公告栏警示状态公告栏
错误状态公告栏错误状态公告栏
"`; + exports[`ssr snapshot test > ssr test src/overlay/_example/base.tsx 1`] = `"
"`; exports[`ssr snapshot test > ssr test src/overlay/_example/index.tsx 1`] = `"

Overlay 遮罩层

通过遮罩层,可以强调部分内容

01 组件

基础遮罩层

"`; diff --git a/test/snap/__snapshots__/ssr.test.jsx.snap b/test/snap/__snapshots__/ssr.test.jsx.snap index a9fa0e2d..c6605a6f 100644 --- a/test/snap/__snapshots__/ssr.test.jsx.snap +++ b/test/snap/__snapshots__/ssr.test.jsx.snap @@ -174,6 +174,24 @@ exports[`ssr snapshot test > ssr test src/navbar/_example/search.tsx 1`] = `" ssr test src/navbar/_example/size.tsx 1`] = `"
标题文字
标题左对齐
大尺寸标题
"`; +exports[`ssr snapshot test > ssr test src/notice-bar/_example/base.tsx 1`] = `"
这是一条普通的通知消息
"`; + +exports[`ssr snapshot test > ssr test src/notice-bar/_example/custom.tsx 1`] = `"
提示文字描述提示文字描述提示文字描述
"`; + +exports[`ssr snapshot test > ssr test src/notice-bar/_example/customization.tsx 1`] = `"
提示文字描述提示文字描述提示文字描述提示文字描述提示文字描述提示文字描述详情
"`; + +exports[`ssr snapshot test > ssr test src/notice-bar/_example/event.tsx 1`] = `"
这是一条普通的消息通知
"`; + +exports[`ssr snapshot test > ssr test src/notice-bar/_example/icon.tsx 1`] = `"
提示文字描述提示文字描述提示文字描述
"`; + +exports[`ssr snapshot test > ssr test src/notice-bar/_example/mobile.tsx 1`] = `"

NoticeBar 公告栏

在导航栏下方,用于给用户显示提示消息。

01 组件类型

纯文字的公告栏

这是一条普通的通知消息

带图标静态公告栏

提示文字描述提示文字描述提示文字描述

带关闭的公告栏

这是一条普通的通知信息

带入口的公告栏

这是一条普通的消息通知

自定样式的公告栏

提示文字描述提示文字描述提示文字描述

自定义内容的公告栏

提示文字描述提示文字描述提示文字描述提示文字描述提示文字描述提示文字描述详情

02 组件状态

公告栏类型有普通(info)、警示(warning)、成功(success)、错误(error)

默认状态公告栏默认状态公告栏
成功状态公告栏成功状态公告栏
警示状态公告栏警示状态公告栏
错误状态公告栏错误状态公告栏

03 可滚动的公告栏

可滚动公告栏有水平 (horizontal) 和垂直 (vertical)

提示文字描述提示文字描述提示文字描述提示文字描述文
提示文字描述提示文字描述提示文字描述提示文字描述文
莫使金樽空对月
君不见
高堂明镜悲白发
朝如青丝暮成雪
人生得意须尽欢
莫使金樽空对月
君不见
"`; + +exports[`ssr snapshot test > ssr test src/notice-bar/_example/scrolling.tsx 1`] = `"
提示文字描述提示文字描述提示文字描述提示文字描述文
提示文字描述提示文字描述提示文字描述提示文字描述文
莫使金樽空对月
君不见
高堂明镜悲白发
朝如青丝暮成雪
人生得意须尽欢
莫使金樽空对月
君不见
"`; + +exports[`ssr snapshot test > ssr test src/notice-bar/_example/suffixIcon.tsx 1`] = `"
这是一条普通的通知信息
"`; + +exports[`ssr snapshot test > ssr test src/notice-bar/_example/theme.tsx 1`] = `"
默认状态公告栏默认状态公告栏
成功状态公告栏成功状态公告栏
警示状态公告栏警示状态公告栏
错误状态公告栏错误状态公告栏
"`; + exports[`ssr snapshot test > ssr test src/overlay/_example/base.tsx 1`] = `"
"`; exports[`ssr snapshot test > ssr test src/overlay/_example/index.tsx 1`] = `"

Overlay 遮罩层

通过遮罩层,可以强调部分内容

01 组件

基础遮罩层

"`;