Merge pull request #15775 from mauriciofauth/bootstrap-navbar

Convert top menu to Bootstrap's navbar component
This commit is contained in:
Maurício Meneghini Fauth 2020-01-17 15:26:36 -03:00 committed by GitHub
commit fc8396f467
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 201 additions and 453 deletions

View File

@ -28,50 +28,29 @@
if (windowWidth < 768) {
$('#pma_navigation_resizer').css({ 'width': '0px' });
}
// Sets the image for the left and right scroll indicator
$('.scrollindicator--left').html($(Functions.getImage('b_left').toString()));
$('.scrollindicator--right').html($(Functions.getImage('b_right').toString()));
// Set the width of the navigation bar without scroll indicator
$('.navigationbar').css({ 'width': widthCalculator.call($container) - 60 });
// Scroll the navigation bar on click
$('.scrollindicator--right').on('click', function () {
$('.navigationbar').scrollLeft($('.navigationbar').scrollLeft() + 70);
});
$('.scrollindicator--left').on('click', function () {
$('.navigationbar').scrollLeft($('.navigationbar').scrollLeft() - 70);
});
// create submenu container
var link = $('<a></a>', { href: '#', 'class': 'tab nowrap' })
.text(Messages.strMore)
.on('click', false); // same as event.preventDefault()
var link = $('<a></a>', {
'href': '#',
'class': 'nav-link dropdown-toggle',
'id': 'navbarDropdown',
'role': 'button',
'data-toggle': 'dropdown',
'aria-haspopup': 'true',
'aria-expanded': 'false'
}).text(Messages.strMore);
var img = $container.find('li img');
if (img.length) {
$(Functions.getImage('b_more').toString()).prependTo(link);
}
var $submenu = $('<li></li>', { 'class': 'submenu' })
var $submenu = $('<li></li>', { 'class': 'nav-item dropdown d-none' })
.append(link)
.append($('<ul></ul>'))
.on('mouseenter', function () {
if ($(this).find('ul .tabactive').length === 0) {
$(this)
.addClass('submenuhover')
.find('> a')
.addClass('tabactive');
}
})
.on('mouseleave', function () {
if ($(this).find('ul .tabactive').length === 0) {
$(this)
.removeClass('submenuhover')
.find('> a')
.removeClass('tabactive');
}
});
$container.children('.clearfloat').remove();
$container.append($submenu).append('<div class=\'clearfloat\'></div>');
.append($('<ul></ul>', {
'class': 'dropdown-menu dropdown-menu-right',
'aria-labelledby': 'navbarDropdown'
}));
$container.append($submenu);
setTimeout(function () {
self.resize();
}, 4);
@ -79,11 +58,11 @@
MenuResizer.prototype.resize = function () {
var wmax = this.widthCalculator.call(this.$container);
var windowWidth = $(window).width();
var $submenu = this.$container.find('.submenu:last');
var $submenu = this.$container.find('.nav-item.dropdown:last');
var submenuW = $submenu.outerWidth(true);
var $submenuUl = $submenu.find('ul');
var $submenuUl = $submenu.find('.dropdown-menu');
var $li = this.$container.find('> li');
var $li2 = $submenuUl.find('li');
var $li2 = $submenuUl.find('.dropdown-item');
var moreShown = $li2.length > 0;
// Calculate the total width used by all the shown tabs
var totalLen = moreShown ? submenuW : 0;
@ -106,6 +85,7 @@
while (totalLen >= wmax && --l >= 0) { // Process the tabs backwards
hidden = true;
var el = $($li[l]);
el.removeClass('nav-item').addClass('dropdown-item');
var elWidth = el.outerWidth(true);
el.data('width', elWidth);
if (! moreShown) {
@ -128,6 +108,7 @@
if (totalLen < wmax ||
(i === $li2.length - 1 && totalLen - submenuW < wmax)
) {
$($li2[i]).removeClass('dropdown-item').addClass('nav-item');
$($li2[i]).insertBefore($submenu);
} else {
break;
@ -136,42 +117,21 @@
}
// Show/hide the "More" tab as needed
if (windowWidth < 768) {
$('.navigationbar').css({ 'width': windowWidth - 80 - $('#pma_navigation').width() });
$submenu.removeClass('shown');
$('.navigationbar').css({ 'overflow': 'hidden' });
$('.navbar-collapse').css({ 'width': windowWidth - 80 - $('#pma_navigation').width() });
$submenu.addClass('d-none');
$('.navbar-collapse').css({ 'overflow': 'hidden' });
} else {
$('.navigationbar').css({ 'width': 'auto' });
$('.navigationbar').css({ 'overflow': 'visible' });
$('.navbar-collapse').css({ 'width': 'auto' });
$('.navbar-collapse').css({ 'overflow': 'visible' });
if ($submenuUl.find('li').length > 0) {
$submenu.addClass('shown');
$submenu.removeClass('d-none');
} else {
$submenu.removeClass('shown');
$submenu.addClass('d-none');
}
}
if (this.$container.find('> li').length === 1) {
// If there is only the "More" tab left, then we need
// to align the submenu to the left edge of the tab
$submenuUl.removeClass().addClass('only');
} else {
// Otherwise we align the submenu to the right edge of the tab
$submenuUl.removeClass().addClass('notonly');
}
if ($submenu.find('.tabactive').length) {
$submenu
.addClass('active')
.find('> a')
.removeClass('tab')
.addClass('tabactive');
} else {
$submenu
.removeClass('active')
.find('> a')
.addClass('tab')
.removeClass('tabactive');
}
};
MenuResizer.prototype.destroy = function () {
var $submenu = this.$container.find('li.submenu').removeData();
var $submenu = this.$container.find('.nav-item.dropdown').removeData();
$submenu.find('li').appendTo(this.$container);
$submenu.remove();
};

View File

@ -1,16 +1,22 @@
<div id="topmenucontainer" class="menucontainer">
<i class="scrollindicator scrollindicator--left"><a href="#" class="tab"></a></i>
<div class="navigationbar">
<ul id="topmenu" class="resizable-menu">
{% for tab in tabs %}
<li{{ tab.active ? ' class="active"' }}>
<a href="{{ url(tab.route, url_params|merge(tab.args ?? [])) }}" class="tab{{ tab.active ? 'active' }}">
{{ get_icon(tab.icon, tab.text, false, true, 'TabsMode') }}
</a>
</li>
{% endfor %}
<div class="clearfloat"></div>
</ul>
</div>
<i class="scrollindicator scrollindicator--right"><a href="#" class="tab"></a></i>
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-label="
{%- trans 'Toggle navigation' %}" aria-controls="navbarNav" aria-expanded="false">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul id="topmenu" class="navbar-nav">
{% for tab in tabs %}
<li class="nav-item{{ tab.active ? ' active' }}">
<a class="nav-link text-nowrap" href="{{ url(tab.route, url_params|merge(tab.args ?? [])) }}">
{{ get_icon(tab.icon, tab.text, false, true, 'TabsMode') }}
{% if tab.active %}
<span class="sr-only">{% trans %}(current){% notes %}Current page{% endtrans %}</span>
{% endif %}
</a>
</li>
{% endfor %}
</ul>
</div>
</nav>
</div>

View File

@ -10,13 +10,13 @@
@import "../../../node_modules/bootstrap/scss/tables";
@import "../../../node_modules/bootstrap/scss/forms";
@import "../../../node_modules/bootstrap/scss/buttons";
//@import "../../../node_modules/bootstrap/scss/transitions";
//@import "../../../node_modules/bootstrap/scss/dropdown";
@import "../../../node_modules/bootstrap/scss/transitions";
@import "../../../node_modules/bootstrap/scss/dropdown";
//@import "../../../node_modules/bootstrap/scss/button-group";
//@import "../../../node_modules/bootstrap/scss/input-group";
//@import "../../../node_modules/bootstrap/scss/custom-forms";
//@import "../../../node_modules/bootstrap/scss/nav";
//@import "../../../node_modules/bootstrap/scss/navbar";
@import "../../../node_modules/bootstrap/scss/nav";
@import "../../../node_modules/bootstrap/scss/navbar";
@import "../../../node_modules/bootstrap/scss/card";
@import "../../../node_modules/bootstrap/scss/breadcrumb";
//@import "../../../node_modules/bootstrap/scss/pagination";

View File

@ -934,19 +934,7 @@ li.last.database {
margin-bottom: 15px;
}
/* specific elements */
#topmenu {
margin-top: 0.5em;
padding: 0.1em 0.3em;
a {
text-shadow: 0 1px 0 #fff;
}
}
ul {
&#topmenu,
&#topmenu2,
&.tabs {
font-weight: bold;
@ -961,7 +949,6 @@ ul {
clear: both;
}
&#topmenu li,
&#topmenu2 li {
float: left;
margin: 0;
@ -969,21 +956,11 @@ ul {
}
}
#topmenu img,
#topmenu2 img {
margin-#{$right}: 0.5em;
vertical-align: -3px;
}
.menucontainer {
background: linear-gradient(#fff, #dcdcdc);
border-top: 1px solid #aaa;
}
.scrollindicator {
display: none;
}
// default tab styles
.tabactive {
background: #fff !important;
@ -1022,64 +999,6 @@ fieldset.caution a {
}
ul {
&#topmenu {
ul {
@if $direction == rtl {
-moz-box-shadow: -1px 1px 6px #ddd;
-webkit-box-shadow: -2px 2px 3px #666;
box-shadow: -2px 2px 3px #666;
} @else {
-moz-box-shadow: 1px 1px 6px #ddd;
-webkit-box-shadow: 2px 2px 3px #666;
box-shadow: 2px 2px 3px #666;
}
&.only {
#{$left}: 0;
}
}
> li {
border-#{$right}: 1px solid #fff;
border-#{$left}: 1px solid #ccc;
border-bottom: 1px solid #ccc;
&:first-child {
border-#{$left}: 0;
}
}
a,
span {
padding: 0.6em;
}
ul {
a {
border-width: 1pt 0 0 0;
-moz-border-radius: 0;
-webkit-border-radius: 0;
border-radius: 0;
}
li:first-child a {
border-width: 0;
}
a:hover,
.tabactive {
text-decoration: none;
}
}
> li > {
a:hover,
.tabactive {
text-decoration: none;
}
}
}
&#topmenu2 a {
&.tab:hover,
&.tabactive {
@ -1090,14 +1009,7 @@ ul {
text-decoration: none;
}
}
// to be able to cancel the bottom border, use <li class="active">
&#topmenu > li.active {
border-#{$right}: 0;
border-bottom-color: #fff;
}
}
// end topmenu
// zoom search
div#dataDisplay {
@ -3866,25 +3778,11 @@ body .ui-dialog {
@media only screen and (max-width: 768px) {
ul {
&#topmenu,
&.tabs {
display: flex;
}
}
.navigationbar {
display: inline-flex;
margin: 0 !important;
border-radius: 0 !important;
overflow: auto;
}
.scrollindicator {
padding: 5px;
cursor: pointer;
display: inline;
}
.responsivetable {
overflow-x: auto;
}

View File

@ -45,6 +45,10 @@ $bg-one: #e5e5e5;
// table data row background, alternate
$bg-two: #d5d5d5;
// Navbar
$enable-transitions: false;
// Breadcrumbs
$breadcrumb-padding-y: 0.5rem;

View File

@ -897,10 +897,7 @@ td.disabled {
/* specific elements */
/* topmenu */
ul {
&#topmenu,
&#topmenu2 {
list-style-type: none;
margin: 0;
@ -918,7 +915,6 @@ ul {
clear: both;
}
&#topmenu li,
&#topmenu2 li {
float: $left;
margin: 0;
@ -928,26 +924,11 @@ ul {
}
}
#topmenu img,
#topmenu2 img {
margin-#{$right}: 0.5em;
vertical-align: -3px;
}
.menucontainer {
background-color: $th-background;
height: 48px;
}
.scrollindicator {
display: none;
}
/* default tab styles */
#topmenu .tabactive {
background: #fff !important;
}
#topmenu2 .tabactive {
background: #ccc;
}
@ -1033,54 +1014,8 @@ fieldset.caution li {
}
}
#topmenu {
padding-#{$left}: 20px;
padding-#{$right}: 20px;
}
/* default tab styles */
ul {
&#topmenu {
ul.only {
#{$left}: 0;
}
a,
span {
padding: 5px 10px;
height: 28px;
line-height: 28px;
font-family: $font-family-extra-bold;
text-transform: uppercase;
color: #666;
font-weight: normal;
}
ul {
a {
border-width: 1pt 0 0 0;
}
li:first-child a {
border-width: 0;
}
a:hover,
.tabactive {
text-decoration: none;
}
}
/* enabled hover/active tabs */
> li > {
a:hover,
.tabactive {
text-decoration: none;
color: #333;
}
}
}
&#topmenu2 a {
text-decoration: none;
@ -1088,11 +1023,6 @@ ul {
text-decoration: none;
}
}
/* to be able to cancel the bottom border, use <li class="active"> */
&#topmenu > li.active {
border-#{$right}: 0;
}
}
/* zoom search */

View File

@ -0,0 +1,24 @@
.navbar {
background-color: $th-background;
padding-#{$left}: 20px;
padding-#{$right}: 20px;
}
.navbar-nav .icon {
margin-#{$right}: 0.5em;
vertical-align: -3px;
}
.navbar-nav .nav-item {
padding: 8px 10px;
&.active {
background: #fff;
}
}
.navbar-nav .nav-link {
text-transform: uppercase;
font-family: $font-family-extra-bold;
font-weight: normal;
}

View File

@ -175,6 +175,22 @@ $btn-border-radius: 0;
$btn-line-height: 1;
$btn-padding-x: 0.5rem;
// Dropdowns
$dropdown-border-radius: 0;
// Navbar
$enable-caret: false;
$navbar-padding-y: 0;
$navbar-padding-x: 0;
$navbar-nav-link-padding-x: 0;
$navbar-nav-link-padding-y: 0;
$navbar-light-color: #666;
$navbar-light-hover-color: #333;
$navbar-light-active-color: #666;
$navbar-light-disabled-color: #666;
// Card
$card-border-width: 0;

View File

@ -13,6 +13,7 @@
@import "resizable-menu";
@import "icons";
@import "reboot";
@import "navbar";
@import "card";
@import "breadcrumbs";
@import "alert";

View File

@ -683,10 +683,7 @@ li.last.database {
/* specific elements */
/* topmenu */
ul {
&#topmenu,
&#topmenu2,
&.tabs {
font-weight: bold;
@ -701,7 +698,6 @@ ul {
clear: both;
}
&#topmenu li,
&#topmenu2 li {
float: $left;
margin: 0;
@ -710,7 +706,6 @@ ul {
}
}
#topmenu img,
#topmenu2 img {
vertical-align: middle;
margin-#{$right}: 0.1em;
@ -719,16 +714,6 @@ ul {
/* default tab styles */
ul {
&#topmenu {
a,
span {
display: block;
margin: 2px 2px 0;
padding: 2px 2px 0;
white-space: nowrap;
}
}
&#topmenu2 a {
display: block;
margin: 0.1em;
@ -756,64 +741,7 @@ fieldset.caution a {
}
}
#topmenu {
margin-top: 0.5em;
padding: 0.1em 0.3em 0.1em 0.3em;
}
ul {
&#topmenu {
ul {
-moz-box-shadow: 2px 2px 3px #666;
-webkit-box-shadow: 2px 2px 3px #666;
box-shadow: 2px 2px 3px #666;
}
> li {
border-bottom: 1pt solid black;
}
a,
span {
background-color: $bg-one;
border: 0 solid $bg-two;
border-width: 1pt 1pt 0 1pt;
-moz-border-radius: 0.4em 0.4em 0 0;
border-radius: 0.4em 0.4em 0 0;
}
ul {
a {
border-width: 1pt 0 0 0;
-moz-border-radius: 0;
border-radius: 0;
}
li:first-child a {
border-width: 0;
}
a:hover,
.tabactive {
text-decoration: none;
}
}
> li > {
a:hover,
.tabactive {
margin: 0;
padding: 2px 4px;
text-decoration: none;
}
}
a.tab:hover,
.tabactive {
background-color: $body-bg;
}
}
&#topmenu2 a {
&.tab:hover,
&.tabactive {
@ -823,10 +751,6 @@ ul {
text-decoration: none;
}
}
&#topmenu > li.active {
border-bottom: 1pt solid $body-bg;
}
}
/* zoom search */
@ -3452,10 +3376,6 @@ body {
}
}
.scrollindicator {
display: none;
}
/* templates/database/multi_table_query */
.multi_table_query_form {
@ -3496,25 +3416,11 @@ body {
@media only screen and (max-width: 768px) {
ul {
&#topmenu,
&.tabs {
display: flex;
}
}
.navigationbar {
display: inline-flex;
margin: 0 !important;
border-radius: 0 !important;
overflow: auto;
}
.scrollindicator {
padding: 5px;
cursor: pointer;
display: inline;
}
.responsivetable {
overflow-x: auto;
}

View File

@ -0,0 +1,34 @@
.navbar-nav {
font-weight: bold;
}
.navbar-nav .icon {
vertical-align: middle;
margin-#{$right}: 0.1em;
}
.navbar-nav .nav-item {
border-bottom: 1pt solid black;
&.active .nav-link {
margin: 0;
background-color: $body-bg;
padding: 2px 4px;
}
}
.navbar-nav .nav-link {
margin: 2px 2px 0;
padding: 2px 2px 0;
background-color: $bg-one;
border-color: $bg-two;
border-style: solid;
border-width: 1pt 1pt 0 1pt;
border-radius: 0.4em 0.4em 0 0;
&:hover {
margin: 0;
background-color: $body-bg;
padding: 2px 4px;
}
}

View File

@ -63,6 +63,25 @@ $font-family-monospace: monospace;
$font-size-base: 0.82rem;
// Dropdowns
$dropdown-padding-y: 0;
$dropdown-item-padding-y: 0;
$dropdown-item-padding-x: 0;
// Navbar
$enable-transitions: false;
$enable-caret: false;
$navbar-padding-y: 0;
$navbar-padding-x: 0;
$navbar-nav-link-padding-x: 2px;
$navbar-nav-link-padding-y: 2px;
$navbar-light-color: #00f;
$navbar-light-hover-color: #f00;
$navbar-light-active-color: #00f;
$navbar-light-disabled-color: #00f;
// Card
$card-border-radius: 0;

View File

@ -12,6 +12,7 @@
@import "../../pmahomme/scss/resizable-menu";
@import "icons";
@import "reboot";
@import "navbar";
@import "card";
@import "breadcrumbs";
@import "alert";

View File

@ -941,17 +941,7 @@ li.last.database {
/* specific elements */
#topmenu {
margin-top: 0.5em;
padding: 0.1em 0.3em;
a {
text-shadow: 0 1px 0 #fff;
}
}
ul {
&#topmenu,
&#topmenu2,
&.tabs {
font-weight: bold;
@ -966,7 +956,6 @@ ul {
clear: both;
}
&#topmenu li,
&#topmenu2 li {
float: left;
margin: 0;
@ -974,21 +963,11 @@ ul {
}
}
#topmenu img,
#topmenu2 img {
margin-#{$right}: 0.5em;
vertical-align: -3px;
}
.menucontainer {
background: linear-gradient(#fff, #dcdcdc);
border-top: 1px solid #aaa;
}
.scrollindicator {
display: none;
}
// default tab styles
.tabactive {
background: #fff !important;
@ -1027,64 +1006,6 @@ fieldset.caution a {
}
ul {
&#topmenu {
ul {
@if $direction == rtl {
-moz-box-shadow: -1px 1px 6px #ddd;
-webkit-box-shadow: -2px 2px 3px #666;
box-shadow: -2px 2px 3px #666;
} @else {
-moz-box-shadow: 1px 1px 6px #ddd;
-webkit-box-shadow: 2px 2px 3px #666;
box-shadow: 2px 2px 3px #666;
}
&.only {
#{$left}: 0;
}
}
> li {
border-#{$right}: 1px solid #fff;
border-#{$left}: 1px solid #ccc;
border-bottom: 1px solid #ccc;
&:first-child {
border-#{$left}: 0;
}
}
a,
span {
padding: 0.6em;
}
ul {
a {
border-width: 1pt 0 0 0;
-moz-border-radius: 0;
-webkit-border-radius: 0;
border-radius: 0;
}
li:first-child a {
border-width: 0;
}
a:hover,
.tabactive {
text-decoration: none;
}
}
> li > {
a:hover,
.tabactive {
text-decoration: none;
}
}
}
&#topmenu2 a {
&.tab:hover,
&.tabactive {
@ -1095,14 +1016,7 @@ ul {
text-decoration: none;
}
}
// to be able to cancel the bottom border, use <li class="active">
&#topmenu > li.active {
border-#{$right}: 0;
border-bottom-color: #fff;
}
}
// end topmenu
// zoom search
div#dataDisplay {
@ -3882,25 +3796,11 @@ body .ui-dialog {
@media only screen and (max-width: 768px) {
ul {
&#topmenu,
&.tabs {
display: flex;
}
}
.navigationbar {
display: inline-flex;
margin: 0 !important;
border-radius: 0 !important;
overflow: auto;
}
.scrollindicator {
padding: 5px;
cursor: pointer;
display: inline;
}
.responsivetable {
overflow-x: auto;
}

View File

@ -0,0 +1,32 @@
.navbar.bg-light {
background: linear-gradient(#fff, #dcdcdc);
}
.navbar-nav {
font-weight: bold;
}
.navbar-nav .icon {
margin-#{$right}: 0.5em;
vertical-align: -3px;
}
.navbar-nav .nav-item {
background: linear-gradient(#fff, #dcdcdc);
border-#{$right}: 1px solid #fff;
border-#{$left}: 1px solid #ccc;
border-bottom: 1px solid #ccc;
&:first-child {
border-#{$left}: 0;
}
&:hover {
background: linear-gradient(#fff, #e5e5e5);
}
&.active {
background: #fff;
border-bottom: 0;
}
}

View File

@ -74,6 +74,22 @@ $secondary: #ddd;
$btn-border-radius: 0.85rem;
$btn-line-height: 1.15;
// Dropdowns
$dropdown-padding-y: 0;
$dropdown-item-padding-y: 0;
$dropdown-item-padding-x: 0;
// Navbar
$enable-caret: false;
$navbar-padding-y: 0;
$navbar-padding-x: 0;
$navbar-light-color: #235a81;
$navbar-light-hover-color: #235a81;
$navbar-light-active-color: #235a81;
$navbar-light-disabled-color: #235a81;
// Card
$card-border-color: #999;

View File

@ -13,6 +13,7 @@
@import "icons";
@import "reboot";
@import "buttons";
@import "navbar";
@import "card";
@import "breadcrumb";
@import "alert";