Make contextual sidebar collapsible
This commit is contained in:
parent
4b3011e1c2
commit
d7ef168c52
8 changed files with 159 additions and 2 deletions
|
@ -23,6 +23,7 @@ export const showSubLevelItems = (el) => {
|
|||
const top = calculateTop(boundingRect, subItems.offsetHeight);
|
||||
const isAbove = top < boundingRect.top;
|
||||
|
||||
subItems.classList.add('fly-out-list');
|
||||
subItems.style.transform = `translate3d(0, ${Math.floor(top)}px, 0)`;
|
||||
|
||||
if (isAbove) {
|
||||
|
|
|
@ -1,23 +1,63 @@
|
|||
import Cookies from 'js-cookie';
|
||||
import _ from 'underscore';
|
||||
/* global bp */
|
||||
import './breakpoints';
|
||||
|
||||
export default class NewNavSidebar {
|
||||
constructor() {
|
||||
this.initDomElements();
|
||||
this.render();
|
||||
}
|
||||
|
||||
initDomElements() {
|
||||
this.$page = $('.page-with-sidebar');
|
||||
this.$sidebar = $('.nav-sidebar');
|
||||
this.$overlay = $('.mobile-overlay');
|
||||
this.$openSidebar = $('.toggle-mobile-nav');
|
||||
this.$closeSidebar = $('.close-nav-button');
|
||||
this.$sidebarToggle = $('.js-toggle-sidebar');
|
||||
}
|
||||
|
||||
bindEvents() {
|
||||
this.$openSidebar.on('click', () => this.toggleSidebarNav(true));
|
||||
this.$closeSidebar.on('click', () => this.toggleSidebarNav(false));
|
||||
this.$overlay.on('click', () => this.toggleSidebarNav(false));
|
||||
this.$sidebarToggle.on('click', () => {
|
||||
const value = !this.$sidebar.hasClass('sidebar-icons-only');
|
||||
this.toggleCollapsedSidebar(value);
|
||||
});
|
||||
|
||||
$(window).on('resize', () => _.debounce(this.render(), 100));
|
||||
}
|
||||
|
||||
static setCollapsedCookie(value) {
|
||||
if (bp.getBreakpointSize() !== 'lg') {
|
||||
return;
|
||||
}
|
||||
Cookies.set('sidebar_collapsed', value, { expires: 365 * 10 });
|
||||
}
|
||||
|
||||
toggleSidebarNav(show) {
|
||||
this.$sidebar.toggleClass('nav-sidebar-expanded', show);
|
||||
this.$overlay.toggleClass('mobile-nav-open', show);
|
||||
this.$sidebar.removeClass('sidebar-icons-only');
|
||||
}
|
||||
|
||||
toggleCollapsedSidebar(collapsed) {
|
||||
this.$sidebar.toggleClass('sidebar-icons-only', collapsed);
|
||||
this.$page.toggleClass('page-with-new-sidebar', !collapsed);
|
||||
this.$page.toggleClass('page-with-icon-sidebar', collapsed);
|
||||
NewNavSidebar.setCollapsedCookie(collapsed);
|
||||
}
|
||||
|
||||
render() {
|
||||
const breakpoint = bp.getBreakpointSize();
|
||||
|
||||
if (breakpoint === 'sm' || breakpoint === 'md') {
|
||||
this.toggleCollapsedSidebar(true);
|
||||
} else if (breakpoint === 'lg') {
|
||||
const collapse = Cookies.get('sidebar_collapsed') === 'true';
|
||||
this.toggleCollapsedSidebar(collapse);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,9 +12,12 @@ $hover-background: $indigo-700;
|
|||
$hover-color: $white-light;
|
||||
$inactive-color: $gl-text-color-secondary;
|
||||
$new-sidebar-width: 220px;
|
||||
$new-sidebar-collapsed-width: 50px;
|
||||
|
||||
.page-with-new-sidebar {
|
||||
@media (min-width: $screen-sm-min) {
|
||||
padding-left: $new-sidebar-collapsed-width;
|
||||
|
||||
@media (min-width: $screen-lg-min) {
|
||||
padding-left: $new-sidebar-width;
|
||||
}
|
||||
|
||||
|
@ -29,6 +32,12 @@ $new-sidebar-width: 220px;
|
|||
}
|
||||
}
|
||||
|
||||
.page-with-icon-sidebar {
|
||||
@media (min-width: $screen-sm-min) {
|
||||
padding-left: $new-sidebar-collapsed-width;
|
||||
}
|
||||
}
|
||||
|
||||
.context-header {
|
||||
position: relative;
|
||||
|
||||
|
@ -125,6 +134,20 @@ $new-sidebar-width: 220px;
|
|||
background-color: $gray-normal;
|
||||
box-shadow: inset -2px 0 0 $border-color;
|
||||
|
||||
// .expand-full-sidebar-button {
|
||||
// display: none;
|
||||
// }
|
||||
|
||||
&.sidebar-icons-only {
|
||||
width: $new-sidebar-collapsed-width;
|
||||
|
||||
.nav-item-name,
|
||||
.badge,
|
||||
.project-title {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
&.nav-sidebar-expanded {
|
||||
left: 0;
|
||||
}
|
||||
|
@ -219,6 +242,8 @@ $new-sidebar-width: 220px;
|
|||
}
|
||||
|
||||
.sidebar-top-level-items {
|
||||
margin-bottom: 60px;
|
||||
|
||||
> li {
|
||||
> a {
|
||||
@media (min-width: $screen-sm-min) {
|
||||
|
@ -240,7 +265,7 @@ $new-sidebar-width: 220px;
|
|||
@media (min-width: $screen-sm-min) {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 220px;
|
||||
left: $new-sidebar-width;
|
||||
width: 150px;
|
||||
margin-top: -1px;
|
||||
padding: 8px 1px;
|
||||
|
@ -326,6 +351,85 @@ $new-sidebar-width: 220px;
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// Collapsed nav
|
||||
|
||||
.toggle-sidebar-button {
|
||||
width: $new-sidebar-width - 2px;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
padding: 16px;
|
||||
background-color: $gray-normal;
|
||||
border-top: 2px solid $border-color;
|
||||
color: $gl-text-color-secondary;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
@media (max-width: $screen-xs-max) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
i {
|
||||
font-size: 20px;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.fa-angle-double-right {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: $border-color;
|
||||
color: $gl-text-color;
|
||||
}
|
||||
}
|
||||
|
||||
.sidebar-icons-only {
|
||||
.context-header {
|
||||
height: 60px;
|
||||
|
||||
a {
|
||||
padding: 10px 4px;
|
||||
}
|
||||
}
|
||||
|
||||
li a {
|
||||
padding: 12px 15px;
|
||||
}
|
||||
|
||||
.sidebar-top-level-items > li {
|
||||
&.active a {
|
||||
padding-left: 12px;
|
||||
}
|
||||
|
||||
.sidebar-sub-level-items {
|
||||
@media (min-width: $screen-sm-min) {
|
||||
left: $new-sidebar-collapsed-width;
|
||||
}
|
||||
|
||||
&:not(.flyout-list) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.toggle-sidebar-button {
|
||||
width: $new-sidebar-collapsed-width - 2px;
|
||||
|
||||
.collapse-text,
|
||||
.fa-angle-double-left {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.fa-angle-double-right {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Mobile nav
|
||||
|
||||
.toggle-mobile-nav {
|
||||
display: none;
|
||||
background-color: transparent;
|
||||
|
|
|
@ -149,3 +149,5 @@
|
|||
= custom_icon('settings')
|
||||
%span.nav-item-name
|
||||
Settings
|
||||
|
||||
= render 'shared/sidebar_toggle_button'
|
||||
|
|
|
@ -88,3 +88,5 @@
|
|||
= link_to group_settings_ci_cd_path(@group), title: 'CI / CD' do
|
||||
%span
|
||||
CI / CD
|
||||
|
||||
= render 'shared/sidebar_toggle_button'
|
||||
|
|
|
@ -83,3 +83,5 @@
|
|||
= custom_icon('authentication_log')
|
||||
%span.nav-item-name
|
||||
Authentication log
|
||||
|
||||
= render 'shared/sidebar_toggle_button'
|
||||
|
|
|
@ -222,6 +222,8 @@
|
|||
%span
|
||||
Members
|
||||
|
||||
= render 'shared/sidebar_toggle_button'
|
||||
|
||||
-# Shortcut to Project > Activity
|
||||
%li.hidden
|
||||
= link_to activity_project_path(@project), title: 'Activity', class: 'shortcuts-project-activity' do
|
||||
|
|
4
app/views/shared/_sidebar_toggle_button.html.haml
Normal file
4
app/views/shared/_sidebar_toggle_button.html.haml
Normal file
|
@ -0,0 +1,4 @@
|
|||
%a.toggle-sidebar-button.js-toggle-sidebar{ role: "button", type: "button", title: "Toggle sidebar" }
|
||||
= icon('angle-double-left')
|
||||
= icon('angle-double-right')
|
||||
%span.collapse-text Collapse sidebar
|
Loading…
Reference in a new issue