Create switches and remove label with empty slot

This commit is contained in:
Marcos Moura 2016-08-09 03:41:29 -03:00
parent 310baef919
commit 32d58d7bcf
13 changed files with 306 additions and 8 deletions

View file

@ -16,7 +16,8 @@
},
"dependencies": {
"autosize": "^3.0.17",
"scopedQuerySelectorShim": "github:lazd/scopedQuerySelectorShim"
"scopedQuerySelectorShim": "github:lazd/scopedQuerySelectorShim",
"vue-touch": "^1.1.0"
},
"devDependencies": {
"babel-core": "^6.11.4",

View file

@ -12,7 +12,6 @@ $checkbox-ripple-size: 48px;
.md-checkbox-container {
width: $checkbox-size;
height: $checkbox-size;
margin-right: 8px;
position: relative;
border-radius: 2px;
border: 2px solid rgba(#000, .54);
@ -59,6 +58,7 @@ $checkbox-ripple-size: 48px;
.md-checkbox-label {
height: $checkbox-size;
padding-left: 8px;
line-height: $checkbox-size;
}
}

View file

@ -1,10 +1,10 @@
<template>
<div class="md-checkbox" :class="classes">
<div class="md-checkbox-container" @mousedown="toggleCheck" v-md-ink-ripple="disabled">
<div class="md-checkbox-container" @click="toggleCheck" v-md-ink-ripple="disabled">
<input type="checkbox" v-model="model" :name="name" :id="id" :disabled="disabled" :value="value">
</div>
<label :for="id || name" class="md-checkbox-label">
<label :for="id || name" class="md-checkbox-label" v-if="hasSlot">
<slot></slot>
</label>
</div>
@ -24,6 +24,11 @@
id: String,
disabled: Boolean
},
data() {
return {
hasSlot: true
};
},
computed: {
classes() {
return {
@ -40,7 +45,7 @@
}
},
ready() {
this.hasSlot = this.$el.querySelector('label').innerHTML.trim() !== '';
}
};
</script>

View file

View file

@ -12,7 +12,6 @@ $radio-ripple-size: 48px;
.md-radio-container {
width: $radio-size;
height: $radio-size;
margin-right: 8px;
position: relative;
border-radius: 50%;
border: 2px solid rgba(#000, .54);
@ -57,6 +56,7 @@ $radio-ripple-size: 48px;
.md-radio-label {
height: $radio-size;
padding-left: 8px;
line-height: $radio-size;
}
}

View file

@ -1,10 +1,10 @@
<template>
<div class="md-radio" :class="classes">
<div class="md-radio-container" @mousedown="toggleCheck" v-md-ink-ripple="disabled">
<div class="md-radio-container" @click="toggleCheck" v-md-ink-ripple="disabled">
<input type="radio" v-model="model" :name="name" :id="id" :disabled="disabled" :value="value">
</div>
<label :for="id || name" class="md-radio-label">
<label :for="id || name" class="md-radio-label" v-if="hasSlot">
<slot></slot>
</label>
</div>
@ -27,6 +27,11 @@
id: String,
disabled: Boolean
},
data() {
return {
hasSlot: true
};
},
computed: {
classes() {
return {
@ -41,6 +46,9 @@
this.model = this.value;
}
}
},
ready() {
this.hasSlot = this.$el.querySelector('label').innerHTML.trim() !== '';
}
};
</script>

View file

@ -0,0 +1,14 @@
import VueTouch from 'vue-touch';
import mdSwitch from './mdSwitch.vue';
import mdSwitchTheme from './mdSwitch.theme';
export default function install(Vue) {
Vue.use(VueTouch);
VueTouch.config.pan = {
threshold: 1
};
Vue.component('md-switch', Vue.extend(mdSwitch));
window.VueMaterial.styles.push(mdSwitchTheme);
}

View file

@ -0,0 +1,76 @@
@import '../../core/variables.scss';
$switch-width: 34px;
$switch-height: 14px;
$switch-thumb-size: 20px;
$switch-ripple-size: 48px;
.md-switch {
width: auto;
margin: 16px 8px 16px 0;
display: inline-flex;
position: relative;
.md-switch-container {
width: $switch-width;
height: $switch-height;
position: relative;
border-radius: $switch-height;
transition: $swift-ease-out;
background-color: rgba(#000, .38);
.md-switch-thumb {
width: $switch-thumb-size;
height: $switch-thumb-size;
position: absolute;
top: 50%;
left: 0;
cursor: grab;
background-color: #fafafa;
border-radius: 50%;
box-shadow: $material-shadow-1dp;
transition: $swift-linear;
}
input {
position: absolute;
left: -999em;
}
.md-ink-ripple {
top: -16px;
right: -16px;
bottom: -16px;
left: -16px;
border-radius: 50%;
color: rgba(#000, .54);
.md-ripple {
width: $switch-ripple-size !important;
height: $switch-ripple-size !important;
top: 0 !important;
right: 0 !important;
bottom: 0 !important;
left: 0 !important;
}
}
}
.md-switch-label {
height: $switch-height;
padding-left: 8px;
line-height: $switch-height;
}
}
.md-switch.md-dragging {
.md-switch-thumb {
cursor: grabbing;
}
}
.md-switch.md-disabled {
.md-switch-thumb {
cursor: default;
}
}

View file

@ -0,0 +1,29 @@
.THEME_NAME {
.md-switch,
&.md-switch {
&.md-checked {
.md-switch-container,
.md-switch-thumb {
background-color: ACCENT-COLOR;
}
.md-ink-ripple {
color: ACCENT-COLOR;
}
.md-ripple {
opacity: .38;
}
}
&.md-disabled {
.md-switch-container {
background-color: rgba(#000, .12);
}
.md-switch-thumb {
background-color: #bdbdbd;
}
}
}
}

View file

@ -0,0 +1,108 @@
<template>
<div class="md-switch" :class="classes">
<div class="md-switch-container" @click="onClick">
<div class="md-switch-thumb" :style="styles" v-md-ink-ripple="disabled" v-touch:panstart="onDragStart" v-touch:panmove="onDrag" v-touch:panend="onDragEnd" v-touch-options:pan="{ direction: 'horizontal' }">
<input type="checkbox" v-model="model" :name="name" :id="id" :disabled="disabled" :value="value">
</div>
</div>
<label :for="id || name" class="md-switch-label" v-if="hasSlot">
<slot></slot>
</label>
</div>
</template>
<style lang="scss" src="./mdSwitch.scss"></style>
<script>
let dragFrame;
let fullThreshold = 75;
let initialThreshold = '-1px';
export default {
props: {
model: {
type: Boolean,
required: true,
twoWay: true
},
name: String,
id: String,
disabled: Boolean
},
data() {
return {
hasSlot: true,
leftPos: initialThreshold,
percent: 0,
dragging: false
};
},
computed: {
classes() {
return {
'md-checked': Boolean(this.model),
'md-disabled': this.disabled,
'md-dragging': this.dragging
};
},
styles() {
return {
transform: `translate3D(${this.leftPos}, -50%, 0)`
};
}
},
watch: {
model() {
this.leftPos = this.model ? fullThreshold + '%' : initialThreshold;
}
},
methods: {
onClick() {
if (!this.disabled && !this.dragging) {
this.model = !this.model;
}
},
onDragStart() {
if (!this.disabled) {
this.dragging = true;
}
},
onDrag(event) {
if (!this.disabled) {
dragFrame = requestAnimationFrame(() => {
let percent = 0;
if (this.model) {
percent = 20;
}
percent = Math.round((event.deltaX + percent) * 100 / 34);
if (percent >= 0 && percent <= fullThreshold) {
this.percent = percent;
this.leftPos = percent + '%';
}
});
}
},
onDragEnd() {
if (!this.disabled) {
setTimeout(() => {
this.dragging = false;
}, 50);
this.model = this.percent >= fullThreshold / 2;
this.leftPos = this.model ? fullThreshold + '%' : initialThreshold;
}
}
},
ready() {
this.hasSlot = this.$el.querySelector('label').innerHTML.trim() !== '';
this.leftPos = this.model ? fullThreshold + '%' : initialThreshold;
},
destroyed() {
cancelAnimationFrame(dragFrame);
}
};
</script>

50
src/docs/pages/Switch.vue Normal file
View file

@ -0,0 +1,50 @@
<template>
<section>
<h2 class="title">Switch</h2>
<div>
<md-switch :model.sync="checked0" id="my-test0" name="my-test0"></md-switch>
</div>
<div v-md-theme="'indigo'">
<md-switch :model.sync="checked1" id="my-test1" name="my-test1"></md-switch>
</div>
<div v-md-theme="'blue'">
<md-switch :model.sync="checked2" id="my-test2" name="my-test2"></md-switch>
</div>
<div v-md-theme="'orange'">
<md-switch :model.sync="checked3" id="my-test3" name="my-test3"></md-switch>
</div>
<div v-md-theme="'bottom-bar'">
<md-switch :model.sync="checked4" id="my-test4" name="my-test4"></md-switch>
</div>
<div v-md-theme="'bottom-bar'">
<md-switch :model.sync="checked5" id="my-test5" name="my-test5" disabled></md-switch>
</div>
</section>
</template>
<style lang="scss" scoped>
section {
padding: 0 24px;
}
</style>
<script>
export default {
data() {
return {
checked0: true,
checked1: true,
checked2: true,
checked3: true,
checked4: true,
checked5: true
};
}
};
</script>

View file

@ -5,6 +5,7 @@ import Buttons from './pages/Buttons';
import ButtonToggle from './pages/ButtonToggle';
import Checkbox from './pages/Checkbox';
import Radio from './pages/Radio';
import Switch from './pages/Switch';
import Divider from './pages/Divider';
import Icon from './pages/Icon';
import Input from './pages/Input';
@ -41,6 +42,10 @@ const routes = {
name: 'radio',
component: Radio
},
'/switch': {
name: 'switch',
component: Switch
},
'/checkbox': {
name: 'checkbox',
component: Checkbox

View file

@ -5,6 +5,7 @@ import MdButton from './components/mdButton';
import MdButtonToggle from './components/mdButtonToggle';
import MdCheckbox from './components/mdCheckbox';
import mdRadio from './components/mdRadio';
import mdSwitch from './components/mdSwitch';
import MdDivider from './components/mdDivider';
import MdIcon from './components/mdIcon';
import MdInputContainer from './components/mdInputContainer';
@ -23,6 +24,7 @@ let options = {
MdButtonToggle,
MdCheckbox,
mdRadio,
mdSwitch,
MdDivider,
MdIcon,
MdInputContainer,