From 09393ad2de88328b420e27e2d334d3be9a588169 Mon Sep 17 00:00:00 2001 From: Marcos Moura Date: Mon, 5 Dec 2016 05:19:01 -0200 Subject: [PATCH] start creation of snackbars --- docs/src/App.vue | 4 + docs/src/components/ExampleBox.vue | 2 +- docs/src/config.js | 5 +- docs/src/pages/components/Snackbar.vue | 79 ++++++++++++ docs/src/routes.js | 24 ++-- src/components/mdButton/mdButton.scss | 2 +- src/components/mdSnackbar/index.js | 8 ++ src/components/mdSnackbar/mdSnackbar.scss | 137 +++++++++++++++++++++ src/components/mdSnackbar/mdSnackbar.theme | 8 ++ src/components/mdSnackbar/mdSnackbar.vue | 90 ++++++++++++++ src/components/mdTabs/mdTab.vue | 14 +-- src/components/mdTabs/mdTabs.vue | 3 +- src/index.js | 2 + 13 files changed, 354 insertions(+), 24 deletions(-) create mode 100644 docs/src/pages/components/Snackbar.vue create mode 100644 src/components/mdSnackbar/index.js create mode 100644 src/components/mdSnackbar/mdSnackbar.scss create mode 100644 src/components/mdSnackbar/mdSnackbar.theme create mode 100644 src/components/mdSnackbar/mdSnackbar.vue diff --git a/docs/src/App.vue b/docs/src/App.vue index 8a1b9d4..aa4485b 100644 --- a/docs/src/App.vue +++ b/docs/src/App.vue @@ -101,6 +101,10 @@ Sidenav + + Snackbar + + Subheader diff --git a/docs/src/components/ExampleBox.vue b/docs/src/components/ExampleBox.vue index 203dd85..adc6cc2 100644 --- a/docs/src/components/ExampleBox.vue +++ b/docs/src/components/ExampleBox.vue @@ -7,7 +7,7 @@ - + diff --git a/docs/src/config.js b/docs/src/config.js index 3f5a58f..49bc568 100644 --- a/docs/src/config.js +++ b/docs/src/config.js @@ -34,10 +34,7 @@ Vue.material.theme.registerAll({ }, 'light-blue': { primary: 'light-blue', - accent: { - color: 'cyan', - hue: 'A200' - } + accent: 'yellow' }, teal: { primary: 'teal', diff --git a/docs/src/pages/components/Snackbar.vue b/docs/src/pages/components/Snackbar.vue new file mode 100644 index 0000000..8ba00ba --- /dev/null +++ b/docs/src/pages/components/Snackbar.vue @@ -0,0 +1,79 @@ + + + + + diff --git a/docs/src/routes.js b/docs/src/routes.js index 31898f5..2036f0a 100644 --- a/docs/src/routes.js +++ b/docs/src/routes.js @@ -14,13 +14,14 @@ import Card from './pages/components/Card'; import Checkbox from './pages/components/Checkbox'; import Dialog from './pages/components/Dialog'; import Icon from './pages/components/Icon'; +import InkRipple from './pages/components/InkRipple'; import Input from './pages/components/Input'; import List from './pages/components/List'; import Menu from './pages/components/Menu'; import Radio from './pages/components/Radio'; -import InkRipple from './pages/components/InkRipple'; import Select from './pages/components/Select'; import Sidenav from './pages/components/Sidenav'; +import Snackbar from './pages/components/Snackbar'; import Subheader from './pages/components/Subheader'; import Switch from './pages/components/Switch'; import Table from './pages/components/Table'; @@ -106,6 +107,11 @@ const components = [ name: 'components:icon', component: Icon }, + { + path: '/components/ink-ripple', + name: 'components:ink-ripple', + component: InkRipple + }, { path: '/components/input', name: 'components:input', @@ -126,11 +132,6 @@ const components = [ name: 'components:radio', component: Radio }, - { - path: '/components/ink-ripple', - name: 'components:ink-ripple', - component: InkRipple - }, { path: '/components/select', name: 'components:select', @@ -142,15 +143,20 @@ const components = [ component: Sidenav }, { - path: '/components/switch', - name: 'components:switch', - component: Switch + path: '/components/snackbar', + name: 'components:snackbar', + component: Snackbar }, { path: '/components/subheader', name: 'components:subheader', component: Subheader }, + { + path: '/components/switch', + name: 'components:switch', + component: Switch + }, { path: '/components/table', name: 'components:table', diff --git a/src/components/mdButton/mdButton.scss b/src/components/mdButton/mdButton.scss index 73a27f8..a37deec 100644 --- a/src/components/mdButton/mdButton.scss +++ b/src/components/mdButton/mdButton.scss @@ -135,7 +135,7 @@ $button-icon-size: 40px; border-radius: $button-fab-size; line-height: $button-fab-size; background-clip: padding-box; - transition: $swift-ease-in; + transition: $swift-ease-out; transition-property: background-color, box-shadow, transform; diff --git a/src/components/mdSnackbar/index.js b/src/components/mdSnackbar/index.js new file mode 100644 index 0000000..79e077f --- /dev/null +++ b/src/components/mdSnackbar/index.js @@ -0,0 +1,8 @@ +import mdSnackbar from './mdSnackbar.vue'; +import mdSnackbarTheme from './mdSnackbar.theme'; + +export default function install(Vue) { + Vue.component('md-snackbar', Vue.extend(mdSnackbar)); + + Vue.material.styles.push(mdSnackbarTheme); +} diff --git a/src/components/mdSnackbar/mdSnackbar.scss b/src/components/mdSnackbar/mdSnackbar.scss new file mode 100644 index 0000000..348c794 --- /dev/null +++ b/src/components/mdSnackbar/mdSnackbar.scss @@ -0,0 +1,137 @@ +@import '../../core/stylesheets/variables.scss'; + +.md-snackbar { + min-width: 288px; + max-width: 568px; + min-height: 48px; + padding: 14px 24px; + position: fixed; + z-index: 120; + overflow: hidden; + border-radius: 2px; + background-color: #323232; + transition: $swift-ease-out; + color: #fff; + font-size: 14px; + + &.md-position-bottom-center { + bottom: 0; + left: 50%; + transform: translate(-50%, 100%, 0); + } + + &.md-position-bottom-right { + bottom: 8px; + right: 8px; + transform: translate(0, 100%, 0); + } + + &.md-position-bottom-left { + bottom: 8px; + left: 8px; + transform: translate(0, 100%, 0); + } + + &.md-position-top-center { + top: 0; + left: 50%; + transform: translate(-50%, -100%, 0); + } + + &.md-position-top-right { + top: 8px; + right: 8px; + transform: translate(0, -100%, 0); + } + + &.md-position-top-left { + top: 8px; + left: 8px; + transform: translate(0, -100%, 0); + } + + &.md-active { + &.md-position-bottom-center { + transform: translate(-50%, 0, 0); + } + + &.md-position-bottom-right { + transform: translate(0, 0, 0); + } + + &.md-position-bottom-left { + transform: translate(0, 0, 0); + } + + &.md-position-top-center { + transform: translate(-50%, 0, 0); + } + + &.md-position-top-right { + transform: translate(0, 0, 0); + } + + &.md-position-top-left { + transform: translate(0, 0, 0); + } + + .md-snackbar-content { + opacity: 1; + transition: opacity .4s .1s $swift-ease-out-timing-function; + } + } + + .md-snackbar-content { + display: flex; + align-items: center; + justify-content: space-between; + opacity: 0; + transition: opacity .2s $swift-ease-out-timing-function; + will-change: opacity; + } + + .md-button { + min-width: 64px; + margin: -8px -16px; + + &:last-child { + margin-left: 48px; + } + } +} + +.md-has-toast-top-right { + .md-fab.md-fab-top-right { + transform: translate(0, 48px, 0); + } +} + +.md-has-toast-top-center { + .md-fab.md-fab-top-center { + transform: translate(-50%, 48px, 0); + } +} + +.md-has-toast-top-left { + .md-fab.md-fab-top-left { + transform: translate(0, 48px, 0); + } +} + +.md-has-toast-bottom-right { + .md-fab.md-fab-bottom-right { + transform: translate(0, -48px, 0); + } +} + +.md-has-toast-bottom-center { + .md-fab.md-fab-bottom-center { + transform: translate(-50%, -48px, 0); + } +} + +.md-has-toast-bottom-left { + .md-fab.md-fab-bottom-left { + transform: translate(0, -48px, 0); + } +} diff --git a/src/components/mdSnackbar/mdSnackbar.theme b/src/components/mdSnackbar/mdSnackbar.theme new file mode 100644 index 0000000..c77a4bf --- /dev/null +++ b/src/components/mdSnackbar/mdSnackbar.theme @@ -0,0 +1,8 @@ +.THEME_NAME { + .md-snackbar, + &.md-snackbar { + .md-ink-ripple { + color: #fff; + } + } +} diff --git a/src/components/mdSnackbar/mdSnackbar.vue b/src/components/mdSnackbar/mdSnackbar.vue new file mode 100644 index 0000000..f16c6e1 --- /dev/null +++ b/src/components/mdSnackbar/mdSnackbar.vue @@ -0,0 +1,90 @@ + + + + + diff --git a/src/components/mdTabs/mdTab.vue b/src/components/mdTabs/mdTab.vue index d1f4f5a..a809cf1 100644 --- a/src/components/mdTabs/mdTab.vue +++ b/src/components/mdTabs/mdTab.vue @@ -62,20 +62,20 @@ } }, mounted() { + let tabData = this.getTabData(); + this.parentTabs = getClosestVueParent(this.$parent, 'md-tabs'); if (!this.parentTabs) { throw new Error('You must wrap the md-tab in a md-tabs'); } - this.$nextTick(() => { - this.mounted = true; - this.parentTabs.registerTab(this.getTabData()); + this.mounted = true; + this.parentTabs.registerTab(tabData); - if (this.mdActive) { - this.parentTabs.activeTab = this.tabId; - } - }); + if (this.mdActive) { + this.parentTabs.setActiveTab(tabData); + } }, beforeDestroy() { this.parentTabs.unregisterTab(this.getTabData()); diff --git a/src/components/mdTabs/mdTabs.vue b/src/components/mdTabs/mdTabs.vue index 7e76eeb..07a0ab8 100644 --- a/src/components/mdTabs/mdTabs.vue +++ b/src/components/mdTabs/mdTabs.vue @@ -94,7 +94,6 @@ }, registerTab(tabData) { this.tabList[tabData.id] = tabData; - this.$forceUpdate(); }, unregisterTab(tabData) { delete this.tabList[tabData.id]; @@ -196,7 +195,7 @@ this.observeElementChanges(); window.addEventListener('resize', this.calculateOnWatch); - if (!this.activeTab) { + if (this.tabList.length && !this.activeTab) { let firstTab = Object.keys(this.tabList)[0]; this.setActiveTab(this.tabList[firstTab]); diff --git a/src/index.js b/src/index.js index bc8fb4d..5131dca 100644 --- a/src/index.js +++ b/src/index.js @@ -15,6 +15,7 @@ import MdMenu from './components/mdMenu'; import MdRadio from './components/mdRadio'; import MdSelect from './components/mdSelect'; import MdSidenav from './components/mdSidenav'; +import MdSnackbar from './components/mdSnackbar'; import MdSubheader from './components/mdSubheader'; import MdSwitch from './components/mdSwitch'; import MdTable from './components/mdTable'; @@ -41,6 +42,7 @@ const options = { MdRadio, MdSelect, MdSidenav, + MdSnackbar, MdSubheader, MdSwitch, MdTable,