Merge branch 'develop' of https://github.com/marcosmoura/vue-material into develop

* 'develop' of https://github.com/marcosmoura/vue-material:
  Components/md speed dial (#318)
This commit is contained in:
Marcos Moura 2017-01-11 00:02:03 -02:00
commit 35538240e0
10 changed files with 504 additions and 49 deletions

View file

@ -47,7 +47,13 @@ export default merge(baseConfig, {
]
},
externals: {
vue: 'vue'
vue: {
commonjs: 'vue',
commonjs2: 'vue',
amd: 'vue',
root: 'Vue',
var: 'Vue'
}
},
plugins: [
new webpack.optimize.DedupePlugin(),

View file

@ -119,6 +119,10 @@
<router-link exact to="/components/snackbar">Snackbar</router-link>
</md-list-item>
<md-list-item class="md-inset">
<router-link exact to="/components/speed-dial">Speed Dial</router-link>
</md-list-item>
<md-list-item class="md-inset">
<router-link exact to="/components/spinner">Spinner</router-link>
</md-list-item>

View file

@ -0,0 +1,202 @@
<template>
<page-content page-title="Components - Speed Dial">
<docs-component>
<div slot="description">
<p>The floating action button can fling out related actions upon press. The button should remain on screen after the menu is invoked. Tapping in the same spot should either activate the most commonly used action or close the open menu.</p>
<p>You will need to add the <code>md-fab-trigger</code> attribute in the first md-button to indicate the trigger.</p>
<p>If you want the "morph" effect on icons, you should create two icons inside the <code>md-fab-trigger</code> element and add the <code>md-icon-morph</code> attribute to the first one. When the speed dial gets activated the md-icon-morph will be shown.</p>
</div>
<div slot="api">
<api-table name="md-speed-dial">
<md-table slot="classes">
<md-table-header>
<md-table-row>
<md-table-head>Name</md-table-head>
<md-table-head>Description</md-table-head>
</md-table-row>
</md-table-header>
<md-table-body>
<md-table-row>
<md-table-cell>md-fab-top-left</md-table-cell>
<md-table-cell>Position the md-fab absolutely on the top left of his parent</md-table-cell>
</md-table-row>
<md-table-row>
<md-table-cell>md-fab-top-center</md-table-cell>
<md-table-cell>Position the md-fab absolutely on the top center of his parent</md-table-cell>
</md-table-row>
<md-table-row>
<md-table-cell>md-fab-top-right</md-table-cell>
<md-table-cell>Position the md-fab absolutely on the top right of his parent</md-table-cell>
</md-table-row>
<md-table-row>
<md-table-cell>md-fab-bottom-left</md-table-cell>
<md-table-cell>Position the md-fab absolutely on the bottom left of his parent</md-table-cell>
</md-table-row>
</md-table-body>
</md-table>
<md-table slot="properties">
<md-table-header>
<md-table-row>
<md-table-head>Name</md-table-head>
<md-table-head>Type</md-table-head>
<md-table-head>Description</md-table-head>
</md-table-row>
</md-table-header>
<md-table-body>
<md-table-row>
<md-table-cell>md-open</md-table-cell>
<md-table-cell><code>String</code></md-table-cell>
<md-table-cell>The type of event that will trigger the Speed Dial. Accepts: <code>click</code>|<code>hover</code>. Default: <code>click</code> <br><small>* This attribute is not reactive.</small></md-table-cell>
</md-table-row>
<md-table-row>
<md-table-cell>md-mode</md-table-cell>
<md-table-cell><code>String</code></md-table-cell>
<md-table-cell>The type of effect that will be applied. Accepts: <code>fling</code>|<code>scale</code>. Default: <code>fling</code></md-table-cell>
</md-table-row>
<md-table-row>
<md-table-cell>md-direction</md-table-cell>
<md-table-cell><code>String</code></md-table-cell>
<md-table-cell>The direction that the Speed Dial will dispose the buttons. Accepts: <code>top</code>|<code>right</code>|<code>bottom</code>|<code>left</code>. Default: <code>top</code></md-table-cell>
</md-table-row>
</md-table-body>
</md-table>
</api-table>
</div>
<div slot="example">
<example-box card-title="Mode and event type">
<div class="speed-dial-demo" slot="demo">
<md-speed-dial md-open="hover" class="md-fab-bottom-left" md-theme="purple">
<md-button class="md-fab" md-fab-trigger>
<md-icon md-icon-morph>close</md-icon>
<md-icon>share</md-icon>
</md-button>
<md-button class="md-fab md-primary md-mini md-clean">
<md-icon>email</md-icon>
</md-button>
<md-button class="md-fab md-primary md-mini md-clean">
<md-icon>content_copy</md-icon>
</md-button>
</md-speed-dial>
<md-speed-dial md-mode="scale" class="md-fab-bottom-right">
<md-button class="md-fab" md-fab-trigger>
<md-icon md-icon-morph>close</md-icon>
<md-icon>share</md-icon>
</md-button>
<md-button class="md-fab md-mini md-clean">
<md-icon>email</md-icon>
</md-button>
<md-button class="md-fab md-mini md-clean">
<md-icon>content_copy</md-icon>
</md-button>
</md-speed-dial>
</div>
<div slot="code">
<code-block lang="xml">
</code-block>
</div>
</example-box>
<example-box card-title="Directions">
<div class="speed-dial-demo" slot="demo">
<md-speed-dial md-open="hover" md-direction="bottom" class="md-fab-top-left" md-theme="light-blue">
<md-button class="md-fab" md-fab-trigger>
<md-icon md-icon-morph>event</md-icon>
<md-icon>add</md-icon>
</md-button>
<md-button class="md-fab md-primary md-mini md-clean">
<md-icon>note_add</md-icon>
</md-button>
<md-button class="md-fab md-primary md-mini md-clean">
<md-icon>alarm_add</md-icon>
</md-button>
</md-speed-dial>
<md-speed-dial md-open="hover" md-direction="left" class="md-fab-top-right" md-theme="light-blue">
<md-button class="md-fab" md-fab-trigger>
<md-icon md-icon-morph>event</md-icon>
<md-icon>add</md-icon>
</md-button>
<md-button class="md-fab md-primary md-mini md-clean">
<md-icon>note_add</md-icon>
</md-button>
<md-button class="md-fab md-primary md-mini md-clean">
<md-icon>alarm_add</md-icon>
</md-button>
</md-speed-dial>
<md-speed-dial md-open="hover" md-direction="top" class="md-fab-bottom-right" md-theme="light-blue">
<md-button class="md-fab" md-fab-trigger>
<md-icon md-icon-morph>event</md-icon>
<md-icon>add</md-icon>
</md-button>
<md-button class="md-fab md-primary md-mini md-clean">
<md-icon>note_add</md-icon>
</md-button>
<md-button class="md-fab md-primary md-mini md-clean">
<md-icon>alarm_add</md-icon>
</md-button>
</md-speed-dial>
<md-speed-dial md-open="hover" md-direction="right" class="md-fab-bottom-left" md-theme="light-blue">
<md-button class="md-fab" md-fab-trigger>
<md-icon md-icon-morph>event</md-icon>
<md-icon>add</md-icon>
</md-button>
<md-button class="md-fab md-primary md-mini md-clean">
<md-icon>note_add</md-icon>
</md-button>
<md-button class="md-fab md-primary md-mini md-clean">
<md-icon>alarm_add</md-icon>
</md-button>
</md-speed-dial>
</div>
<div slot="code">
<code-block lang="xml">
</code-block>
</div>
</example-box>
</div>
</docs-component>
</page-content>
</template>
<style lang="sass" scoped>
.speed-dial-demo {
height: 250px;
}
</style>
<script>
export default {
data: () => ({
})
};
</script>

View file

@ -26,6 +26,7 @@ const Radio = (resolve) => require(['./pages/components/Radio'], resolve);
const Select = (resolve) => require(['./pages/components/Select'], resolve);
const Sidenav = (resolve) => require(['./pages/components/Sidenav'], resolve);
const Snackbar = (resolve) => require(['./pages/components/Snackbar'], resolve);
const SpeedDial = (resolve) => require(['./pages/components/SpeedDial'], resolve);
const Spinner = (resolve) => require(['./pages/components/Spinner'], resolve);
const Subheader = (resolve) => require(['./pages/components/Subheader'], resolve);
const Switch = (resolve) => require(['./pages/components/Switch'], resolve);
@ -172,6 +173,11 @@ const components = [
name: 'components:snackbar',
component: Snackbar
},
{
path: '/components/speed-dial',
name: 'components:speed-dial',
component: SpeedDial
},
{
path: '/components/spinner',
name: 'components:spinner',

View file

@ -6,6 +6,7 @@ $button-radius: 2px;
$button-fab-size: 56px;
$button-fab-size-mini: 40px;
$button-fab-space: 24px;
$button-dense-height: 32px;
@ -78,11 +79,11 @@ $button-icon-size: 40px;
&.md-icon-button,
&.md-fab {
.md-icon {
margin-top: 1px;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
top: 1px;
right: 0;
bottom: 0;
left: 0;
}
}
@ -129,6 +130,7 @@ $button-icon-size: 40px;
&.md-fab {
width: $button-fab-size;
height: $button-fab-size;
padding: 0;
min-width: 0;
overflow: hidden;
box-shadow: $material-shadow-2dp;
@ -145,50 +147,6 @@ $button-icon-size: 40px;
box-shadow: $material-shadow-5dp;
}
&.md-fab-top-left {
position: absolute;
top: 16px;
left: 16px;
z-index: 10;
}
&.md-fab-top-center {
position: absolute;
top: 16px;
left: 50%;
z-index: 10;
transform: translateX(-50%);
}
&.md-fab-top-right {
position: absolute;
top: 16px;
right: 16px;
z-index: 10;
}
&.md-fab-bottom-left {
position: absolute;
bottom: 16px;
left: 16px;
z-index: 10;
}
&.md-fab-bottom-center {
position: absolute;
bottom: 16px;
left: 50%;
transform: translateX(-50%);
z-index: 10;
}
&.md-fab-bottom-right {
position: absolute;
right: 16px;
bottom: 16px;
z-index: 10;
}
&.md-mini {
width: $button-fab-size-mini;
height: $button-fab-size-mini;
@ -232,6 +190,52 @@ $button-icon-size: 40px;
}
}
.md-fab,
.md-speed-dial {
&.md-fab-top-left,
&.md-fab-top-center,
&.md-fab-top-right,
&.md-fab-bottom-left,
&.md-fab-bottom-center,
&.md-fab-bottom-right {
margin: 0;
position: absolute;
z-index: 10;
}
&.md-fab-top-left {
top: $button-fab-space;
left: $button-fab-space;
}
&.md-fab-top-center {
top: $button-fab-space;
left: 50%;
transform: translateX(-50%);
}
&.md-fab-top-right {
top: $button-fab-space;
right: $button-fab-space;
}
&.md-fab-bottom-left {
bottom: $button-fab-space;
left: $button-fab-space;
}
&.md-fab-bottom-center {
bottom: $button-fab-space;
left: 50%;
transform: translateX(-50%);
}
&.md-fab-bottom-right {
right: $button-fab-space;
bottom: $button-fab-space;
}
}
.md-button-tooltip {
&.md-tooltip-top {
margin-top: -8px;

View file

@ -0,0 +1,8 @@
import mdSpeedDial from './mdSpeedDial.vue';
import mdSpeedDialTheme from './mdSpeedDial.theme';
export default function install(Vue) {
Vue.component('md-speed-dial', Vue.extend(mdSpeedDial));
Vue.material.styles.push(mdSpeedDialTheme);
}

View file

@ -0,0 +1,142 @@
@import '../../core/stylesheets/variables.scss';
.md-speed-dial {
display: flex;
flex-direction: column-reverse;
align-items: center;
&.md-direction-top {
&.md-mode-fling {
[md-fab-trigger] ~ .md-button {
transform: scale(.95) translate3D(0, 80%, 0);
}
}
[md-fab-trigger] {
margin-top: 8px;
~ .md-button {
margin-bottom: 16px;
}
}
}
&.md-direction-right {
flex-direction: row;
justify-content: center;
&.md-mode-fling {
[md-fab-trigger] ~ .md-button {
transform: scale(.95) translate3D(-80%, 0, 0);
}
}
[md-fab-trigger] {
margin-right: 8px;
~ .md-button {
margin-left: 16px;
}
}
}
&.md-direction-bottom {
flex-direction: column;
&.md-mode-fling {
[md-fab-trigger] ~ .md-button {
transform: scale(.95) translate3D(0, -80%, 0);
}
}
[md-fab-trigger] {
margin-bottom: 8px;
~ .md-button {
margin-top: 16px;
}
}
}
&.md-direction-left {
flex-direction: row-reverse;
justify-content: center;
&.md-mode-fling {
[md-fab-trigger] ~ .md-button {
transform: scale(.95) translate3D(80%, 0, 0);
}
}
[md-fab-trigger] {
margin-left: 8px;
~ .md-button {
margin-right: 16px;
}
}
}
&.md-mode-scale {
[md-fab-trigger] ~ .md-button {
transform: scale(.6);
}
}
&.md-active {
[md-fab-trigger] {
~ .md-button {
opacity: 1;
transform: translate3D(0, 0, 0) !important;
@for $i from 1 through 10 {
&:nth-child(#{$i + 1}) {
transition-delay: $i * .05s;
}
}
}
[md-icon-morph] {
transform: rotateZ(0);
opacity: 1;
+ .md-icon {
transform: rotateZ(90deg) scale(.8);
opacity: 0;
}
}
}
}
.md-button {
margin: 0;
}
[md-fab-trigger] {
position: relative;
z-index: 2;
~ .md-button {
position: relative;
z-index: 1;
opacity: 0;
transition: $swift-ease-out;
@for $i from 1 through 10 {
&:nth-last-child(#{$i + 1}) {
transition-delay: $i * .05s;
}
}
}
}
[md-icon-morph] + .md-icon,
[md-icon-morph] {
transition: $swift-ease-out;
}
[md-icon-morph] {
opacity: 0;
transform: rotateZ(-90deg) scale(.8);
}
}

View file

@ -0,0 +1,5 @@
.THEME_NAME {
&.md-speed-dial {
}
}

View file

@ -0,0 +1,76 @@
<template>
<div class="md-speed-dial" :class="[themeClass, classes]">
<slot></slot>
</div>
</template>
<style lang="scss" src="./mdSpeedDial.scss"></style>
<script>
import theme from '../../core/components/mdTheme/mixin';
export default {
props: {
mdOpen: {
type: String,
default: 'click'
},
mdMode: {
type: String,
default: 'fling'
},
mdDirection: {
type: String,
default: 'top'
}
},
mixins: [theme],
data: () => ({
fabTrigger: null,
active: false
}),
computed: {
classes() {
let classes = {
'md-active': this.active
};
classes['md-mode-' + this.mdMode] = true;
classes['md-direction-' + this.mdDirection] = true;
return classes;
}
},
methods: {
closeSpeedDial(event) {
if (!event.target === this.fabTrigger || !this.fabTrigger.contains(event.target)) {
this.active = false;
document.body.removeEventListener('click', this.closeSpeedDial);
}
},
toggleSpeedDial() {
this.active = !this.active;
window.setTimeout(() => {
document.body.addEventListener('click', this.closeSpeedDial);
}, 50);
}
},
mounted() {
this.$nextTick(() => {
this.fabTrigger = this.$el.querySelector('[md-fab-trigger]');
if (this.mdOpen === 'click') {
this.fabTrigger.addEventListener('click', this.toggleSpeedDial);
} else {
this.$el.addEventListener('mouseenter', this.toggleSpeedDial);
this.$el.addEventListener('mouseleave', this.toggleSpeedDial);
}
});
},
beforeDestroy() {
this.fabTrigger.removeEventListener('click', this.toggleSpeedDial);
document.body.removeEventListener('click', this.closeSpeedDial);
}
};
</script>

View file

@ -21,6 +21,7 @@ import MdRadio from './components/mdRadio';
import MdSelect from './components/mdSelect';
import MdSidenav from './components/mdSidenav';
import MdSnackbar from './components/mdSnackbar';
import MdSpeedDial from './components/mdSpeedDial';
import MdSpinner from './components/mdSpinner';
import MdSubheader from './components/mdSubheader';
import MdSwitch from './components/mdSwitch';
@ -54,6 +55,7 @@ const options = {
MdSelect,
MdSidenav,
MdSnackbar,
MdSpeedDial,
MdSpinner,
MdSubheader,
MdSwitch,