diff --git a/website/docs/Gemfile b/website/docs/Gemfile index a2e8e3374..45b497f6b 100644 --- a/website/docs/Gemfile +++ b/website/docs/Gemfile @@ -2,7 +2,7 @@ source "https://rubygems.org" ruby "2.2.2" -gem "less", "~> 2.2.2" +gem "less", "~> 2.6.0" gem "middleman", "~> 3.0.6" gem "middleman-minify-html", "~> 3.0.0" gem "rack-contrib", "~> 1.1.0" diff --git a/website/docs/Gemfile.lock b/website/docs/Gemfile.lock index c79012744..103f8d809 100644 --- a/website/docs/Gemfile.lock +++ b/website/docs/Gemfile.lock @@ -36,8 +36,8 @@ GEM rack (>= 1.0.0) url_mount (~> 0.2.1) i18n (0.6.1) - less (2.2.2) - commonjs (~> 0.2.6) + less (2.6.0) + commonjs (~> 0.2.7) libv8 (3.16.14.7) listen (0.7.3) maruku (0.6.1) @@ -134,7 +134,7 @@ PLATFORMS DEPENDENCIES highline (~> 1.6.15) - less (~> 2.2.2) + less (~> 2.6.0) middleman (~> 3.0.6) middleman-minify-html (~> 3.0.0) rack-contrib (~> 1.1.0) @@ -143,3 +143,6 @@ DEPENDENCIES redcarpet (~> 2.2.2) therubyracer (~> 0.12.0) thin (~> 1.5.0) + +BUNDLED WITH + 1.10.6 diff --git a/website/docs/source/images/logo-header-docs.png b/website/docs/source/images/logo-header-docs.png new file mode 100644 index 000000000..497994a04 Binary files /dev/null and b/website/docs/source/images/logo-header-docs.png differ diff --git a/website/docs/source/images/logo-header-docs@2x.png b/website/docs/source/images/logo-header-docs@2x.png new file mode 100644 index 000000000..47eb8378a Binary files /dev/null and b/website/docs/source/images/logo-header-docs@2x.png differ diff --git a/website/docs/source/images/logo-header.png b/website/docs/source/images/logo-header.png new file mode 100644 index 000000000..a058de16f Binary files /dev/null and b/website/docs/source/images/logo-header.png differ diff --git a/website/docs/source/images/logo-header@2x.png b/website/docs/source/images/logo-header@2x.png new file mode 100644 index 000000000..5ebdf1d10 Binary files /dev/null and b/website/docs/source/images/logo-header@2x.png differ diff --git a/website/docs/source/javascripts/Sidebar.js b/website/docs/source/javascripts/Sidebar.js new file mode 100644 index 000000000..94f2cbdb6 --- /dev/null +++ b/website/docs/source/javascripts/Sidebar.js @@ -0,0 +1,50 @@ +(function(){ + + Sidebar = Base.extend({ + + $body: null, + $overlay: null, + $sidebar: null, + $sidebarHeader: null, + $sidebarImg: null, + $toggleButton: null, + + constructor: function(){ + this.$body = $('body'); + this.$overlay = $('.mobile-nav-overlay'); + this.$sidebar = $('#mobile-nav'); + this.$sidebarHeader = $('#mobile-nav .mobile-nav-header'); + this.$toggleButton = $('.navbar-toggle'); + this.sidebarImg = this.$sidebarHeader.css('background-image'); + + this.addEventListeners(); + }, + + addEventListeners: function(){ + var _this = this; + + _this.$toggleButton.on('click', function() { + _this.$sidebar.toggleClass('open'); + if ((_this.$sidebar.hasClass('mobile-nav-fixed-left') || _this.$sidebar.hasClass('mobile-nav-fixed-right')) && _this.$sidebar.hasClass('open')) { + _this.$overlay.addClass('active'); + _this.$body.css('overflow', 'hidden'); + } else { + _this.$overlay.removeClass('active'); + _this.$body.css('overflow', 'auto'); + } + + return false; + }); + + _this.$overlay.on('click', function() { + $(this).removeClass('active'); + _this.$body.css('overflow', 'auto'); + _this.$sidebar.removeClass('open'); + }); + } + + }); + + window.Sidebar = Sidebar; + +})(); diff --git a/website/docs/source/javascripts/lib/Base.js b/website/docs/source/javascripts/lib/Base.js new file mode 100644 index 000000000..504e2beea --- /dev/null +++ b/website/docs/source/javascripts/lib/Base.js @@ -0,0 +1,145 @@ +/* + Based on Base.js 1.1a (c) 2006-2010, Dean Edwards + Updated to pass JSHint and converted into a module by Kenneth Powers + License: http://www.opensource.org/licenses/mit-license.php +*/ +/*global define:true module:true*/ +/*jshint eqeqeq:true*/ +(function (name, global, definition) { + if (typeof module !== 'undefined') { + module.exports = definition(); + } else if (typeof define !== 'undefined' && typeof define.amd === 'object') { + define(definition); + } else { + global[name] = definition(); + } +})('Base', this, function () { + // Base Object + var Base = function () {}; + + // Implementation + Base.extend = function (_instance, _static) { // subclass + var extend = Base.prototype.extend; + // build the prototype + Base._prototyping = true; + var proto = new this(); + extend.call(proto, _instance); + proto.base = function () { + // call this method from any other method to invoke that method's ancestor + }; + delete Base._prototyping; + // create the wrapper for the constructor function + //var constructor = proto.constructor.valueOf(); //-dean + var constructor = proto.constructor; + var klass = proto.constructor = function () { + if (!Base._prototyping) { + if (this._constructing || this.constructor === klass) { // instantiation + this._constructing = true; + constructor.apply(this, arguments); + delete this._constructing; + } else if (arguments[0] !== null) { // casting + return (arguments[0].extend || extend).call(arguments[0], proto); + } + } + }; + // build the class interface + klass.ancestor = this; + klass.extend = this.extend; + klass.forEach = this.forEach; + klass.implement = this.implement; + klass.prototype = proto; + klass.toString = this.toString; + klass.valueOf = function (type) { + return (type === 'object') ? klass : constructor.valueOf(); + }; + extend.call(klass, _static); + // class initialization + if (typeof klass.init === 'function') klass.init(); + return klass; + }; + + Base.prototype = { + extend: function (source, value) { + if (arguments.length > 1) { // extending with a name/value pair + var ancestor = this[source]; + if (ancestor && (typeof value === 'function') && // overriding a method? + // the valueOf() comparison is to avoid circular references + (!ancestor.valueOf || ancestor.valueOf() !== value.valueOf()) && /\bbase\b/.test(value)) { + // get the underlying method + var method = value.valueOf(); + // override + value = function () { + var previous = this.base || Base.prototype.base; + this.base = ancestor; + var returnValue = method.apply(this, arguments); + this.base = previous; + return returnValue; + }; + // point to the underlying method + value.valueOf = function (type) { + return (type === 'object') ? value : method; + }; + value.toString = Base.toString; + } + this[source] = value; + } else if (source) { // extending with an object literal + var extend = Base.prototype.extend; + // if this object has a customized extend method then use it + if (!Base._prototyping && typeof this !== 'function') { + extend = this.extend || extend; + } + var proto = { + toSource: null + }; + // do the "toString" and other methods manually + var hidden = ['constructor', 'toString', 'valueOf']; + // if we are prototyping then include the constructor + for (var i = Base._prototyping ? 0 : 1; i < hidden.length; i++) { + var h = hidden[i]; + if (source[h] !== proto[h]) + extend.call(this, h, source[h]); + } + // copy each of the source object's properties to this object + for (var key in source) { + if (!proto[key]) extend.call(this, key, source[key]); + } + } + return this; + } + }; + + // initialize + Base = Base.extend({ + constructor: function () { + this.extend(arguments[0]); + } + }, { + ancestor: Object, + version: '1.1', + forEach: function (object, block, context) { + for (var key in object) { + if (this.prototype[key] === undefined) { + block.call(context, object[key], key, object); + } + } + }, + implement: function () { + for (var i = 0; i < arguments.length; i++) { + if (typeof arguments[i] === 'function') { + // if it's a function, call it + arguments[i](this.prototype); + } else { + // add the interface using the extend method + this.prototype.extend(arguments[i]); + } + } + return this; + }, + toString: function () { + return String(this.valueOf()); + } + }); + + // Return Base implementation + return Base; +}); diff --git a/website/docs/source/layouts/_mobile_nav.erb b/website/docs/source/layouts/_mobile_nav.erb new file mode 100644 index 000000000..1fb76cf66 --- /dev/null +++ b/website/docs/source/layouts/_mobile_nav.erb @@ -0,0 +1,19 @@ + +
+ + + diff --git a/website/docs/source/layouts/layout.erb b/website/docs/source/layouts/layout.erb index db40d692b..09cf92b42 100644 --- a/website/docs/source/layouts/layout.erb +++ b/website/docs/source/layouts/layout.erb @@ -30,21 +30,33 @@
- + + - + <%= partial "layouts/mobile_nav" %>
@@ -326,15 +338,18 @@
+ <% relative_path = current_page.path.match(/.*\//).to_s + file = current_page.source_file.split("/").last + github_link = "https://github.com/mitchellh/vagrant/blob/master/website/docs/source/#{relative_path}#{file}" + %> + +
+ <%= javascript_include_tag "lib/Base" %> + <%= javascript_include_tag "Sidebar" %> + diff --git a/website/docs/source/layouts/svg/_svg-by-hashicorp.erb b/website/docs/source/layouts/svg/_svg-by-hashicorp.erb new file mode 100644 index 000000000..607d16b1e --- /dev/null +++ b/website/docs/source/layouts/svg/_svg-by-hashicorp.erb @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/website/docs/source/layouts/svg/_svg-download.erb b/website/docs/source/layouts/svg/_svg-download.erb new file mode 100644 index 000000000..6d8441fea --- /dev/null +++ b/website/docs/source/layouts/svg/_svg-download.erb @@ -0,0 +1,4 @@ + + + diff --git a/website/docs/source/layouts/svg/_svg-github.erb b/website/docs/source/layouts/svg/_svg-github.erb new file mode 100644 index 000000000..f0264d5aa --- /dev/null +++ b/website/docs/source/layouts/svg/_svg-github.erb @@ -0,0 +1,9 @@ + + + + diff --git a/website/docs/source/layouts/svg/_svg-hashicorp-logo.erb b/website/docs/source/layouts/svg/_svg-hashicorp-logo.erb new file mode 100644 index 000000000..60663e140 --- /dev/null +++ b/website/docs/source/layouts/svg/_svg-hashicorp-logo.erb @@ -0,0 +1,7 @@ + diff --git a/website/docs/source/stylesheets/_footer.less b/website/docs/source/stylesheets/_footer.less index 1f5635808..9c74f93e6 100644 --- a/website/docs/source/stylesheets/_footer.less +++ b/website/docs/source/stylesheets/_footer.less @@ -2,6 +2,7 @@ footer { padding: 80px 0; +margin-top: 20px; background: @black url(/images/footer_background.png) center center; text-align: center; color: @white; @@ -94,8 +95,23 @@ position: relative; //z-index needs position! } } //contact link - - - - } //footer + +.edit-page-link{ + position: absolute; + top: -120px; + right: 15px; + z-index: 9999; + + a{ + text-transform: uppercase; + color: @black; + font-size: 13px; + } +} + +@media (max-width: 480px){ + .edit-page-link{ + top: -90px; + } +} diff --git a/website/docs/source/stylesheets/_header.less b/website/docs/source/stylesheets/_header.less new file mode 100644 index 000000000..2a01bd332 --- /dev/null +++ b/website/docs/source/stylesheets/_header.less @@ -0,0 +1,166 @@ +// +// Header +// - Project Specific +// - edits should be made here +// -------------------------------------------------- + +#header { + width: 100%; + // font-size: 15px; + text-transform: uppercase; + height: @header-height; + position: fixed; + top: 0; + left: 0; + background-color: @white; + z-index: 1001; + + &.docs { + background: @gray-background; + } + + .navbar-toggle{ + margin-right: 15px; + } + + .navbar-brand { + float: left; + .logo{ + padding-left: 36px; + font-size: 0; + line-height: 77px; + width: @project-logo-width; + padding-left: 0; + .img-retina('/images/logo-header-docs.png', @project-logo-width, @project-logo-height, no-repeat); + background-position: 0 center; + + &:hover{ + opacity: .6; + } + } + + .by-hashicorp{ + color: @project-link-color; + + svg{ + path, + polygon, + rect{ + fill: @project-link-color; + } + } + + &:hover{ + color: black; + svg{ + path, + polygon, + rect{ + fill: black; + } + } + } + + .svg-wrap{ + font-weight: 400; + } + } + } + + .buttons{ + display: none; + margin-top: 2px; //baseline everything + + .navigation-links{ + float: right; + } + } + + .main-links, + .external-links { + li > a { + .project-a-style(); + } + } + + .main-links { + margin-right: 0; + + li { + &.pill{ + background-color: #48b4fb; + border-radius: 25px; + padding: 5px 2px; + line-height: 26px; + margin-top: 22px; + a{ + color: #FFF; + line-height: 24px; + } + } + + > a { + color: @project-link-color; + + &:hover{ + color: @black; + } + } + } + } +} + +@media (min-width: 768px) { + .navbar-toggle{ + display: none; + } + + #header{ + .buttons{ + display: block; + } + } +} + +@media (max-width: 768px) { + .navbar-header{ + margin-left: 15px; + } +} + +@media (max-width: 480px) { + #header { + height: auto; + + .navbar-toggle{ + padding-top: 7px; + } + + .by-hashicorp{ + margin-top: 2px; + } + + .navbar-brand { + .logo{ + width: @project-logo-width * .75; + background-size: (@project-logo-width * .75) (@project-logo-height * .75); + //background-position: 0 45%; + } + } + } +} + + +@media (max-width: 320px) { + #header { + .by-hashicorp{ + margin-left: -2px; + } + + .navbar-brand { + .logo{ + width: 40px; + } + } + } +} diff --git a/website/docs/source/stylesheets/_media-queries.less b/website/docs/source/stylesheets/_media-queries.less index 3dce5d028..a654b9a39 100644 --- a/website/docs/source/stylesheets/_media-queries.less +++ b/website/docs/source/stylesheets/_media-queries.less @@ -324,10 +324,6 @@ background-position: center center !important; } - .wrapper { - margin-top: 128px; - } - .sidebar { ul { @@ -450,3 +446,14 @@ } } // < 767 + + +@media (max-width: 480px){ + #header{ + height: 60px; + } + + .wrapper{ + margin-top: 60px; + } +} diff --git a/website/docs/source/stylesheets/_mixins.less b/website/docs/source/stylesheets/_mixins.less index 45dd9e745..174bc1d41 100644 --- a/website/docs/source/stylesheets/_mixins.less +++ b/website/docs/source/stylesheets/_mixins.less @@ -72,6 +72,25 @@ will-change: transform; } +.transition(@transition) { + -webkit-transition: @transition; + -o-transition: @transition; + transition: @transition; +} + +.translate3d (@x, @y: 0, @z: 0) { + -webkit-transform: translate3d(@x, @y, @z); + -moz-transform: translate3d(@x, @y, @z); + -ms-transform: translate3d(@x, @y, @z); + -o-transform: translate3d(@x, @y, @z); +} + +.clearfix{ + zoom:1; + &:before, &:after{ content:""; display:table; } + &:after{ clear: both; } +} + .inner-bg-large { background-image: #c1b4d5; /* Old browsers */ background-image: url(/images/sidebar_background_inner.png), -moz-linear-gradient(45deg, #c1b4d5 0%, #98d3f8 100%); /* FF3.6+ */ diff --git a/website/docs/source/stylesheets/_mobile-nav.less b/website/docs/source/stylesheets/_mobile-nav.less new file mode 100644 index 000000000..55e5db76b --- /dev/null +++ b/website/docs/source/stylesheets/_mobile-nav.less @@ -0,0 +1,43 @@ +// +// Sidebar +// - Project Specific +// - Make sidebar edits here +// -------------------------------------------------- + +#mobile-nav { + .mobile-nav-nav { + width: 100%; + text-align: center; + // Links + //---------------- + // + li{ + float: none; + + &.pill{ + background-color: #48b4fb; + border-radius: 25px; + padding: 5px 2px; + line-height: 26px; + margin: 10px 10px 10px 10px; + + &:focus, + &:hover{ + a{ + background-color: transparent; + } + } + + a{ + color: @white; + line-height: 24px; + } + } + + a{ + .anti-alias(); + font-size: 13px; + } + } + } +} diff --git a/website/docs/source/stylesheets/_nav.less b/website/docs/source/stylesheets/_nav.less deleted file mode 100644 index 4adfdbfdc..000000000 --- a/website/docs/source/stylesheets/_nav.less +++ /dev/null @@ -1,74 +0,0 @@ -// roll your own nav - -nav { - width: 100%; - font-size: 15px; - text-transform: uppercase; - .museo-sans-light; - color: @medium-gray-text; - height: 80px; - position: fixed; - top: 0; - left: 0; - background-color: @white; - z-index: 9999999999; - - &.docs { - background: @gray-background; - } - - .vagrant-logo { - display: block; - text-indent: -999999px; - background: url(/images/logo_vagrant.png) no-repeat 0 0; - height: 70px; - width: 275px; - float: left; - margin: 10px 20px; - } - - .vagrant-docs-logo { - display: block; - text-indent: -999999px; - background: url(/images/logo_docs.png) no-repeat 0 0; - height: 70px; - width: 350px; - float: left; - margin: 10px 20px; - } - - ul { - margin: 25px 20px; - - li { - display: inline; - margin-left: 15px; - } - - li.pill { - background-color: #48b4fb; - border-radius: 50px; - color: #FFF; - padding: 10px 18px; - } - } - - .active-nav { - color: @blue; - } - - .contact { - - &:hover { - background-color: @light-gray-background; - padding: 10px; - margin-right: -10px; - margin-left: 5px; - .rounded; - } - - &:active { - background-color: darken(@light-gray-background, 5%); - } - } -} diff --git a/website/docs/source/stylesheets/hashicorp-shared/_hashicorp-header.less b/website/docs/source/stylesheets/hashicorp-shared/_hashicorp-header.less new file mode 100755 index 000000000..388df9468 --- /dev/null +++ b/website/docs/source/stylesheets/hashicorp-shared/_hashicorp-header.less @@ -0,0 +1,351 @@ +// +// Hashicorp nav +// -------------------------------------------------- + +.nav{ + float: left; + margin: 0; + padding: 0; + list-style: none; + + li{ + display: block; + float: left; + + a{ + position: relative; + display: block; + } + } +} + +.navigation { + color: black; + text-rendering: optimizeLegibility; + transition: all 1s ease; + + &.white{ + .navbar-brand { + .logo { + color: white; + } + } + + .main-links, + .external-links { + li > a { + &:hover{ + opacity: 1; + } + } + } + } + + .navbar-toggle{ + height: @header-height; + margin: 0; + position: relative; + float: right; + padding: 9px 10px; + background-color: transparent; + background-image: none; + border: none; + + .bar{ + display: block; + width: 22px; + height: 2px; + margin-top: 4px; + background-color: @project-link-color; + } + } + + .external-links { + &.white{ + svg path{ + fill: @white; + } + } + + li { + position: relative; + + svg path{ + .transition( all 300ms ease-in ); + } + + &:hover{ + svg path{ + .transition( all 300ms ease-in ); + } + } + + &.download{ + margin-right: 10px; + } + + > a { + padding-left: 12px !important; + svg{ + position: absolute; + left: -12px; + top: 50%; + margin-top: -7px; + width: 14px; + height: 14px; + } + } + } + } + + .main-links{ + margin-right: @nav-margin-right * 2; + } + + .main-links, + .external-links { + &.white{ + li > a { + color: white; + } + } + li > a { + .hashi-a-style(); + margin: 0 10px; + padding-top: 1px; + line-height: @header-height; + .project-a-style(); + } + } + + .nav > li > a:hover, .nav > li > a:focus { + background-color: transparent; + .transition( all 300ms ease-in ); + } +} + +.navbar-brand { + display: block; + height: @header-height; + padding: 0; + margin: 0 10px 0 0; + + .logo{ + display: inline-block; + height: @header-height; + vertical-align:top; + padding: 0; + line-height: @header-height; + background-position: 0 center; + .transition(all 300ms ease-in); + + &:hover{ + .transition(all 300ms ease-in); + text-decoration: none; + } + } +} + +.navbar-toggle{ + &.white{ + .icon-bar{ + border: 1px solid white; + } + } +} + +.by-hashicorp{ + display: inline-block; + vertical-align:top; + height: @header-height; + margin-left: -3px; + padding-top: 2px; + color: black; + line-height: @header-height; + font-family: @header-font-family; + font-weight: 600; + font-size: 0; + letter-spacing: 0; + text-decoration: none; + text-transform: none; + + &.white{ + color: white; + font-weight: 300; + svg{ + path, + polygon, + rect{ + fill: white; + } + } + } + + &:focus, + &:hover{ + text-decoration: none; + } + + &:hover{ + .transition(all 300ms ease-in); + } + + .svg-wrap{ + font-size: 13px; + .transition(all 300ms ease-in); + } + + svg{ + &.svg-by{ + width: @by-hashicorp-width; + height: @by-hashicorp-height; + margin-bottom: -4px; + margin-left: 4px; + } + + &.svg-logo{ + width: 16px; + height: 16px; + margin-bottom: -3px; + margin-left: 4px; + } + + path, + polygon, + rect{ + fill: black; + .transition(all 300ms ease-in); + + &:hover{ + .transition(all 300ms ease-in); + } + } + } +} + +.hashicorp-project{ + display: inline-block; + height: 30px; + line-height: 30px; + text-decoration: none; + font-size: 14px; + color: @black; + font-weight: 600; + + &.white{ + color: white; + svg{ + path, + polygon{ + fill: white; + } + line{ + stroke: white; + } + } + } + + &:focus{ + text-decoration: none; + } + + &:hover{ + text-decoration: none; + svg{ + &.svg-by{ + line{ + stroke: @purple; + } + } + } + } + + span{ + margin-right: 4px; + font-family: @header-font-family; + font-weight: 500; + } + + span, + svg{ + display: inline-block; + } + + svg{ + &.svg-by{ + width: @by-hashicorp-width; + height: @by-hashicorp-height; + margin-bottom: -4px; + margin-left: -3px; + } + + &.svg-logo{ + width: 30px; + height: 30px; + margin-bottom: -10px; + margin-left: -1px; + } + + path, + line{ + fill: @black; + .transition(all 300ms ease-in); + + &:hover{ + .transition(all 300ms ease-in); + } + } + } +} + +@media (max-width: 992px) { + .navigation { + > .container{ + width: 100%; + } + } +} + +@media (max-width: 768px) { + .navigation { + .main-links{ + margin-right: 0; + } + } +} + +@media (max-width: 480px) { + #header { + .navbar-toggle{ + padding-top: 10px; + height: @header-mobile-height; + } + + .navbar-brand { + height: @header-mobile-height; + + .logo{ + height: @header-mobile-height; + line-height: @header-mobile-height; + } + .by-hashicorp{ + height: @header-mobile-height; + line-height: @header-mobile-height; + padding-top: 0; + } + } + .main-links, + .external-links { + li > a { + line-height: @header-mobile-height; + } + } + } +} + + +@media (min-width: 768px){ + .navbar-toggle { + display: none; + } +} diff --git a/website/docs/source/stylesheets/hashicorp-shared/_hashicorp-mobile-nav.less b/website/docs/source/stylesheets/hashicorp-shared/_hashicorp-mobile-nav.less new file mode 100644 index 000000000..a24e03608 --- /dev/null +++ b/website/docs/source/stylesheets/hashicorp-shared/_hashicorp-mobile-nav.less @@ -0,0 +1,293 @@ +// +// Hashicorp mobile-nav +// - Shared throughout projects +// - Edits should not be made here +// -------------------------------------------------- + +// Base variables +// -------------------------------------------------- +@screen-tablet: 768px; + +@gray-darker: #212121; // #212121 - text +@gray-secondary: #757575; // #757575 - secondary text, icons +@gray: #bdbdbd; // #bdbdbd - hint text +@gray-light: #e0e0e0; // #e0e0e0 - divider +@gray-lighter: #f5f5f5; // #f5f5f5 - background +@link-color: @gray-darker; +@link-bg: transparent; +@link-hover-color: @gray-lighter; +@link-hover-bg: @gray-lighter; +@link-active-color: @gray-darker; +@link-active-bg: @gray-light; +@link-disabled-color: @gray-light; +@link-disabled-bg: transparent; + +/* -- mobile-nav style ------------------------------- */ + +// mobile-nav variables +// -------------------------------------------------- +@zindex-mobile-nav-fixed: 1035; + +@mobile-nav-desktop-width: 280px; +@mobile-nav-width: 240px; + +@mobile-nav-padding: 16px; +@mobile-nav-divider: @mobile-nav-padding/2; + +@mobile-nav-icon-width: 40px; +@mobile-nav-icon-height: 20px; + +.mobile-nav-nav-base { + text-align: center; + + &:last-child{ + border-bottom: none; + } + + li > a { + background-color: @link-bg; + } + li:hover > a { + background-color: @link-hover-bg; + } + li:focus > a, li > a:focus { + background-color: @link-bg; + } + + > .open > a { + &, + &:hover, + &:focus { + background-color: @link-hover-bg; + } + } + + > .active > a { + &, + &:hover, + &:focus { + background-color: @link-active-bg; + } + } + > .disabled > a { + &, + &:hover, + &:focus { + background-color: @link-disabled-bg; + } + } + + // Dropdown menu items + > .dropdown { + // Remove background color from open dropdown + > .dropdown-menu { + background-color: @link-hover-bg; + + > li > a { + &:focus { + background-color: @link-hover-bg; + } + &:hover { + background-color: @link-hover-bg; + } + } + + > .active > a { + &, + &:hover, + &:focus { + color: @link-active-color; + background-color: @link-active-bg; + } + } + } + } +} + +// +// mobile-nav +// -------------------------------------------------- + +// mobile-nav Elements +// +// Basic style of mobile-nav elements +.mobile-nav { + position: relative; + display: block; + min-height: 100%; + overflow-y: auto; + overflow-x: hidden; + border: none; + .transition(all 0.5s cubic-bezier(0.55, 0, 0.1, 1)); + .clearfix(); + background-color: @white; + + ul{ + padding-left: 0; + list-style-type: none; + } + + .mobile-nav-divider, .divider { + width: 80%; + height: 1px; + margin: 8px auto; + background-color: lighten(@gray, 20%); + } + + // mobile-nav heading + //---------------- + .mobile-nav-header { + position: relative; + margin-bottom: @mobile-nav-padding; + .transition(all .2s ease-in-out); + } + + .mobile-nav-image { + padding-top: 24px; + img { + display: block; + margin: 0 auto; + } + } + + + // mobile-nav icons + //---------------- + .mobile-nav-icon { + display: inline-block; + height: @mobile-nav-icon-height; + margin-right: @mobile-nav-divider; + text-align: left; + font-size: @mobile-nav-icon-height; + vertical-align: middle; + + &:before, &:after { + vertical-align: middle; + } + } + + .mobile-nav-nav { + margin: 0; + padding: 0; + + .mobile-nav-nav-base(); + + // Links + //---------------- + li { + position: relative; + list-style-type: none; + text-align: center; + + a { + position: relative; + cursor: pointer; + user-select: none; + .hashi-a-style-core(); + + svg{ + top: 2px; + width: 14px; + height: 14px; + margin-bottom: -2px; + margin-right: 4px; + } + } + } + } +} + +// mobile-nav toggling +// +// Hide mobile-nav +.mobile-nav { + width: 0; + .translate3d(-@mobile-nav-desktop-width, 0, 0); + + &.open { + min-width: @mobile-nav-desktop-width; + width: @mobile-nav-desktop-width; + .translate3d(0, 0, 0); + } +} + +// mobile-nav positions: fix the left/right mobile-navs +.mobile-nav-fixed-left, +.mobile-nav-fixed-right, +.mobile-nav-stacked { + position: fixed; + top: 0; + bottom: 0; + z-index: @zindex-mobile-nav-fixed; +} +.mobile-nav-stacked { + left: 0; +} +.mobile-nav-fixed-left { + left: 0; + box-shadow: 2px 0px 25px rgba(0,0,0,0.15); + -webkit-box-shadow: 2px 0px 25px rgba(0,0,0,0.15); +} +.mobile-nav-fixed-right { + right: 0; + box-shadow: 0px 2px 25px rgba(0,0,0,0.15); + -webkit-box-shadow: 0px 2px 25px rgba(0,0,0,0.15); + + .translate3d(@mobile-nav-desktop-width, 0, 0); + &.open { + .translate3d(0, 0, 0); + } + .icon-material-mobile-nav-arrow:before { + content: "\e614"; // icon-material-arrow-forward + } +} + +// mobile-nav size +// +// Change size of mobile-nav and mobile-nav elements on small screens +@media (max-width: @screen-tablet) { + .mobile-nav.open { + min-width: @mobile-nav-width; + width: @mobile-nav-width; + } + + .mobile-nav .mobile-nav-header { + //height: @mobile-nav-width * 9/16; // 16:9 header dimension + } + + .mobile-nav .mobile-nav-image { + /* img { + width: @mobile-nav-width/4 - @mobile-nav-padding; + height: @mobile-nav-width/4 - @mobile-nav-padding; + } */ + } +} + +.mobile-nav-overlay { + visibility: hidden; + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + opacity: 0; + background: @white; + z-index: @zindex-mobile-nav-fixed - 1; + + -webkit-transition: visibility 0 linear .4s,opacity .4s cubic-bezier(.4,0,.2,1); + -moz-transition: visibility 0 linear .4s,opacity .4s cubic-bezier(.4,0,.2,1); + transition: visibility 0 linear .4s,opacity .4s cubic-bezier(.4,0,.2,1); + -webkit-transform: translateZ(0); + -moz-transform: translateZ(0); + -ms-transform: translateZ(0); + -o-transform: translateZ(0); + transform: translateZ(0); +} + +.mobile-nav-overlay.active { + opacity: 0.3; + visibility: visible; + -webkit-transition-delay: 0; + -moz-transition-delay: 0; + transition-delay: 0; +} diff --git a/website/docs/source/stylesheets/hashicorp-shared/_hashicorp-utility.less b/website/docs/source/stylesheets/hashicorp-shared/_hashicorp-utility.less new file mode 100755 index 000000000..8ecb75ee6 --- /dev/null +++ b/website/docs/source/stylesheets/hashicorp-shared/_hashicorp-utility.less @@ -0,0 +1,89 @@ +// +// Hashicorp Nav (header/footer) Utiliy Vars and Mixins +// +// Notes: +// - Include this in Application.scss before header and feature-footer +// - Open Sans Google (Semibold - 600) font needs to be included if not already +// -------------------------------------------------- + +// Variables +@font-family-open-sans: 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif; +@header-font-family: @font-family-open-sans; +@header-font-weight: 600; // semi-bold + +@header-height: 80px; +@header-mobile-height: 60px; +@by-hashicorp-width: 74px; +@by-hashicorp-height: 16px; +@nav-margin-right: 12px; + +// Mixins +.hashi-a-style-core{ + font-family: @header-font-family; + font-weight: @header-font-weight; + font-size: 14px; + //letter-spacing: 0.0625em; +} + +.hashi-a-style{ + margin: 0 15px; + padding: 0; + line-height: 22px; + .hashi-a-style-core(); + .transition( all 0.3s ease ); + + &:hover{ + .transition( all 0.3s ease ); + background-color: transparent; + } +} + +.img-retina(@image, @width, @height, @repeat: no-repeat) { + @filename : ~`/(.*)\.(jpg|jpeg|png|gif)/.exec(@{image})[1]`; + @extension : ~`/(.*)\.(jpg|jpeg|png|gif)/.exec(@{image})[2]`; + background-image: ~`"url(@{filename}.@{extension})"`; + background-repeat: @repeat; + + @media + only screen and (-webkit-min-device-pixel-ratio: 2), + only screen and ( min--moz-device-pixel-ratio: 2), + only screen and ( -o-min-device-pixel-ratio: 2/1), + only screen and ( min-device-pixel-ratio: 2), + only screen and ( min-resolution: 192dpi), + only screen and ( min-resolution: 2dppx) { + /* on retina, use image that's scaled by 2 */ + background-image: ~`"url(@{filename}@2x.@{extension})"`; + background-size: @width @height; + } +} + +// +// ------------------------- +.anti-alias() { + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; +} + +.open-light() { + font-family: @font-family-open-sans; + font-weight: 300; +} + +.open() { + font-family: @font-family-open-sans; + font-weight: 400; +} + +.open-sb() { + font-family: @font-family-open-sans; + font-weight: 600; +} + +.open-bold() { + font-family: @font-family-open-sans; + font-weight: 700; +} + +.bez-1-transition{ + .transition( all 300ms ease-in-out ); +} diff --git a/website/docs/source/stylesheets/hashicorp-shared/_project-utility.less b/website/docs/source/stylesheets/hashicorp-shared/_project-utility.less new file mode 100755 index 000000000..dac8b0e93 --- /dev/null +++ b/website/docs/source/stylesheets/hashicorp-shared/_project-utility.less @@ -0,0 +1,32 @@ +// +// Mixins Specific to project +// - make edits to mixins here +// -------------------------------------------------- + +// Variables +@project-logo-width: 231px; +@project-logo-height: 46px; +@project-logo-pad-left: 0px; +@project-link-color: #8d9ba8; + +// Mixins +.project-a-style{ + font-weight: 600; + font-size: 14px; + letter-spacing: 0; + text-transform: none; + color: @project-link-color; + .anti-alias(); + + &:hover{ + color: @black; + } +} + +.project-footer-a-style{ + line-height: 30px; + + &:hover{ + opacity: .5; + } +} diff --git a/website/docs/source/stylesheets/vagrantup.less b/website/docs/source/stylesheets/vagrantup.less index b30130124..bc9c07af3 100644 --- a/website/docs/source/stylesheets/vagrantup.less +++ b/website/docs/source/stylesheets/vagrantup.less @@ -8,9 +8,17 @@ v a g r a n t u p @import '_type'; @import '_mixins'; @import '_base'; -@import '_nav'; + +@import 'hashicorp-shared/_hashicorp-utility'; +@import 'hashicorp-shared/_project-utility'; +@import 'hashicorp-shared/_hashicorp-header'; +@import 'hashicorp-shared/_hashicorp-mobile-nav'; + +// @import '_nav'; +@import '_header'; @import '_components'; @import '_sidebar'; +@import '_mobile-nav'; @import '_pages'; @import '_footer'; @import '_media-queries'; diff --git a/website/www/Gemfile b/website/www/Gemfile index 074cfa13c..1d1b3a338 100644 --- a/website/www/Gemfile +++ b/website/www/Gemfile @@ -3,7 +3,7 @@ source 'https://rubygems.org' ruby "2.2.2" gem "builder", "~> 3.2.2" -gem "less", "~> 2.2.2" +gem "less", "~> 2.6.0" gem "middleman", "~> 3.1.5" gem "middleman-blog", "~> 3.3.0" gem "middleman-minify-html", "~> 3.1.1" diff --git a/website/www/Gemfile.lock b/website/www/Gemfile.lock index 946a40701..9f7cbd874 100644 --- a/website/www/Gemfile.lock +++ b/website/www/Gemfile.lock @@ -34,8 +34,8 @@ GEM hike (1.2.3) i18n (0.6.11) kramdown (1.9.0) - less (2.2.2) - commonjs (~> 0.2.6) + less (2.6.0) + commonjs (~> 0.2.7) libv8 (3.16.14.13) listen (1.3.1) rb-fsevent (>= 0.9.3) @@ -123,7 +123,7 @@ PLATFORMS DEPENDENCIES builder (~> 3.2.2) highline (~> 1.6.15) - less (~> 2.2.2) + less (~> 2.6.0) middleman (~> 3.1.5) middleman-blog (~> 3.3.0) middleman-minify-html (~> 3.1.1) @@ -133,3 +133,6 @@ DEPENDENCIES redcarpet (~> 3.0.0) therubyracer (~> 0.12.0) thin (~> 1.5.0) + +BUNDLED WITH + 1.10.6 diff --git a/website/www/source/images/logo-header.png b/website/www/source/images/logo-header.png new file mode 100644 index 000000000..a058de16f Binary files /dev/null and b/website/www/source/images/logo-header.png differ diff --git a/website/www/source/images/logo-header@2x.png b/website/www/source/images/logo-header@2x.png new file mode 100644 index 000000000..5ebdf1d10 Binary files /dev/null and b/website/www/source/images/logo-header@2x.png differ diff --git a/website/www/source/javascripts/Sidebar.js b/website/www/source/javascripts/Sidebar.js new file mode 100644 index 000000000..94f2cbdb6 --- /dev/null +++ b/website/www/source/javascripts/Sidebar.js @@ -0,0 +1,50 @@ +(function(){ + + Sidebar = Base.extend({ + + $body: null, + $overlay: null, + $sidebar: null, + $sidebarHeader: null, + $sidebarImg: null, + $toggleButton: null, + + constructor: function(){ + this.$body = $('body'); + this.$overlay = $('.mobile-nav-overlay'); + this.$sidebar = $('#mobile-nav'); + this.$sidebarHeader = $('#mobile-nav .mobile-nav-header'); + this.$toggleButton = $('.navbar-toggle'); + this.sidebarImg = this.$sidebarHeader.css('background-image'); + + this.addEventListeners(); + }, + + addEventListeners: function(){ + var _this = this; + + _this.$toggleButton.on('click', function() { + _this.$sidebar.toggleClass('open'); + if ((_this.$sidebar.hasClass('mobile-nav-fixed-left') || _this.$sidebar.hasClass('mobile-nav-fixed-right')) && _this.$sidebar.hasClass('open')) { + _this.$overlay.addClass('active'); + _this.$body.css('overflow', 'hidden'); + } else { + _this.$overlay.removeClass('active'); + _this.$body.css('overflow', 'auto'); + } + + return false; + }); + + _this.$overlay.on('click', function() { + $(this).removeClass('active'); + _this.$body.css('overflow', 'auto'); + _this.$sidebar.removeClass('open'); + }); + } + + }); + + window.Sidebar = Sidebar; + +})(); diff --git a/website/www/source/javascripts/lib/Base.js b/website/www/source/javascripts/lib/Base.js new file mode 100644 index 000000000..504e2beea --- /dev/null +++ b/website/www/source/javascripts/lib/Base.js @@ -0,0 +1,145 @@ +/* + Based on Base.js 1.1a (c) 2006-2010, Dean Edwards + Updated to pass JSHint and converted into a module by Kenneth Powers + License: http://www.opensource.org/licenses/mit-license.php +*/ +/*global define:true module:true*/ +/*jshint eqeqeq:true*/ +(function (name, global, definition) { + if (typeof module !== 'undefined') { + module.exports = definition(); + } else if (typeof define !== 'undefined' && typeof define.amd === 'object') { + define(definition); + } else { + global[name] = definition(); + } +})('Base', this, function () { + // Base Object + var Base = function () {}; + + // Implementation + Base.extend = function (_instance, _static) { // subclass + var extend = Base.prototype.extend; + // build the prototype + Base._prototyping = true; + var proto = new this(); + extend.call(proto, _instance); + proto.base = function () { + // call this method from any other method to invoke that method's ancestor + }; + delete Base._prototyping; + // create the wrapper for the constructor function + //var constructor = proto.constructor.valueOf(); //-dean + var constructor = proto.constructor; + var klass = proto.constructor = function () { + if (!Base._prototyping) { + if (this._constructing || this.constructor === klass) { // instantiation + this._constructing = true; + constructor.apply(this, arguments); + delete this._constructing; + } else if (arguments[0] !== null) { // casting + return (arguments[0].extend || extend).call(arguments[0], proto); + } + } + }; + // build the class interface + klass.ancestor = this; + klass.extend = this.extend; + klass.forEach = this.forEach; + klass.implement = this.implement; + klass.prototype = proto; + klass.toString = this.toString; + klass.valueOf = function (type) { + return (type === 'object') ? klass : constructor.valueOf(); + }; + extend.call(klass, _static); + // class initialization + if (typeof klass.init === 'function') klass.init(); + return klass; + }; + + Base.prototype = { + extend: function (source, value) { + if (arguments.length > 1) { // extending with a name/value pair + var ancestor = this[source]; + if (ancestor && (typeof value === 'function') && // overriding a method? + // the valueOf() comparison is to avoid circular references + (!ancestor.valueOf || ancestor.valueOf() !== value.valueOf()) && /\bbase\b/.test(value)) { + // get the underlying method + var method = value.valueOf(); + // override + value = function () { + var previous = this.base || Base.prototype.base; + this.base = ancestor; + var returnValue = method.apply(this, arguments); + this.base = previous; + return returnValue; + }; + // point to the underlying method + value.valueOf = function (type) { + return (type === 'object') ? value : method; + }; + value.toString = Base.toString; + } + this[source] = value; + } else if (source) { // extending with an object literal + var extend = Base.prototype.extend; + // if this object has a customized extend method then use it + if (!Base._prototyping && typeof this !== 'function') { + extend = this.extend || extend; + } + var proto = { + toSource: null + }; + // do the "toString" and other methods manually + var hidden = ['constructor', 'toString', 'valueOf']; + // if we are prototyping then include the constructor + for (var i = Base._prototyping ? 0 : 1; i < hidden.length; i++) { + var h = hidden[i]; + if (source[h] !== proto[h]) + extend.call(this, h, source[h]); + } + // copy each of the source object's properties to this object + for (var key in source) { + if (!proto[key]) extend.call(this, key, source[key]); + } + } + return this; + } + }; + + // initialize + Base = Base.extend({ + constructor: function () { + this.extend(arguments[0]); + } + }, { + ancestor: Object, + version: '1.1', + forEach: function (object, block, context) { + for (var key in object) { + if (this.prototype[key] === undefined) { + block.call(context, object[key], key, object); + } + } + }, + implement: function () { + for (var i = 0; i < arguments.length; i++) { + if (typeof arguments[i] === 'function') { + // if it's a function, call it + arguments[i](this.prototype); + } else { + // add the interface using the extend method + this.prototype.extend(arguments[i]); + } + } + return this; + }, + toString: function () { + return String(this.valueOf()); + } + }); + + // Return Base implementation + return Base; +}); diff --git a/website/www/source/javascripts/vagrantup.js b/website/www/source/javascripts/vagrantup.js index 563c932f8..7527c7746 100644 --- a/website/www/source/javascripts/vagrantup.js +++ b/website/www/source/javascripts/vagrantup.js @@ -1,58 +1,58 @@ // add dropshadow to nav on scroll $(document).ready(function(){ - $(document).scroll(function() { - var top = $(document).scrollTop(); - if (top > 0) $('nav').addClass("drop-shadow"); - if (top === 0) $('nav').removeClass("drop-shadow"); - }); + $(document).scroll(function() { + var top = $(document).scrollTop(); + if (top > 0) $('#header').addClass("drop-shadow"); + if (top === 0) $('header').removeClass("drop-shadow"); + }); }); // open/close documentation side nav on small screens $(document).ready(function(){ - $(".toggle").click(function() { - $(".sidebar-nav ul").slideToggle('slow'); - }); + $(".toggle").click(function() { + $(".sidebar-nav ul").slideToggle('slow'); + }); }); // Redirect to the proper checkout screen for quantity $(document).ready(function() { - var selectedProduct = ""; + var selectedProduct = ""; - function setSelectedProduct() { - selectedProduct = $("input[name=product]:checked").val(); + function setSelectedProduct() { + selectedProduct = $("input[name=product]:checked").val(); + } + + $(".buy-form input[name=product]").change(function() { + setSelectedProduct(); + + var text = selectedProduct.charAt(0).toUpperCase() + selectedProduct.slice(1); + $("#buy-fusion").text("Buy " + text + " Licenses Now"); + }); + + $("#buy-fusion").click(function() { + var seats = parseInt($("#seats").val(), 10); + if (isNaN(seats)) { + alert("The number of seats you want to purchase must be a number."); + return; + } else if (seats <= 0) { + alert("The number of seats you want must be greater than zero."); + return; } - $(".buy-form input[name=product]").change(function() { - setSelectedProduct(); - - var text = selectedProduct.charAt(0).toUpperCase() + selectedProduct.slice(1); - $("#buy-fusion").text("Buy " + text + " Licenses Now"); - }); - - $("#buy-fusion").click(function() { - var seats = parseInt($("#seats").val(), 10); - if (isNaN(seats)) { - alert("The number of seats you want to purchase must be a number."); - return; - } else if (seats <= 0) { - alert("The number of seats you want must be greater than zero."); - return; - } - - var productId = ""; - if (selectedProduct == "fusion") { - productId = "279661674"; - } else if (selectedProduct == "workstation") { - productId = "302167489"; - } else { - alert("Unknown product selected. Please refresh and try again."); - return; - } - - window.location = "http://shopify.hashicorp.com/cart/" + productId + ":" + seats; - }); - - if ($("#buy-fusion").length > 0) { - setSelectedProduct(); + var productId = ""; + if (selectedProduct == "fusion") { + productId = "279661674"; + } else if (selectedProduct == "workstation") { + productId = "302167489"; + } else { + alert("Unknown product selected. Please refresh and try again."); + return; } + + window.location = "http://shopify.hashicorp.com/cart/" + productId + ":" + seats; + }); + + if ($("#buy-fusion").length > 0) { + setSelectedProduct(); + } }); diff --git a/website/www/source/layouts/_mobile_nav.erb b/website/www/source/layouts/_mobile_nav.erb new file mode 100644 index 000000000..b96e98521 --- /dev/null +++ b/website/www/source/layouts/_mobile_nav.erb @@ -0,0 +1,23 @@ + +
+ + + diff --git a/website/www/source/layouts/layout.erb b/website/www/source/layouts/layout.erb index fa0029628..d11b85d2c 100644 --- a/website/www/source/layouts/layout.erb +++ b/website/www/source/layouts/layout.erb @@ -20,7 +20,7 @@ <%= javascript_include_tag "vagrantup" %> - + @@ -32,24 +32,40 @@
- - - + + <%= yield %> + <%= partial "layouts/mobile_nav" %> +