From 8cf3d9ff4fe38a12d8e481bea4ad6c37608ff293 Mon Sep 17 00:00:00 2001 From: Michael Krotscheck Date: Wed, 23 Jul 2014 16:59:45 -0700 Subject: [PATCH] Secondary Submenu Added a secondary menu that extends out from the sidebar, to indicate that there are additional options to choose from. In this case, I've implemented it on the admin menu so that we have room to add team administration. Change-Id: Ie7aa392e172bafc790ed2d28d831171a60be8467 --- src/app/admin/module.js | 9 +- src/app/admin/template/admin_submenu.html | 22 +++ .../controller/application_controller.js | 57 +++++++ src/app/storyboard/template/side_menu.html | 8 +- src/index.html | 3 +- src/theme/base/body.less | 16 ++ src/theme/base/bootstrap/navbar.less | 143 +++++++++++++++++- src/theme/base/icons.less | 1 + src/theme/storyboard/theme.less | 6 + 9 files changed, 256 insertions(+), 9 deletions(-) create mode 100644 src/app/admin/template/admin_submenu.html create mode 100644 src/app/storyboard/controller/application_controller.js diff --git a/src/app/admin/module.js b/src/app/admin/module.js index f30420ea..60a2d5cd 100644 --- a/src/app/admin/module.js +++ b/src/app/admin/module.js @@ -29,7 +29,14 @@ angular.module('sb.admin', [ 'sb.services', 'sb.templates', 'sb.util', $stateProvider .state('admin', { abstract: true, - template: '
', + views: { + 'submenu@': { + templateUrl: 'app/admin/template/admin_submenu.html' + }, + '@': { + template: '
' + } + }, url: '/admin', resolve: { isSuperuser: PermissionResolver diff --git a/src/app/admin/template/admin_submenu.html b/src/app/admin/template/admin_submenu.html new file mode 100644 index 00000000..dd405817 --- /dev/null +++ b/src/app/admin/template/admin_submenu.html @@ -0,0 +1,22 @@ + + \ No newline at end of file diff --git a/src/app/storyboard/controller/application_controller.js b/src/app/storyboard/controller/application_controller.js new file mode 100644 index 00000000..5e934c3d --- /dev/null +++ b/src/app/storyboard/controller/application_controller.js @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2014 Hewlett-Packard Development Company, L.P. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +/** + * Application controller, which keeps track of our active state chain and + * sets global scope variable accordingly. + */ +angular.module('storyboard').controller('ApplicationController', + function ($scope, $state, $rootScope) { + 'use strict'; + + /** + * This method traverses the current active state tree to see if the + * current state, or any of its parents, have a submenu declared. + * + * @param state + */ + function hasSubmenu(state) { + for (var stateName in state.views) { + if (!!stateName.match(/^submenu@/)) { + return true; + } + } + + if (!!state.parent) { + return hasSubmenu(state.parent); + } else { + return false; + } + } + + /** + * Listen to changes in the state machine to trigger our submenu + * scan. + */ + $rootScope.$on('$stateChangeSuccess', + function () { + $scope.hasSubmenu = hasSubmenu($state.$current); + }); + + // Set a sane default. + $scope.hasSubmenu = false; + + }); diff --git a/src/app/storyboard/template/side_menu.html b/src/app/storyboard/template/side_menu.html index adcab0cc..98242c98 100644 --- a/src/app/storyboard/template/side_menu.html +++ b/src/app/storyboard/template/side_menu.html @@ -17,8 +17,8 @@ \ No newline at end of file diff --git a/src/index.html b/src/index.html index 21414301..3af1c7f9 100644 --- a/src/index.html +++ b/src/index.html @@ -44,7 +44,8 @@ - +
diff --git a/src/theme/base/body.less b/src/theme/base/body.less index 6deb08d6..cdbb9041 100644 --- a/src/theme/base/body.less +++ b/src/theme/base/body.less @@ -24,23 +24,39 @@ body { @media (max-width: @screen-xs-max) { body { margin-right: @navbar-fixed-side-width-xs; + + &.submenu { + margin-right: (@navbar-fixed-side-width-xs + @navbar-fixed-side-submenu-width-xs); + } } } @media (min-width: @screen-sm-min) and (max-width: @screen-sm-max) { body { margin-left: @navbar-fixed-side-width-sm; + + &.submenu { + margin-left: (@navbar-fixed-side-width-sm + @navbar-fixed-side-submenu-width-sm); + } } } @media (min-width: @screen-md-min) and (max-width: @screen-md-max) { body { margin-left: @navbar-fixed-side-width-md; + + &.submenu { + margin-left: (@navbar-fixed-side-width-md + @navbar-fixed-side-submenu-width-md); + } } } @media (min-width: @screen-lg-min) { body { margin-left: @navbar-fixed-side-width-lg; + + &.submenu { + margin-left: (@navbar-fixed-side-width-lg + @navbar-fixed-side-submenu-width-lg); + } } } \ No newline at end of file diff --git a/src/theme/base/bootstrap/navbar.less b/src/theme/base/bootstrap/navbar.less index 222ad9c5..9206b8b9 100644 --- a/src/theme/base/bootstrap/navbar.less +++ b/src/theme/base/bootstrap/navbar.less @@ -21,31 +21,101 @@ @media (max-width: @screen-xs-max) { width: @navbar-fixed-side-width-xs; + &.navbar-fixed-side-has-submenu { + width: (@navbar-fixed-side-width-xs + @navbar-fixed-side-submenu-width-xs); + } + top: 0px; right: 0px; bottom: 0px; + + .nav-submenu { + position: absolute; + top: 0px; + left: 0px; + bottom: 0px; + width: @navbar-fixed-side-submenu-width-md; + } } @media (min-width: @screen-sm-min) and (max-width: @screen-sm-max) { width: @navbar-fixed-side-width-sm; + + &.navbar-fixed-side-has-submenu { + width: (@navbar-fixed-side-width-sm + @navbar-fixed-side-submenu-width-sm); + } + top: 0px; left: 0px; bottom: 0px; + + .nav-submenu { + position: absolute; + top: 0px; + right: 0px; + bottom: 0px; + width: @navbar-fixed-side-submenu-width-md; + } } @media (min-width: @screen-md-min) and (max-width: @screen-md-max) { width: @navbar-fixed-side-width-md; + &.navbar-fixed-side-has-submenu { + width: (@navbar-fixed-side-width-md + @navbar-fixed-side-submenu-width-md); + } + top: 0px; left: 0px; bottom: 0px; + + .nav-submenu { + position: absolute; + top: 0px; + right: 0px; + bottom: 0px; + width: @navbar-fixed-side-submenu-width-md; + } } @media (min-width: @screen-lg-min) { width: @navbar-fixed-side-width-lg; + &.navbar-fixed-side-has-submenu { + width: (@navbar-fixed-side-width-lg + @navbar-fixed-side-submenu-width-lg); + } + top: 0px; left: 0px; bottom: 0px; + + .nav-submenu { + position: absolute; + top: 0px; + right: 0px; + bottom: 0px; + width: @navbar-fixed-side-submenu-width-md; + } } - .container-fluid { - padding: 5px; + .nav-main { + padding: 5px 0px 5px 0px; + } + + .nav-submenu { + display: none; + background-color: @navbar-inverse-link-active-bg; + + .nav.nav-pills { + > li { + margin-right: 0px; + margin-left: 0px; + + > a { + border-radius: 0px; + background: none; + + &:hover { + background: none; + } + } + } + } } overflow: hidden; @@ -54,7 +124,12 @@ margin: 0px; &.navbar-inverse .nav { + > li { + + margin-right: 5px; + margin-left: 5px; + > a { color: @navbar-inverse-link-color; background: @navbar-inverse-bg; @@ -91,7 +166,7 @@ } li.active { - background-color: @navbar-inverse-bg + background-color: @navbar-inverse-bg; } } @@ -111,10 +186,70 @@ position: absolute; bottom: 0px; } + + &.navbar-fixed-side-has-submenu { + + .nav-submenu { + display: inherit; + } + + @media (max-width: @screen-xs-max) { + .nav-main { + margin-left: @navbar-fixed-side-submenu-width-xs; + + a { + border-top-left-radius: 0px; + border-bottom-left-radius: 0px; + } + + li { + &.active { + margin-left: 0px; + + a { + padding-left: 10px; + } + } + } + } + } + @media (min-width: @screen-sm-min) and (max-width: @screen-sm-max) { + .nav-main { + margin-right: @navbar-fixed-side-submenu-width-sm; + } + } + @media (min-width: @screen-md-min) and (max-width: @screen-md-max) { + .nav-main { + margin-right: @navbar-fixed-side-submenu-width-md; + } + } + @media (min-width: @screen-lg-min) { + .nav-main { + margin-right: @navbar-fixed-side-submenu-width-lg; + } + } + + @media (min-width: @screen-sm-min) { + .nav-main { + li { + &.active { + margin-right: 0px; + + a { + padding-right: 10px; + } + } + } + a { + border-top-right-radius: 0px; + border-bottom-right-radius: 0px; + } + } + } + } } } - // Stacked pills .nav-stacked { > li { diff --git a/src/theme/base/icons.less b/src/theme/base/icons.less index 75446163..dae8b2e4 100644 --- a/src/theme/base/icons.less +++ b/src/theme/base/icons.less @@ -25,3 +25,4 @@ .@{fa-css-prefix}-sb-story:before { content: @fa-var-list-ul; } .@{fa-css-prefix}-sb-project:before { content: @fa-var-cube; } .@{fa-css-prefix}-sb-project-group:before { content: @fa-var-cubes; } +.@{fa-css-prefix}-sb-team:before { content: @fa-var-users; } diff --git a/src/theme/storyboard/theme.less b/src/theme/storyboard/theme.less index 2835adfa..4b99932f 100644 --- a/src/theme/storyboard/theme.less +++ b/src/theme/storyboard/theme.less @@ -100,6 +100,12 @@ @navbar-fixed-side-width-md: 90px; @navbar-fixed-side-width-lg: 90px; +// Sizes for the side navbar submenu at different container sizes. +@navbar-fixed-side-submenu-width-xs: 40px; +@navbar-fixed-side-submenu-width-sm: 40px; +@navbar-fixed-side-submenu-width-md: 40px; +@navbar-fixed-side-submenu-width-lg: 40px; + // Form Controls @input-height-h1: (ceil(@font-size-h1 * @line-height-large) + (@padding-base-vertical * 2));