mirror of
https://github.com/Hopiu/vue-material.git
synced 2026-05-13 09:43:15 +00:00
Create tabs
This commit is contained in:
parent
f92aaa0487
commit
36d4c26dd1
11 changed files with 465 additions and 0 deletions
|
|
@ -17,6 +17,7 @@
|
|||
"dependencies": {
|
||||
"autosize": "^3.0.17",
|
||||
"element.scrollintoviewifneeded-polyfill": "^1.0.1",
|
||||
"highlightjs": "^8.7.0",
|
||||
"scopedQuerySelectorShim": "github:lazd/scopedQuerySelectorShim"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
|
|||
10
src/components/mdTabs/index.js
Normal file
10
src/components/mdTabs/index.js
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
import mdTabs from './mdTabs.vue';
|
||||
import mdTab from './mdTab.vue';
|
||||
import mdTabsTheme from './mdTabs.theme';
|
||||
|
||||
export default function install(Vue) {
|
||||
Vue.component('md-tabs', Vue.extend(mdTabs));
|
||||
Vue.component('md-tab', Vue.extend(mdTab));
|
||||
|
||||
window.VueMaterial.styles.push(mdTabsTheme);
|
||||
}
|
||||
29
src/components/mdTabs/mdTab.vue
Normal file
29
src/components/mdTabs/mdTab.vue
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
<template>
|
||||
<div class="md-tab" ref="tab">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
mdLabel: String,
|
||||
mdIcon: String,
|
||||
mdActive: Boolean
|
||||
},
|
||||
mounted() {
|
||||
if (!this.$parent.$el.classList.contains('md-tabs')) {
|
||||
this.$destroy();
|
||||
|
||||
throw new Error('You should wrap the md-tab in a md-tabs');
|
||||
}
|
||||
|
||||
this.$parent.registerTab({
|
||||
label: this.mdLabel,
|
||||
icon: this.mdIcon,
|
||||
active: this.mdActive,
|
||||
ref: this.$refs.tab
|
||||
});
|
||||
}
|
||||
};
|
||||
</script>
|
||||
112
src/components/mdTabs/mdTabs.scss
Normal file
112
src/components/mdTabs/mdTabs.scss
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
@import '../../core/stylesheets/variables.scss';
|
||||
|
||||
$tab-width: 72px;
|
||||
$tab-max-width: 264px;
|
||||
|
||||
.md-tabs {
|
||||
width: 100%;
|
||||
position: relative;
|
||||
|
||||
&.md-has-icon.md-has-label {
|
||||
.md-tabs-navigation {
|
||||
height: 72px;
|
||||
|
||||
.md-icon {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.md-centered {
|
||||
.md-tabs-navigation {
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
|
||||
&.md-fixed {
|
||||
.md-tab-header {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.md-tabs-navigation {
|
||||
height: 48px;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
display: flex;
|
||||
transition: $swift-ease-out;
|
||||
}
|
||||
|
||||
.md-tab-header {
|
||||
min-width: $tab-width;
|
||||
max-width: $tab-max-width;
|
||||
margin: 0;
|
||||
padding: 0 12px;
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
border: 0;
|
||||
background: none;
|
||||
transition: $swift-ease-out;
|
||||
color: rgba(#fff, .7);
|
||||
font-size: inherit;
|
||||
font-family: inherit;
|
||||
font-weight: 500;
|
||||
text-transform: uppercase;
|
||||
|
||||
&.md-active,
|
||||
&:hover {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.md-icon {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.md-tab-indicator {
|
||||
height: 2px;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
transform: translate3D(0, 0, 0);
|
||||
transition: left ($swift-ease-in-out-duration * .8) $swift-ease-out-timing-function,
|
||||
right ($swift-ease-out-duration * .8) $swift-ease-out-timing-function;
|
||||
}
|
||||
|
||||
.md-tabs-content {
|
||||
width: 100%;
|
||||
height: 0;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
transition: height ($swift-ease-in-out-duration * .8) $swift-ease-out-timing-function;
|
||||
}
|
||||
|
||||
.md-tabs-wrapper {
|
||||
width: 999em;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
transform: translate3d(0, 0, 0);
|
||||
transition: left ($swift-ease-in-out-duration * .8) $swift-ease-out-timing-function;
|
||||
}
|
||||
|
||||
.md-tab {
|
||||
padding: 16px;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
pointer-events: none;
|
||||
|
||||
&.md-active {
|
||||
pointer-events: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
42
src/components/mdTabs/mdTabs.theme
Normal file
42
src/components/mdTabs/mdTabs.theme
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
.THEME_NAME {
|
||||
.md-tabs,
|
||||
&.md-tabs {
|
||||
.md-tabs-navigation {
|
||||
background-color: #{'PRIMARY-COLOR'};
|
||||
}
|
||||
|
||||
.md-tab-indicator {
|
||||
background-color: #{'ACCENT-COLOR'};
|
||||
}
|
||||
|
||||
&.md-accent {
|
||||
.md-tabs-navigation {
|
||||
background-color: #{'ACCENT-COLOR'};
|
||||
}
|
||||
|
||||
.md-tab-indicator {
|
||||
background-color: #{'BACKGROUND-COLOR'};
|
||||
}
|
||||
}
|
||||
|
||||
&.md-warn {
|
||||
.md-tabs-navigation {
|
||||
background-color: #{'WARN-COLOR'};
|
||||
}
|
||||
|
||||
.md-tab-indicator {
|
||||
background-color: #{'BACKGROUND-COLOR'};
|
||||
}
|
||||
}
|
||||
|
||||
&.md-transparent {
|
||||
.md-tabs-navigation {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.md-tab-indicator {
|
||||
background-color: #{'BACKGROUND-COLOR'};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
110
src/components/mdTabs/mdTabs.vue
Normal file
110
src/components/mdTabs/mdTabs.vue
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
<template>
|
||||
<div class="md-tabs" :class="tabClasses">
|
||||
<div class="md-tabs-navigation">
|
||||
<button
|
||||
v-for="(header, index) in tabs"
|
||||
type="button"
|
||||
class="md-tab-header"
|
||||
:class="{ 'md-active': activeTab === index }"
|
||||
@click="changeTab(index)"
|
||||
v-md-ink-ripple
|
||||
ref="tabHeader">
|
||||
<md-icon v-if="header.icon">{{ header.icon }}</md-icon>
|
||||
<span v-if="header.label">{{ header.label }}</span>
|
||||
</button>
|
||||
<span class="md-tab-indicator" ref="indicator"></span>
|
||||
</div>
|
||||
|
||||
<div class="md-tabs-content" ref="tabContent">
|
||||
<div class="md-tabs-wrapper" ref="tabWrapper">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" src="./mdTabs.scss"></style>
|
||||
|
||||
<script>
|
||||
import Vue from 'vue';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
mdFixed: Boolean,
|
||||
mdCentered: Boolean
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
hasIcons: false,
|
||||
hasLabel: false,
|
||||
activeTab: 0,
|
||||
tabs: []
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
tabClasses() {
|
||||
return {
|
||||
'md-fixed': this.mdFixed,
|
||||
'md-centered': this.mdCentered || this.mdFixed,
|
||||
'md-has-icon': this.hasIcons,
|
||||
'md-has-label': this.hasLabel
|
||||
};
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
calculateIndicatorPos() {
|
||||
let indicator = this.$refs.indicator;
|
||||
let tabsWidth = this.$el.offsetWidth;
|
||||
|
||||
Vue.nextTick(() => {
|
||||
let activeTab = this.$refs.tabHeader[this.activeTab];
|
||||
let left = activeTab.offsetLeft;
|
||||
let right = tabsWidth - left - activeTab.offsetWidth;
|
||||
|
||||
indicator.style.left = left + 'px';
|
||||
indicator.style.right = right + 'px';
|
||||
});
|
||||
},
|
||||
calculateTabPos(ref, index) {
|
||||
this.$refs.tabWrapper.style.left = -this.$refs.tabContent.offsetWidth * this.activeTab + 'px';
|
||||
ref.style.width = this.$refs.tabContent.offsetWidth + 'px';
|
||||
ref.style.left = this.$refs.tabContent.offsetWidth * index + 'px';
|
||||
},
|
||||
setVisibleTab(ref) {
|
||||
Vue.nextTick(() => {
|
||||
this.$refs.tabContent.style.height = ref.offsetHeight + 'px';
|
||||
ref.classList.add('md-active');
|
||||
});
|
||||
},
|
||||
changeTab(index) {
|
||||
this.tabs[this.activeTab].ref.classList.remove('md-active');
|
||||
this.activeTab = index;
|
||||
this.calculateIndicatorPos();
|
||||
this.calculateTabPos(this.tabs[this.activeTab].ref, this.activeTab);
|
||||
this.setVisibleTab(this.tabs[index].ref);
|
||||
},
|
||||
registerTab(options) {
|
||||
this.tabs.push(options);
|
||||
|
||||
if (options.icon) {
|
||||
this.hasIcons = true;
|
||||
}
|
||||
|
||||
if (options.label) {
|
||||
this.hasLabel = true;
|
||||
}
|
||||
|
||||
if (options.active) {
|
||||
this.changeTab(this.tabs.length - 1);
|
||||
}
|
||||
|
||||
this.calculateTabPos(this.tabs[this.tabs.length - 1].ref, this.tabs.length - 1);
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
if (this.activeTab === 0) {
|
||||
this.changeTab(0);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
@ -66,6 +66,10 @@
|
|||
<router-link to="/switch">Switch</router-link>
|
||||
</md-list-item>
|
||||
|
||||
<md-list-item>
|
||||
<router-link to="/tabs">Tabs</router-link>
|
||||
</md-list-item>
|
||||
|
||||
<md-list-item>
|
||||
<router-link to="/theme">Theme</router-link>
|
||||
</md-list-item>
|
||||
|
|
|
|||
|
|
@ -68,6 +68,12 @@
|
|||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.md-whiteframe-1dp {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
mounted() {
|
||||
|
|
|
|||
143
src/docs/pages/Tabs.vue
Normal file
143
src/docs/pages/Tabs.vue
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
<template>
|
||||
<div class="page-content">
|
||||
<md-whiteframe md-elevation="2">
|
||||
<md-toolbar class="md-dense">
|
||||
<md-button>Examples</md-button>
|
||||
<md-button>Code</md-button>
|
||||
<md-button>API</md-button>
|
||||
</md-toolbar>
|
||||
</md-whiteframe>
|
||||
|
||||
<div class="main-content">
|
||||
<md-whiteframe class="cell-phone">
|
||||
<md-toolbar v-md-theme="'grey'">
|
||||
<h2 class="md-title">Default</h2>
|
||||
</md-toolbar>
|
||||
|
||||
<section>
|
||||
<md-tabs>
|
||||
<md-tab md-label="Movies">
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Deserunt dolorum quas amet cum vitae, omnis! Illum quas voluptatem, expedita iste, dicta ipsum ea veniam dolore in, quod saepe reiciendis nihil.</p>
|
||||
</md-tab>
|
||||
|
||||
<md-tab md-label="Music">
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Deserunt dolorum quas amet cum vitae, omnis! Illum quas voluptatem, expedita iste, dicta ipsum ea veniam dolore in, quod saepe reiciendis nihil.</p>
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Deserunt dolorum quas amet cum vitae, omnis! Illum quas voluptatem, expedita iste, dicta ipsum ea veniam dolore in, quod saepe reiciendis nihil.</p>
|
||||
</md-tab>
|
||||
|
||||
<md-tab md-label="Books">
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Deserunt dolorum quas.</p>
|
||||
</md-tab>
|
||||
|
||||
<md-tab md-label="Pictures">
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Deserunt dolorum quas.</p>
|
||||
</md-tab>
|
||||
</md-tabs>
|
||||
</section>
|
||||
</md-whiteframe>
|
||||
|
||||
<md-whiteframe class="cell-phone">
|
||||
<md-toolbar v-md-theme="'grey'">
|
||||
<h2 class="md-title">Fixed</h2>
|
||||
</md-toolbar>
|
||||
|
||||
<section>
|
||||
<md-tabs md-fixed class="md-accent">
|
||||
<md-tab md-label="Movies">
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Deserunt dolorum quas amet cum vitae, omnis! Illum quas voluptatem, expedita iste, dicta ipsum ea veniam dolore in, quod saepe reiciendis nihil.</p>
|
||||
</md-tab>
|
||||
|
||||
<md-tab md-label="Music">
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Deserunt dolorum quas amet cum vitae, omnis! Illum quas voluptatem, expedita iste, dicta ipsum ea veniam dolore in, quod saepe reiciendis nihil.</p>
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Deserunt dolorum quas amet cum vitae, omnis! Illum quas voluptatem, expedita iste, dicta ipsum ea veniam dolore in, quod saepe reiciendis nihil.</p>
|
||||
</md-tab>
|
||||
|
||||
<md-tab md-label="Books">
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Deserunt dolorum quas.</p>
|
||||
</md-tab>
|
||||
|
||||
<md-tab md-label="Pictures">
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Deserunt dolorum quas.</p>
|
||||
</md-tab>
|
||||
</md-tabs>
|
||||
</section>
|
||||
</md-whiteframe>
|
||||
|
||||
<md-whiteframe class="cell-phone">
|
||||
<md-toolbar v-md-theme="'grey'">
|
||||
<h2 class="md-title">With icons and text</h2>
|
||||
</md-toolbar>
|
||||
|
||||
<section>
|
||||
<md-tabs md-fixed v-md-theme="'teal'">
|
||||
<md-tab md-label="Movies" md-icon="ondemand_video">
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Deserunt dolorum quas amet cum vitae, omnis! Illum quas voluptatem, expedita iste, dicta ipsum ea veniam dolore in, quod saepe reiciendis nihil.</p>
|
||||
</md-tab>
|
||||
|
||||
<md-tab md-label="Music" md-icon="music_note">
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Deserunt dolorum quas amet cum vitae, omnis! Illum quas voluptatem, expedita iste, dicta ipsum ea veniam dolore in, quod saepe reiciendis nihil.</p>
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Deserunt dolorum quas amet cum vitae, omnis! Illum quas voluptatem, expedita iste, dicta ipsum ea veniam dolore in, quod saepe reiciendis nihil.</p>
|
||||
</md-tab>
|
||||
|
||||
<md-tab md-label="Books" md-icon="books">
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Deserunt dolorum quas.</p>
|
||||
</md-tab>
|
||||
|
||||
<md-tab md-label="Pictures" md-icon="photo">
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Deserunt dolorum quas.</p>
|
||||
</md-tab>
|
||||
</md-tabs>
|
||||
</section>
|
||||
</md-whiteframe>
|
||||
|
||||
<md-whiteframe class="cell-phone">
|
||||
<md-toolbar v-md-theme="'grey'">
|
||||
<h2 class="md-title">Centered with only icon</h2>
|
||||
</md-toolbar>
|
||||
|
||||
<section>
|
||||
<md-tabs md-centered v-md-theme="'green'">
|
||||
<md-tab md-icon="phone">
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Deserunt dolorum quas amet cum vitae, omnis! Illum quas voluptatem, expedita iste, dicta ipsum ea veniam dolore in, quod saepe reiciendis nihil.</p>
|
||||
</md-tab>
|
||||
|
||||
<md-tab md-icon="favorite">
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Deserunt dolorum quas amet cum vitae, omnis! Illum quas voluptatem, expedita iste, dicta ipsum ea veniam dolore in, quod saepe reiciendis nihil.</p>
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Deserunt dolorum quas amet cum vitae, omnis! Illum quas voluptatem, expedita iste, dicta ipsum ea veniam dolore in, quod saepe reiciendis nihil.</p>
|
||||
</md-tab>
|
||||
|
||||
<md-tab md-icon="near_me">
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Deserunt dolorum quas.</p>
|
||||
</md-tab>
|
||||
</md-tabs>
|
||||
</section>
|
||||
</md-whiteframe>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.cell-phone {
|
||||
width: 100%;
|
||||
height: 732px;
|
||||
max-width: 412px;
|
||||
margin-right: 16px;
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
border: none;
|
||||
background-color: #fafafa;
|
||||
}
|
||||
|
||||
.md-whiteframe-1dp {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
mounted() {
|
||||
this.$root.pageTitle = 'Tabs';
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
@ -15,6 +15,7 @@ import Select from './pages/Select';
|
|||
import Sidenav from './pages/Sidenav';
|
||||
import Subheader from './pages/Subheader';
|
||||
import Switch from './pages/Switch';
|
||||
import Tabs from './pages/Tabs';
|
||||
import Theme from './pages/Theme';
|
||||
import Toolbar from './pages/Toolbar';
|
||||
import Tooltip from './pages/Tooltip';
|
||||
|
|
@ -101,6 +102,11 @@ const routes = [
|
|||
name: 'subheader',
|
||||
component: Subheader
|
||||
},
|
||||
{
|
||||
path: '/tabs',
|
||||
name: 'tabs',
|
||||
component: Tabs
|
||||
},
|
||||
{
|
||||
path: '/theme',
|
||||
name: 'theme',
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import MdSelect from './components/mdSelect';
|
|||
import MdSidenav from './components/mdSidenav';
|
||||
import MdSubheader from './components/mdSubheader';
|
||||
import mdSwitch from './components/mdSwitch';
|
||||
import mdTabs from './components/mdTabs';
|
||||
import MdToolbar from './components/mdToolbar';
|
||||
import MdTooltip from './components/mdTooltip';
|
||||
import MdWhiteframe from './components/mdWhiteframe';
|
||||
|
|
@ -35,6 +36,7 @@ let options = {
|
|||
MdSidenav,
|
||||
MdSubheader,
|
||||
mdSwitch,
|
||||
mdTabs,
|
||||
MdToolbar,
|
||||
MdTooltip,
|
||||
MdWhiteframe,
|
||||
|
|
|
|||
Loading…
Reference in a new issue