Smart toolbar that scales down to a button and popup menu on small screen

pull/5742/merge
Aleksander Machniak 8 years ago
parent 7ab57b1428
commit 96d3fedde3

@ -37,17 +37,5 @@ INSTALLATION:
IDEAS/TODOs:
------------
- Planned use of a css framework, e.g. semantic-ui, bootstrap (to be decided)
- Minimum supported screen width: 320px (or we should support 240px?)
- As we use flexbox, we develop on most recent Chrome/Firefox, we'll
see later what we can do for older browser versions
- use Less
- build custom semantic-ui style/js, we don't really want 800kB (already minified) file
- use semantic-ui/loader when loading content to content-frames (on phones only)?
- make scrollbars pretty (impossible in Firefox?)
- check supported browser versions, looks like flexbox is not supported on Android <= 4,
how old versions we should support?
- popups/modal dialogs
- consider using a dialog popup for Contacts import instead of a separate page. Actually consider
this a UI rule: no full page for functionality that can be in a dialog.
Note: This is for consistency reasons, mail import uses dialog, calendar events import too.
Note: the same rule would apply to contacts advanced search.

@ -106,6 +106,7 @@ body > #layout > div > .header > a.menu-button {
}
@media screen and (max-width: 768px) { /* tablet */
#layout > div > .header > .toolbar:not(.searchbar),
body > #layout > div:not(.selected) {
display: none;
}
@ -115,6 +116,7 @@ body > #layout > div > .header > a.menu-button {
body > #layout > div.list {
max-width: 100%;
}
body > #layout > div > .header > a.menu-button,
body > #layout > div > .header > .buttons {
display: block;
float: right;
@ -207,6 +209,9 @@ body {
border-top: 1px solid #ddd;
}
/*** Login form ***/
.task-login #content {
@ -392,6 +397,10 @@ ul.listing li input[type=checkbox] {
width: 1.2em;
}
.toolbar a.button span.inner {
display: none;
}
.searchbar {
display: table;
text-align: right;
@ -457,6 +466,21 @@ ul.listing li input[type=checkbox] {
}
}
@media screen and (min-width: 769px) {
ul.toolbar {
margin: 0;
}
ul.toolbar > li {
display: inline-block;
}
}
@media screen and (max-width: 768px) {
ul.toolbar a.button .inner {
display: inline;
}
}
@media screen and (max-width: 480px) {
#messagestack {
left: 0.5em;
@ -464,8 +488,8 @@ ul.listing li input[type=checkbox] {
}
}
/* font-icons */
/* font-icons */
button.ui.button.icon:before,
.toolbar a.button:before,
@ -508,10 +532,6 @@ button.ui.button.icon:before {
float: initial;
}
.toolbar a.button span.inner {
display: none;
}
.toolbar a.button {
padding: 0 0.3em;
}

@ -101,28 +101,7 @@ function rcube_elastic_ui()
});
// Initialize menu dropdowns
$('*[data-popup]').each(function() {
var popup_id = $(this).data('popup');
$('#' + popup_id).data('button', this);
$(this).attr({
'aria-haspopup': 'true',
'aria-expanded': 'false',
'aria-owns': popup_id + '-menu'
})
.popup({
popup: '#' + popup_id,
exclusive: true,
on: 'click',
position: $(this).data('popup-pos') || 'bottom left',
lastResort: true
});
// TODO: Set aria attributes on menu show/hide
// TODO: Set popup height so it is less that window height
});
$('.ui.popup').attr('aria-hidden', 'true');
$('*[data-popup]').each(function() { popup_init(this); });
// close popups on click in an iframe on the page
var close_all_popups = function() {
@ -134,11 +113,9 @@ function rcube_elastic_ui()
rcube_webmail.set_iframe_events({mousedown: close_all_popups});
// Move form buttons from the content frame into the frame header (on parent window)
// TODO: There really should be only one button in most forms, Cancel buttons
// should not be used at all, other buttons will need to be verified
// TODO: Active button state
var form_buttons = [];
$('.formbuttons > .primary').each(function() {
$('.formbuttons').children(':not(.cancel)').each(function() {
var target = this, button = $(this).clone();
form_buttons.push(
@ -183,6 +160,9 @@ function rcube_elastic_ui()
// Initialize search forms (in list headers)
$('.header > .searchbar').each(function() { searchbar_init(this); });
// Initialize responsive toolbars
toolbar_init();
// Make login form pretty
if (rcmail.env.task == 'login') {
var inputs = [],
@ -287,6 +267,8 @@ function rcube_elastic_ui()
buttons.back_list.show();
}
$('.header > ul.toolbar', layout.content).addClass('hidden ui popup');
$.each(content_buttons, function() { $(this).hide(); });
};
@ -307,6 +289,7 @@ function rcube_elastic_ui()
$(layout.menu).css('display', 'flex');
buttons.back_list.hide();
$.each(content_buttons, function() { $(this).show(); });
$('ul.toolbar.ui.popup').removeClass('hidden ui popup');
};
function screen_resize_wide()
@ -314,6 +297,7 @@ function rcube_elastic_ui()
$.each(layout, function(name, item) { $(item).css('display', 'flex'); });
buttons.back_list.hide();
$.each(content_buttons, function() { $(this).show(); });
$('ul.toolbar.ui.popup').removeClass('hidden ui popup');
};
function show_sidebar()
@ -449,6 +433,76 @@ function rcube_elastic_ui()
}
});
};
/**
* Converts toolbar menu into popup-menu for small screens
*/
function toolbar_init()
{
if (env.got_smart_toolbar) {
return;
}
env.got_smart_toolbar = true;
// TODO: if the toolbar contains "global or list only" buttons
// another popup menu with these options should be created
// on the list (or sidebar if there's no list element).
// TODO: spacer item
// TODO: dropbutton item
// TODO: a way to inject buttons to the menu from content iframe
var items = [];
// convert toolbar to a popup list
$('.header > .toolbar', layout.content).each(function() {
var toolbar = $(this);
toolbar.children().each(function() {
var button = $(this).detach();
items.push($('<li role="menuitem">').append(button));
});
});
// append the new toolbar and menu button
if (items.length) {
var menu_button = $('<a class="button menu-button" href="#menu">')
.html('<i class="icon ellipsis vertical"></i>')
.data('popup', 'toolbar-menu')
.data('popup-pos', 'bottom right');
$(layout.content).children('.header')
// TODO: copy original toolbar attributes (class, role, aria-*)
.append($('<ul>').attr({'class': 'toolbar ui popup', id: 'toolbar-menu'}).append(items))
.append(menu_button);
popup_init(menu_button);
}
}
function popup_init(item)
{
var popup_id = $(item).data('popup');
$('#' + popup_id).data('button', item);
$(item).attr({
'aria-haspopup': 'true',
'aria-expanded': 'false',
'aria-owns': popup_id + '-menu'
})
.popup({
popup: '#' + popup_id,
exclusive: true,
on: 'click',
position: $(item).data('popup-pos') || 'bottom left',
lastResort: true
});
// TODO: Set aria attributes on menu show/hide
// TODO: Set popup height so it is less that window height
$('#' + popup_id).attr('aria-hidden', 'true');
}
}
var UI = new rcube_elastic_ui();

Loading…
Cancel
Save