Skip to content

Commit

Permalink
feat: add component bottom-navigation
Browse files Browse the repository at this point in the history
  • Loading branch information
zhenyuWang committed May 23, 2022
1 parent 00a799b commit 13dd6bb
Show file tree
Hide file tree
Showing 25 changed files with 1,675 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
<template>
<button
class="var-bottom-navigation-item"
ref="bottomNavigationItem"
v-ripple
:style="{
color: computeColorStyle(),
}"
@click="handleClick"
>
<var-icon
v-if="icon && !$slots.icon"
:name="icon"
:namespace="namespace"
class="var-bottom-navigation-item__icon"
/>
<slot name="icon" :active="isActive"></slot>
<var-badge v-if="badge" v-bind="badgeProps" class="var-bottom-navigation-item__badge" />
<span class="var-bottom-navigation-item__label">
<template v-if="!$slots.default">
{{ label }}
</template>
<slot></slot>
</span>
</button>
</template>

<script>
import Ripple from '../ripple'
import VarBadge from '../badge'
import VarIcon from '../icon'
import { defineComponent } from '../utils/create'
import { props } from './props'
import { createChildrenMixin } from '../utils/mixins/relation'
const defaultBadgeProps = {
type: 'danger',
dot: true,
}
export default defineComponent({
name: 'VarBottomNavigationItem',
components: {
VarBadge,
VarIcon,
},
directives: { Ripple },
mixins: [
createChildrenMixin('bottomNavigation', { parentKey: 'bottomNavigation', childrenKey: 'bottomNavigationItems' }),
],
inheritAttrs: false,
props,
data: () => ({
isActive: false,
badgeProps: {},
}),
mounted() {
this.isActive = this.name === this.bottomNavigation.active || this.index === this.bottomNavigation.active
if (this.isActive) {
this.$refs.bottomNavigationItem.classList.add('var-bottom-navigation-item--active')
}
},
watch: {
badge: {
handler(newValue) {
this.badgeProps = newValue === true ? defaultBadgeProps : this.badge
},
immediate: true,
},
},
methods: {
computeColorStyle() {
const { activeColor, inactiveColor } = this.bottomNavigation
return this.isActive ? activeColor : inactiveColor
},
setCurrent(value) {
const _isActive = value === this.index || value === this.name
if (_isActive === this.isActive) {
return
}
this.isActive = _isActive
if (this.isActive) {
this.$refs.bottomNavigationItem.classList.add('var-bottom-navigation-item--active')
} else {
this.$refs.bottomNavigationItem.classList.remove('var-bottom-navigation-item--active')
}
},
handleClick() {
const { name, getListeners, index } = this
const active = name ?? index
getListeners().onClick?.(active)
this.bottomNavigation.onToggle(active)
},
},
})
</script>
<style lang="less">
@import '../styles/common';
@import '../ripple/ripple';
@import '../badge/badge';
@import '../icon/icon';
@import './bottomNavigationItem';
</style>
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
@bottom-navigation-item-font-size: var(--font-size-sm);
@bottom-navigation-item-inactive-color: #646566;
@bottom-navigation-item-active-color: var(--color-primary);
@bottom-navigation-item-active-background-color: #fff;
@bottom-navigation-item-line-height: 1;
@bottom-navigation-item-icon-size: 22px;
@bottom-navigation-item-icon-margin-bottom: 5px;

:root {
--bottom-navigation-item-font-size: @bottom-navigation-item-font-size;
--bottom-navigation-item-inactive-color: @bottom-navigation-item-inactive-color;
--bottom-navigation-item-active-color: @bottom-navigation-item-active-color;
--bottom-navigation-item-active-background-color: @bottom-navigation-item-active-background-color;
--bottom-navigation-item-line-height: @bottom-navigation-item-line-height;
--bottom-navigation-item-icon-size: @bottom-navigation-item-icon-size;
--bottom-navigation-item-icon-margin-bottom: @bottom-navigation-item-icon-margin-bottom;
}

.var-bottom-navigation-item {
height: 100%;
padding: 6px 12px 8px;
position: relative;
display: inline-flex;
flex: 1 1 0%;
flex-direction: column;
align-items: center;
justify-content: center;
line-height: var(--bottom-navigation-item-line-height);
color: var(--bottom-navigation-item-inactive-color);
cursor: pointer;
user-select: none;
vertical-align: middle;
appearance: none;
text-decoration: none;
background-color: transparent;
outline: 0;
border: 0;
transition: color 250ms, margin 250ms;

&--active {
color: var(--bottom-navigation-item-active-color);
background-color: var(--bottom-navigation-item-active-background-color);
transition: background-color 250ms;

.var-bottom-navigation-item__label {
font-size: calc(var(--bottom-navigation-item-font-size) * 1.16);
}
}

&--right-half-space {
margin-right: calc(var(--bottom-navigation-height) / 2);
}

&--left-half-space {
margin-left: calc(var(--bottom-navigation-height) / 2);
}

&--right-space {
margin-right: calc(var(--bottom-navigation-height) + var(--bottom-navigation-fab-offset));
}

&__icon {
font-size: var(--bottom-navigation-item-icon-size);
}

&__badge {
position: absolute;
left: 40px;
transform: translateY(-16px);
}

&__label {
margin-top: var(--bottom-navigation-item-icon-margin-bottom);
font-size: var(--bottom-navigation-item-font-size);
transition: font-size 0.2s ease 0.1s;
white-space: nowrap;
}
}
24 changes: 24 additions & 0 deletions packages/varlet-vue2-ui/src/bottom-navigation-item/docs/zh-CN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
## API

### 属性

|参数 | 说明 | 类型 | 默认值 |
| ---- | ---- | ---- | ---- |
| `name` | 标签名称,作为匹配的标识符 | _string_ | `-` |
| `icon` | 图标名称,等同于 Icon 组件的 [name 属性](/#/zh-CN/icon) | _string_ | `-` |
| `label` | 标签文字内容 | _string_ | - |
| `namespace` | 图标的命名空间, 可扩展自定义图标库,等同于 Icon 组件的 [namespace 属性](/#/zh-CN/icon) | _string_ | `var-icon` |
| `badge` | 图标右上角徽标 | _boolean \| BadgeProps_ | `false` |

### 事件

|事件名 | 说明 | 回调参数 |
| ---- | ---- | ---- |
| `click` | 点击时触发 | `active: number \| string` |

### 插槽

| 名称 | 说明 | 参数 |
| ---- | ---- | ----|
| `default` | 自定义标签文字内容,会覆盖 `label` 的内容 | `-` |
| `icon` | 自定义图标 | `active: boolean` |
10 changes: 10 additions & 0 deletions packages/varlet-vue2-ui/src/bottom-navigation-item/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import type { VueConstructor } from 'vue'
import BottomNavigationItem from './BottomNavigationItem.vue'

BottomNavigationItem.install = function (app: VueConstructor) {
app.component(BottomNavigationItem.name, BottomNavigationItem)
}

export const _BottomNavigationItemComponent = BottomNavigationItem

export default BottomNavigationItem
25 changes: 25 additions & 0 deletions packages/varlet-vue2-ui/src/bottom-navigation-item/props.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import type { PropType } from 'vue'
import type { BadgeProps } from '../../types'

export const props = {
name: {
type: String,
},
icon: {
type: String,
},
label: {
type: String,
},
namespace: {
type: String,
default: 'var-icon',
},
badge: {
type: [Boolean, Object] as PropType<boolean | Partial<BadgeProps>>,
default: false,
},
onClick: {
type: Function as PropType<(active: number | string) => void>,
},
}
Loading

0 comments on commit 13dd6bb

Please sign in to comment.