Use Bootstrap 4, forget about Semantic UI

pull/5742/merge
Aleksander Machniak 8 years ago
parent 8ee2b96a3d
commit 5929dc2ac8

@ -57,10 +57,3 @@ RULES:
- Minimum supported screen width is 240px (note that even if the device screen
resolution is e.g.320x372 changing the text size in device settings will reduce
the resolution)
IDEAS/TODOs:
------------
- Planned use of a css framework, e.g. semantic-ui, bootstrap (to be decided)
- 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)?

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -4,7 +4,8 @@
<roundcube:object name="message" id="messagestack" />
<script src="/semantic-ui/semantic.min.js"></script>
<script src="/bootstrap/tether.min.js"></script>
<script src="/bootstrap/bootstrap.min.js"></script>
<script src="/ui.js"></script>
</body>

@ -2,9 +2,9 @@
<html>
<head>
<title><roundcube:object name="pagetitle" /></title>
<meta name="viewport" content="width=device-width, initial-scale=1.0" id="viewport" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no" id="viewport" />
<link rel="shortcut icon" href="/images/favicon.ico"/>
<link rel="stylesheet" href="/semantic-ui/semantic.min.css">
<link rel="stylesheet" href="/bootstrap/bootstrap.min.css">
<roundcube:if condition="config:devel_mode" />
<link rel="stylesheet/less" type="text/css" href="/styles/styles.less" />
<script src="/styles/less.min.js" data-env="development"></script>

@ -25,7 +25,7 @@
<roundcube:if condition="template:name == 'message'" />
<roundcube:button command="move" type="link"
class="button move disabled" classAct="button move"
label="move" title="moveto" data-menu-pos="bottom" innerclass="inner" />
label="move" title="moveto" innerclass="inner" />
<roundcube:button command="print" type="link"
class="button print disabled" classAct="button print"
label="print" title="printmessage" innerclass="inner" />
@ -33,10 +33,10 @@
<roundcube:container name="toolbar" id="mailtoolbar" />
<roundcube:button name="markmenulink" id="markmessagemenulink" type="link"
class="button markmessage" label="mark" title="markmessages"
data-popup="markmessage-menu" data-popup-pos="bottom right" innerclass="inner" />
data-popup="markmessage-menu" innerclass="inner" />
<roundcube:button name="messagemenulink" id="messagemenulink" type="link"
class="button more" label="more" title="moreactions"
data-popup="message-menu" data-popup-pos="bottom right" innerclass="inner" />
data-popup="message-menu" innerclass="inner" />
</div>
<div id="forward-menu" class="ui popup">

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 434 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

@ -1,3 +1,14 @@
@font-face {
font-family: 'Icons';
src: url("../fonts/fontawesome.woff2") format('woff2'),
url("../fonts/fontawesome.woff") format('woff');
font-style: normal;
font-weight: normal;
font-variant: normal;
text-decoration: inherit;
text-transform: none;
}
/* roboto-regular - greek-ext_greek_latin_cyrillic-ext_latin-ext_cyrillic */
@font-face {
font-family: 'Roboto';
@ -38,7 +49,7 @@
url('../fonts/roboto-v15-greek-ext_greek_latin_cyrillic-ext_latin-ext_cyrillic-700italic.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
}
/* Define font-family. h1-h5 is needed here to overwrite semantic-ui font */
body,h1,h2,h3,h4,h5 {
/* Define font-family. h1-h5 is needed here to overwrite bootstrap font */
body,button,input,optgroup,select,textarea {
font-family: Roboto, sans-serif;
}

@ -1,8 +1,10 @@
/* font-icons */
button.ui.button.icon:before,
button.btn.icon:before,
a.btn.icon:before,
a.button.icon:before,
.toolbar a.button:before,
.ui.alert > i.icon:before,
.toolbarmenu li a:before,
.folderlist li a:before,
.listing.iconized tr td:before,
@ -39,8 +41,31 @@ a.rcmaddcontact:before,
backface-visibility: hidden;
}
button.ui.button.icon:before {
height: auto;
@-webkit-keyframes fa-spin {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(359deg);
transform: rotate(359deg);
}
}
@keyframes fa-spin {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(359deg);
transform: rotate(359deg);
}
}
button.btn.icon:before {
font-size: 1em;
}
.toolbar a.button:before {
@ -104,6 +129,21 @@ button.ui.button.icon:before {
content: @fa-var-edit;
}
.ui.alert > i.icon:before {
content: @fa-var-info-circle;
}
.ui.alert.loading > i.icon:before {
content: @fa-var-circle-o-notch;
-webkit-animation: fa-spin 2s infinite linear;
animation: fa-spin 2s infinite linear;
}
.ui.alert.alert-warning > i.icon:before {
content: @fa-var-warning;
}
.ui.alert.alert-danger > i.icon:before {
content: @fa-var-exclamation-circle;
}
.listing.iconized li.preferences > a:before {
content: @fa-var-sliders;
}

@ -1,6 +1,6 @@
@import "fonts.less";
@page-font-size: 1em;
@page-font-size: 14px;
@page-min-width: 240px;
@taskmenu-width: 65px;
@ -30,9 +30,16 @@ NOTE: below 1024px we do some UI elements bigger, as this is good (imho)
should we rather feature detect tables/phones?
*/
html {
height: 100%;
overflow: hidden;
}
body {
font-size: @page-font-size;
min-width: @page-min-width; /* overwrite semantic-ui's limit of 320px */
line-height: 1;
min-width: @page-min-width;
height: 100%;
}
body > #layout {
@ -123,7 +130,7 @@ body > #layout > div > .header > a.menu-button {
padding: 0 0.5em;
margin: 0;
position: relative; /* for absolute positioning of searchbar */
/* overflow: hidden; breaks semantic-ui popups */
overflow: hidden;
}
#layout > div > .header {
border-bottom: 1px solid #ddd;
@ -212,7 +219,7 @@ body > #layout > div > .header > a.menu-button {
body > #layout > div.menu {
display: none;
position: absolute;
z-index: 2;
z-index: 100;
top: 0;
left: 0;
right: 0;

@ -18,12 +18,3 @@
width: 95%;
max-width: 320px;
}
#login-form table {
display: none;
}
#login-form div.ui.input {
width: 100%;
margin-bottom: 1em;
}

@ -2,6 +2,7 @@
#uploadform,
.ui.modal,
.ui.popup,
.voice {
display: none;
}
@ -19,7 +20,7 @@ body.iframe .formbuttons {
bottom: 0.5em;
right: 0.5em;
z-index: 50000;
width: 300px;
width: 320px;
height: auto;
max-height: 85%;
overflow-y: auto;
@ -30,10 +31,6 @@ body.iframe .formbuttons {
top: -1000px;
}
#messagestack div a {
color: #94c0da; /* TODO: less'ify this color */
}
#messagestack div i.icon {
font-size: 2em !important;
}
@ -43,8 +40,19 @@ body.iframe .formbuttons {
cursor: pointer;
}
.ui.message {
margin-top: 0.5em;
.ui.alert {
margin: 0;
margin-bottom: 0.2em;
opacity: 0.95;
float: left;
width: 100%;
padding-left: 0.75em;
}
.ui.alert > i.icon:before {
height: 1em;
width: 1em;
line-height: 1em;
}
.ui-dialog iframe {
@ -63,6 +71,13 @@ body.iframe .formbuttons {
min-width: 180px;
}
#taskmenu a,
.toolbar a,
a.listbutton,
a.rcmaddcontact {
text-decoration: none;
}
.button.disabled,
.toolbarmenu li a {
opacity: 0.5;
@ -72,6 +87,14 @@ body.iframe .formbuttons {
opacity: 1;
}
.toolbarmenu li:last-child {
border-bottom: none;
}
a.button {
text-decoration: none;
}
.toolbar > .spacer {
display: inline-block;
width: 1.2em;
@ -125,6 +148,7 @@ body.iframe .formbuttons {
border: none;
border-bottom: 1px solid #ddd;
background: transparent;
line-height: 1;
}
.searchbar > a.button.search.active {
@ -355,6 +379,14 @@ table.fixedcopy {
border: none;
}
div.popover-content {
padding: 0;
}
div.popover > h3 {
display: none;
}
/* make some elements bigger on tablets/phones */
/* TODO: we should/could maybe do this more globally? */

@ -121,7 +121,7 @@
<li role="menuitem"><label><input type="checkbox" name="s_mods[]" value="email" id="s_mod_email" onclick="UI.set_searchmod(this)" /> <span><roundcube:label name="email" /></span></label></li>
<li role="menuitem"><label><input type="checkbox" name="s_mods[]" value="*" id="s_mod_all" onclick="UI.set_searchmod(this)" /> <span><roundcube:label name="allfields" /></span></label></li>
</ul>
<div class="buttons"><button class="ui button primary icon search" href="#" onclick="if (rcmail.command('search')) UI.show_popup('searchmenu',false)"><roundcube:label name="search" /></button></div>
<div class="buttons"><button class="btn btn-primary icon search" href="#" onclick="if (rcmail.command('search')) UI.show_popup('searchmenu',false)"><roundcube:label name="search" /></button></div>
</div>
<div id="dragcontact-menu" class="ui popup">

@ -20,9 +20,9 @@
</div>
<div class="formbuttons">
<roundcube:button command="edit" class="ui button icon edit primary" label="edit" condition="!ENV:readonly" />
<roundcube:button command="edit" class="btn btn-primary icon edit" label="edit" condition="!ENV:readonly" />
<roundcube:if condition="env:qrcode" />
<roundcube:button command="qrcode" class="ui button icon qrcode" label="qrcode" />
<roundcube:button command="qrcode" class="btn icon qrcode" label="qrcode" />
<roundcube:endif />
</div>

@ -33,8 +33,8 @@
</form>
<div class="formbuttons">
<roundcube:button command="save" class="ui button primary icon save" label="save" />
<roundcube:button command="show" class="ui button cancel" label="cancel" condition="env:action == 'edit'" />
<roundcube:button command="save" class="btn btn-primary icon save" label="save" />
<roundcube:button command="show" class="btn cancel" label="cancel" condition="env:action == 'edit'" />
</div>
<roundcube:object name="photoUploadForm" id="upload-form" mode="smart" />

@ -117,7 +117,7 @@
<li role="menuitem"><label><input type="radio" name="s_scope" value="sub" id="s_scope_sub" onclick="UI.set_searchscope(this)" /> <span><roundcube:label name="subfolders" /></span></label></li>
<li role="menuitem"><label><input type="radio" name="s_scope" value="all" id="s_scope_all" onclick="UI.set_searchscope(this)" /> <span><roundcube:label name="allfolders" /></span></label></li>
</ul>
<div class="buttons"><button class="ui button primary icon search" href="#" onclick="if (rcmail.command('search')) UI.show_popup('searchmenu',false)"><roundcube:label name="search" /></button></div>
<div class="buttons"><button class="btn btn-primary icon search" href="#" onclick="if (rcmail.command('search')) UI.show_popup('searchmenu',false)"><roundcube:label name="search" /></button></div>
</div>
<div id="dragmessage-menu" class="ui popup">

@ -77,7 +77,8 @@ function rcube_elastic_ui()
.addEventListener('afterlistsearch', list_handler)
.addEventListener('message', message_displayed)
.addEventListener('menu-open', menu_toggle)
.addEventListener('menu-close', menu_toggle);
.addEventListener('menu-close', menu_toggle)
.addEventListener('init', init);
// menu/sidebar button
buttons.menu.on('click', function() { show_menu(); return false; });
@ -93,36 +94,8 @@ function rcube_elastic_ui()
});
// Semantic-UI style
$('input.button').addClass('ui');
$('input.button.mainaction').addClass('primary');
// TODO: Most of this style-related code should not be needed
// We should implement some features in the core that would
// allow as to tell the engine to add additional html code/attribs
$('select').dropdown();
// Make forms pretty with semantic-ui's accordion widget
// TODO: Consider using tabs when the page width is big enough
$('form.propform,.tabbed').each(function() {
var form = $(this), fieldsets = form.children('fieldset');
if (fieldsets.length) {
$(this).addClass('ui styled fluid accordion');
fieldsets.each(function(i, fieldset) {
var title = $('<div>').attr('class', 'title' + (i ? '' : ' active'))
.html('<i class="dropdown icon"></i>') // TODO: replace <i> with css
.append($('<span>').text($('legend', fieldset).text()));
var content = $('<div>').attr('class', 'content' + (i ? '' : ' active'))
.append($(fieldset).children().not('legend'));
form.append(title).append(content);
$(fieldset).remove();
});
form.accordion({animateChildren: false});
}
});
// Convert some elements to bootstrap style
bootstrap_style();
// Initialize responsive toolbars (have to be before popups init)
toolbar_init();
@ -132,11 +105,14 @@ function rcube_elastic_ui()
// close popups on click in an iframe on the page
var close_all_popups = function() {
$('.ui.popup:visible').each(function() {
$($(this).data('button')).popup('hide');
$('.popover-content:visible').each(function() {
console.log($(this).children('*:first').data('button'));
$($(this).children('*:first').data('button')).popover('hide');
});
};
// TODO: Fix unwanted popups closing on click inside a popup
$(document).on('click', close_all_popups);
rcube_webmail.set_iframe_events({mousedown: close_all_popups});
// Move form buttons from the content frame into the frame header (on parent window)
@ -195,24 +171,6 @@ function rcube_elastic_ui()
// Initialize search forms (in list headers)
$('.header > .searchbar').each(function() { searchbar_init(this); });
// Make login form pretty
if (rcmail.env.task == 'login') {
var inputs = [],
icon_map = {user: 'user', pass: 'lock', host: 'home'},
table = $('#login-form table');
$('tr', table).each(function() {
var input = $('input', this).detach(),
input_name = input.attr('name').replace('_', ''),
icon = $('<i>').attr('class', 'icon ' + icon_map[input_name]);
input.attr('placeholder', $('label', this).text());
inputs.push($('<div>').attr('class', 'ui left icon input').append([input, icon]));
});
table.after(inputs);
}
// Intercept jQuery-UI dialogs to re-style them
if ($.ui) {
$.widget('ui.dialog', $.ui.dialog, {
@ -224,15 +182,23 @@ function rcube_elastic_ui()
});
}
// Add checkbox selection to list widgets
rcmail.addEventListener('init', function() {
// rcmail 'init' event handler
function init() {
// Add checkbox selection to list widgets
$('table[data-list]').each(function() {
var list = $(this).data('list');
if (rcmail[list] && rcmail[list].multiselect) {
rcmail[list].checkbox_selection = true;
}
});
});
};
function bootstrap_style(parent)
{
$('input.button,button', parent || window).addClass('btn');
$('input.button.mainaction,button.primary,button.mainaction', parent || window).addClass('btn-primary');
};
// window resize handler
function resize()
@ -417,24 +383,23 @@ function rcube_elastic_ui()
*/
function message_displayed(p)
{
var icon, classes = 'ui icon message',
var cl, classes = 'ui alert',
map = {
information: ['success', 'info circle icon'],
confirmation: ['success', 'info circle icon'],
notice: ['', 'info circle icon'],
error: ['negative', 'warning circle icon'],
warning: ['negative', 'warning sign icon'],
loading: ['', 'notched circle loading icon']
information: 'alert-success',
confirmation: 'alert-success',
notice: 'alert-info',
error: 'alert-danger',
warning: 'alert-warning',
loading: 'alert-info loading'
};
if (icon = map[p.type]) {
if (icon[0])
classes += ' ' + icon[0];
$('<i>').attr('class', icon[1]).prependTo(p.object);
if (cl = map[p.type]) {
classes += ' ' + cl;
$('<i>').attr('class', 'icon').prependTo(p.object);
}
$(p.object).addClass(classes);
$(p.object).addClass(classes).attr('role', 'alert');
$('a', p.object).addClass('alert-link');
/*
var siblings = $(p.object).siblings('div');
if (siblings.length)
@ -455,6 +420,7 @@ function rcube_elastic_ui()
{
var input = $('input', bar),
button = $('a.button.search', bar),
settings_button = $('a.button.settings', bar)[0],
form = $('form', bar),
all_elements = $('form, a.button.options, a.button.reset', bar),
is_search_pending = function() {
@ -543,7 +509,7 @@ function rcube_elastic_ui()
// append the new toolbar and menu button
if (items.length) {
var menu_button = $('<a class="button icon toolbar-menu-button" href="#menu">')
.attr({'data-popup': 'toolbar-menu', 'data-popup-pos': 'bottom right'});
.attr({'data-popup': 'toolbar-menu'});
layout.content.children('.header')
// TODO: copy original toolbar attributes (class, role, aria-*)
@ -562,22 +528,26 @@ function rcube_elastic_ui()
{
var popup_id = $(item).data('popup'),
popup = $('#' + popup_id)[0],
popup_position = $(item).data('popup-pos') || 'bottom left';
title = $(item).attr('title'),
popup_position = $(item).data('popup-pos') || 'bottom';
$(item).attr({
'aria-haspopup': 'true',
'aria-expanded': 'false',
'aria-owns': popup_id
})
.popup({
popup: popup,
exclusive: true,
on: 'click',
position: popup_position,
lastResort: true
});
.popover({
trigger: 'click',
container: 'body',
content: popup,
placement: popup_position,
html: true
})
.on('show.bs.popover', function() { $(popup).removeClass('popup').attr('aria-hidden', false); })
.on('hide.bs.popover', function() { $(popup).attr('aria-hidden', true); })
.attr('title', title); // re-add title attribute removed by bootstrap
// TODO: Set aria attributes on menu show/hide
// TODO: Fix popup positioning
// TODO: Set popup height so it is less that window height
$(popup).attr('aria-hidden', 'true')
.data('button', item);
@ -607,6 +577,7 @@ function rcube_elastic_ui()
}
// TODO: style buttons/forms
bootstrap_style(dialog.uiDialog);
};
/**

Loading…
Cancel
Save