diff --git a/site/mobile/mobile.config.js b/site/mobile/mobile.config.js index d5967f20..ef7b4e1e 100644 --- a/site/mobile/mobile.config.js +++ b/site/mobile/mobile.config.js @@ -210,7 +210,7 @@ export default { { title: 'TabBar 标签栏', name: 'tab-bar', - component: () => import('tdesign-mobile-react/tab-bar/_example/mobile.jsx'), + component: () => import('tdesign-mobile-react/tab-bar/_example/mobile.tsx'), }, { title: 'Fab 悬浮按钮', diff --git a/src/_common b/src/_common index 074d44f1..3e51c011 160000 --- a/src/_common +++ b/src/_common @@ -1 +1 @@ -Subproject commit 074d44f1a1b06c4ee97759e3edf6cb3bbef2f61a +Subproject commit 3e51c01173a3a30cefe60dae7e802231c787d410 diff --git a/src/tab-bar/TabBar.tsx b/src/tab-bar/TabBar.tsx index 9cafeb0a..348c7883 100644 --- a/src/tab-bar/TabBar.tsx +++ b/src/tab-bar/TabBar.tsx @@ -1,47 +1,59 @@ import React, { forwardRef, memo, useMemo, useRef } from 'react'; import cls from 'classnames'; -import useConfig from '../_util/useConfig'; import useDefault from '../_util/useDefault'; import type { StyledProps } from '../common'; import type { TdTabBarProps } from './type'; import { TabBarProvider } from './TabBarContext'; +import parseTNode from '../_util/parseTNode'; +import useDefaultProps from '../hooks/useDefaultProps'; +import { usePrefixClass } from '../hooks/useClass'; +import { tabBarDefaultProps } from './defaultProps'; export interface TabBarProps extends TdTabBarProps, StyledProps {} -const TabBar = forwardRef((props, ref) => { - const { bordered, fixed, onChange, value, defaultValue } = props; - const { classPrefix } = useConfig(); - const name = `${classPrefix}-tab-bar`; +const TabBar = forwardRef((originProps, ref) => { + const props = useDefaultProps(originProps, tabBarDefaultProps); + const { bordered, fixed, onChange, value, defaultValue, safeAreaInsetBottom, shape, split, theme, children } = props; + + const tabBarClass = usePrefixClass('tab-bar'); const [activeValue, onToggleActiveValue] = useDefault(value, defaultValue, onChange); const defaultIndex = useRef(-1); const updateChild = onToggleActiveValue; - const tabBarClass = cls(name, { - [`${name}--bordered`]: bordered, - [`${name}--fixed`]: fixed, - }); + const itemCount = React.Children.count(parseTNode(children)); const memoProviderValues = useMemo( () => ({ defaultIndex, activeValue, updateChild, + shape, + split, + theme, + itemCount, }), - [defaultIndex, activeValue, updateChild], + [defaultIndex, activeValue, updateChild, shape, split, theme, itemCount], ); return ( -
- {props.children} +
+ {parseTNode(children)}
); }); -TabBar.defaultProps = { - bordered: true, - fixed: true, -}; - export default memo(TabBar); diff --git a/src/tab-bar/TabBarContext.tsx b/src/tab-bar/TabBarContext.tsx index 18a41018..36ab8646 100644 --- a/src/tab-bar/TabBarContext.tsx +++ b/src/tab-bar/TabBarContext.tsx @@ -1,11 +1,15 @@ import React, { createContext, MutableRefObject, useMemo } from 'react'; import { ChangeHandler } from '../_util/useDefault'; +import { TdTabBarProps } from './type'; -export const TabBarContext = createContext<{ - defaultIndex: MutableRefObject; - activeValue: number | string | (number | string)[]; - updateChild: ChangeHandler; -}>(null); +export const TabBarContext = createContext< + { + defaultIndex: MutableRefObject; + activeValue: number | string | (number | string)[]; + updateChild: ChangeHandler; + itemCount: number; + } & Pick +>(null); export function TabBarProvider({ children, value }) { const memoValue = useMemo(() => value, [value]); diff --git a/src/tab-bar/TabBarItem.tsx b/src/tab-bar/TabBarItem.tsx index 4d854e9c..a2a8dba1 100644 --- a/src/tab-bar/TabBarItem.tsx +++ b/src/tab-bar/TabBarItem.tsx @@ -1,24 +1,34 @@ import cls from 'classnames'; -import React, { forwardRef, memo, useContext, useEffect, useMemo, useState } from 'react'; - +import React, { forwardRef, memo, useContext, useEffect, useMemo, useRef, useState } from 'react'; import { CSSTransition } from 'react-transition-group'; +import { Icon } from 'tdesign-icons-react'; import type { StyledProps } from '../common'; import type { TdTabBarItemProps } from './type'; import { TabBarContext } from './TabBarContext'; import Badge from '../badge'; -import useConfig from '../_util/useConfig'; import useTabBarCssTransition from './useTabBarCssTransition'; +import parseTNode from '../_util/parseTNode'; +import useDefaultProps from '../hooks/useDefaultProps'; +import { usePrefixClass } from '../hooks/useClass'; export interface TabBarItemProps extends TdTabBarItemProps, StyledProps {} -const defaultBadgeOffset = [0, 5]; +const defaultBadgeOffset = [0, 0]; const defaultBadgeMaxCount = 99; -const TabBarItem = forwardRef((props, ref) => { +const TabBarItem = forwardRef((originProps, ref) => { + const props = useDefaultProps(originProps, {}); const { subTabBar, icon, badgeProps, value, children } = props; const hasSubTabBar = useMemo(() => !!subTabBar, [subTabBar]); - const { defaultIndex, activeValue, updateChild } = useContext(TabBarContext); + const { defaultIndex, activeValue, updateChild, shape, split, theme, itemCount } = useContext(TabBarContext); + + const tabBarItemClass = usePrefixClass('tab-bar-item'); + + const textNode = useRef(null); + + const [iconOnly, setIconOnly] = useState(false); + // 组件每次 render 生成一个临时的当前组件唯一值 const [currentName] = useState(() => { if (value) { @@ -27,9 +37,10 @@ const TabBarItem = forwardRef((props, ref) => { return (defaultIndex.current += 1); }); - const { classPrefix } = useConfig(); - - const componentName = `${classPrefix}-tab-bar-item`; + useEffect(() => { + const height = textNode?.current?.clientHeight; + setIconOnly(Number(height) === 0); + }, [textNode]); const [isSpread, setIsSpread] = useState(false); @@ -42,6 +53,8 @@ const TabBarItem = forwardRef((props, ref) => { const mergedBadgeProps = useMemo( () => ({ + count: 0, + dot: false, offset: defaultBadgeOffset, maxCount: defaultBadgeMaxCount, ...badgeProps, @@ -83,68 +96,92 @@ const TabBarItem = forwardRef((props, ref) => { setIsSpread(() => false); }; - const tabItemCls = cls(componentName, { - [`${classPrefix}-no-border`]: icon, - }); - const tabItemInnerCls = cls(`${componentName}__content`, { - [`${classPrefix}-is-checked`]: isChecked, - [`${componentName}--onlytext`]: !icon, + /** 拥挤否 */ + const crowded = itemCount > 3; + + const tabItemCls = cls( + tabBarItemClass, + { + [`${tabBarItemClass}--split`]: split, + [`${tabBarItemClass}--text-only`]: !icon, + [`${tabBarItemClass}--crowded`]: crowded, + }, + `${tabBarItemClass}--${shape}`, + ); + const tabItemInnerCls = cls( + `${tabBarItemClass}__content`, + { + [`${tabBarItemClass}__content--checked`]: isChecked, + }, + `${tabBarItemClass}__content--${theme}`, + ); + const tabItemTextCls = cls(`${tabBarItemClass}__text`, { + [`${tabBarItemClass}__text--small`]: icon, }); - const tabItemIconCls = cls(`${componentName}__icon`); - const tabItemSpreadCls = cls(`${componentName}__spread`); - const tabItemSpreadItemCls = cls(`${componentName}__spread-item`); - const tabItemTextCls = cls(`${componentName}__text`); - const tabItemIconMenuCls = cls(`${componentName}__icon-menu`); const transitionClsNames = useTabBarCssTransition({ name: 'spread', }); + const iconSize = `${iconOnly ? 24 : 20}px`; + + const iconContent = + icon && + React.cloneElement(icon, { + style: { fontSize: iconSize }, + }); + return ( -
-
+
+
{icon && ( -
+
{badgeProps && (badgeProps?.dot || badgeProps?.count) ? ( - + ) : ( - icon + iconContent )}
)} {children && ( -
- {shouldShowSubTabBar &&
} - {children} +
+ {shouldShowSubTabBar && ( + <> + +
+ + )} + {parseTNode(children)}
)} - - -
    - {subTabBar?.map((child, index) => ( -
  • { - e.stopPropagation(); - selectChild(child.value || index); - }} - > - {child.label} -
  • - ))} -
-
+ + +
    + {subTabBar?.map((child, index) => ( +
    { + e.stopPropagation(); + selectChild(child.value || index); + }} + > + {index !== 0 &&
    } +
    {child.label}
    +
    + ))} +
+
); }); diff --git a/src/tab-bar/_example/badge-props.tsx b/src/tab-bar/_example/badge-props.tsx new file mode 100644 index 00000000..b844fda6 --- /dev/null +++ b/src/tab-bar/_example/badge-props.tsx @@ -0,0 +1,41 @@ +import React, { useState, useEffect } from 'react'; +import { TabBar, TabBarItem } from 'tdesign-mobile-react'; +import { Icon } from 'tdesign-icons-react'; + +function TabBarBaseDemo() { + const list = [ + { name: 'label_1', text: '首页', icon: 'home', badgeProps: { count: 16 }, ariaLabel: '首页,有16条消息' }, + { name: 'label_2', text: '软件', icon: 'app', badgeProps: { dot: true }, ariaLabel: '软件,有新的消息' }, + { name: 'label_3', text: '聊天', icon: 'chat', badgeProps: { count: 'New' }, ariaLabel: '聊天,New' }, + { name: 'label_4', text: '我的', icon: 'user', badgeProps: { count: '···' }, ariaLabel: '我的,有很多消息' }, + ]; + const [value, setValue] = useState('label_1'); + + const change = (changeValue) => { + setValue(changeValue); + console.log('TabBar 值改变为:', changeValue); + }; + + useEffect(() => { + console.log('当前值:', value); + }, [value]); + + return ( +
+ + {list.map((item, i) => ( + } + value={item.name} + badgeProps={item.badgeProps} + > + {item.text} + + ))} + +
+ ); +} + +export default TabBarBaseDemo; diff --git a/src/tab-bar/_example/badge-props.jsx b/src/tab-bar/_example/base.tsx similarity index 50% rename from src/tab-bar/_example/badge-props.jsx rename to src/tab-bar/_example/base.tsx index 8c6fab1b..2136f4ad 100644 --- a/src/tab-bar/_example/badge-props.jsx +++ b/src/tab-bar/_example/base.tsx @@ -1,13 +1,13 @@ import React, { useState, useEffect } from 'react'; import { TabBar, TabBarItem } from 'tdesign-mobile-react'; -import { AppIcon } from 'tdesign-icons-react'; +import { Icon } from 'tdesign-icons-react'; function TabBarBaseDemo() { const list = [ - { name: 'label_1', text: '文字', icon: , badgeProps: { count: 16 } }, - { name: 'label_2', text: '文字', icon: , badgeProps: { dot: true } }, - { name: 'label_3', text: '文字', icon: , badgeProps: { count: 'New' } }, - { name: 'label_4', text: '文字', icon: , badgeProps: { count: '···' } }, + { value: 'label_1', label: '首页', icon: 'home' }, + { value: 'label_2', label: '应用', icon: 'app' }, + { value: 'label_3', label: '聊天', icon: 'chat' }, + { value: 'label_4', label: '我的', icon: 'user' }, ]; const [value, setValue] = useState('label_1'); @@ -22,10 +22,10 @@ function TabBarBaseDemo() { return (
- + {list.map((item, i) => ( - - {item.text} + } value={item.value}> + {item.label} ))} diff --git a/src/tab-bar/_example/base.jsx b/src/tab-bar/_example/custom.tsx similarity index 56% rename from src/tab-bar/_example/base.jsx rename to src/tab-bar/_example/custom.tsx index a3a46da6..a8fb00eb 100644 --- a/src/tab-bar/_example/base.jsx +++ b/src/tab-bar/_example/custom.tsx @@ -1,13 +1,13 @@ import React, { useState, useEffect } from 'react'; import { TabBar, TabBarItem } from 'tdesign-mobile-react'; -import { AppIcon } from 'tdesign-icons-react'; +import { Icon } from 'tdesign-icons-react'; function TabBarBaseDemo() { const list = [ - { name: 'label_1', text: '文字', icon: }, - { name: 'label_2', text: '文字', icon: }, - { name: 'label_3', text: '文字', icon: }, - { name: 'label_4', text: '文字', icon: }, + { value: 'label_1', icon: 'home', ariaLabel: '首页' }, + { value: 'label_2', icon: 'app', ariaLabel: '软件' }, + { value: 'label_3', icon: 'chat', ariaLabel: '聊天' }, + { value: 'label_4', icon: 'user', ariaLabel: '我的' }, ]; const [value, setValue] = useState('label_1'); @@ -21,12 +21,10 @@ function TabBarBaseDemo() { }, [value]); return ( -
+
{list.map((item, i) => ( - - {item.text} - + } value={item.value} /> ))}
diff --git a/src/tab-bar/_example/mobile.jsx b/src/tab-bar/_example/mobile.tsx similarity index 58% rename from src/tab-bar/_example/mobile.jsx rename to src/tab-bar/_example/mobile.tsx index d7e63e98..46108059 100644 --- a/src/tab-bar/_example/mobile.jsx +++ b/src/tab-bar/_example/mobile.tsx @@ -7,28 +7,36 @@ import BadgePropsDemo from './badge-props'; import TextDemo from './text'; import PureIconDemo from './pure-icon'; import TextSpreadDemo from './text-spread'; +import RoundDemo from './round'; +import CustomDemo from './custom'; import './style/index.less'; function TabBarMobileDemo() { return (
- - - - - - - - + + + + + + + + + + + + + +
); } diff --git a/src/tab-bar/_example/pure-icon.jsx b/src/tab-bar/_example/pure-icon.tsx similarity index 53% rename from src/tab-bar/_example/pure-icon.jsx rename to src/tab-bar/_example/pure-icon.tsx index 813d0479..06a2f07a 100644 --- a/src/tab-bar/_example/pure-icon.jsx +++ b/src/tab-bar/_example/pure-icon.tsx @@ -1,9 +1,14 @@ import React, { useState, useEffect } from 'react'; import { TabBar, TabBarItem } from 'tdesign-mobile-react'; -import { AppIcon } from 'tdesign-icons-react'; +import { Icon } from 'tdesign-icons-react'; function TabBarBaseDemo() { - const list = [{ name: 'label_1' }, { name: 'label_2' }, { name: 'label_3' }, { name: 'label_4' }]; + const list = [ + { value: 'label_1', icon: 'home', ariaLabel: '首页' }, + { value: 'label_2', icon: 'app', ariaLabel: '软件' }, + { value: 'label_3', icon: 'chat', ariaLabel: '聊天' }, + { value: 'label_4', icon: 'user', ariaLabel: '我的' }, + ]; const [value, setValue] = useState('label_1'); const change = (changeValue) => { @@ -17,9 +22,9 @@ function TabBarBaseDemo() { return (
- + {list.map((item, i) => ( - } value={item.name} /> + } value={item.value} /> ))}
diff --git a/src/tab-bar/_example/round.tsx b/src/tab-bar/_example/round.tsx new file mode 100644 index 00000000..201f1b23 --- /dev/null +++ b/src/tab-bar/_example/round.tsx @@ -0,0 +1,34 @@ +import React, { useState, useEffect } from 'react'; +import { TabBar, TabBarItem } from 'tdesign-mobile-react'; +import { Icon } from 'tdesign-icons-react'; + +function TabBarBaseDemo() { + const list = [ + { value: 'label_1', icon: 'home', ariaLabel: '首页' }, + { value: 'label_2', icon: 'app', ariaLabel: '软件' }, + { value: 'label_3', icon: 'chat', ariaLabel: '聊天' }, + { value: 'label_4', icon: 'user', ariaLabel: '我的' }, + ]; + const [value, setValue] = useState('label_1'); + + const change = (changeValue) => { + setValue(changeValue); + console.log('TabBar 值改变为:', changeValue); + }; + + useEffect(() => { + console.log('当前值:', value); + }, [value]); + + return ( +
+ + {list.map((item, i) => ( + } value={item.value} /> + ))} + +
+ ); +} + +export default TabBarBaseDemo; diff --git a/src/tab-bar/_example/style/index.less b/src/tab-bar/_example/style/index.less index 374185e0..21a757ef 100644 --- a/src/tab-bar/_example/style/index.less +++ b/src/tab-bar/_example/style/index.less @@ -5,4 +5,24 @@ .t-tab-bar + .t-tab-bar { margin-top: 16px; } + + .section { + &-custom { + --td-tab-bar-border-color: #e7e7e7; + --td-tab-bar-bg-color: #eee; + --td-tab-bar-hover-color: #ddd; + --td-tab-bar-item-color: #bbb; + --td-tab-bar-item-active-color: #333; + } + } +} + +:root[theme-mode='dark'] { + .tdesign-mobile-demo { + .section { + &-custom { + --td-tab-bar-color: rgba(0, 0, 0, 0.9); + } + } + } } diff --git a/src/tab-bar/_example/text-spread.jsx b/src/tab-bar/_example/text-spread.jsx deleted file mode 100644 index 0b4b2883..00000000 --- a/src/tab-bar/_example/text-spread.jsx +++ /dev/null @@ -1,47 +0,0 @@ -import React from 'react'; -import { TabBar, TabBarItem } from 'tdesign-mobile-react'; - -function TabBarBaseDemo() { - const list = [ - { - name: 'label_1', - text: '标签栏一', - }, - { - name: 'label_2', - text: '标签栏二', - }, - { - name: 'label_3', - text: '此处展开', - children: [ - { - value: 'spread_3', - label: '展开项三', - }, - { - value: 'spread_2', - label: '展开项二', - }, - { - value: 'spread_1', - label: '展开项一', - }, - ], - }, - ]; - - return ( -
- - {list.map((item, i) => ( - - {item.text} - - ))} - -
- ); -} - -export default TabBarBaseDemo; diff --git a/src/tab-bar/_example/text-spread.tsx b/src/tab-bar/_example/text-spread.tsx new file mode 100644 index 00000000..75698218 --- /dev/null +++ b/src/tab-bar/_example/text-spread.tsx @@ -0,0 +1,49 @@ +import React from 'react'; +import { TabBar, TabBarItem } from 'tdesign-mobile-react'; + +function TabBarBaseDemo() { + const list = [ + { + value: 'home', + label: '首页', + icon: 'home', + }, + { + value: 'app', + label: '应用', + icon: 'app', + }, + { + value: 'user', + label: '我的', + children: [ + { + value: 'info', + label: '基本信息', + }, + { + value: 'home-page', + label: '个人主页', + }, + { + value: 'setting', + label: '设置', + }, + ], + }, + ]; + + return ( +
+ + {list.map((item, i) => ( + + {item.label} + + ))} + +
+ ); +} + +export default TabBarBaseDemo; diff --git a/src/tab-bar/_example/text.jsx b/src/tab-bar/_example/text.tsx similarity index 59% rename from src/tab-bar/_example/text.jsx rename to src/tab-bar/_example/text.tsx index 66c816bd..0cc38e73 100644 --- a/src/tab-bar/_example/text.jsx +++ b/src/tab-bar/_example/text.tsx @@ -3,12 +3,12 @@ import { TabBar, TabBarItem } from 'tdesign-mobile-react'; function TabBarBaseDemo() { const list = [ - { name: 'label_1', text: '标签栏一' }, - { name: 'label_2', text: '标签栏二' }, - { name: 'label_3', text: '标签栏三' }, - { name: 'label_4', text: '标签栏四' }, + { value: 'home', label: '首页' }, + { value: 'app', label: '应用' }, + { value: 'chat', label: '聊天' }, + { value: 'user', label: '我的' }, ]; - const [value, setValue] = useState('label_1'); + const [value, setValue] = useState('home'); const change = (changeValue) => { setValue(changeValue); @@ -21,10 +21,10 @@ function TabBarBaseDemo() { return (
- + {list.map((item, i) => ( - - {item.text} + + {item.label} ))} diff --git a/src/tab-bar/defaultProps.ts b/src/tab-bar/defaultProps.ts new file mode 100644 index 00000000..af85cd59 --- /dev/null +++ b/src/tab-bar/defaultProps.ts @@ -0,0 +1,15 @@ +/** + * 该文件为脚本自动生成文件,请勿随意修改。如需修改请联系 PMC + * */ + +import { TdTabBarProps } from './type'; + +export const tabBarDefaultProps: TdTabBarProps = { + bordered: true, + fixed: true, + safeAreaInsetBottom: true, + shape: 'normal', + split: true, + theme: 'normal', + defaultValue: undefined, +}; diff --git a/src/tab-bar/style/index.js b/src/tab-bar/style/index.js index 702d60a8..5d6c7d7d 100644 --- a/src/tab-bar/style/index.js +++ b/src/tab-bar/style/index.js @@ -1 +1,2 @@ -import '../../_common/style/mobile/components/tab-bar/_index.less'; +import '../../_common/style/mobile/components/tab-bar/v2/_index.less'; +import '../../_common/style/mobile/components/tab-bar-item/v2/_index.less'; diff --git a/src/tab-bar/tab-bar.en-US.md b/src/tab-bar/tab-bar.en-US.md new file mode 100644 index 00000000..087a8848 --- /dev/null +++ b/src/tab-bar/tab-bar.en-US.md @@ -0,0 +1,50 @@ +:: BASE_DOC :: + +## API + +### TabBar Props + +name | type | default | description | required +-- | -- | -- | -- | -- +className | String | - | className of component | N +style | Object | - | CSS(Cascading Style Sheets),Typescript:`React.CSSProperties` | N +bordered | Boolean | true | \- | N +children | TNode | - | Typescript:`TNode`。[see more ts definition](https://github.com/Tencent/tdesign-mobile-react/blob/develop/src/common.ts) | N +fixed | Boolean | true | \- | N +safeAreaInsetBottom | Boolean | true | \- | N +shape | String | 'normal' | options: normal/round | N +split | Boolean | true | \- | N +theme | String | 'normal' | options: normal/tag | N +value | String / Number / Array | undefined | Typescript:`string \| number \| Array` | N +defaultValue | String / Number / Array | undefined | uncontrolled property。Typescript:`string \| number \| Array` | N +onChange | Function | | Typescript:`(value: string \| number) => void`
| N + + +### TabBarItem Props + +name | type | default | description | required +-- | -- | -- | -- | -- +className | String | - | className of component | N +style | Object | - | CSS(Cascading Style Sheets),Typescript:`React.CSSProperties` | N +badgeProps | Object | - | Typescript:`BadgeProps`,[Badge API Documents](./badge?tab=api)。[see more ts definition](https://github.com/Tencent/tdesign-mobile-react/tree/develop/src/tab-bar/type.ts) | N +children | TNode | - | Typescript:`TNode`。[see more ts definition](https://github.com/Tencent/tdesign-mobile-react/blob/develop/src/common.ts) | N +icon | TElement | - | Typescript:`TNode`。[see more ts definition](https://github.com/Tencent/tdesign-mobile-react/blob/develop/src/common.ts) | N +subTabBar | Array | - | Typescript:`SubTabBarItem[] ` `interface SubTabBarItem { value: string; label: string }`。[see more ts definition](https://github.com/Tencent/tdesign-mobile-react/tree/develop/src/tab-bar/type.ts) | N +value | String / Number | - | \- | N + +### CSS Variables + +The component provides the following CSS variables, which can be used to customize styles. +Name | Default Value | Description +-- | -- | -- +--td-tab-bar-active-bg | @brand-color-light | - +--td-tab-bar-active-color | @brand-color | - +--td-tab-bar-bg-color | @bg-color-container | - +--td-tab-bar-border-color | @border-color | - +--td-tab-bar-color | @font-gray-1 | - +--td-tab-bar-height | 40px | - +--td-tab-bar-hover-bg-color | rgba(0, 0, 0, .05) | - +--td-tab-bar-spread-border-color | @border-color | - +--td-tab-bar-spread-shadow | @shadow-3 | - +--td-tab-bar-border-color | @border-color | - +--td-tab-bar-round-shadow | @shadow-3 | - \ No newline at end of file diff --git a/src/tab-bar/tab-bar.md b/src/tab-bar/tab-bar.md index acb6981d..3b381250 100644 --- a/src/tab-bar/tab-bar.md +++ b/src/tab-bar/tab-bar.md @@ -4,23 +4,47 @@ ### TabBar Props -名称 | 类型 | 默认值 | 说明 | 必传 +名称 | 类型 | 默认值 | 描述 | 必传 -- | -- | -- | -- | -- className | String | - | 类名 | N style | Object | - | 样式,TS 类型:`React.CSSProperties` | N bordered | Boolean | true | 是否显示外边框 | N +children | TNode | - | 标签栏内容。TS 类型:`TNode`。[通用类型定义](https://github.com/Tencent/tdesign-mobile-react/blob/develop/src/common.ts) | N fixed | Boolean | true | 是否固定在底部 | N -value | String / Number / Array | undefined | 当前选中标签的索引。TS 类型:`string | number | Array` | N -defaultValue | String / Number / Array | undefined | 当前选中标签的索引。非受控属性。TS 类型:`string | number | Array` | N -onChange | Function | | TS 类型:`() => void`
选中标签切换时触发 | N +safeAreaInsetBottom | Boolean | true | 是否为 iPhoneX 留出底部安全距离 | N +shape | String | 'normal' | 标签栏的形状。可选项:normal/round | N +split | Boolean | true | 是否需要分割线 | N +theme | String | 'normal' | 选项风格。可选项:normal/tag | N +value | String / Number / Array | undefined | 当前选中标签的索引。TS 类型:`string \| number \| Array` | N +defaultValue | String / Number / Array | undefined | 当前选中标签的索引。非受控属性。TS 类型:`string \| number \| Array` | N +onChange | Function | | TS 类型:`(value: string \| number) => void`
选中标签切换时触发 | N + ### TabBarItem Props -名称 | 类型 | 默认值 | 说明 | 必传 +名称 | 类型 | 默认值 | 描述 | 必传 -- | -- | -- | -- | -- className | String | - | 类名 | N style | Object | - | 样式,TS 类型:`React.CSSProperties` | N -badgeProps | Object | - | 图标右上角提示信息。TS 类型:`TdBadgeProps`,[Badge API Documents](./badge?tab=api)。[详细类型定义](https://github.com/Tencent/tdesign-mobile-react/tree/develop/src/tab-bar/type.ts) | N -icon | TNode | - | 图标名称。TS 类型:`string | TNode`。[通用类型定义](https://github.com/Tencent/tdesign-mobile-react/blob/develop/src/common.ts) | N +badgeProps | Object | - | 图标右上角提示信息。TS 类型:`BadgeProps`,[Badge API Documents](./badge?tab=api)。[详细类型定义](https://github.com/Tencent/tdesign-mobile-react/tree/develop/src/tab-bar/type.ts) | N +children | TNode | - | 标签内容。TS 类型:`TNode`。[通用类型定义](https://github.com/Tencent/tdesign-mobile-react/blob/develop/src/common.ts) | N +icon | TElement | - | 图标名称。TS 类型:`TNode`。[通用类型定义](https://github.com/Tencent/tdesign-mobile-react/blob/develop/src/common.ts) | N subTabBar | Array | - | 二级菜单。TS 类型:`SubTabBarItem[] ` `interface SubTabBarItem { value: string; label: string }`。[详细类型定义](https://github.com/Tencent/tdesign-mobile-react/tree/develop/src/tab-bar/type.ts) | N value | String / Number | - | 标识符 | N + +### CSS Variables + +组件提供了下列 CSS 变量,可用于自定义样式。 +名称 | 默认值 | 描述 +-- | -- | -- +--td-tab-bar-active-bg | @brand-color-light | - +--td-tab-bar-active-color | @brand-color | - +--td-tab-bar-bg-color | @bg-color-container | - +--td-tab-bar-border-color | @border-color | - +--td-tab-bar-color | @font-gray-1 | - +--td-tab-bar-height | 40px | - +--td-tab-bar-hover-bg-color | rgba(0, 0, 0, .05) | - +--td-tab-bar-spread-border-color | @border-color | - +--td-tab-bar-spread-shadow | @shadow-3 | - +--td-tab-bar-border-color | @border-color | - +--td-tab-bar-round-shadow | @shadow-3 | - \ No newline at end of file diff --git a/src/tab-bar/type.ts b/src/tab-bar/type.ts index 004e9cf3..2dfbae2c 100644 --- a/src/tab-bar/type.ts +++ b/src/tab-bar/type.ts @@ -4,8 +4,8 @@ * 该文件为脚本自动生成文件,请勿随意修改。如需修改请联系 PMC * */ -import { TdBadgeProps } from '../badge'; -import { TNode } from '../common'; +import { BadgeProps } from '../badge'; +import { TNode, TElement } from '../common'; export interface TdTabBarProps { /** @@ -13,11 +13,35 @@ export interface TdTabBarProps { * @default true */ bordered?: boolean; + /** + * 标签栏内容 + */ + children?: TNode; /** * 是否固定在底部 * @default true */ fixed?: boolean; + /** + * 是否为 iPhoneX 留出底部安全距离 + * @default true + */ + safeAreaInsetBottom?: boolean; + /** + * 标签栏的形状 + * @default 'normal' + */ + shape?: 'normal' | 'round'; + /** + * 是否需要分割线 + * @default true + */ + split?: boolean; + /** + * 选项风格 + * @default 'normal' + */ + theme?: 'normal' | 'tag'; /** * 当前选中标签的索引 */ @@ -29,26 +53,33 @@ export interface TdTabBarProps { /** * 选中标签切换时触发 */ - onChange?: () => void; + onChange?: (value: string | number) => void; } export interface TdTabBarItemProps { /** * 图标右上角提示信息 */ - badgeProps?: TdBadgeProps; + badgeProps?: BadgeProps; + /** + * 标签内容 + */ + children?: TNode; /** * 图标名称 */ - icon?: TNode; + icon?: TElement; /** * 二级菜单 */ - subTabBar?: SubTabBarItem[] ; + subTabBar?: SubTabBarItem[]; /** * 标识符 */ value?: string | number; } -export interface SubTabBarItem { value: string; label: string }; +export interface SubTabBarItem { + value: string; + label: string; +} diff --git a/test/snap/__snapshots__/csr.test.jsx.snap b/test/snap/__snapshots__/csr.test.jsx.snap index a6cfcae1..0abd2ff0 100644 --- a/test/snap/__snapshots__/csr.test.jsx.snap +++ b/test/snap/__snapshots__/csr.test.jsx.snap @@ -23531,6 +23531,1750 @@ exports[`csr snapshot test > csr test src/sticky/_example/offset.tsx 1`] = `
`; +exports[`csr snapshot test > csr test src/tab-bar/_example/badge-props.tsx 1`] = ` +
+
+
+
+ +
+
+ +
+ +
+
+ +
+
+
+
+`; + +exports[`csr snapshot test > csr test src/tab-bar/_example/base.tsx 1`] = ` +
+
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+`; + +exports[`csr snapshot test > csr test src/tab-bar/_example/custom.tsx 1`] = ` +
+
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+`; + +exports[`csr snapshot test > csr test src/tab-bar/_example/mobile.tsx 1`] = ` +
+
+
+

+ TabBar 标签栏 +

+

+ 用于在不同功能模块之间进行快速切换,位于页面底部。 +

+
+
+
+

+ 01 组件类型 +

+

+ 纯文本标签栏 +

+
+
+
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+
+
+
+

+ 图标加文字标签栏 +

+
+
+
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+
+
+
+

+ 纯图标标签栏 +

+
+
+
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+
+
+
+

+ 双层级纯文本标签栏 +

+
+
+
+
+
+ +
+
+ +
+
+ +
+
+
+
+
+
+

+ 01 组件类型 +

+

+ 弱选中标签栏 +

+
+
+
+
+
+ +
+
+ +
+ +
+
+ +
+
+
+
+
+
+
+

+ 悬浮胶囊标签栏 +

+
+
+
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+
+
+
+

+ 03 自定义 +

+

+ 自定义样式 +

+
+
+
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+
+
+
+`; + +exports[`csr snapshot test > csr test src/tab-bar/_example/pure-icon.tsx 1`] = ` +
+
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+`; + +exports[`csr snapshot test > csr test src/tab-bar/_example/round.tsx 1`] = ` +
+
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+`; + +exports[`csr snapshot test > csr test src/tab-bar/_example/text.tsx 1`] = ` +
+
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+`; + +exports[`csr snapshot test > csr test src/tab-bar/_example/text-spread.tsx 1`] = ` +
+
+
+
+ +
+
+ +
+
+ +
+
+
+`; + exports[`csr snapshot test > csr test src/tag/_example/checkable.tsx 1`] = `
ssr test src/sticky/_example/index.tsx 1`] = `"
ssr test src/sticky/_example/offset.tsx 1`] = `"
"`; +exports[`ssr snapshot test > ssr test src/tab-bar/_example/badge-props.tsx 1`] = `"
"`; + +exports[`ssr snapshot test > ssr test src/tab-bar/_example/base.tsx 1`] = `"
"`; + +exports[`ssr snapshot test > ssr test src/tab-bar/_example/custom.tsx 1`] = `"
"`; + +exports[`ssr snapshot test > ssr test src/tab-bar/_example/mobile.tsx 1`] = `"

TabBar 标签栏

用于在不同功能模块之间进行快速切换,位于页面底部。

01 组件类型

纯文本标签栏

图标加文字标签栏

纯图标标签栏

双层级纯文本标签栏

01 组件类型

弱选中标签栏

悬浮胶囊标签栏

03 自定义

自定义样式

"`; + +exports[`ssr snapshot test > ssr test src/tab-bar/_example/pure-icon.tsx 1`] = `"
"`; + +exports[`ssr snapshot test > ssr test src/tab-bar/_example/round.tsx 1`] = `"
"`; + +exports[`ssr snapshot test > ssr test src/tab-bar/_example/text.tsx 1`] = `"
"`; + +exports[`ssr snapshot test > ssr test src/tab-bar/_example/text-spread.tsx 1`] = `"
"`; + exports[`ssr snapshot test > ssr test src/tag/_example/checkable.tsx 1`] = `"
可选中的标签
light
未选中态已选中态
dark
未选中态已选中态
outline
未选中态已选中态
light-outline
未选中态已选中态
"`; exports[`ssr snapshot test > ssr test src/tag/_example/closable.tsx 1`] = `"
可关闭标签
文字标签文字标签
"`; diff --git a/test/snap/__snapshots__/ssr.test.jsx.snap b/test/snap/__snapshots__/ssr.test.jsx.snap index 4701822c..b66f9e59 100644 --- a/test/snap/__snapshots__/ssr.test.jsx.snap +++ b/test/snap/__snapshots__/ssr.test.jsx.snap @@ -234,6 +234,22 @@ exports[`ssr snapshot test > ssr test src/sticky/_example/index.tsx 1`] = `"
ssr test src/sticky/_example/offset.tsx 1`] = `"
"`; +exports[`ssr snapshot test > ssr test src/tab-bar/_example/badge-props.tsx 1`] = `"
"`; + +exports[`ssr snapshot test > ssr test src/tab-bar/_example/base.tsx 1`] = `"
"`; + +exports[`ssr snapshot test > ssr test src/tab-bar/_example/custom.tsx 1`] = `"
"`; + +exports[`ssr snapshot test > ssr test src/tab-bar/_example/mobile.tsx 1`] = `"

TabBar 标签栏

用于在不同功能模块之间进行快速切换,位于页面底部。

01 组件类型

纯文本标签栏

图标加文字标签栏

纯图标标签栏

双层级纯文本标签栏

01 组件类型

弱选中标签栏

悬浮胶囊标签栏

03 自定义

自定义样式

"`; + +exports[`ssr snapshot test > ssr test src/tab-bar/_example/pure-icon.tsx 1`] = `"
"`; + +exports[`ssr snapshot test > ssr test src/tab-bar/_example/round.tsx 1`] = `"
"`; + +exports[`ssr snapshot test > ssr test src/tab-bar/_example/text.tsx 1`] = `"
"`; + +exports[`ssr snapshot test > ssr test src/tab-bar/_example/text-spread.tsx 1`] = `"
"`; + exports[`ssr snapshot test > ssr test src/tag/_example/checkable.tsx 1`] = `"
可选中的标签
light
未选中态已选中态
dark
未选中态已选中态
outline
未选中态已选中态
light-outline
未选中态已选中态
"`; exports[`ssr snapshot test > ssr test src/tag/_example/closable.tsx 1`] = `"
可关闭标签
文字标签文字标签
"`;