Skip to content

Commit

Permalink
feat(top-app-bar): Implement mdc-top-app-bar
Browse files Browse the repository at this point in the history
as per MDC 0.32.0
  • Loading branch information
pgbross authored and stasson committed Mar 11, 2018
1 parent f09aa67 commit c6a46dd
Show file tree
Hide file tree
Showing 13 changed files with 336 additions and 94 deletions.
116 changes: 59 additions & 57 deletions components/index.js
Original file line number Diff line number Diff line change
@@ -1,63 +1,65 @@
//
// vue PlugIn
//
import VueMDCButton from './button'
import VueMDCCard from './card'
import VueMDCCheckbox from './checkbox'
import VueMDCChipSet from './chips'
import VueMDCDialog from './dialog'
import VueMDCDrawer from './drawer'
import VueMDCElevation from './elevation'
import VueMDCFab from './fab'
import VueMDCGridList from './grid-list'
import VueMDCIcon from './icon'
import VueMDCIconToggle from './icon-toggle'
import VueMDCLayoutApp from './layout-app'
import VueMDCLayoutGrid from './layout-grid'
import VueMDCLinearProgress from './linear-progress'
import VueMDCList from './list'
import VueMDCMenu from './menu'
import VueMDCRadio from './radio'
import VueMDCRipple from './ripple'
import VueMDCSelect from './select'
import VueMDCSlider from './slider'
import VueMDCSnackbar from './snackbar'
import VueMDCSwitch from './switch'
import VueMDCTabs from './tabs'
import VueMDCTextfield from './textfield'
import VueMDCTheme from './theme'
import VueMDCToolbar from './toolbar'
import VueMDCTypography from './typography'
import VueMDCButton from './button';
import VueMDCCard from './card';
import VueMDCCheckbox from './checkbox';
import VueMDCChipSet from './chips';
import VueMDCDialog from './dialog';
import VueMDCDrawer from './drawer';
import VueMDCElevation from './elevation';
import VueMDCFab from './fab';
import VueMDCGridList from './grid-list';
import VueMDCIcon from './icon';
import VueMDCIconToggle from './icon-toggle';
import VueMDCLayoutApp from './layout-app';
import VueMDCLayoutGrid from './layout-grid';
import VueMDCLinearProgress from './linear-progress';
import VueMDCList from './list';
import VueMDCMenu from './menu';
import VueMDCRadio from './radio';
import VueMDCRipple from './ripple';
import VueMDCSelect from './select';
import VueMDCSlider from './slider';
import VueMDCSnackbar from './snackbar';
import VueMDCSwitch from './switch';
import VueMDCTabs from './tabs';
import VueMDCTextfield from './textfield';
import VueMDCTheme from './theme';
import VueMDCToolbar from './toolbar';
import VueMDCTopAppBar from './top-app-bar';
import VueMDCTypography from './typography';

export default {
version: '__VERSION__',
install (vm) {
vm.use(VueMDCButton)
vm.use(VueMDCCard)
vm.use(VueMDCCheckbox)
vm.use(VueMDCChipSet)
vm.use(VueMDCDialog)
vm.use(VueMDCDrawer)
vm.use(VueMDCElevation)
vm.use(VueMDCFab)
vm.use(VueMDCGridList)
vm.use(VueMDCIcon)
vm.use(VueMDCIconToggle)
vm.use(VueMDCLayoutApp)
vm.use(VueMDCLayoutGrid)
vm.use(VueMDCLinearProgress)
vm.use(VueMDCList)
vm.use(VueMDCMenu)
vm.use(VueMDCRadio)
vm.use(VueMDCRipple)
vm.use(VueMDCSelect)
vm.use(VueMDCSlider)
vm.use(VueMDCSnackbar)
vm.use(VueMDCSwitch)
vm.use(VueMDCTabs)
vm.use(VueMDCTextfield)
vm.use(VueMDCTheme)
vm.use(VueMDCToolbar)
vm.use(VueMDCTypography)
}
}
install(vm) {
vm.use(VueMDCButton);
vm.use(VueMDCCard);
vm.use(VueMDCCheckbox);
vm.use(VueMDCChipSet);
vm.use(VueMDCDialog);
vm.use(VueMDCDrawer);
vm.use(VueMDCElevation);
vm.use(VueMDCFab);
vm.use(VueMDCGridList);
vm.use(VueMDCIcon);
vm.use(VueMDCIconToggle);
vm.use(VueMDCLayoutApp);
vm.use(VueMDCLayoutGrid);
vm.use(VueMDCLinearProgress);
vm.use(VueMDCList);
vm.use(VueMDCMenu);
vm.use(VueMDCRadio);
vm.use(VueMDCRipple);
vm.use(VueMDCSelect);
vm.use(VueMDCSlider);
vm.use(VueMDCSnackbar);
vm.use(VueMDCSwitch);
vm.use(VueMDCTabs);
vm.use(VueMDCTextfield);
vm.use(VueMDCTheme);
vm.use(VueMDCToolbar);
vm.use(VueMDCTopAppBar);
vm.use(VueMDCTypography);
},
};
1 change: 1 addition & 0 deletions components/styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,6 @@
@import './tabs/styles';
@import './textfield/styles';
@import './toolbar/styles';
@import './top-app-bar/styles';
@import './theme/styles';
@import './typography/styles';
2 changes: 1 addition & 1 deletion components/textfield/demo.vue
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,6 @@ export default {
};
</script>

<<style>
<style>
@import url('https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css');
</style>
56 changes: 56 additions & 0 deletions components/top-app-bar/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
## Usage

```html
<mdc-top-app-bar title="Title2">
<mdc-top-app-bar--action event="show-help" icon="help"></mdc-top-app-bar--action>
</mdc-top-app-bar>
```

### top-app-bars

`mdc-top-app-bar` acts as a container for multiple rows containing items such as
application title, navigation menu, and tabs, among other things.
top-app-bars scroll with content by default.

| props | Type | Default | Description |
| -------------- | ------- | -------- | --------------------------------------------------------------- |
| `short` | Boolean | | Short top app bars should only be used with one action item |
| `collapsed` | String | false | Short top app bars can be configured to always appear collapsed |
| `event` | String | optional | optional event to emit on navigation click |
| `event-target` | Object | vm.$root | optional event target, defaults to root bus |

Short top app bars should only be used with one action item.
Short top app bars can be configured to always appear collapsed by applying the `collapsed` attribute.

### Action icons

* `mdc-top-app-bar--action` wraps any icons placed on the right side of an
mdc-top-app-bar.

| props | Type | Default | Description |
| -------------- | ------ | -------- | ------------------------------------------- |
| `icon` | String | | the material icon name |
| `event` | String | optional | optional event to emit on action click |
| `event-target` | Object | vm.$root | optional event target, defaults to root bus |

```html
<mdc-top-app-bar title="Title" event="toggle-drawer">
<mdc-top-app-bar--action event="show-help" icon="help"></mdc-top-app-bar--action>
<mdc-top-app-bar--action event="do-download" icon="file_download"></mdc-top-app-bar--action>
</mdc-top-app-bar>
```

> if the `event` property is not specified, use @click to catch click events
> do not set the icon prop to render your custom icons
**Font Awsome**

```html
<mdc-top-app-bar--action event="show-help" iconClasses="fa fa-star"></mdc-top-app-bar--action>
```

refer to the [MDC Documentation](https://material.io/components/web/catalog/toolbar/#flexible-toolbar-requires-javascript) to learn about customization options.

### Reference

* <https://material.io/components/web/catalog/top-app-bar>
22 changes: 22 additions & 0 deletions components/top-app-bar/demo.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<template>
<div class="mdc-demo--appbar">
<section class="mdc-demo">
<mdc-top-app-bar title="Title2">
<mdc-top-app-bar--action event="show-help" icon="help"></mdc-top-app-bar--action>
<mdc-top-app-bar--action event="show-info" icon="info_outline"></mdc-top-app-bar--action>
</mdc-top-app-bar>
</section>

</div>
</template>

<script>
</script>

<style>
@import url('https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css');
.mdc-demo--appbar {
width: 100%;
}
</style>
6 changes: 6 additions & 0 deletions components/top-app-bar/entry.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import './styles.scss'
import {autoInit} from '../base'
import plugin from './index.js'
export default plugin

autoInit(plugin)
10 changes: 10 additions & 0 deletions components/top-app-bar/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { BasePlugin } from '../base';
import mdcTopAppBar from './mdc-top-app-bar.vue';
import mdcTopAppBarAction from './mdc-top-app-bar--action.vue';

export { mdcTopAppBar, mdcTopAppBarAction };

export default BasePlugin({
mdcTopAppBar,
mdcTopAppBarAction,
});
27 changes: 27 additions & 0 deletions components/top-app-bar/mdc-top-app-bar--action.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<template>
<a href="#" class="mdc-top-app-bar--action mdc-top-app-bar__action-item" :class="actioniconClasses" @click="dispatchEvent">
<slot>{{icon}}</slot>
</a>
</template>

<script>
import { DispatchEventMixin } from '../base';
import { RippleMixin } from '../ripple';
export default {
name: 'mdc-top-app-bar--action',
mixins: [DispatchEventMixin, RippleMixin],
props: {
icon: String,
iconClasses: Object,
},
computed: {
actioniconClasses() {
return {
'material-icons': !!this.icon,
...this.iconClasses,
};
},
},
};
</script>
105 changes: 105 additions & 0 deletions components/top-app-bar/mdc-top-app-bar.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
<template>
<header ref="root" :class="rootClasses">
<div class="mdc-top-app-bar__row">
<section class="mdc-top-app-bar__section mdc-top-app-bar__section--align-start">
<a ref="navigationIcon" href="#" :class="naviconClasses" v-if="haveNavigationIcon" @click="dispatchEvent">{{icon}}</a>
<span class="mdc-top-app-bar__title" v-if="!!title">{{title}}</span>
</section>
<section class="mdc-top-app-bar__section mdc-top-app-bar__section--align-end" v-if="$slots.default">
<slot></slot>
</section>
</div>
</header>
</template>

<script>
import MDCTopAppBarFoundation from '@material/top-app-bar/foundation';
import * as util from '@material/top-app-bar/util';
import { DispatchEventMixin, emitCustomEvent } from '../base';
export default {
name: 'mdc-top-app-bar',
props: {
short: Boolean,
shortCollapsed: Boolean,
title: String,
icon: {
type: String,
default: 'menu',
},
iconClasses: Object,
},
data() {
return {
rootClasses: {
'mdc-top-app-bar': true,
'mdc-top-app-bar--short': this.short,
'mdc-top-app-bar--short-collapsed': this.shortCollapsed,
},
foundation: null,
};
},
mixins: [DispatchEventMixin],
mounted() {
this.foundation = new MDCTopAppBarFoundation({
addClass: className => {
this.$set(this.rootClasses, className, true);
},
removeClass: className => {
this.$delete(this.rootClasses, className);
},
hasClass: className => {
return this.$refs.root.classList.contains(className);
},
registerNavigationIconInteractionHandler: (type, handler) => {
if (this.$refs.navigationIcon) {
this.$refs.navigationIcon.addEventListener(type, handler);
}
},
deregisterNavigationIconInteractionHandler: (type, handler) => {
if (this.$refs.navigationIcon) {
this.$refs.navigationIcon.removeEventListener(type, handler);
}
},
notifyNavigationIconClicked: () => {
emitCustomEvent(
this.$el,
MDCTopAppBarFoundation.strings.NAVIGATION_EVENT,
{},
true,
);
},
registerScrollHandler: handler => {
window.addEventListener('scroll', handler, util.applyPassive());
},
deregisterScrollHandler: handler => {
window.removeEventListener('scroll', handler);
},
getViewportScrollY: () => {
return window.pageYOffset;
},
getTotalActionItems: () =>
this.$refs.root.querySelectorAll(
MDCTopAppBarFoundation.strings.ACTION_ITEM_SELECTOR,
).length,
});
this.foundation.init();
},
computed: {
haveNavigationIcon() {
return !!this.icon || this.iconClasses;
},
naviconClasses() {
return {
'mdc-top-app-bar__navigation-icon': true,
'material-icons': !!this.icon,
...this.iconClasses,
};
},
},
beforeDestroy() {
this.foundation.destroy();
},
};
</script>
1 change: 1 addition & 0 deletions components/top-app-bar/styles.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
@import '@material/top-app-bar/mdc-top-app-bar';
4 changes: 4 additions & 0 deletions components/top-app-bar/test.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { pluginSanityCheck } from '../unit-test'
import plugin from './index.js';

pluginSanityCheck(__dirname, plugin)
Loading

0 comments on commit c6a46dd

Please sign in to comment.