From f724e8a80b61bc8a2846e7152f8777fb79961ff2 Mon Sep 17 00:00:00 2001 From: Kate Hudson Date: Tue, 1 Oct 2013 14:46:56 -0400 Subject: [PATCH] bug 914634 - New navigation with mobile styles --- app.js | 22 +- locale/en_US/messages.json | 9 + navigation.json | 106 ++++++++++ public/css/breakpoints.less | 1 + public/css/colors.less | 1 + public/css/components/navigation.less | 278 ++++++++++++++++++++++++++ public/css/headerfooter.less | 153 ++------------ public/css/style.less | 1 + public/css/ui.less | 12 ++ public/js/base/navigation.js | 40 ++++ public/js/main.js | 16 +- views/components/navigation.html | 62 ++++++ views/layout.html | 76 +++---- 13 files changed, 582 insertions(+), 195 deletions(-) create mode 100644 navigation.json create mode 100644 public/css/components/navigation.less create mode 100644 public/js/base/navigation.js create mode 100644 views/components/navigation.html diff --git a/app.js b/app.js index e4ab44427..061216d6e 100644 --- a/app.js +++ b/app.js @@ -10,7 +10,8 @@ var express = require( "express" ), nunjucks = require( "nunjucks" ), path = require( "path" ), lessMiddleWare = require( "less-middleware" ), - i18n = require( "webmaker-i18n" ); + i18n = require( "webmaker-i18n" ), + navigation = require( "./navigation" ); habitat.load(); @@ -28,6 +29,22 @@ nunjucksEnv.addFilter("instantiate", function(input) { return tmpl.render(this.getVariables()); }); +// For navigation +nunjucksEnv.addFilter("getSection", function (pageId) { + var section; + var page; + for (var i in navigation) { + section = navigation[i]; + for (var j in section.pages) { + page = section.pages[j]; + if (page.id === pageId) { + return section.id; + } + } + } + return ""; +}); + if ( !( env.get( "MAKE_ENDPOINT" ) && env.get( "MAKE_PRIVATEKEY" ) && env.get( "MAKE_PUBLICKEY" ) ) ) { throw new Error( "MakeAPI Config setting invalid or missing!" ); } @@ -187,7 +204,8 @@ app.use(function( req, res, next ) { email: req.session.email || '', username: req.session.username|| '', makerID: req.session.id || '', - csrf: req.session._csrf + csrf: req.session._csrf, + navigation: navigation }); next(); }); diff --git a/locale/en_US/messages.json b/locale/en_US/messages.json index 4976f20d0..efc83b1b2 100644 --- a/locale/en_US/messages.json +++ b/locale/en_US/messages.json @@ -114,6 +114,7 @@ "Events": "Events", "Expand your network.": "Expand your network.", "Explore our mentoring program": "Explore our mentoring program", + "Explore": "Explore", "Familiarize yourself with our survey": "Familiarize yourself with our survey.", "Featured": "Featured", "Feedback": "Feedback", @@ -131,6 +132,7 @@ "From June 15 to September 15": "From June 15 to September 15, thousands of people around the world are meeting up, making cool stuff and teaching others at the 2013 Maker Party. Come celebrate with people across the globe to make and learn new things on the web. It doesn't matter where you are in the world; friends, families, and individuals everywhere are uniting to celebrate what we can make (and break!) on the web. Here's how you can participate:", "From newsletters to community calls": "From newsletters to community calls, there are many ways you can join our community.", "From starter make": "From starter make", + "Gallery": "Gallery", "Get gear.": "Get gear.", "Get Involved Desc": "Access support and connect with the Webmaker community.", "Get involved with Webmaker.": "Get involved with Webmaker.", @@ -166,6 +168,7 @@ "If you don’t see the Whiteboard field": "If you don’t see the Whiteboard field, make sure the advanced options are showing.", "indexDesc": "We're a global community that creates the web by making, teaching and remixing. Check out this week's most inspiring Makes and sign up to create your own.", "indexHeader": "Make Something with Webmaker.", + "Info": "Info", "Introduce your community to hacking": "Introduce your community to hacking", "Join our community call": "Join our community calls every Tuesday. All are welcome! Ask questions, meet our community and staff and find the resources you need.", "Join our global conversation forum.": "Join our global conversation forum.", @@ -290,9 +293,12 @@ "Remix a project": "Remix a make", "Remix": "Remix", "Remixed from": "Remixed from", + "Resource Templates": "Resource Templates", + "Resources": "Resources", "Save": "Save", "Say hello on a Webmaker cummunity call": "Say hello on a Webmaker Community call.", "School, library": "At a school, library or flexible space", + "Search makes": "Search makes", "Search": "Search", "See how above": "See how above.", "see how it works": "We've built everything so you can see how it works, take it apart and remix it.", @@ -354,6 +360,7 @@ "teachtemplateKitDesc": "Create a lesson plan or session outline", "TeachTemplates": "Teach Templates", "Team up to explore": "Team up people with different skill-sets to explore an interesting challenge", + "Templates": "Templates", "The fastest way to get help": "The fastest way to get help, offer help and connect with other mentors.", "The web is still open.": "The web is still open.", "The worldwide Maker Party will bring people together": "From coding your first line of HTML to building innovative apps, Maker Party is your chance to connect with a global community of creators. The easiest way to join the party is to build something yourself! Take a project from scratch or remix a project and make it your own.", @@ -380,6 +387,7 @@ "Users": "Users", "vdo-profile": "a video profile to introduce yourself to the world", "Video remixing and open source for youth": "Video remixing and open source for youth", + "Videos with Popcorn": "Videos with Popcorn", "View Events": "Start Making", "Visit our communications wiki": "Visit our communications wiki to find even more places you can reach us.", "Wait, there's more!": "Wait, there's more!", @@ -394,6 +402,7 @@ "Webmaker uses Persona, a secure way to sign in.": "Webmaker uses Persona, a secure way to sign in.", "Webmaker's mentor community": "Webmaker's mentor community spans the entire globe. Connect with other techies, educators and mentors to exchange ideas and creative new ways for teaching technology.", "Webmaking made easy": "Webmaking made easy", + "Webpages with Thimble": "Webpages with Thimble", "Welcome to Webmaker-Mozilla": "Welcome to Webmaker — a Mozilla project dedicated to helping you create something amazing on the web.", "What are you looking for?": "What are you looking for?", "when we understand the building blocks": "After all, it's only when we understand the building blocks of the web that we can have a hand in shaping its future.", diff --git a/navigation.json b/navigation.json new file mode 100644 index 000000000..46c02717f --- /dev/null +++ b/navigation.json @@ -0,0 +1,106 @@ +[ + { + "id": "explore", + "title": "Explore", + "icon": "icon-random", + "pages": [ + { + "id": "index", + "title": "Gallery", + "url": "" + }, + { + "id": "tools", + "title": "Tools", + "url": "tools" + } + ] + }, + { + "id": "make", + "title": "Make", + "icon": "icon-hand-up", + "pages": [ + { + "id": "starterMakes", + "title": "Starter Makes", + "url": "starter-makes" + }, + { + "id": "popcorn", + "title": "Videos with Popcorn", + "url": "https://popcorn.webmaker.org", + "external": "true" + }, + { + "id": "thimble", + "title": "Webpages with Thimble", + "url": "https://thimble.webmaker.org", + "external": "true" + }, + { + "id": "xray", + "title": "Remixes with X-Ray Goggles", + "url": "https://goggles.webmaker.org", + "external": "true" + } + ] + }, + { + "id": "teach", + "title": "Teach", + "icon": "icon-book", + "pages": [ + { + "id": "teach", + "title": "Resources", + "url": "teach" + }, + { + "id": "teach-templates", + "title": "Resource Templates", + "url": "teach-templates" + } + ] + }, + { + "id": "events", + "title": "Events", + "icon": "icon-map-marker", + "pages": [ + { + "id": "events", + "title": "Events", + "url": "events" + }, + { + "id": "party", + "title": "Maker Party", + "url": "party" + } + ] + }, + { + "id": "info", + "title": "Info", + "icon": "icon-info", + "pages": [ + { + "id": "about", + "title": "About Us", + "url": "about" + }, + { + "id": "getinvolved", + "title": "Get Involved", + "url": "getinvolved" + }, + { + "id": "help", + "title": "Help", + "url": "https://support.mozilla.org/en-US/products/webmaker", + "external": "true" + } + ] + } +] diff --git a/public/css/breakpoints.less b/public/css/breakpoints.less index 602f0f1e0..9d3fc73d2 100644 --- a/public/css/breakpoints.less +++ b/public/css/breakpoints.less @@ -2,5 +2,6 @@ @width-small: 320px; @width-medium: 640px; +@medium: 768px; @width-large: 960px; @width-xlarge: 1540px; diff --git a/public/css/colors.less b/public/css/colors.less index ffc09688e..5f941eb03 100644 --- a/public/css/colors.less +++ b/public/css/colors.less @@ -13,3 +13,4 @@ @midgrey: #ddd; @white: #fff; @black: #000; +@navy: #013E5F; diff --git a/public/css/components/navigation.less b/public/css/components/navigation.less new file mode 100644 index 000000000..39a12b472 --- /dev/null +++ b/public/css/components/navigation.less @@ -0,0 +1,278 @@ +@lightnavy: lighten(@navy, 6%); + +.navigation-container { + font-size: 14px; +} +.navigation-wrapper { + position: relative; + margin: 0; + padding: 0; + @media (min-width: @medium) { + margin: 0 auto; + left: -1.5em; + .border-box; + .width(8); + } + @media (min-width: 1540px) { + .width(12); + } +} + +.navigation-list { + .border-box; + position: relative; + list-style: none; + padding: 0; + color: @white; + + li { + display: inline; + } + a { + display: inline-block; + padding: 14px 18px; + color: inherit; + @media (min-width: @medium) { + line-height: 32px; + } + &:hover { + text-decoration: none; + } + } +} + +// Icons +.navigation-list .icon { + width: 30px; + height: 30px; + line-height: 30px; + text-align: center; + margin-right: 2px; + box-shadow: inset 0 0 0 2px fade(@white, 20%); + color: @white; + border-radius: 20px; + font-size: 12px; + display: inline-block; + + // Hack: this icon looks off, needs a slight adjustment. + &.icon-random:before { + position: relative; + left: 0.1em; + top: 0.1em; + } + +} + +.navigation-list .active .icon, +.on .icon { + display: inline-block; +} + +.navigation-list .active .icon, +.navigation-list a:hover .icon, +.on .icon { + box-shadow: none; + // Section colours + &.icon-random { + background: #F5A906; + } + &.icon-hand-up { + background: @blue; + } + &.icon-book { + background: #03845C; + } + &.icon-map-marker { + background: #E5352D; + } + &.icon-info { + background: #945361; + } +} + +#navigation-primary { + background: @navy; + a:hover, + .active { + background: @lightnavy; + } + + // Don't show on mobile + display: none; + + @media (min-width: @medium) { + display: block; + } + +} + +#navigation-secondary { + font-size: 13px; + background: @lightnavy; + + .navigation-list { + .clearfix; + display: none; + &.active { + display: block; + } + } + + li { + position: relative; + float: left; + width: 50%; + color: fade(@white, 60%); + display: inline-block; + &:hover, + .active { + color: @white; + } + @media (min-width: @medium) { + width: auto; + } + + } + + li:first-child { + display: block; + color: @white; + font-size: 16px; + width: 100%; + background: @navy; + .icon { + display: inline-block; + } + .navigation-more { + float: right; + line-height: 30px; + } + @media (min-width: @medium) { + background: none; + display: none; + } + } + + @media (min-width: @medium) { + a { + position: relative; + } + + a.active:after { + content: ""; + display: block; + position: absolute; + top: 100%; + left: 50%; + width: 0; + height: 0; + border-left: 10px solid transparent; + border-right: 10px solid transparent; + border-top: 10px solid @lightnavy; + margin-left: -10px; + } + } +} + +#expanded-navigation { + .clearfix; + position: relative; + background: @lightnavy; + display: none; + padding: 20px; + @media (min-width: @medium) { + padding: 20px 0; + } + &.on { + display: block; + } + + .navigation-wrapper { + left: 0; + } + + .navigation-list { + margin: 0 0 20px 0; + @media (min-width: @medium) { + float: left; + // Grid calculation for 5 colums with 4% gutter + width: ((100% - (4 * 4%)) / 5); + margin: 0 4% 0 0; + &:last-of-type { + margin-right: 0; + } + } + + a { + padding: 0; + line-height: 1.2; + } + + + li { + display: block; + color: fade(@white, 80%); + margin-bottom: 1em; + &:hover { + color: @white; + } + + // Section titles + &:first-child { + color: @white; + font-size: 18px; + //margin-left: -8px; + } + } + + .icon { + display: none; + } + + + } + + #navigation-expanded-close { + position: absolute; + cursor: pointer; + right: 20px; + top: 15px; + background: darken(@navy, 2%); + border: none; + display: block; + height: 30px; + width: 30px; + text-align: center; + color: @white; + } +} + +#nav-search { + float: right; + padding: 5px; + input { + .border-box; + border-radius: 2px; + color: @navy; + background: @white; + font-family: inherit; + font-size: 13px; + width: 150px; + padding: 10px 15px; + border: none; + transition: width 0.2s, background-color 0.2s; + &:focus { + background-color: @white; + width: 250px; + outline: none; + } + } + #nav-search-trigger { + padding: 10px; + color: @white; + font-size: 16px; + background: none; + cursor: pointer; + border: none; + } +} diff --git a/public/css/headerfooter.less b/public/css/headerfooter.less index 56d12c822..320a8fd7b 100644 --- a/public/css/headerfooter.less +++ b/public/css/headerfooter.less @@ -16,6 +16,10 @@ z-index: 4; } +.user-info { + margin-top: 20px; +} + #tabzilla { position: absolute; top: 0; @@ -24,6 +28,7 @@ #logo { margin-top: 10px; + margin-left: -18px; } // Contains SSO and main navigation @@ -33,124 +38,6 @@ margin-right: 150px; } -.nav-list { - position: absolute; - z-index: 3; - bottom: 0; - right: 0; - margin: 0; - list-style: none; - font-size: 1.5em; - - li { - display: inline-block; - position: relative; - text-align: center; - padding: 0.5em 1em; - border: 1px solid transparent; - .border-box; - &:last-of-type { - padding-right: 0; - } - - &:hover .makenav-hover { - display: block; - } - - &:first-child:hover { - color: #55575c; - background: url(../img/bkgFooter.jpg); - border: 1px solid #fff; - border-bottom: none; - box-shadow: 0 3px 3px #888888; - } - - .makenav-hover { - display: none; - position: absolute; - left: -1px; - border: 1px solid #fff; - border-top: none; - width: 365px; - padding-top: 15px; - font-size: 13px; - color: #55575c; - .border-box; - background: url(../img/bkgFooter.jpg); - box-shadow: 0 3px 3px #888888; - - #template:hover { - span { - color: #27aae1; - } - } - - .makenav-hover-item { - cursor: pointer; - text-align: center; - height: 110px; - display: inline-block; - padding-left: 15px; - width: 50px; - margin: 5px 15px 0 0; - - img { - display: inline-block; - margin-bottom: 5px; - } - - span { - float: left; - margin-right: 15px; - width: 100%; - } - } // makenav-hover-item - - .help { - width: 100%; - height: 40px; - text-align: left; - line-height: 40px; - background-color: #FFF; - .border-box; - a { - color: #000; - text-decoration: underline; - display: inline; - } - height: 40px; - line-height: 40px; - padding-left: 15px; - background-color: #FFF; - i { - font-size: 20px; - } - span { - vertical-align: 1px; - padding-left: 5px; - a { - vertical-align: 1px; - } - } - } - } - - a { - display: block; - color: @grey; - text-decoration: none; - font-weight: normal; - &:hover { - color: #27aae1; - } - } - - .on { - color: #b6b7b9; - } - } -} - li.lang-picker:first-child { border-right: none; } @@ -670,13 +557,18 @@ footer { header { .webmaker-nav-container { - height: auto; + height: 65px; } .user-info { display: none; } #logo { - float: none; + width: 150px; + margin-left: 0; + display: inline-block; + img { + width: 100%; + } } .user-nav-container { margin: 0; @@ -807,27 +699,10 @@ footer { * MOBILE (320px wide, retina) */ @media only screen and (max-width: 320px) { - header { - .webmaker-nav-container { - height: 140px; - #logo { - text-align: center; - } - - #tabzilla { - display: none; - } - } - .nav-list { - li { - width: 25%; - border: none; - float: left; - } - } + #tabzilla { + display: none; } - #footer-actions { left: 0; } diff --git a/public/css/style.less b/public/css/style.less index 1af30b750..54bdd77e1 100644 --- a/public/css/style.less +++ b/public/css/style.less @@ -13,6 +13,7 @@ @import "components/chevron-list"; @import "components/powertip"; @import "components/ol-circled"; +@import "components/navigation"; @import "page-specific/feedback"; diff --git a/public/css/ui.less b/public/css/ui.less index 715672075..56f49590f 100644 --- a/public/css/ui.less +++ b/public/css/ui.less @@ -109,6 +109,18 @@ * Wrappers, main secitons */ +.ui-grid-wrapper { + position: relative; + margin: 0 auto; + width: 100%; + @media (min-width: @width-large) { + .width(8) + } + @media (min-width: @width-xlarge) { + .width(12) + } +} + .ui-wrapper { display: block; position: relative; diff --git a/public/js/base/navigation.js b/public/js/base/navigation.js new file mode 100644 index 000000000..e64182777 --- /dev/null +++ b/public/js/base/navigation.js @@ -0,0 +1,40 @@ +define(['jquery'], function ($) { + return function navigation() { + + var $mainNavContainer = $('#main-navigation-container'); + var currentPage = $mainNavContainer.data('current-page'); + var currentSection = $mainNavContainer.data('current-section'); + + var $expandedNavTriggers = $('.navigation-more'); + var $expandedNav = $('#expanded-navigation'); + var $activeNavItems = $('[data-page="' + currentPage + '"], [data-section="' + currentSection + '"]'); + + var $searchTrigger = $('#nav-search-trigger'); + var $searchInput = $('#nav-search-input'); + + function toggleExpandedMenu(e) { + e.preventDefault(); + $expandedNav.toggleClass('on'); + $activeNavItems.toggleClass('active'); + $expandedNavTriggers.toggleClass('active'); + } + + function doSearch() { + $searchTrigger.find('.icon-search') + .removeClass('icon-search') + .addClass('icon-spinner') + .addClass('icon-spin'); + window.location = '/search/?type=all&q=' + encodeURIComponent($searchInput.val()); + } + + $expandedNavTriggers.on('click', toggleExpandedMenu); + + $searchTrigger.on('click', doSearch); + $searchInput.on('keyup', function (e) { + if (e.which === 13) { + doSearch(); + } + }); + + }; +}); diff --git a/public/js/main.js b/public/js/main.js index 0d0eeea87..b0b565d33 100644 --- a/public/js/main.js +++ b/public/js/main.js @@ -20,8 +20,17 @@ requirejs.config({ } }); -require(['jquery', 'base/cta', 'base/marquee', 'base/email-signup', 'base/anchor-slide', '/bower/webmaker-ui/ui.js', 'tabzilla', 'sso-ux'], - function ($, cta, Marquee, privacy, AnchorSlide, WebmakerUI) { +require([ + 'jquery', + 'base/cta', + 'base/marquee', + 'base/email-signup', + 'base/anchor-slide', + '/bower/webmaker-ui/ui.js', + 'base/navigation', + 'tabzilla', + 'sso-ux' +], function ($, cta, Marquee, privacy, AnchorSlide, WebmakerUI, navigation) { 'use strict'; var $html = $('html, body'); @@ -38,6 +47,9 @@ require(['jquery', 'base/cta', 'base/marquee', 'base/email-signup', 'base/anchor } }); + // Attach navigation UI + navigation(); + // Generate CTA bar in footer cta.attachToCTA(); diff --git a/views/components/navigation.html b/views/components/navigation.html new file mode 100644 index 000000000..dfee40e82 --- /dev/null +++ b/views/components/navigation.html @@ -0,0 +1,62 @@ +{% set currentPage = page %} +{% set currentSection = page|getSection %} + diff --git a/views/layout.html b/views/layout.html index 03dbb3707..3ffee172e 100644 --- a/views/layout.html +++ b/views/layout.html @@ -30,60 +30,32 @@ {% block header %}
+ + {% include "components/navigation.html" %} +
{% endblock %}
{% block midbar %}{% endblock %}