UX: Use dropdown for hamburger on wide screens, full height on smaller

This commit is contained in:
Robin Ward 2015-08-26 14:42:42 -04:00
parent 9760369e4c
commit e66f111348
6 changed files with 90 additions and 45 deletions

View File

@ -2,19 +2,56 @@ import { default as computed, on, observes } from 'ember-addons/ember-computed-d
export default Ember.Component.extend({ export default Ember.Component.extend({
classNameBindings: ['visible::slideright'], classNameBindings: ['visible::hidden', 'viewMode'],
attributeBindings: ['style'],
elementId: 'hamburger-menu', elementId: 'hamburger-menu',
viewMode: 'dropDown',
showClose: Ember.computed.equal('viewMode', 'slide-in'),
@computed('viewMode')
style(viewMode) {
if (viewMode === 'drop-down') {
const $buttonPanel = $('header ul.icons');
const buttonPanelPos = $buttonPanel.offset();
const myWidth = this.$().width();
const posTop = parseInt(buttonPanelPos.top + $buttonPanel.height());
const posLeft = parseInt(buttonPanelPos.left + $buttonPanel.width() - myWidth);
return `left: ${posLeft}px; top: ${posTop}px`.htmlSafe();
}
},
@computed('viewMode')
bodyStyle(viewMode) {
if (viewMode === 'drop-down') {
const height = parseInt($(window).height() * 0.8)
return `height: ${height}px`.htmlSafe();
}
},
@observes('visible') @observes('visible')
_catchClickOutside() { _visibleChanged() {
if (this.get('visible')) { if (this.get('visible')) {
$('.hamburger-dropdown').addClass('active');
if ($(window).width() < 1024) {
this.set('viewMode', 'slide-in');
} else {
this.set('viewMode', 'drop-down');
}
$('html').on('click.close-hamburger', (e) => { $('html').on('click.close-hamburger', (e) => {
const $target = $(e.target); const $target = $(e.target);
if ($target.closest('.dropdown.hamburger').length > 0) { return; } if ($target.closest('.hamburger-dropdown').length > 0) { return; }
if ($target.closest('#hamburger-menu').length > 0) { return; } if ($target.closest('#hamburger-menu').length > 0) { return; }
this.set('visible', false); this.hide();
}); });
} else { } else {
$('.hamburger-dropdown').removeClass('active');
$('html').off('click.close-hamburger'); $('html').off('click.close-hamburger');
} }
}, },
@ -42,19 +79,21 @@ export default Ember.Component.extend({
@on('didInsertElement') @on('didInsertElement')
_bindEvents() { _bindEvents() {
this.$().on('click.discourse-hamburger', 'a', () => { this.$().on('click.discourse-hamburger', 'a', () => {
this.set('visible', false); this.hide();
}); });
this.appEvents.on('dropdowns:closeAll', this, this.hide);
$('body').on('keydown.discourse-hambuger', (e) => { $('body').on('keydown.discourse-hambuger', (e) => {
if (e.which === 27) { if (e.which === 27) {
this.set('visible', false); this.hide();
} }
}); });
}, },
@on('willDestroyElement') @on('willDestroyElement')
_removeEvents() { _removeEvents() {
this.appEvents.off('dropdowns:closeAll', this, this.hide);
this.$().off('click.discourse-hamburger'); this.$().off('click.discourse-hamburger');
$('body').off('keydown.discourse-hambuger'); $('body').off('keydown.discourse-hambuger');
$('html').off('click.close-hamburger'); $('html').off('click.close-hamburger');
@ -73,9 +112,13 @@ export default Ember.Component.extend({
}); });
}, },
hide() {
this.set('visible', false);
},
actions: { actions: {
close() { close() {
this.set('visible', false); this.hide();
}, },
keyboardShortcuts() { keyboardShortcuts() {
this.sendAction('showKeyboardAction'); this.sendAction('showKeyboardAction');

View File

@ -1,8 +1,11 @@
{{#if visible}} {{#if visible}}
{{#if showClose}}
<div class='hamburger-header clearfix'> <div class='hamburger-header clearfix'>
<a href {{action "close"}} class='close-hamburger'>{{fa-icon 'times'}}</a> <a href {{action "close"}} class='close-hamburger'>{{fa-icon 'times'}}</a>
</div> </div>
<div class='hamburger-body'> {{/if}}
<div class='hamburger-body' style={{bodyStyle}}>
<ul class="location-links"> <ul class="location-links">
{{#if currentUser.staff}} {{#if currentUser.staff}}
<li> <li>

View File

@ -42,7 +42,7 @@
</a> </a>
{{/if}} {{/if}}
</li> </li>
<li class='hamburger categories dropdown'> <li class='hamburger-dropdown'>
{{#if loginRequired}} {{#if loginRequired}}
<a class='icon' <a class='icon'
href href

View File

@ -7,9 +7,11 @@ export default Ember.View.extend({
templateName: 'header', templateName: 'header',
renderDropdowns: false, renderDropdowns: false,
showDropdown: function($target) { showDropdown($target) {
var self = this; var self = this;
this.appEvents.trigger('dropdowns:closeAll');
if (!this.get("renderDropdowns")) { if (!this.get("renderDropdowns")) {
this.set("renderDropdowns", true); this.set("renderDropdowns", true);
Em.run.next(function(){ Em.run.next(function(){
@ -138,7 +140,7 @@ export default Ember.View.extend({
const self = this; const self = this;
this.$('a[data-dropdown]').on('click.dropdown', function(e) { this.$('a[data-dropdown]').on('click.dropdown', function(e) {
self.showDropdown.apply(self, [$(e.currentTarget)]); self.showDropdown.call(self, $(e.currentTarget));
return false; return false;
}); });
this.$().on('click.notifications','a.unread-private-messages, a.unread-notifications, a[data-notifications]', function(e) { this.$().on('click.notifications','a.unread-private-messages, a.unread-notifications, a[data-notifications]', function(e) {

View File

@ -1,15 +1,27 @@
#hamburger-menu { #hamburger-menu.slide-in {
position: fixed; position: fixed;
right: 0; right: 0;
top: 0; top: 0;
background-color: $secondary;
z-index: 1002;
height: 100%; height: 100%;
overflow: none;
transition: 0.3s ease-in-out;
@include transform(translateX(0));
box-shadow: 0 4px 4px 4px rgba(0,0,0, .25); box-shadow: 0 4px 4px 4px rgba(0,0,0, .25);
.hamburger-body {
position: absolute;
top: 40px;
bottom: 37px;
}
}
#hamburger-menu.drop-down {
border: 1px solid dark-light-diff($primary, $secondary, 90%, -60%);
box-shadow: 0 2px 2px rgba(0,0,0, .25);
position: absolute;
}
#hamburger-menu {
background-color: $secondary;
z-index: 1100;
overflow: none;
padding: 0.5em 0.5em 0.5em 0.5em; padding: 0.5em 0.5em 0.5em 0.5em;
width: 300px; width: 300px;
@ -28,13 +40,6 @@
right: 20px; right: 20px;
} }
.hamburger-body {
overflow-y: auto;
overflow-x: hidden;
position: absolute;
top: 40px;
bottom: 37px;
}
ul { ul {
@ -73,8 +78,10 @@
font-weight: normal; font-weight: normal;
font-size: 11px; font-size: 11px;
} }
.hamburger-body {
overflow-y: auto;
overflow-x: hidden;
}
} }
#hamburger-menu.slideright {
@include transform(translateX(330px));
}

View File

@ -5,27 +5,17 @@ acceptance("Hamburger Menu");
test("Toggle Menu", (assert) => { test("Toggle Menu", (assert) => {
visit("/"); visit("/");
andThen(() => { andThen(() => {
assert.ok(exists("#hamburger-menu.slideright"), "hidden by default"); assert.ok(exists("#hamburger-menu.hidden"), "hidden by default");
}); });
click("#toggle-hamburger-menu"); click("#toggle-hamburger-menu");
andThen(() => { andThen(() => {
assert.ok(!exists("#hamburger-menu.slideright"), "a click makes it appear"); assert.ok(!exists("#hamburger-menu.hidden"), "a click makes it appear");
});
click(".close-hamburger");
andThen(() => {
assert.ok(exists("#hamburger-menu.slideright"), "clicking the X hides it");
});
click("#toggle-hamburger-menu");
andThen(() => {
assert.ok(!exists("#hamburger-menu.slideright"), "it opens again");
}); });
click('#main-outlet') click('#main-outlet')
andThen(() => { andThen(() => {
assert.ok(exists("#hamburger-menu.slideright"), "clicking the body hides the menu"); assert.ok(exists("#hamburger-menu.hidden"), "clicking the body hides the menu");
}); });
}); });