Skip to content

Commit 8caef27

Browse files
authored
comp(MdTabs): add bottom bar (#18)
* comp(MdTabs): start creation of tabs * feat(MdTabs): add activetab prop to md-tabs * chore(MdTabs): reinstall libs * feat(MdTabs): make tabs work with Vue Router * feat(MdTabs): add support for transparent tab navigation * feat(MdTabs): add support for tabs with inner content * perf(MdTabs): improve tabs initial time to be ready * perf(MdTabs): add rAF to improve resize check * chore(MdTabs): upgrade CI versions * feat(MdTabs): elevation option for md-tabs * feat(MdTabs): alignment options: left, right, centered and fixed * feat(MdTabs): make tabs work with toolbars * feat(MdTabs): support to icons * feat(MdTabs): disabled tabs * feat(MdTabs): support for custom templates * feat(MdTabs): add events to md-tab * comp(MdBottomBar): initial files for bottom bar * build: upgrade yarn file * fix(MdTabs): remove old file * feat(MdBottomBar): add fixed navigation bars with vue router support * feat(MdBottomBar): add shift bottom bar and create dynamic morph themes * feat(MdBottomBar): add support for custom templates * docs(MdBottomBar): remove example file * fix(MdBottomBar): add missing dependency * fix(MdBottomBar): improve label transition from active/nonactive * test(MdBottomBar): fix broken tests * docs(MdBottomBar): rename section titles to better match the example
1 parent af565f4 commit 8caef27

20 files changed

+830
-20
lines changed

docs/app/i18n/en-US.js

+3
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ export default {
3131
avatar: {
3232
title: 'Avatar'
3333
},
34+
bottomBar: {
35+
title: 'Bottom Bar'
36+
},
3437
card: {
3538
title: 'Card'
3639
},
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<example src="./examples/VueRouter.vue" />
2+
<example src="./examples/Shift.vue" />
3+
<example src="./examples/ChangingThemes.vue" />
4+
<example src="./examples/CustomTemplate.vue" />
5+
6+
<template>
7+
<page-container centered :title="$t('pages.bottomBar.title')">
8+
<div class="page-container-section">
9+
<p>Lorem ipsum</p>
10+
</div>
11+
12+
<div class="page-container-section">
13+
<h2>Seamless integration with Vue Router</h2>
14+
15+
<code-example title="With default fixed style" :component="examples['vue-router']" />
16+
</div>
17+
18+
<div class="page-container-section">
19+
<h2>Shift effect</h2>
20+
21+
<code-example title="With Primary and Accent colors" :component="examples['shift']" />
22+
</div>
23+
24+
<div class="page-container-section">
25+
<h2>Dynamic Themes</h2>
26+
27+
<code-example title="Morphing States" :component="examples['changing-themes']" />
28+
</div>
29+
30+
<div class="page-container-section">
31+
<h2>Custom Template</h2>
32+
33+
<code-example title="Template Slot" :component="examples['custom-template']" />
34+
35+
<api-item title="API - md-bottom-bar">
36+
<p>This component do not have any extra option.</p>
37+
</api-item>
38+
</div>
39+
</page-container>
40+
</template>
41+
42+
<script>
43+
import examples from 'docs-mixins/docsExample'
44+
45+
export default {
46+
name: 'BottomBar',
47+
mixins: [examples]
48+
}
49+
</script>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
<template>
2+
<div>
3+
<div class="phone-viewport">
4+
<md-bottom-bar md-type="shift" :md-theme="'bottom-bar-' + theme">
5+
<md-bottom-bar-item md-label="Home" md-icon="home" @click="theme = 'teal'"></md-bottom-bar-item>
6+
<md-bottom-bar-item md-label="Pages" md-icon="pages" @click="theme = 'orange'"></md-bottom-bar-item>
7+
<md-bottom-bar-item md-label="Posts" md-icon="assets/icon-whatshot.svg" @click="theme = 'blue'"></md-bottom-bar-item>
8+
<md-bottom-bar-item md-label="Favorites" md-icon="favorite" @click="theme = 'red'"></md-bottom-bar-item>
9+
</md-bottom-bar>
10+
</div>
11+
</div>
12+
</template>
13+
14+
<script>
15+
export default {
16+
name: 'ChangingThemes',
17+
data: () => ({
18+
theme: 'teal'
19+
})
20+
}
21+
</script>
22+
23+
<style lang="scss">
24+
@import "~vue-material/theme/factory";
25+
26+
@include md-register-theme("bottom-bar-teal", (
27+
primary: md-get-palette-color(teal, A200)
28+
));
29+
30+
@include md-register-theme("bottom-bar-orange", (
31+
primary: md-get-palette-color(orange, A200)
32+
));
33+
34+
@include md-register-theme("bottom-bar-blue", (
35+
primary: md-get-palette-color(blue, A200),
36+
accent: md-get-palette-color(red, A200)
37+
));
38+
39+
@include md-register-theme("bottom-bar-red", (
40+
primary: md-get-palette-color(red, A200)
41+
));
42+
43+
@import "~vue-material/theme/all";
44+
</style>
45+
46+
<style lang="scss" scoped>
47+
.phone-viewport {
48+
width: 322px;
49+
height: 200px;
50+
display: inline-flex;
51+
align-items: flex-end;
52+
overflow: hidden;
53+
border: 1px solid rgba(#000, .26);
54+
background: rgba(#000, .06);
55+
}
56+
</style>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
<template>
2+
<div>
3+
<div class="phone-viewport">
4+
<md-bottom-bar class="md-accent" md-type="shift" @md-changed="checkNewPosts">
5+
<md-bottom-bar-item md-label="Home" md-icon="home"></md-bottom-bar-item>
6+
<md-bottom-bar-item md-label="Pages" md-icon="pages"></md-bottom-bar-item>
7+
8+
<md-bottom-bar-item id="item-posts" @click="clearNewPosts">
9+
<md-icon class="md-bottom-bar-icon" md-src="assets/icon-whatshot.svg"></md-icon>
10+
<span class="md-bottom-bar-label">Posts</span>
11+
<i class="badge" v-if="newPosts">{{ newPosts }}</i>
12+
</md-bottom-bar-item>
13+
14+
<md-bottom-bar-item md-label="Favorites" md-icon="favorite"></md-bottom-bar-item>
15+
</md-bottom-bar>
16+
</div>
17+
</div>
18+
</template>
19+
20+
<script>
21+
export default {
22+
name: 'CustomTemplate',
23+
data: () => ({
24+
newPosts: 0,
25+
checkInterval: null
26+
}),
27+
methods: {
28+
clearCheckPosts () {
29+
window.clearInterval(this.checkInterval)
30+
this.checkInterval = null
31+
},
32+
clearNewPosts () {
33+
this.clearCheckPosts()
34+
this.newPosts = 0
35+
},
36+
checkNewPosts (activeItem) {
37+
if (activeItem !== 'item-posts' && !this.checkInterval) {
38+
this.checkInterval = window.setInterval(() => {
39+
if (this.newPosts === 99) {
40+
this.newPosts = '99+'
41+
this.clearCheckPosts()
42+
} else {
43+
this.newPosts++
44+
}
45+
}, 1000)
46+
}
47+
}
48+
},
49+
mounted () {
50+
this.checkNewPosts()
51+
}
52+
}
53+
</script>
54+
55+
<style lang="scss" scoped>
56+
@import "~vue-material/theme/factory";
57+
58+
.phone-viewport {
59+
width: 322px;
60+
height: 200px;
61+
display: inline-flex;
62+
align-items: flex-end;
63+
overflow: hidden;
64+
border: 1px solid rgba(#000, .26);
65+
background: rgba(#000, .06);
66+
}
67+
68+
.badge {
69+
width: 19px;
70+
height: 19px;
71+
display: flex;
72+
justify-content: center;
73+
align-items: center;
74+
position: absolute;
75+
top: 6px;
76+
right: 6px;
77+
background: #fff;
78+
border-radius: 100%;
79+
color: #000;
80+
font-size: 10px;
81+
font-style: normal;
82+
font-weight: 600;
83+
letter-spacing: -.05em;
84+
font-family: 'Roboto Mono', monospace;
85+
}
86+
</style>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<template>
2+
<div>
3+
<div class="phone-viewport">
4+
<md-bottom-bar md-type="shift">
5+
<md-bottom-bar-item id="bottom-bar-item-home" md-label="Home" md-icon="home"></md-bottom-bar-item>
6+
<md-bottom-bar-item id="bottom-bar-item-pages" md-label="Pages" md-icon="pages"></md-bottom-bar-item>
7+
<md-bottom-bar-item id="bottom-bar-item-posts" md-label="Posts" md-icon="assets/icon-whatshot.svg"></md-bottom-bar-item>
8+
<md-bottom-bar-item id="bottom-bar-item-favorites" md-label="Favorites" md-icon="favorite"></md-bottom-bar-item>
9+
</md-bottom-bar>
10+
</div>
11+
12+
<div class="phone-viewport">
13+
<md-bottom-bar class="md-accent" md-type="shift">
14+
<md-bottom-bar-item id="bottom-bar-item-home" md-label="Home" md-icon="home"></md-bottom-bar-item>
15+
<md-bottom-bar-item id="bottom-bar-item-pages" md-label="Pages" md-icon="pages"></md-bottom-bar-item>
16+
<md-bottom-bar-item id="bottom-bar-item-posts" md-label="Posts" md-icon="assets/icon-whatshot.svg"></md-bottom-bar-item>
17+
<md-bottom-bar-item id="bottom-bar-item-favorites" md-label="Favorites" md-icon="favorite"></md-bottom-bar-item>
18+
</md-bottom-bar>
19+
</div>
20+
</div>
21+
</template>
22+
23+
<script>
24+
export default {
25+
name: 'Shift'
26+
}
27+
</script>
28+
29+
<style lang="scss" scoped>
30+
.phone-viewport {
31+
width: 322px;
32+
height: 200px;
33+
display: inline-flex;
34+
align-items: flex-end;
35+
overflow: hidden;
36+
border: 1px solid rgba(#000, .26);
37+
background: rgba(#000, .06);
38+
}
39+
</style>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<template>
2+
<div>
3+
<div class="phone-viewport">
4+
<md-bottom-bar md-sync-route>
5+
<md-bottom-bar-item id="bottom-bar-item-home" to="/components/bottom-bar/home" md-label="Home" md-icon="home"></md-bottom-bar-item>
6+
<md-bottom-bar-item id="bottom-bar-item-posts" to="/components/bottom-bar/posts" md-label="Posts" md-icon="assets/icon-whatshot.svg"></md-bottom-bar-item>
7+
<md-bottom-bar-item id="bottom-bar-item-favorites" to="/components/bottom-bar/favorites" md-label="Favorites" md-icon="favorite"></md-bottom-bar-item>
8+
</md-bottom-bar>
9+
</div>
10+
11+
<div class="phone-viewport">
12+
<md-bottom-bar class="md-accent" md-sync-route>
13+
<md-bottom-bar-item id="bottom-bar-item-home" to="/components/bottom-bar/home" md-label="Home" md-icon="home"></md-bottom-bar-item>
14+
<md-bottom-bar-item id="bottom-bar-item-posts" to="/components/bottom-bar/posts" md-label="Posts" md-icon="assets/icon-whatshot.svg"></md-bottom-bar-item>
15+
<md-bottom-bar-item id="bottom-bar-item-favorites" to="/components/bottom-bar/favorites" md-label="Favorites" md-icon="favorite"></md-bottom-bar-item>
16+
</md-bottom-bar>
17+
</div>
18+
</div>
19+
</template>
20+
21+
<script>
22+
export default {
23+
name: 'VueRouter'
24+
}
25+
</script>
26+
27+
<style lang="scss" scoped>
28+
.phone-viewport {
29+
width: 322px;
30+
height: 200px;
31+
display: inline-flex;
32+
align-items: flex-end;
33+
overflow: hidden;
34+
border: 1px solid rgba(#000, .26);
35+
background: rgba(#000, .06);
36+
}
37+
</style>

docs/app/routes.js

+5
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@ export const routes = [
99
name: 'components/tabs',
1010
component: () => import(/* webpackChunkName: "tabs" */ './pages/Components/Tabs/Tabs.vue')
1111
},
12+
{
13+
path: '/components/bottom-bar/:test?',
14+
name: 'components/bottom-bar',
15+
component: () => import(/* webpackChunkName: "bottom-bar" */ './pages/Components/BottomBar/BottomBar.vue')
16+
},
1217
{
1318
path: '/components/chips',
1419
name: 'components/chips',

docs/app/template/MainNav.vue

+2-1
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,9 @@ export default {
4141
})
4242
},
4343
created () {
44-
this.$router.afterEach((to, from, next) => {
44+
this.$router.beforeEach((to, from, next) => {
4545
this.hideMenu()
46+
next()
4647
})
4748
}
4849
}

docs/app/template/MainNavContent.vue

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
<div class="main-nav-level">
88
<router-link to="/components/app">{{ $t('pages.app.title') }}</router-link>
99
<router-link to="/components/avatar">{{ $t('pages.avatar.title') }}</router-link>
10+
<router-link to="/components/bottom-bar">{{ $t('pages.bottomBar.title') }}</router-link>
1011
<router-link to="/components/button">{{ $t('pages.button.title') }}</router-link>
1112
<router-link to="/components/card">{{ $t('pages.card.title') }}</router-link>
1213
<router-link to="/components/chips">{{ $t('pages.chips.title') }}</router-link>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import mountTemplate from 'test/utils/mountTemplate'
2+
import MdBottomBar from './MdBottomBar.vue'
3+
4+
test('should render the bottombar', async () => {
5+
const template = '<md-bottom-bar></md-bottom-bar>'
6+
const wrapper = await mountTemplate(MdBottomBar, template)
7+
8+
expect(wrapper.hasClass('md-bottom-bar')).toBe(true)
9+
})
10+
11+
test('should render the theme class', async () => {
12+
const template = '<md-bottom-bar md-theme="alt"></md-bottom-bar>'
13+
const wrapper = await mountTemplate(MdBottomBar, template)
14+
15+
expect(wrapper.hasClass('md-theme-alt')).toBe(true)
16+
})

0 commit comments

Comments
 (0)