Skip to content

Commit

Permalink
feat(top-app-bar): add default scroll behavior (#2417)
Browse files Browse the repository at this point in the history
BREAKING CHANGE: New adapter methods for setting the top app bar position and adding resize event handlers that must be implemented.
  • Loading branch information
williamernest committed Apr 6, 2018
1 parent afe5367 commit 18be342
Show file tree
Hide file tree
Showing 13 changed files with 620 additions and 38 deletions.
22 changes: 19 additions & 3 deletions demos/top-app-bar.html
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@
</aside>

<main class="demo-main">
<div>
<div id="content-main" class="mdc-top-app-bar--fixed-adjust">
<p class="demo-paragraph">
Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est.
</p>
Expand Down Expand Up @@ -208,6 +208,7 @@ <h3 class="mdc-typography--title">Demo Controls</h3>
var rightItemEl = document.getElementById('right-item');
var rightSection = document.getElementById('iconSection');
var drawerEl = document.querySelector('.mdc-drawer');
var contentMainEl = document.getElementById('content-main');

var drawer = new mdc.drawer.MDCTemporaryDrawer(drawerEl);
var appBar = mdc.topAppBar.MDCTopAppBar.attachTo(appBarEl);
Expand Down Expand Up @@ -247,6 +248,14 @@ <h3 class="mdc-typography--title">Demo Controls</h3>
// Top App Bar Specific Options
denseCheckbox.addEventListener('change', function() {
appBarEl.classList[this.checked ? 'add' : 'remove']('mdc-top-app-bar--dense');
contentMainEl.classList[this.checked ? 'add' : 'remove']('mdc-top-app-bar--dense-fixed-adjust');
if (prominentCheckbox.checked) {
contentMainEl.classList[this.checked ? 'add' : 'remove']('mdc-top-app-bar--dense-prominent-fixed-adjust');
}


appBar.destroy();
appBar = mdc.topAppBar.MDCTopAppBar.attachTo(appBarEl);

shortCheckbox.disabled = this.checked || prominentCheckbox.checked || fixedCheckbox.checked;
});
Expand All @@ -264,6 +273,14 @@ <h3 class="mdc-typography--title">Demo Controls</h3>

prominentCheckbox.addEventListener('change', function() {
appBarEl.classList[this.checked ? 'add' : 'remove']('mdc-top-app-bar--prominent');
contentMainEl.classList[this.checked ? 'add' : 'remove']('mdc-top-app-bar--prominent-fixed-adjust');

if (denseCheckbox.checked) {
contentMainEl.classList[this.checked ? 'add' : 'remove']('mdc-top-app-bar--dense-prominent-fixed-adjust');
}

appBar.destroy();
appBar = mdc.topAppBar.MDCTopAppBar.attachTo(appBarEl);

shortCheckbox.disabled = this.checked || denseCheckbox.checked || fixedCheckbox.checked;
});
Expand All @@ -272,6 +289,7 @@ <h3 class="mdc-typography--title">Demo Controls</h3>
shortCheckbox.addEventListener('change', function() {
appBarEl.classList[this.checked ? 'add' : 'remove']('mdc-top-app-bar--short');
appBarEl.classList.remove('mdc-top-app-bar--short-has-action-item');
contentMainEl.classList[this.checked ? 'add' : 'remove']('mdc-top-app-bar--short-fixed-adjust');

appBar.destroy();
appBar = mdc.topAppBar.MDCTopAppBar.attachTo(appBarEl);
Expand All @@ -294,8 +312,6 @@ <h3 class="mdc-typography--title">Demo Controls</h3>
appBar.destroy();
appBar = mdc.topAppBar.MDCTopAppBar.attachTo(appBarEl);
});


});
</script>
</body>
Expand Down
4 changes: 4 additions & 0 deletions packages/mdc-top-app-bar/_mixins.scss
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,10 @@
padding-bottom: $mdc-top-app-bar-prominent-mobile-title-bottom-padding;
}
}

.mdc-top-app-bar--fixed-adjust {
margin-top: $mdc-top-app-bar-mobile-row-height;
}
}
}

Expand Down
19 changes: 19 additions & 0 deletions packages/mdc-top-app-bar/adapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,19 @@ class MDCTopAppBarAdapter {
*/
hasClass(className) {}

/**
* Sets the specified inline style property on the root Element to the given value.
* @param {string} property
* @param {string} value
*/
setStyle(property, value) {}

/**
* Gets the height of the top app bar.
* @return {number}
*/
getTopAppBarHeight() {}

/**
* Registers an event handler on the navigation icon element for a given event.
* @param {string} type
Expand All @@ -72,6 +85,12 @@ class MDCTopAppBarAdapter {
/** @param {function(!Event)} handler */
deregisterScrollHandler(handler) {}

/** @param {function(!Event)} handler */
registerResizeHandler(handler) {}

/** @param {function(!Event)} handler */
deregisterResizeHandler(handler) {}

/** @return {number} */
getViewportScrollY() {}

Expand Down
26 changes: 16 additions & 10 deletions packages/mdc-top-app-bar/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,6 @@
* limitations under the License.
*/

/** @enum {string} */
const strings = {
NAVIGATION_EVENT: 'MDCTopAppBar:nav',
ROOT_SELECTOR: '.mdc-top-app-bar',
TITLE_SELECTOR: '.mdc-top-app-bar__title',
NAVIGATION_ICON_SELECTOR: '.mdc-top-app-bar__navigation-icon',
ACTION_ITEM_SELECTOR: '.mdc-top-app-bar__action-item',
};

/** @enum {string} */
const cssClasses = {
FIXED_CLASS: 'mdc-top-app-bar--fixed',
Expand All @@ -33,4 +24,19 @@ const cssClasses = {
SHORT_COLLAPSED_CLASS: 'mdc-top-app-bar--short-collapsed',
};

export {strings, cssClasses};
/** @enum {number} */
const numbers = {
DEBOUNCE_THROTTLE_RESIZE_TIME_MS: 100,
MAX_TOP_APP_BAR_HEIGHT: 128,
};

/** @enum {string} */
const strings = {
ACTION_ITEM_SELECTOR: '.mdc-top-app-bar__action-item',
NAVIGATION_EVENT: 'MDCTopAppBar:nav',
NAVIGATION_ICON_SELECTOR: '.mdc-top-app-bar__navigation-icon',
ROOT_SELECTOR: '.mdc-top-app-bar',
TITLE_SELECTOR: '.mdc-top-app-bar__title',
};

export {strings, cssClasses, numbers};
19 changes: 14 additions & 5 deletions packages/mdc-top-app-bar/foundation.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,14 @@
* limitations under the License.
*/

import {strings, cssClasses} from './constants';
import {strings, cssClasses, numbers} from './constants';
import MDCTopAppBarAdapter from './adapter';
import MDCFoundation from '@material/base/foundation';

/**
* @extends {MDCFoundation<!MDCTopAppBarAdapter>}
*/
class MDCTopAppBarFoundation extends MDCFoundation {
class MDCTopAppBarBaseFoundation extends MDCFoundation {
/** @return enum {string} */
static get strings() {
return strings;
Expand All @@ -33,6 +33,11 @@ class MDCTopAppBarFoundation extends MDCFoundation {
return cssClasses;
}

/** @return enum {number} */
static get numbers() {
return numbers;
}

/**
* {@see MDCTopAppBarAdapter} for typing information on parameters and return
* types.
Expand All @@ -43,11 +48,15 @@ class MDCTopAppBarFoundation extends MDCFoundation {
hasClass: (/* className: string */) => {},
addClass: (/* className: string */) => {},
removeClass: (/* className: string */) => {},
setStyle: (/* property: string, value: string */) => {},
getTopAppBarHeight: () => {},
registerNavigationIconInteractionHandler: (/* type: string, handler: EventListener */) => {},
deregisterNavigationIconInteractionHandler: (/* type: string, handler: EventListener */) => {},
notifyNavigationIconClicked: () => {},
registerScrollHandler: (/* handler: EventListener */) => {},
deregisterScrollHandler: (/* handler: EventListener */) => {},
registerResizeHandler: (/* handler: EventListener */) => {},
deregisterResizeHandler: (/* handler: EventListener */) => {},
getViewportScrollY: () => /* number */ 0,
getTotalActionItems: () => /* number */ 0,
});
Expand All @@ -56,8 +65,8 @@ class MDCTopAppBarFoundation extends MDCFoundation {
/**
* @param {!MDCTopAppBarAdapter} adapter
*/
constructor(adapter) {
super(Object.assign(MDCTopAppBarFoundation.defaultAdapter, adapter));
constructor(/** @type {!MDCTopAppBarAdapter} */ adapter) {
super(Object.assign(MDCTopAppBarBaseFoundation.defaultAdapter, adapter));

this.navClickHandler_ = () => this.adapter_.notifyNavigationIconClicked();
}
Expand All @@ -71,4 +80,4 @@ class MDCTopAppBarFoundation extends MDCFoundation {
}
}

export default MDCTopAppBarFoundation;
export default MDCTopAppBarBaseFoundation;
16 changes: 12 additions & 4 deletions packages/mdc-top-app-bar/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,16 @@
*/

import MDCTopAppBarAdapter from './adapter';
import MDCTopAppBarFoundation from './foundation';
import MDCComponent from '@material/base/component';
import {MDCRipple} from '@material/ripple/index';
import {cssClasses, strings} from './constants';
import MDCTopAppBarBaseFoundation from './foundation';
import MDCFixedTopAppBarFoundation from './fixed/foundation';
import MDCShortTopAppBarFoundation from './short/foundation';
import MDCTopAppBarFoundation from './standard/foundation';

/**
* @extends {MDCComponent<!MDCTopAppBarFoundation>}
* @extends {MDCComponent<!MDCTopAppBarBaseFoundation>}
* @final
*/
class MDCTopAppBar extends MDCComponent {
Expand Down Expand Up @@ -68,14 +69,16 @@ class MDCTopAppBar extends MDCComponent {
}

/**
* @return {!MDCTopAppBarFoundation}
* @return {!MDCTopAppBarBaseFoundation}
*/
getDefaultFoundation() {
/** @type {!MDCTopAppBarAdapter} */
const adapter = /** @type {!MDCTopAppBarAdapter} */ (Object.assign({
hasClass: (className) => this.root_.classList.contains(className),
addClass: (className) => this.root_.classList.add(className),
removeClass: (className) => this.root_.classList.remove(className),
setStyle: (property, value) => this.root_.style.setProperty(property, value),
getTopAppBarHeight: () => this.root_.clientHeight,
registerNavigationIconInteractionHandler: (evtType, handler) => {
if (this.navIcon_) {
this.navIcon_.addEventListener(evtType, handler);
Expand All @@ -91,12 +94,15 @@ class MDCTopAppBar extends MDCComponent {
},
registerScrollHandler: (handler) => window.addEventListener('scroll', handler),
deregisterScrollHandler: (handler) => window.removeEventListener('scroll', handler),
registerResizeHandler: (handler) => window.addEventListener('resize', handler),
deregisterResizeHandler: (handler) => window.removeEventListener('resize', handler),
getViewportScrollY: () => window.pageYOffset,
getTotalActionItems: () =>
this.root_.querySelectorAll(strings.ACTION_ITEM_SELECTOR).length,
})
);

/** @type {!MDCTopAppBarBaseFoundation} */
let foundation;
if (this.root_.classList.contains(cssClasses.SHORT_CLASS)) {
foundation = new MDCShortTopAppBarFoundation(adapter);
Expand All @@ -110,4 +116,6 @@ class MDCTopAppBar extends MDCComponent {
}
}

export {MDCTopAppBar, MDCTopAppBarFoundation, MDCFixedTopAppBarFoundation, MDCShortTopAppBarFoundation};
export {MDCTopAppBar, MDCTopAppBarBaseFoundation,
MDCTopAppBarFoundation, MDCFixedTopAppBarFoundation,
MDCShortTopAppBarFoundation};
23 changes: 22 additions & 1 deletion packages/mdc-top-app-bar/mdc-top-app-bar.scss
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
@include mdc-top-app-bar-icon-ink-color(text-primary-on-primary);

display: flex;
position: relative;
position: fixed;
flex-direction: column;
justify-content: space-between;
box-sizing: border-box;
Expand Down Expand Up @@ -159,6 +159,7 @@
}
}

// stylelint-disable-next-line plugin/selector-bem-pattern
.mdc-top-app-bar--fixed {
position: fixed;
transition: box-shadow 200ms linear;
Expand Down Expand Up @@ -189,5 +190,25 @@
}
// stylelint-enable plugin/selector-bem-pattern

.mdc-top-app-bar--fixed-adjust {
margin-top: $mdc-top-app-bar-row-height;
}

.mdc-top-app-bar--dense-fixed-adjust {
margin-top: $mdc-top-app-bar-dense-row-height;
}

.mdc-top-app-bar--short-fixed-adjust {
margin-top: $mdc-top-app-bar-mobile-row-height;
}

.mdc-top-app-bar--prominent-fixed-adjust {
margin-top: $mdc-top-app-bar-prominent-row-height;
}

.mdc-top-app-bar--dense-prominent-fixed-adjust {
margin-top: $mdc-top-app-bar-dense-row-height * 2;
}

// Mobile Styles
@include mdc-top-app-bar-mobile-breakpoint_;
9 changes: 5 additions & 4 deletions packages/mdc-top-app-bar/short/foundation.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@
* limitations under the License.
*/

import {cssClasses} from '../constants';
import MDCTopAppBarAdapter from '../adapter';
import MDCTopAppBarFoundation from '../foundation';
import MDCTopAppBarBaseFoundation from '../foundation';
import {cssClasses} from '../constants';

/**
* @extends {MDCTopAppBarFoundation<!MDCShortTopAppBarFoundation>}
* @extends {MDCTopAppBarBaseFoundation<!MDCShortTopAppBarFoundation>}
* @final
*/
class MDCShortTopAppBarFoundation extends MDCTopAppBarFoundation {
class MDCShortTopAppBarFoundation extends MDCTopAppBarBaseFoundation {
/**
* @param {!MDCTopAppBarAdapter} adapter
*/
Expand Down Expand Up @@ -58,6 +58,7 @@ class MDCShortTopAppBarFoundation extends MDCTopAppBarFoundation {
/**
* Scroll handler for applying/removing the collapsed modifier class
* on the short top app bar.
* @private
*/
shortAppBarScrollHandler_() {
const currentScroll = this.adapter_.getViewportScrollY();
Expand Down
Loading

0 comments on commit 18be342

Please sign in to comment.