-
Notifications
You must be signed in to change notification settings - Fork 0
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
1 parent
d9b67e8
commit 29ac385
Showing
10 changed files
with
342 additions
and
1 deletion.
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,17 @@ | ||
.van-tabbar { | ||
display: flex; | ||
width: 100%; | ||
height: 50px; | ||
height: var(--tabbar-height, 50px); | ||
background-color: #fff; | ||
background-color: var(--tabbar-background-color, #fff); | ||
} | ||
.van-tabbar--fixed { | ||
position: fixed; | ||
bottom: 0; | ||
left: 0; | ||
} | ||
.van-tabbar--safe { | ||
padding-bottom: constant(safe-area-inset-bottom); | ||
padding-bottom: env(safe-area-inset-bottom); | ||
} |
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,98 @@ | ||
// packages | ||
import React, { | ||
FunctionComponent, | ||
CSSProperties, | ||
Children, | ||
isValidElement, | ||
cloneElement, | ||
} from 'react'; | ||
import clsx from 'clsx'; | ||
import { View } from 'remax/wechat'; | ||
// internal | ||
import TabbarContext from './TabbarContext'; | ||
import pickStyle from '../tools/pick-style'; | ||
import withDefaultProps from '../tools/with-default-props-advance'; | ||
import './Tabbar.css'; | ||
|
||
// 默认值填充属性 | ||
interface NeutralTabbarProps { | ||
fixed: boolean; | ||
border: boolean; | ||
safeAreaInsetBottom: boolean; | ||
zIndex: number; | ||
// pass down for tabbar item | ||
activeColor: string; | ||
inactiveColor: string; | ||
} | ||
|
||
interface ExogenousTabbarProps { | ||
// 选中索引 | ||
active: number; | ||
// 容器类名,用以覆盖内部 | ||
className?: string; | ||
// trigger on every item click | ||
onChange: (event: { detail: number }) => void; | ||
} | ||
|
||
type TabbarProps = NeutralTabbarProps & ExogenousTabbarProps; | ||
|
||
const DefaultTabbarProps: NeutralTabbarProps = { | ||
fixed: true, | ||
border: true, | ||
safeAreaInsetBottom: true, | ||
zIndex: 1, | ||
// remember TabbarContext default value, createContext type mis-annotation | ||
activeColor: '#1989fa', | ||
inactiveColor: '#7d7e80', | ||
}; | ||
|
||
// TODO - support name match machanism | ||
const Tabbar: FunctionComponent<TabbarProps> = (props) => { | ||
const { | ||
className, | ||
border, | ||
fixed, | ||
safeAreaInsetBottom, | ||
zIndex, | ||
active, | ||
activeColor, | ||
inactiveColor, | ||
children, | ||
onChange, | ||
} = props; | ||
|
||
const style: CSSProperties = { | ||
zIndex, | ||
}; | ||
const classnames = { | ||
container: clsx(className, 'van-tabbar', { | ||
'van-tabbar--fixed': fixed, | ||
'van-tabbar--safe': safeAreaInsetBottom, | ||
'van-hairline--top-bottom': border, | ||
}), | ||
}; | ||
const payload = { | ||
activeColor, | ||
inactiveColor, | ||
}; | ||
const elements = Children.map(children, (child, index) => | ||
!isValidElement(child) | ||
? child | ||
: cloneElement(child, { | ||
active: active === index, | ||
onClick: () => onChange({ detail: index }), | ||
}) | ||
); | ||
|
||
return ( | ||
<TabbarContext.Provider value={payload}> | ||
<View style={pickStyle(style)} className={classnames.container}> | ||
{elements} | ||
</View> | ||
</TabbarContext.Provider> | ||
); | ||
}; | ||
|
||
export default withDefaultProps<ExogenousTabbarProps, NeutralTabbarProps>( | ||
DefaultTabbarProps | ||
)(Tabbar); |
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,14 @@ | ||
// packages | ||
import { createContext } from 'react'; | ||
|
||
interface TabbarContextPayload { | ||
activeColor: string; | ||
inactiveColor: string; | ||
} | ||
|
||
const TabbarContext = createContext<TabbarContextPayload>({ | ||
activeColor: '#1989fa', | ||
inactiveColor: '#7d7e80', | ||
}); | ||
|
||
export default TabbarContext; |
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 @@ | ||
/** | ||
* @description - nothing but export component | ||
*/ | ||
export { default } from './Tabbar'; |
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 @@ | ||
:host { | ||
flex: 1; | ||
} | ||
.van-tabbar-item { | ||
display: flex; | ||
flex-direction: column; | ||
align-items: center; | ||
justify-content: center; | ||
height: 100%; | ||
color: #646566; | ||
color: var(--tabbar-item-text-color, #646566); | ||
font-size: 12px; | ||
font-size: var(--tabbar-item-font-size, 12px); | ||
line-height: 1; | ||
line-height: var(--tabbar-item-line-height, 1); | ||
} | ||
.van-tabbar-item__icon { | ||
position: relative; | ||
margin-bottom: 5px; | ||
margin-bottom: var(--tabbar-item-margin-bottom, 5px); | ||
font-size: 18px; | ||
font-size: var(--tabbar-item-icon-size, 18px); | ||
} | ||
.van-tabbar-item__icon__inner { | ||
display: block; | ||
min-width: 1em; | ||
} | ||
.van-tabbar-item--active { | ||
color: #1989fa; | ||
color: var(--tabbar-item-active-color, #1989fa); | ||
} | ||
.van-tabbar-item__info { | ||
margin-top: 2px; | ||
} |
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,74 @@ | ||
// packages | ||
import React, { | ||
FunctionComponent, | ||
useContext, | ||
CSSProperties, | ||
ReactNode, | ||
} from 'react'; | ||
import clsx from 'clsx'; | ||
import { View } from 'remax/wechat'; | ||
// internal | ||
import Icon from '../Icon'; | ||
import Info from '../Info'; | ||
import { Switch, Case } from '../tools/Switch'; | ||
import TabbarContext from '../Tabbar/TabbarContext'; | ||
import './TabbarItem.css'; | ||
|
||
// 默认值填充属性 | ||
type renderIcon = (active: boolean) => ReactNode; | ||
|
||
interface ExogenousTabbarItemProps { | ||
// use render prop within complicated | ||
icon: string | renderIcon; | ||
// 容器类名,用以覆盖内部 | ||
className?: string; | ||
// 传递 Info 组件 | ||
dot?: boolean; | ||
info?: string; | ||
// 匹配状态,父组件 Tabbar 隐式传递 | ||
active?: boolean; | ||
// 事件绑定,父组件 Tabbar 隐式传递 | ||
onClick?: (event: any) => void; | ||
} | ||
|
||
type TabbarItemProps = ExogenousTabbarItemProps; | ||
|
||
const TabbarItem: FunctionComponent<TabbarItemProps> = (props) => { | ||
const { active, className, children, icon, dot, info, onClick } = props; | ||
const { activeColor, inactiveColor } = useContext(TabbarContext); | ||
const style: CSSProperties = { | ||
// weired css | ||
flex: 1, | ||
color: active ? activeColor : inactiveColor, | ||
}; | ||
const classnames = { | ||
container: clsx(className, 'van-tabbar-item', { | ||
'van-tabbar-item--active': active, | ||
}), | ||
}; | ||
|
||
return ( | ||
<View style={style} className={classnames.container} onClick={onClick}> | ||
{/* item icon */} | ||
<View className="van-tabbar-item__icon"> | ||
<Switch> | ||
<Case in={typeof icon === 'string'}> | ||
<Icon | ||
name={icon as string} | ||
className="van-tabbar-item__icon__inner" | ||
/> | ||
</Case> | ||
<Case default> | ||
{typeof icon === 'function' && icon(active as boolean)} | ||
</Case> | ||
</Switch> | ||
<Info dot={dot} info={info} className="van-tabbar-item__info" /> | ||
</View> | ||
|
||
{/* item text */} | ||
<View className="van-tabbar-item__text">{children}</View> | ||
</View> | ||
); | ||
}; | ||
|
||
export default TabbarItem; |
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 @@ | ||
/** | ||
* @description - nothing but export component | ||
*/ | ||
export { default } from './TabbarItem'; |
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,95 @@ | ||
// packages | ||
import React, { useState } from 'react'; | ||
import { View, Text } from 'remax/wechat'; | ||
|
||
// internal | ||
import Tabbar from '../../../packages/Tabbar'; | ||
import TabbarItem from '../../../packages/TabbarItem'; | ||
import Image from '../../../packages/Image'; | ||
|
||
export default () => { | ||
const [activeIndex, seteActiveIndex] = useState(0); | ||
|
||
const customIcons = { | ||
inactive: ( | ||
<Image | ||
src="https://img.yzcdn.cn/vant/user-inactive.png" | ||
width="18px" | ||
height="18px" | ||
mode="aspectFit" | ||
/> | ||
), | ||
active: ( | ||
<Image | ||
src="https://img.yzcdn.cn/vant/user-active.png" | ||
width="18px" | ||
height="18px" | ||
mode="aspectFit" | ||
/> | ||
), | ||
}; | ||
|
||
const iconFunction = (active: boolean) => | ||
active ? customIcons.active : customIcons.inactive; | ||
|
||
return ( | ||
<View className="demo-block"> | ||
<Text className="demo-block__title">基础用法</Text> | ||
<View> | ||
<Tabbar | ||
active={activeIndex} | ||
onChange={(event) => seteActiveIndex(event.detail)} | ||
> | ||
<TabbarItem icon="home-o">Home</TabbarItem> | ||
<TabbarItem icon="search">Search</TabbarItem> | ||
<TabbarItem icon="friends-o">Friends</TabbarItem> | ||
<TabbarItem icon="setting-o">Setting</TabbarItem> | ||
</Tabbar> | ||
</View> | ||
<Text className="demo-block__title">显示徽标</Text> | ||
<View> | ||
<Tabbar | ||
active={activeIndex} | ||
onChange={(event) => seteActiveIndex(event.detail)} | ||
> | ||
<TabbarItem icon="home-o">Home</TabbarItem> | ||
<TabbarItem icon="search" dot> | ||
Search | ||
</TabbarItem> | ||
<TabbarItem icon="friends-o" info="5+"> | ||
Friends | ||
</TabbarItem> | ||
<TabbarItem icon="setting-o" info="99+"> | ||
Setting | ||
</TabbarItem> | ||
</Tabbar> | ||
</View> | ||
<Text className="demo-block__title">自定义图标</Text> | ||
<View> | ||
<Tabbar | ||
active={activeIndex} | ||
onChange={(event) => seteActiveIndex(event.detail)} | ||
> | ||
<TabbarItem icon={iconFunction}>Home</TabbarItem> | ||
<TabbarItem icon={iconFunction}>Search</TabbarItem> | ||
<TabbarItem icon={iconFunction}>Friends</TabbarItem> | ||
<TabbarItem icon={iconFunction}>Setting</TabbarItem> | ||
</Tabbar> | ||
</View> | ||
<Text className="demo-block__title">自定义颜色</Text> | ||
<View> | ||
<Tabbar | ||
active={activeIndex} | ||
activeColor="#07c160" | ||
inactiveColor="#000" | ||
onChange={(event) => seteActiveIndex(event.detail)} | ||
> | ||
<TabbarItem icon="home-o">Home</TabbarItem> | ||
<TabbarItem icon="search">Search</TabbarItem> | ||
<TabbarItem icon="friends-o">Friends</TabbarItem> | ||
<TabbarItem icon="setting-o">Setting</TabbarItem> | ||
</Tabbar> | ||
</View> | ||
</View> | ||
); | ||
}; |