Move chats to a separate slideout menu on the right side

- Switched to the Pulling library
- Moved nav menu to the left side, as is normal elsewhere
- Added chat button on right side
- Unread icon on it shows unread chats
- Added slideout menu on right for only chats
- Both sides will slide open and everything
- Switched to drawer menus instead of the previous reveal style menus
main
Peter Jaszkowiak 7 years ago
parent 025d1f7bc4
commit 78580d7be1

@ -1,4 +1,4 @@
#menu, .header {
.header, .slideout-menu {
.notification-list {
overflow-x: hidden;
overflow-y: auto;
@ -298,8 +298,8 @@
.unread-count:after {
content: attr(data-content);
position: absolute;
left: 23px;
top: 10px;
left: 23px;
top: 10px;
font-size: 10px;
text-align: center;
border: 1px solid #890405;
@ -314,10 +314,10 @@
font-family: @font-family-sans-serif;
}
#mobile-menu [component="notifications/icon"].unread-count:after, .slideout-menu .unread-count:after {
.slideout-menu .unread-count:after {
position: relative;
left: -6px;
top: -7px;
left: -6px;
top: -7px;
}
#search-form {

@ -1,15 +1,7 @@
.slideout-menu {
position: fixed;
left: auto;
top: 0;
bottom: 0;
right: 0;
z-index: 0;
width: 256px;
overflow-y: auto;
-webkit-overflow-scrolling: touch;
display: none;
}
/* iPhone 5 and other such devices */
@ -58,9 +50,31 @@
-webkit-overflow-scrolling: touch;
}
#menu {
.navbar-toggle {
line-height: 10px;
&.pull-left {
margin-left: @navbar-padding-horizontal;
margin-right: 0;
}
.header & .notification-icon {
left: auto;
top: -3px;
right: -8px;
&.unread-count::after {
position: static;
}
}
}
#menu {
padding-top: 100px;
}
.slideout-menu {
z-index: 10000 !important;
background-color: #1D1F20;
background-image: linear-gradient(145deg, #1D1F20, #404348);
@ -128,25 +142,27 @@
}
}
.menu-section .chat-list, .menu-section .notification-list-mobile {
.user-link {
display: inline;
}
.unread {
background-color: inherit;
a:after {
content: "new";
text-transform: uppercase;
color: #FFF;
margin-left: 5px;
font-size: 10px;
background: #C91106;
border: 1px solid #890405;
padding: 2px 3px;
border-radius: 5px;
.menu-section {
.chat-list, .notification-list-mobile {
.user-link {
display: inline;
}
.unread {
background-color: inherit;
}
}
.chat-list .unread .room-name::after,
.notification-list-mobile .unread a::after {
content: "new";
text-transform: uppercase;
color: #FFF;
margin-left: 5px;
font-size: 10px;
background: #C91106;
border: 1px solid #890405;
padding: 2px 3px;
border-radius: 5px;
}
}
.counter {
@ -204,11 +220,6 @@
}
}
.slideout-panel {
position: relative;
z-index: 1;
}
.slideout-open,
.slideout-open body,
.slideout-open .slideout-panel {
@ -216,13 +227,42 @@
overflow-y: hidden !important;
}
.slideout-open .slideout-menu {
@keyframes fade {
from {
opacity: 0;
}
to {
opacity: .3;
}
}
.subnav-is-opened .main-nav__secondary-nav {
display: block;
animation: fade 250ms ease-in-out both;
}
.slideout-open {
overflow-y: hidden;
height: 100%;
.slideout-panel {
&::after {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
z-index: 1040;
content: ' ';
background: rgba(0, 0, 0, 0.300);
opacity: 0;
visibility: hidden;
transition-property: opacity, visibility;
transition-duration: 200ms, 0s;
transition-delay: 0s, 100ms;
transition-timing-function: ease-in-out;
}
.slideout-open &::after {
opacity: 1;
visibility: visible;
}
}
.menu-profile {

@ -19,7 +19,7 @@ body {
}
@media (max-width: @screen-xs-max) {
#panel.slideout-panel {
.slideout-panel {
min-height: 100vh;
}
}

@ -1,484 +0,0 @@
!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.Slideout=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
'use strict';
/**
* Module dependencies
*/
var decouple = require('decouple');
var Emitter = require('emitter');
/**
* Privates
*/
var scrollTimeout;
var scrolling = false;
var doc = window.document;
var html = doc.documentElement;
var msPointerSupported = window.navigator.msPointerEnabled;
var touch = {
'start': msPointerSupported ? 'MSPointerDown' : 'touchstart',
'move': msPointerSupported ? 'MSPointerMove' : 'touchmove',
'end': msPointerSupported ? 'MSPointerUp' : 'touchend'
};
var prefix = (function prefix() {
var regex = /^(Webkit|Khtml|Moz|ms|O)(?=[A-Z])/;
var styleDeclaration = doc.getElementsByTagName('script')[0].style;
for (var prop in styleDeclaration) {
if (regex.test(prop)) {
return '-' + prop.match(regex)[0].toLowerCase() + '-';
}
}
// Nothing found so far? Webkit does not enumerate over the CSS properties of the style object.
// However (prop in style) returns the correct value, so we'll have to test for
// the precence of a specific property
if ('WebkitOpacity' in styleDeclaration) { return '-webkit-'; }
if ('KhtmlOpacity' in styleDeclaration) { return '-khtml-'; }
return '';
}());
function extend(destination, from) {
for (var prop in from) {
if (from[prop]) {
destination[prop] = from[prop];
}
}
return destination;
}
function inherits(child, uber) {
child.prototype = extend(child.prototype || {}, uber.prototype);
}
/**
* Slideout constructor
*/
function Slideout(options) {
options = options || {};
// Sets default values
this._startOffsetX = 0;
this._currentOffsetX = 0;
this._opening = false;
this._moved = false;
this._opened = false;
this._preventOpen = false;
this._touch = options.touch === undefined ? true : options.touch && true;
// Sets panel
this.panel = options.panel;
this.menu = options.menu;
// Sets classnames
if(this.panel.className.search('slideout-panel') === -1) { this.panel.className += ' slideout-panel'; }
if(this.menu.className.search('slideout-menu') === -1) { this.menu.className += ' slideout-menu'; }
// Sets options
this._fx = options.fx || 'ease';
this._duration = parseInt(options.duration, 10) || 300;
this._tolerance = parseInt(options.tolerance, 10) || 70;
this._padding = this._translateTo = parseInt(options.padding, 10) || 256;
this._orientation = options.side === 'right' ? -1 : 1;
this._translateTo *= this._orientation;
// Init touch events
if (this._touch) {
this._initTouchEvents();
}
}
/**
* Inherits from Emitter
*/
inherits(Slideout, Emitter);
/**
* Opens the slideout menu.
*/
Slideout.prototype.open = function() {
var self = this;
this.emit('beforeopen');
if (html.className.search('slideout-open') === -1) { html.className += ' slideout-open'; }
this._setTransition();
this._translateXTo(this._translateTo);
this._opened = true;
setTimeout(function() {
self.panel.style.transition = self.panel.style['-webkit-transition'] = '';
self.emit('open');
}, this._duration + 50);
return this;
};
/**
* Closes slideout menu.
*/
Slideout.prototype.close = function() {
var self = this;
if (!this.isOpen() && !this._opening) { return this; }
this.emit('beforeclose');
this._setTransition();
this._translateXTo(0);
this._opened = false;
setTimeout(function() {
html.className = html.className.replace(/ slideout-open/, '');
self.panel.style.transition = self.panel.style['-webkit-transition'] = self.panel.style[prefix + 'transform'] = self.panel.style.transform = '';
self.emit('close');
}, this._duration + 50);
return this;
};
/**
* Toggles (open/close) slideout menu.
*/
Slideout.prototype.toggle = function() {
return this.isOpen() ? this.close() : this.open();
};
/**
* Returns true if the slideout is currently open, and false if it is closed.
*/
Slideout.prototype.isOpen = function() {
return this._opened;
};
/**
* Translates panel and updates currentOffset with a given X point
*/
Slideout.prototype._translateXTo = function(translateX) {
this._currentOffsetX = translateX;
this.panel.style[prefix + 'transform'] = this.panel.style.transform = 'translate3d(' + translateX + 'px, 0, 0)';
};
/**
* Set transition properties
*/
Slideout.prototype._setTransition = function() {
this.panel.style[prefix + 'transition'] = this.panel.style.transition = prefix + 'transform ' + this._duration + 'ms ' + this._fx;
};
/**
* Initializes touch event
*/
Slideout.prototype._initTouchEvents = function() {
var self = this;
/**
* Decouple scroll event
*/
this._onScrollFn = decouple(doc, 'scroll', function() {
if (!self._moved) {
clearTimeout(scrollTimeout);
scrolling = true;
scrollTimeout = setTimeout(function() {
scrolling = false;
}, 250);
}
});
/**
* Prevents touchmove event if slideout is moving
*/
this._preventMove = function(eve) {
if (self._moved) {
eve.preventDefault();
}
};
doc.addEventListener(touch.move, this._preventMove);
/**
* Resets values on touchstart
*/
this._resetTouchFn = function(eve) {
if (typeof eve.touches === 'undefined') { return; }
self._moved = false;
self._opening = false;
self._startOffsetX = eve.touches[0].pageX;
self._preventOpen = (!self._touch || (!self.isOpen() && self.menu.clientWidth !== 0));
};
this.panel.addEventListener(touch.start, this._resetTouchFn);
/**
* Resets values on touchcancel
*/
this._onTouchCancelFn = function() {
self._moved = false;
self._opening = false;
};
this.panel.addEventListener('touchcancel', this._onTouchCancelFn);
/**
* Toggles slideout on touchend
*/
this._onTouchEndFn = function() {
if (self._moved) {
(self._opening && Math.abs(self._currentOffsetX) > self._tolerance) ? self.open() : self.close();
}
self._moved = false;
};
this.panel.addEventListener(touch.end, this._onTouchEndFn);
/**
* Translates panel on touchmove
*/
this._onTouchMoveFn = function(eve) {
self.emit('touchmove', eve.target);
if (scrolling || self._preventOpen || typeof eve.touches === 'undefined') { return; }
var dif_x = eve.touches[0].clientX - self._startOffsetX;
var translateX = self._currentOffsetX = dif_x;
if (Math.abs(translateX) > self._padding) { return; }
if (Math.abs(dif_x) > 20) {
self._opening = true;
var oriented_dif_x = dif_x * self._orientation;
if (self._opened && oriented_dif_x > 0 || !self._opened && oriented_dif_x < 0) { return; }
if (oriented_dif_x <= 0) {
translateX = dif_x + self._padding * self._orientation;
self._opening = false;
}
if (!self._moved && html.className.search('slideout-open') === -1) {
html.className += ' slideout-open';
}
self.panel.style[prefix + 'transform'] = self.panel.style.transform = 'translate3d(' + translateX + 'px, 0, 0)';
self.emit('translate', translateX, eve.target);
self._moved = true;
}
};
this.panel.addEventListener(touch.move, this._onTouchMoveFn);
};
Slideout.prototype.enableTouch = function() {
this._touch = true;
return this;
};
Slideout.prototype.disableTouch = function() {
this._touch = false;
return this;
};
Slideout.prototype.destroy = function() {
// Close before clean
this.close();
// Remove event listeners
doc.removeEventListener(touch.move, this._preventMove);
this.panel.removeEventListener(touch.start, this._resetTouchFn);
this.panel.removeEventListener('touchcancel', this._onTouchCancelFn);
this.panel.removeEventListener(touch.end, this._onTouchEndFn);
this.panel.removeEventListener(touch.move, this._onTouchMoveFn);
doc.removeEventListener('scroll', this._onScrollFn);
// Remove methods
this.open = this.close = function() {};
// Return the instance so it can be easily dereferenced
return this;
};
/**
* Expose Slideout
*/
module.exports = Slideout;
},{"decouple":2,"emitter":3}],2:[function(require,module,exports){
'use strict';
var requestAnimFrame = (function() {
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
function (callback) {
window.setTimeout(callback, 1000 / 60);
};
}());
function decouple(node, event, fn) {
var eve,
tracking = false;
function captureEvent(e) {
eve = e;
track();
}
function track() {
if (!tracking) {
requestAnimFrame(update);
tracking = true;
}
}
function update() {
fn.call(node, eve);
tracking = false;
}
node.addEventListener(event, captureEvent, false);
return captureEvent;
}
/**
* Expose decouple
*/
module.exports = decouple;
},{}],3:[function(require,module,exports){
"use strict";
var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } };
exports.__esModule = true;
/**
* Creates a new instance of Emitter.
* @class
* @returns {Object} Returns a new instance of Emitter.
* @example
* // Creates a new instance of Emitter.
* var Emitter = require('emitter');
*
* var emitter = new Emitter();
*/
var Emitter = (function () {
function Emitter() {
_classCallCheck(this, Emitter);
}
/**
* Adds a listener to the collection for the specified event.
* @memberof! Emitter.prototype
* @function
* @param {String} event - The event name.
* @param {Function} listener - A listener function to add.
* @returns {Object} Returns an instance of Emitter.
* @example
* // Add an event listener to "foo" event.
* emitter.on('foo', listener);
*/
Emitter.prototype.on = function on(event, listener) {
// Use the current collection or create it.
this._eventCollection = this._eventCollection || {};
// Use the current collection of an event or create it.
this._eventCollection[event] = this._eventCollection[event] || [];
// Appends the listener into the collection of the given event
this._eventCollection[event].push(listener);
return this;
};
/**
* Adds a listener to the collection for the specified event that will be called only once.
* @memberof! Emitter.prototype
* @function
* @param {String} event - The event name.
* @param {Function} listener - A listener function to add.
* @returns {Object} Returns an instance of Emitter.
* @example
* // Will add an event handler to "foo" event once.
* emitter.once('foo', listener);
*/
Emitter.prototype.once = function once(event, listener) {
var self = this;
function fn() {
self.off(event, fn);
listener.apply(this, arguments);
}
fn.listener = listener;
this.on(event, fn);
return this;
};
/**
* Removes a listener from the collection for the specified event.
* @memberof! Emitter.prototype
* @function
* @param {String} event - The event name.
* @param {Function} listener - A listener function to remove.
* @returns {Object} Returns an instance of Emitter.
* @example
* // Remove a given listener.
* emitter.off('foo', listener);
*/
Emitter.prototype.off = function off(event, listener) {
var listeners = undefined;
// Defines listeners value.
if (!this._eventCollection || !(listeners = this._eventCollection[event])) {
return this;
}
listeners.forEach(function (fn, i) {
if (fn === listener || fn.listener === listener) {
// Removes the given listener.
listeners.splice(i, 1);
}
});
// Removes an empty event collection.
if (listeners.length === 0) {
delete this._eventCollection[event];
}
return this;
};
/**
* Execute each item in the listener collection in order with the specified data.
* @memberof! Emitter.prototype
* @function
* @param {String} event - The name of the event you want to emit.
* @param {...Object} data - Data to pass to the listeners.
* @returns {Object} Returns an instance of Emitter.
* @example
* // Emits the "foo" event with 'param1' and 'param2' as arguments.
* emitter.emit('foo', 'param1', 'param2');
*/
Emitter.prototype.emit = function emit(event) {
var _this = this;
for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
args[_key - 1] = arguments[_key];
}
var listeners = undefined;
// Defines listeners value.
if (!this._eventCollection || !(listeners = this._eventCollection[event])) {
return this;
}
// Clone listeners
listeners = listeners.slice(0);
listeners.forEach(function (fn) {
return fn.apply(_this, args);
});
return this;
};
return Emitter;
})();
/**
* Exports Emitter
*/
exports["default"] = Emitter;
module.exports = exports["default"];
},{}]},{},[1])(1)
});

@ -1,6 +1,6 @@
"use strict";
/*globals ajaxify, config, utils, app, socket, Slideout, NProgress*/
/*globals ajaxify, config, utils, app, socket, NProgress*/
$(document).ready(function() {
var env = utils.findBootstrapEnvironment();
@ -113,87 +113,168 @@ $(document).ready(function() {
return;
}
$('#menu').removeClass('hidden');
var slideout = new Slideout({
'panel': document.getElementById('panel'),
'menu': document.getElementById('menu'),
'padding': 256,
'tolerance': 70,
'side': 'right'
});
require(['pulling', 'storage'], function (Pulling, Storage) {
// initialization
if (env !== 'xs') {
slideout.disableTouch();
}
var guest = !app.user || !parseInt(app.user.uid, 10);
var legacy = !!Storage.getItem('persona:menus:legacy-layout');
var margin = window.innerWidth * 0.4;
$('#mobile-menu').on('click', function() {
slideout.toggle();
});
if (legacy) {
$('#mobile-menu').removeClass('pull-left');
$('#mobile-chats').addClass('pull-left');
}
$('#menu a').on('click', function() {
slideout.close();
});
var navSlideout = Pulling.create({
panel: document.getElementById('panel'),
menu: document.getElementById('menu'),
width: 256,
margin: margin,
side: legacy ? 'right' : 'left',
});
$('#menu').removeClass('hidden');
var chatsSlideout;
if (!guest) {
chatsSlideout = Pulling.create({
panel: document.getElementById('panel'),
menu: document.getElementById('chats-menu'),
width: 256,
margin: margin,
side: legacy ? 'left' : 'right',
});
$('#chats-menu').removeClass('hidden');
}
$(window).on('resize action:ajaxify.start', function() {
slideout.close();
$('.account .cover').css('top', $('[component="navbar"]').height());
});
// all menus
function openingMenuAndLoad() {
openingMenu();
loadNotificationsAndChat();
}
function closeOnClick() {
navSlideout.close();
if (chatsSlideout) { chatsSlideout.close(); }
}
function openingMenu() {
$('#header-menu').css({
'top': $(window).scrollTop() + 'px',
'position': 'absolute'
function onBeforeOpen() {
document.documentElement.classList.add('slideout-open');
}
function onClose() {
document.documentElement.classList.remove('slideout-open');
$('#panel').off('click', closeOnClick);
}
$(window).on('resize action:ajaxify.start', function () {
navSlideout.close();
chatsSlideout.close();
$('.account .cover').css('top', $('[component="navbar"]').height());
});
}
function loadNotificationsAndChat() {
require(['chat', 'notifications'], function(chat, notifications) {
chat.loadChatsDropdown($('#menu [data-section="chats"] ul'));
notifications.loadNotifications($('#menu [data-section="notifications"] ul'));
navSlideout
.ignore('code, code *, .preventSlideout, .preventSlideout *')
.on('closed', onClose)
.on('beforeopen', onBeforeOpen)
.on('opened', function () {
$('#panel').one('click', closeOnClick);
});
if (!guest) {
chatsSlideout
.ignore('code, code *, .preventSlideout, .preventSlideout *')
.on('closed', onClose)
.on('beforeopen', onBeforeOpen)
.on('opened', function () {
$('#panel').one('click', closeOnClick);
});
}
// left slideout navigation menu
$('#mobile-menu').on('click', function () {
navSlideout.enable().toggle();
});
}
slideout.on('open', openingMenuAndLoad);
slideout.on('touchmove', function(target) {
var $target = $(target);
if ($target.length && ($target.is('table') || $target.parents('table').length || $target.is('code') || $target.parents('code').length || $target.hasClass('preventSlideOut') || $target.parents('.preventSlideOut').length)) {
slideout._preventOpen = true;
function loadNotifications() {
require(['notifications'], function(notifications) {
notifications.loadNotifications($('#menu [data-section="notifications"] ul'));
});
}
});
slideout.on('close', function() {
$('#header-menu').css({
'top': '0px',
'position': 'fixed'
navSlideout.on('opened', loadNotifications);
if (!guest) {
navSlideout.on('beforeopen', function () {
chatsSlideout.close();
chatsSlideout.disable();
}).on('closed', function () {
chatsSlideout.enable();
});
}
$('#menu [data-section="navigation"] ul').html($('#main-nav').html() + ($('#search-menu').html() || '') + ($('#logged-out-menu').html() || ''));
$('#user-control-list').children().clone(true, true).appendTo($('#menu [data-section="profile"] ul'));
$('#menu [data-section="profile"] ul').find('[component="user/status"]').remove();
socket.on('event:user_status_change', function(data) {
if (parseInt(data.uid, 10) === app.user.uid) {
app.updateUserStatus($('#menu [component="user/status"]'), data.status);
navSlideout.close();
}
});
$('.slideout-open').removeClass('slideout-open');
$('.topic .pagination-block').css({ bottom: 0 });
});
slideout.on('beforeopen', function() {
var paginator = $('.topic .pagination-block')[0];
if (paginator) {
paginator.style.bottom = 0; // to trigger reflow
paginator.style.bottom = (paginator.getBoundingClientRect().bottom - window.innerHeight).toString() + 'px';
// right slideout chats menu
function loadChats() {
require(['chat'], function (chat) {
chat.loadChatsDropdown($('#chats-menu .chat-list'));
});
}
});
$('#menu [data-section="navigation"] ul').html($('#main-nav').html() + ($('#search-menu').html() || '') + ($('#logged-out-menu').html() || ''));
if (!guest) {
$('#mobile-chats').removeClass('hidden').on('click', function() {
navSlideout.close();
chatsSlideout.enable().toggle();
});
$('#chats-menu').on('click', 'li[data-roomid]', function () {
chatsSlideout.close();
});
$('#user-control-list').children().clone(true, true).appendTo($('#menu [data-section="profile"] ul'));
$('#menu [data-section="profile"] ul').find('[component="user/status"]').remove();
chatsSlideout
.on('opened', loadChats)
.on('beforeopen', function () {
navSlideout.close().disable();
})
.on('closed', function () {
navSlideout.enable();
});
}
socket.on('event:user_status_change', function(data) {
if (parseInt(data.uid, 10) === app.user.uid) {
app.updateUserStatus($('#menu [component="user/status"]'), data.status);
slideout.close();
// for debugging
// window.navSlideout = navSlideout;
// window.chatsSlideout = chatsSlideout;
// add a checkbox in the user settings page
// so users can swap the sides the menus appear on
function setupSetting() {
if (ajaxify.data.template['account/settings'] && !document.getElementById('persona:menus:legacy-layout')) {
$('<div class="col-xs-12 hidden-md"><div class="well checkbox"><label><input type="checkbox" id="persona:menus:legacy-layout"/><strong>Switch which side each mobile menu is on</strong></label></div></div>')
.appendTo('#content .account > .row')
.find('input')
.prop('checked', Storage.getItem('persona:menus:legacy-layout', 'true'))
.change(function (e) {
if (e.target.checked) {
Storage.setItem('persona:menus:legacy-layout', 'true');
} else {
Storage.removeItem('persona:menus:legacy-layout');
}
});
}
}
$(window).on('action:ajaxify.end', setupSetting);
setupSetting();
});
}
@ -299,12 +380,12 @@ $(document).ready(function() {
drop.css({top: y + 'px', left: x + 'px'}).addClass('animate');
});
}
function setupQuickReply() {
$(window).on('action:ajaxify.end', function(ev, data) {
if (data.url && data.url.match('^topic/')) {
require(['persona/quickreply'], function(quickreply) {
quickreply.init();
quickreply.init();
});
}
});

@ -39,6 +39,7 @@
"url": "https://github.com/psychobunny/nodebb-theme-persona/issues"
},
"dependencies": {
"striptags": "^3.1.0"
"striptags": "^3.1.0",
"pulling": "^1.1.0"
}
}

@ -14,9 +14,11 @@
"lib/persona.js",
"lib/modules/nprogress.js",
"lib/modules/autohidingnavbar.min.js",
"lib/modules/slideout.min.js",
"lib/modules/quickreply.js"
],
"modules": {
"pulling.js": "node_modules/pulling/build/pulling-drawer.js"
},
"acpScripts": [
"lib/admin.js"
]

@ -25,7 +25,7 @@
</head>
<body class="{bodyClass} skin-{config.bootswatchSkin}">
<nav id="menu" class="hidden">
<nav id="menu" class="slideout-menu hidden">
<div class="menu-profile">
<!-- IF user.uid -->
<!-- IF user.picture -->
@ -56,7 +56,10 @@
<ul class="menu-section-list notification-list-mobile" component="notifications/list"></ul>
<p class="menu-section-list"><a href="{relative_path}/notifications">[[notifications:see_all]]</a></p>
</section>
<!-- ENDIF config.loggedIn -->
</nav>
<nav id="chats-menu" class="slideout-menu hidden">
<!-- IF config.loggedIn -->
<section class="menu-section" data-section="chats">
<h3 class="menu-section-title">
[[global:header.chats]]
@ -67,7 +70,7 @@
<!-- ENDIF config.loggedIn -->
</nav>
<main id="panel">
<main id="panel" class="slideout-panel">
<nav class="navbar navbar-default navbar-fixed-top header" id="header-menu" component="navbar">
<div class="container">
<!-- IMPORT partials/menu.tpl -->

@ -1,10 +1,14 @@
<div class="navbar-header">
<button type="button" class="navbar-toggle" id="mobile-menu">
<button type="button" class="navbar-toggle pull-left" id="mobile-menu">
<span component="notifications/icon" class="notification-icon fa fa-fw fa-bell-o" data-content="0"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<button type="button" class="navbar-toggle hidden" id="mobile-chats">
<span component="chat/icon" class="notification-icon fa fa-fw fa-comments" data-content="0"></span>
<i class="fa fa-comment-o"></i>
</button>
<!-- IF brand:logo -->
<a href="<!-- IF brand:logo:url -->{brand:logo:url}<!-- ELSE -->{relative_path}/<!-- ENDIF brand:logo:url -->">

Loading…
Cancel
Save