diff --git a/CHANGELOG.md b/CHANGELOG.md index 548a42291f..9280fdc1b9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,7 @@ ## 3/21/2013 + * More design tweaks to header & avatars: https://github.com/lefnire/habitrpg/issues/585 + +## 3/20/2013 * New Design: https://github.com/lefnire/habitrpg/issues/585 * Toggle helm visible: https://trello.com/card/toggle-helm-visible/50e5d3684fe3a7266b0036d6/153 * Toggle Header: https://trello.com/card/toggle-header/50e5d3684fe3a7266b0036d6/241 diff --git a/public/sticky.js b/public/sticky.js new file mode 100644 index 0000000000..8e9fa66045 --- /dev/null +++ b/public/sticky.js @@ -0,0 +1,129 @@ +// Sticky Plugin v1.0.0 for jQuery +// ============= +// Author: Anthony Garand +// Improvements by German M. Bravo (Kronuz) and Ruud Kamphuis (ruudk) +// Improvements by Leonardo C. Daronco (daronco) +// Created: 2/14/2011 +// Date: 2/12/2012 +// Website: http://labs.anthonygarand.com/sticky +// Description: Makes an element on the page stick on the screen as you scroll +// It will only set the 'top' and 'position' of your element, you +// might need to adjust the width in some cases. + +(function($) { + var defaults = { + topSpacing: 0, + bottomSpacing: 0, + className: 'is-sticky', + wrapperClassName: 'sticky-wrapper', + center: false, + getWidthFrom: '' + }, + $window = $(window), + $document = $(document), + sticked = [], + windowHeight = $window.height(), + scroller = function() { + var scrollTop = $window.scrollTop(), + documentHeight = $document.height(), + dwh = documentHeight - windowHeight, + extra = (scrollTop > dwh) ? dwh - scrollTop : 0; + + for (var i = 0; i < sticked.length; i++) { + var s = sticked[i], + elementTop = s.stickyWrapper.offset().top, + etse = elementTop - s.topSpacing - extra; + + if (scrollTop <= etse) { + if (s.currentTop !== null) { + s.stickyElement + .css('position', '') + .css('top', ''); + s.stickyElement.parent().removeClass(s.className); + s.currentTop = null; + } + } + else { + var newTop = documentHeight - s.stickyElement.outerHeight() + - s.topSpacing - s.bottomSpacing - scrollTop - extra; + if (newTop < 0) { + newTop = newTop + s.topSpacing; + } else { + newTop = s.topSpacing; + } + if (s.currentTop != newTop) { + s.stickyElement + .css('position', 'fixed') + .css('top', newTop); + + if (typeof s.getWidthFrom !== 'undefined') { + s.stickyElement.css('width', $(s.getWidthFrom).width()); + } + + s.stickyElement.parent().addClass(s.className); + s.currentTop = newTop; + } + } + } + }, + resizer = function() { + windowHeight = $window.height(); + }, + methods = { + init: function(options) { + var o = $.extend(defaults, options); + return this.each(function() { + var stickyElement = $(this); + + stickyId = stickyElement.attr('id'); + wrapper = $('
') + .attr('id', stickyId + '-sticky-wrapper') + .addClass(o.wrapperClassName); + stickyElement.wrapAll(wrapper); + + if (o.center) { + stickyElement.parent().css({width:stickyElement.outerWidth(),marginLeft:"auto",marginRight:"auto"}); + } + + if (stickyElement.css("float") == "right") { + stickyElement.css({"float":"none"}).parent().css({"float":"right"}); + } + + var stickyWrapper = stickyElement.parent(); + stickyWrapper.css('height', stickyElement.outerHeight()); + sticked.push({ + topSpacing: o.topSpacing, + bottomSpacing: o.bottomSpacing, + stickyElement: stickyElement, + currentTop: null, + stickyWrapper: stickyWrapper, + className: o.className, + getWidthFrom: o.getWidthFrom + }); + }); + }, + update: scroller + }; + + // should be more efficient than using $window.scroll(scroller) and $window.resize(resizer): + if (window.addEventListener) { + window.addEventListener('scroll', scroller, false); + window.addEventListener('resize', resizer, false); + } else if (window.attachEvent) { + window.attachEvent('onscroll', scroller); + window.attachEvent('onresize', resizer); + } + + $.fn.sticky = function(method) { + if (methods[method]) { + return methods[method].apply(this, Array.prototype.slice.call(arguments, 1)); + } else if (typeof method === 'object' || !method ) { + return methods.init.apply( this, arguments ); + } else { + $.error('Method ' + method + ' does not exist on jQuery.sticky'); + } + }; + $(function() { + setTimeout(scroller, 0); + }); +})(jQuery); \ No newline at end of file diff --git a/src/app/browser.coffee b/src/app/browser.coffee index 6042821d90..a097bb8035 100644 --- a/src/app/browser.coffee +++ b/src/app/browser.coffee @@ -20,6 +20,7 @@ loadJavaScripts = (model) -> require '../../public/vendor/jquery-ui/ui/jquery.ui.widget' require '../../public/vendor/jquery-ui/ui/jquery.ui.mouse' require '../../public/vendor/jquery-ui/ui/jquery.ui.sortable' + require '../../public/sticky.js' require '../../public/vendor/bootstrap-tour/bootstrap-tour' @@ -120,6 +121,11 @@ setupTour = (model) -> tour._current = 0 if isNaN(tour._current) #bootstrap-tour bug tour.start() + +# jquery sticky header on scroll, no need for position fixed +initStickyHeader = (model) -> + $('.header-wrap').sticky({topSpacing:0}) + ### Sets up "+1 Exp", "Level Up", etc notifications ### @@ -192,6 +198,7 @@ module.exports.app = (appExports, model, app) -> setupSortable(model) setupTooltips(model) setupTour(model) + initStickyHeader(model) unless model.get('_view.mobileDevice') $('.datepicker').datepicker({autoclose:true, todayBtn:true}) .on 'changeDate', (ev) -> #for some reason selecting a date doesn't fire a change event on the field, meaning our changes aren't saved diff --git a/src/app/helpers.coffee b/src/app/helpers.coffee index 363f0b7ada..88230466ce 100644 --- a/src/app/helpers.coffee +++ b/src/app/helpers.coffee @@ -42,4 +42,6 @@ module.exports.viewHelpers = (view) -> view.fn "and", -> _.reduce arguments, (cumm, curr) -> cumm && curr view.fn "or", -> _.reduce arguments, (cumm, curr) -> cumm || curr + view.fn "truarr", (num) -> + return num-1 diff --git a/styles/app/avatar.styl b/styles/app/avatar.styl index 369f0483c4..91e4260aab 100644 --- a/styles/app/avatar.styl +++ b/styles/app/avatar.styl @@ -1,23 +1,86 @@ -// basic avatar sprite group -.avatar - cursor: pointer - position: relative - width: 90px - height: 90px +/* herobox & avatar +====================== +* this is the canonical `herobox` avatar component +* it can be placed anywhere on the site and look the +* way it's supposed to. TODO: add variables for show/ +* or hiding user metadata in different situations - .character-sprites - position: absolute +Seeing as the sprites might change drastically in the +future re: pets and whatnot, this is just temporary. +---------------------------------------------------- */ - .lvl - position: absolute - bottom: 0px - right: 10px +// basic herobox styles +.herobox + height: 10.5em // higher to acct for the name area + width: 10em + max-width: 10em + margin: 0 // need this b/c of bootstrap, remove or reset later + padding: 0 // push down the sprite + position: relative + cursor: pointer + background: #f5f5f5 + transition: padding 0.13s ease-out, border 0.25s ease-out, background 0.25s ease-out + outline: 1px solid rgba(0,0,0,0.1) -// main and party avatars -.main-avatar, .party-avatar - .character-sprites - top: -15px +// the hero's info frame +.herobox:after + content: attr(data-name) " – " "lvl " attr(data-level) // " " attr(data-class) + position: absolute + top: 0 + display: block + width: 100% + line-height: 2 + color: black + text-align: center + border-bottom: 1px solid rgba(0,0,0,0.1) + background: darken($good, 15%) + transition: opacity 0.2s ease-out + +// info revealed on hover/focus for party +// always visible on the user's own avatar +.herobox:after + opacity: 0 +.herobox[data-checkuser="isUser"]:after + opacity: 1 + // make it a bit special + background darken($better, 15%) + +// vertically center avatar sprite +// depending on if they have a pet +.herobox[data-checkpet="hasPet"] + padding-top: 2em +.herobox:not([data-checkpet="hasPet"]) + padding-top: 1.75em + +// if it is the user's avatar, check if +// they have a pet and pad accordingly +.herobox[data-checkpet="hasPet"][data-checkuser="isUser"] + padding-top: 3.25em + +// if not user's avatar, remove lines for party unity +.herobox:not([data-checkuser="isUser"]) + outline: 0 + +// expose hero info on hover, taking +// into account the extra pet space +.herobox:hover, .herobox:focus + background: desaturate(lighten($better, 30%), 10%) + &:after + opacity: 1 +.herobox[data-checkpet="hasPet"] + &:hover, &:focus + padding-top: 3.25em +.herobox:not([data-checkpet="hasPet"]) + &:hover, &:focus + padding-top: 2.5em -.character-sprites span - position: absolute \ No newline at end of file +// positioning the sprites, etc +.herobox + .character-sprites + width: 6.428571429em // 90px + height: 6.428571429em + margin: 0 auto + + .character-sprites span, .pet + position: absolute \ No newline at end of file diff --git a/styles/app/color-vars.styl b/styles/app/color-vars.styl new file mode 100644 index 0000000000..2b2250be6f --- /dev/null +++ b/styles/app/color-vars.styl @@ -0,0 +1,9 @@ +// color variables +$worst = rgb(230, 184, 175) +$worse = rgb(244, 204, 204) +$bad = rgb(252, 229, 205) +$neutral = rgb(255, 242, 204) +$good = rgb(217, 234, 211) +$better = rgb(208, 224, 227) +$best = rgb(201, 218, 248) +$completed = rgb(217, 217, 217) \ No newline at end of file diff --git a/styles/app/customizer.styl b/styles/app/customizer.styl index 6e881355d4..7cbbdf3360 100644 --- a/styles/app/customizer.styl +++ b/styles/app/customizer.styl @@ -1,17 +1,8 @@ // $customizations-modal layout .avatar-window - margin: 0 - border: 1px solid darkgrey; - width: 107px; float: right; - - .char-name - margin-top: 6px; - border-top: 1px solid darkgrey; - text-align: center - line-height: 2 - + margin: 0 1em 0 0 menu padding: 0; diff --git a/styles/app/header.styl b/styles/app/header.styl new file mode 100644 index 0000000000..18a3f13cc2 --- /dev/null +++ b/styles/app/header.styl @@ -0,0 +1,151 @@ +/* header wrapper +-------------------- */ +.header-wrap + width: 100% // this is for the sticky + padding: 0 + z-index: 1 + background: #f5f5f5 + border-bottom: 1px solid rgba(0,0,0,0.2) + // margin-top: -1px + overflow: hidden + +/* login/menu buttons +--------------------- */ +.user-menu + position: absolute + top: 0.5em + right: 0.5em + font-size: 0.85em + .tile + cursor: pointer + font-weight: 400 + color: #494949 + color: hsla(0, 0%, 15%, 0.8) + background-color: darken($better, 5%) + &:hover, &:focus + background-color: darken($good, 15%) + &:active + background-color: darken($good, 25%) + +.user-reporter:after + content: '▾' + float: right + + +/* flyout navigation pattern +----------------------------- */ +.stacked > li + display:list-item + > a + display:block + +.flyout, .flyout-alt + position: relative +.flyout-content + position: absolute + top: 100% + right: -99999px + height: 0 + overflow: hidden +.flyout:hover > .flyout-content + right: 0 +.flyout-alt:hover > .flyout-content + top: 0 + right: 100% + +.flyout:hover > .flyout-content, +.flyout-alt:hover > .flyout-content + height: auto + overflow: visible + +.flyout .tile { + min-width: 5em; +} +.stacked .tile { + outline: 0 + border: 1px solid rgba(0,0,0,0.2) + border-top: 0 +} + + +/* header layout +-------------------- */ +.site-header + display: table + height: 10.5em + +@media (min-width: 42.5em) + .site-header + width: 75% +@media (min-width: 60em) + .site-header + // margin: 0 auto + width: 66% +@media (min-width: 70em) + .site-header + width: 70% + + +// this is a wrapper for avatars in the header +// inside this is the actual `herobox` module +// that can be used anywhere on the site +.herobox-wrap + display: table-cell + vertical-align: middle + width: 10em + height: 10.5em + +/* progress bars +-------------------- */ +.hero-stats + padding: 0 1.25em + margin: 0 + display: table-cell + vertical-align: middle + + .meter, .bar + box-shadow: none + border-radius: 0 + + .meter + position: relative + background: white + opacity: 1 + outline: 1px solid rgba(0,0,0,0.2) + outline-offset: -1px + overflow: hidden // firefox outline fix + height: 2.25em + margin: 0 0 1em + cursor: help; + color: #111 + &:last-of-type + margin-bottom: 0 + &:after + content: attr(title) + position: absolute + left: -1em + top 0.4em + font-weight: 400 + z-index: -1 + transition: all 0.25s ease-out + + .bar + border: 1px solid rgba(0,0,0,0.1) + height: 100% + transition: width 0.25s ease-out + + .meter:hover:after + left: 1em + z-index: 1 + + .health .bar + background: darken($worse, 38%) + .experience .bar + background: darken($neutral, 30%) + + .meter-text + position: absolute + top: 0 + right: 0.5em + z-index: 1 + line-height: 2.25 \ No newline at end of file diff --git a/styles/app/index.styl b/styles/app/index.styl index 66ab88d827..008f8a3f29 100644 --- a/styles/app/index.styl +++ b/styles/app/index.styl @@ -9,6 +9,7 @@ @import "./alerts.styl"; @import "./helpers.styl"; @import "./responsive.styl"; +@import "./header.styl"; @import "./scrollbars.styl"; @@ -25,90 +26,15 @@ html,body,p,h1,ul,li,table,tr,th,td -moz-box-sizing: border-box box-sizing: border-box +* { font-family: "Lato", sans-serif } + hr border-top: 0 border-bottom: 1px solid #ddd border-color: rgba(0,0,0,0.1) -/* Header --------------------------------------------------- */ -#head - background: #ddd - background: -webkit-gradient(linear,0 0,0 100%,from(#e7e7e7),to(#d0d0d0)) - background: -moz-linear-gradient(#e7e7e7, #d0d0d0) - background: -ms-linear-gradient(#e7e7e7, #d0d0d0) - background: -o-linear-gradient(#e7e7e7, #d0d0d0) - background: linear-gradient(#e7e7e7, #d0d0d0) - -webkit-box-shadow: inset 0 1px #f7f7f7, 0 1px #888, 0 2px #e7e7e7 - -moz-box-shadow: inset 0 1px #f7f7f7, 0 1px #888, 0 2px #e7e7e7 - box-shadow: inset 0 1px #f7f7f7, 0 1px #888, 0 2px #e7e7e7 - padding: 12px 16px - white-space: nowrap - position:fixed - width: 100% - box-sizing: border-box - z-index: 1000 - -@media (max-width: 600px) { - #head { - position: static; - } -} - -#head .pull-right - margin-right: 0 - margin-left: 1% - -.modal - whitespace:normal - -.dropdown-menu - right: 0 - left: auto - -.char-status - // border: 1px dotted grey - -.main-avatar-wrap - margin: 0 5px 0 0 - float: left - -.party-avatar-wrap - margin: 0 - float: right - -.progress-bars - padding-top: 15px - -.progress - position: relative - height: 25px -.bar - height: 25px - border: 1px solid black -.progress-text - position: absolute - right: 5px - top: 3px - color: black - -@media (max-width: 600px) { - .char-status { - padding-top: 30px - } - .main-avatar-wrap { - border-right: 1px solid grey; - padding-right: 20px - } - .party-avatar-wrap { - float: left; - } - .progress-bars { - clear: both - } -} /* Footer -------------------------------------------------- */ @@ -132,10 +58,11 @@ hr } /* Customizations to make footer sticky */ -/*html, body {height: 100%;}*/ -#wrap {min-height: 100%; margin-top:130px; z-index:-1} -#main - /*overflow:auto;*/ +/*html, body {height: 100%;}*/ +#wrap + min-height: 100% + z-index:-1 +#main padding-bottom: 250px; /* don't know why this works, sticky footers are weird */ @media (max-width: 600px) { @@ -189,6 +116,9 @@ hr /* Misc -------------------------------------------------- */ +.modal + whitespace: normal + .notification-character float:left @@ -205,4 +135,4 @@ hr position: fixed; top: 0; right: 0px; - z-index: 1001; \ No newline at end of file + z-index: 1001; diff --git a/styles/app/items.styl b/styles/app/items.styl index b90d2ea53a..dc8700d359 100644 --- a/styles/app/items.styl +++ b/styles/app/items.styl @@ -42,6 +42,7 @@ background-color: $bad .item-img + float: left display: inline-block vertical-align: top // background-color: $bad diff --git a/styles/app/tasks.styl b/styles/app/tasks.styl index 2e1d445c23..cd15eea245 100644 --- a/styles/app/tasks.styl +++ b/styles/app/tasks.styl @@ -2,14 +2,7 @@ // ======================== // color variables -$worst = rgb(230, 184, 175) -$worse = rgb(244, 204, 204) -$bad = rgb(252, 229, 205) -$neutral = rgb(255, 242, 204) -$good = rgb(217, 234, 211) -$better = rgb(208, 224, 227) -$best = rgb(201, 218, 248) -$completed = rgb(217, 217, 217) +@import "./color-vars.styl"; // array of keywords and their associated color vars $stages = (worst $worst) (worse $worse) (bad $bad) (neutral $neutral) (good $good) (better $better) (best $best) @@ -96,13 +89,10 @@ for $stage in $stages border: 0 border-radius: 0 //required to nuke BB-playbook user agent styles background-color: darken($best, 15%) - &:hover, - &:focus - // opacity: 1 + &:hover, &:focus background-color: darken($best, 20%) &:active background-color: darken($best, 30%) - // opacity: 1 // an individual task entry @@ -124,7 +114,8 @@ for $stage in $stages // task content .task-text - display: inline + padding: 0.75em 0 + line-height: 1.4 // when a task is being dragged .task.ui-sortable-helper { @@ -136,7 +127,8 @@ for $stage in $stages // primary task commands // ---------------------- .task-controls - display: inline + display: inline-block + float: left margin-left: -0.5em margin-right: 0.5em @@ -201,7 +193,6 @@ for $stage in $stages position: relative // uncompleted icon label:after, label:before - // content: '◯' content: '' display: block height: 1.714285714em @@ -213,7 +204,7 @@ for $stage in $stages opacity: 0.2 label:after - content: '▨' + content: '' label:before position: absolute left: 0 @@ -260,6 +251,8 @@ for $stage in $stages .task:hover .task-meta-controls opacity: 1 +.popover + line-height: 1.5 // task editing // ------------ @@ -314,6 +307,14 @@ for $stage in $stages vertical-align: 20% padding-left: 0.25em +.option-medium + .option-content + width: 6em + display: inline-block + .input-suffix + vertical-align: 20% + padding-left: 0.25em + // button-group .task-controls.tile-group display: block @@ -335,6 +336,8 @@ for $stage in $stages &.active opacity: 1 +.tile.solid + opacity: 1 .tile.spacious margin: 0.75em 0 font-size: 1.5em diff --git a/styles/base.styl b/styles/base.styl index f5e0233db5..c3f33b8642 100644 --- a/styles/base.styl +++ b/styles/base.styl @@ -3,6 +3,9 @@ body { padding: 2em; + // I am getting really frustrated that I can't override base bootstrap styles :( + // is there a fix? + font-family: 'Lato', sans-serif !important; // remember to remove !important once shenanigans solved } h1 { font-size: 2em; diff --git a/styles/reset.styl b/styles/reset.styl index 8f42218c28..0bb961d75a 100644 --- a/styles/reset.styl +++ b/styles/reset.styl @@ -1,6 +1,3 @@ -body,h1,h2,h3,h4,th { - font: 13px/normal Arial,sans-serif; -} body { background: #fff; color: #000; diff --git a/views/app/avatar.html b/views/app/avatar.html index 2723368c90..024e6eda27 100644 --- a/views/app/avatar.html +++ b/views/app/avatar.html @@ -22,37 +22,44 @@HabitRPG is quite Beta-quality at present, and many find they need to restore character attributes as a result. Enter your numbers here and it will be applied automatically to your character. This will be removed once Habit is more stable.
{#with _user} -