Skip to content
This repository has been archived by the owner on Jan 13, 2025. It is now read-only.

Commit

Permalink
feat(top app bar): Add short top app bar always collapsed feature (#2327
Browse files Browse the repository at this point in the history
)
  • Loading branch information
williamernest authored Mar 2, 2018
1 parent 0ba7d10 commit bc17291
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 22 deletions.
43 changes: 29 additions & 14 deletions demos/top-app-bar.html
Original file line number Diff line number Diff line change
Expand Up @@ -163,13 +163,17 @@ <h3>Demo Controls</h3>
<input type="checkbox" id="rtl-checkbox"/>
<label for="rtl-checkbox">RTL</label>
</div>
<div>
<input type="checkbox" id="no-action-item-checkbox"/>
<label for="no-action-item-checkbox">No Action Item</label>
</div>
<div>
<input type="checkbox" id="short-checkbox"/>
<label for="short-checkbox">Short</label>
</div>
<div>
<input type="checkbox" id="no-action-item-checkbox"/>
<label for="no-action-item-checkbox">No Action Item</label>
<input type="checkbox" id="always-collapsed-checkbox" disabled/>
<label for="always-collapsed-checkbox">Always Collapsed (Short Only)&#x200E;</label>
</div>
</div>

Expand All @@ -185,25 +189,21 @@ <h3>Demo Controls</h3>
var drawer = new mdc.drawer.MDCTemporaryDrawer(drawerEl);
var appBar = mdc.topAppBar.MDCTopAppBar.attachTo(appBarEl);

var shortCheckbox = document.getElementById('short-checkbox');
var noActionItemCheckbox = document.getElementById('no-action-item-checkbox');
var rtlCheckbox = document.getElementById('rtl-checkbox');
var noActionItemCheckbox = document.getElementById('no-action-item-checkbox');
var shortCheckbox = document.getElementById('short-checkbox');
var alwaysCollapsedCheckbox = document.getElementById('always-collapsed-checkbox');

appBarEl.addEventListener('MDCTopAppBar:nav', function() {
drawer.open = true;
});

shortCheckbox.addEventListener('change', function() {
appBarEl.classList[this.checked ? 'add' : 'remove']('mdc-top-app-bar--short');
rtlCheckbox.addEventListener('change', function() {
document.body[this.checked ? 'setAttribute' : 'removeAttribute']("dir", "rtl");
appBarEl.classList.remove('mdc-top-app-bar--short-has-action-item');

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

if (!this.checked) {
appBarEl.classList.remove('mdc-top-app-bar--short-collapsed');
appBarEl.classList.remove('mdc-top-app-bar--short-has-action-item');
}
});

noActionItemCheckbox.addEventListener('change', function() {
Expand All @@ -216,13 +216,28 @@ <h3>Demo Controls</h3>
}
});

rtlCheckbox.addEventListener('change', function() {
document.body[this.checked ? 'setAttribute' : 'removeAttribute']("dir", "rtl");
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');

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

if (!this.checked) {
appBarEl.classList.remove('mdc-top-app-bar--short-collapsed');
appBarEl.classList.remove('mdc-top-app-bar--short-has-action-item');
alwaysCollapsedCheckbox.checked = false;
}

alwaysCollapsedCheckbox.disabled = !this.checked;
});

alwaysCollapsedCheckbox.addEventListener('change', function() {
appBarEl.classList[this.checked ? 'add' : 'remove']('mdc-top-app-bar--short-collapsed');

appBar.destroy();
appBar = mdc.topAppBar.MDCTopAppBar.attachTo(appBarEl);
});
});
</script>
</body>
Expand Down
4 changes: 4 additions & 0 deletions demos/top-app-bar.scss
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,7 @@
background-color: white;
padding: 10px;
}

input[type="checkbox"]:disabled + label {
opacity: .4;
}
16 changes: 16 additions & 0 deletions packages/mdc-top-app-bar/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,22 @@ Short top app bars should only be used with one action item:
</header>
```

Short top app bars can be configured to always appear collapsed by applying the `mdc-top-app-bar--short-collapsed` before instantiating the component :

```html
<header class="mdc-top-app-bar mdc-top-app-bar--short mdc-top-app-bar--short-collapsed">
<div class="mdc-top-app-bar__row">
<section class="mdc-top-app-bar__section mdc-top-app-bar__section--align-start">
<a href="#" class="material-icons mdc-top-app-bar__navigation-icon">menu</a>
<span class="mdc-top-app-bar__title">Title</span>
</section>
<section class="mdc-top-app-bar__section mdc-top-app-bar__section--align-end" role="top-app-bar">
<a href="#" class="material-icons mdc-top-app-bar__icon" aria-label="Bookmark this page" alt="Bookmark this page">bookmark</a>
</section>
</div>
</header>
```

### JavaScript

```js
Expand Down
18 changes: 12 additions & 6 deletions packages/mdc-top-app-bar/foundation.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,14 +67,13 @@ class MDCTopAppBarFoundation extends MDCFoundation {
}

init() {
this.adapter_.registerNavigationIconInteractionHandler('click', this.navClickHandler_);

const isShortTopAppBar = this.adapter_.hasClass(cssClasses.SHORT_CLASS);

if (isShortTopAppBar) {
this.adapter_.registerScrollHandler(this.scrollHandler_);
this.initShortAppBar_();
this.initShortTopAppBar_();
}

this.adapter_.registerNavigationIconInteractionHandler('click', this.navClickHandler_);
}

destroy() {
Expand All @@ -85,14 +84,21 @@ class MDCTopAppBarFoundation extends MDCFoundation {
/**
* Used to set the initial style of the short top app bar
*/
initShortAppBar_() {
initShortTopAppBar_() {
const isAlwaysCollapsed = this.adapter_.hasClass(cssClasses.SHORT_COLLAPSED_CLASS);

if (this.adapter_.getTotalActionItems() > 0) {
this.adapter_.addClass(cssClasses.SHORT_HAS_ACTION_ITEM_CLASS);
}

if (!isAlwaysCollapsed) {
this.adapter_.registerScrollHandler(this.scrollHandler_);
this.shortAppBarScrollHandler_();
}
}

/**
* Scroll handler for applying/removing the closed modifier class
* Scroll handler for applying/removing the collapsed modifier class
* on the short top app bar.
*/
shortAppBarScrollHandler_() {
Expand Down
18 changes: 16 additions & 2 deletions test/unit/mdc-top-app-bar/foundation.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -93,15 +93,27 @@ test('short top app bar: scroll listener is removed on destroy', () => {
td.verify(mockAdapter.deregisterScrollHandler(td.matchers.isA(Function)), {times: 1});
});

test('short top app bar: scroll listener is not registered if collapsed class exists before init', () => {
const {foundation, mockAdapter} = setupTest();
td.when(mockAdapter.hasClass(MDCTopAppBarFoundation.cssClasses.SHORT_CLASS)).thenReturn(true);
td.when(mockAdapter.hasClass(MDCTopAppBarFoundation.cssClasses.SHORT_COLLAPSED_CLASS)).thenReturn(true);
td.when(mockAdapter.getTotalActionItems()).thenReturn(0);
foundation.init();
td.verify(mockAdapter.registerScrollHandler(td.matchers.anything()), {times: 0});
});

test('short top app bar: class is added once when page is scrolled from the top', () => {
const {foundation, mockAdapter} = setupTest();
const mockRaf = createMockRaf();

td.when(mockAdapter.hasClass(MDCTopAppBarFoundation.cssClasses.SHORT_CLASS)).thenReturn(true);
td.when(mockAdapter.hasClass(MDCTopAppBarFoundation.cssClasses.SHORT_COLLAPSED_CLASS)).thenReturn(false);
td.when(mockAdapter.getTotalActionItems()).thenReturn(0);
td.when(mockAdapter.getViewportScrollY()).thenReturn(0);

const {scrollHandler} = createMockHandlers(foundation, mockAdapter, mockRaf);

td.when(mockAdapter.getViewportScrollY()).thenReturn(1);

scrollHandler();
scrollHandler();

Expand All @@ -113,9 +125,11 @@ test('short top app bar: class is removed once when page is scrolled to the top'
const mockRaf = createMockRaf();

td.when(mockAdapter.hasClass(MDCTopAppBarFoundation.cssClasses.SHORT_CLASS)).thenReturn(true);
td.when(mockAdapter.hasClass(MDCTopAppBarFoundation.cssClasses.SHORT_COLLAPSED_CLASS)).thenReturn(false);
td.when(mockAdapter.getTotalActionItems()).thenReturn(0);

const {scrollHandler} = createMockHandlers(foundation, mockAdapter, mockRaf);
// Apply the closed class
// Apply the collapsed class
td.when(mockAdapter.getViewportScrollY()).thenReturn(1);
scrollHandler();

Expand Down

0 comments on commit bc17291

Please sign in to comment.