FEATURE: Scroll-based logo on mobile (#6632)
This commit is contained in:
parent
d984323e23
commit
ee6c0170ce
|
@ -12,6 +12,9 @@ function highlight(postNumber) {
|
|||
$contents.on("animationend", () => $contents.removeClass("highlighted"));
|
||||
}
|
||||
|
||||
// used to determine scroll direction on mobile
|
||||
let lastScroll, scrollDirection, delta;
|
||||
|
||||
export default Ember.Component.extend(AddArchetypeClass, Scrolling, {
|
||||
userFilters: Ember.computed.alias("topic.userFilters"),
|
||||
classNameBindings: [
|
||||
|
@ -94,6 +97,23 @@ export default Ember.Component.extend(AddArchetypeClass, Scrolling, {
|
|||
this.appEvents.trigger("header:hide-topic");
|
||||
}
|
||||
});
|
||||
// setup mobile scroll logo
|
||||
if (this.site.mobileView) {
|
||||
this.appEvents.on("topic:scrolled", offset =>
|
||||
this.mobileScrollGaurd(offset)
|
||||
);
|
||||
// used to animate header contents on scroll
|
||||
this.appEvents.on("header:show-topic", () => {
|
||||
$("header.d-header")
|
||||
.removeClass("scroll-up")
|
||||
.addClass("scroll-down");
|
||||
});
|
||||
this.appEvents.on("header:hide-topic", () => {
|
||||
$("header.d-header")
|
||||
.removeClass("scroll-down")
|
||||
.addClass("scroll-up");
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
willDestroyElement() {
|
||||
|
@ -109,6 +129,11 @@ export default Ember.Component.extend(AddArchetypeClass, Scrolling, {
|
|||
// this happens after route exit, stuff could have trickled in
|
||||
this.appEvents.trigger("header:hide-topic");
|
||||
this.appEvents.off("post:highlight");
|
||||
// mobile scroll logo clean up.
|
||||
if (this.site.mobileView) {
|
||||
this.appEvents.off("topic:scrolled");
|
||||
$("header.d-header").removeClass("scroll-down scroll-up");
|
||||
}
|
||||
},
|
||||
|
||||
@observes("Discourse.hasFocus")
|
||||
|
@ -123,9 +148,18 @@ export default Ember.Component.extend(AddArchetypeClass, Scrolling, {
|
|||
},
|
||||
|
||||
showTopicInHeader(topic, offset) {
|
||||
return offset > this.get("dockAt");
|
||||
// conditions for showing topic title in the header for mobile
|
||||
if (
|
||||
this.site.mobileView &&
|
||||
scrollDirection !== "up" &&
|
||||
offset > this.dockAt
|
||||
) {
|
||||
return true;
|
||||
// condition for desktops
|
||||
} else {
|
||||
return offset > this.dockAt;
|
||||
}
|
||||
},
|
||||
|
||||
// The user has scrolled the window, or it is finished rendering and ready for processing.
|
||||
scrolled() {
|
||||
if (this.isDestroyed || this.isDestroying || this._state !== "inDOM") {
|
||||
|
@ -161,5 +195,23 @@ export default Ember.Component.extend(AddArchetypeClass, Scrolling, {
|
|||
|
||||
// Trigger a scrolled event
|
||||
this.appEvents.trigger("topic:scrolled", offset);
|
||||
},
|
||||
|
||||
// determines scroll direction, triggers header topic info on mobile
|
||||
// and ensures that the switch happens only once per scroll direction change
|
||||
mobileScrollGaurd(offset) {
|
||||
// user hasn't scrolled past topic title.
|
||||
if (offset < this.dockAt) return;
|
||||
|
||||
delta = offset - lastScroll;
|
||||
// 3px buffer so that the switch doesn't happen with tiny scrolls
|
||||
if (delta > 3 && scrollDirection !== "down") {
|
||||
scrollDirection = "down";
|
||||
this.appEvents.trigger("header:show-topic", this.topic);
|
||||
} else if (delta < -3 && scrollDirection !== "up") {
|
||||
scrollDirection = "up";
|
||||
this.appEvents.trigger("header:hide-topic");
|
||||
}
|
||||
lastScroll = offset;
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { getOwner } from "discourse-common/lib/get-owner";
|
||||
import {
|
||||
default as computed,
|
||||
observes
|
||||
|
@ -154,15 +155,14 @@ export default Ember.Component.extend({
|
|||
const $wrapper = this.$();
|
||||
if (!$wrapper || $wrapper.length === 0) return;
|
||||
|
||||
const offset = window.pageYOffset || $("html").scrollTop();
|
||||
const progressHeight = this.site.mobileView
|
||||
? 0
|
||||
: $("#topic-progress").height();
|
||||
const maximumOffset = $("#topic-bottom").offset().top + progressHeight;
|
||||
const windowHeight = $(window).height();
|
||||
const composerHeight = $("#reply-control").height() || 0;
|
||||
const isDocked = offset >= maximumOffset - windowHeight + composerHeight;
|
||||
const bottom = $("body").height() - maximumOffset;
|
||||
const offset = window.pageYOffset || $("html").scrollTop(),
|
||||
progressHeight = this.site.mobileView ? 0 : $("#topic-progress").height(),
|
||||
maximumOffset = $("#topic-bottom").offset().top + progressHeight,
|
||||
windowHeight = $(window).height(),
|
||||
bodyHeight = $("body").height(),
|
||||
composerHeight = $("#reply-control").height() || 0,
|
||||
isDocked = offset >= maximumOffset - windowHeight + composerHeight,
|
||||
bottom = bodyHeight - maximumOffset;
|
||||
|
||||
if (composerHeight > 0) {
|
||||
$wrapper.css("bottom", isDocked ? bottom : composerHeight);
|
||||
|
@ -178,6 +178,23 @@ export default Ember.Component.extend({
|
|||
} else {
|
||||
$wrapper.css("right", "1em");
|
||||
}
|
||||
|
||||
// switch mobile scroll logo at the very bottom of topics
|
||||
const isIOS = this.capabilities.isIOS,
|
||||
switchHeight = bodyHeight - offset - windowHeight,
|
||||
appEvents = getOwner(this).lookup("app-events:main");
|
||||
|
||||
if (isIOS && switchHeight < -10) {
|
||||
// match elastic-scroll behaviour in iOS
|
||||
setTimeout(function() {
|
||||
appEvents.trigger("header:hide-topic");
|
||||
}, 300);
|
||||
} else if (!isIOS && switchHeight < 5) {
|
||||
// normal switch for everyone else
|
||||
setTimeout(function() {
|
||||
appEvents.trigger("header:hide-topic");
|
||||
}, 300);
|
||||
}
|
||||
},
|
||||
|
||||
click(e) {
|
||||
|
|
|
@ -5,9 +5,9 @@ createWidget("header-contents", {
|
|||
tagName: "div.contents.clearfix",
|
||||
template: hbs`
|
||||
{{attach widget="home-logo" attrs=attrs}}
|
||||
<div class="panel clearfix">{{yield}}</div>
|
||||
{{#if attrs.topic}}
|
||||
{{attach widget="header-topic-info" attrs=attrs}}
|
||||
{{/if}}
|
||||
<div class="panel clearfix">{{yield}}</div>
|
||||
`
|
||||
});
|
||||
|
|
|
@ -20,7 +20,7 @@ export default createWidget("header-topic-info", {
|
|||
if (href) {
|
||||
heading.push(
|
||||
h(
|
||||
"a",
|
||||
"a.private-message-glyph-wrapper",
|
||||
{ attributes: { href } },
|
||||
h("span.private-message-glyph", iconNode("envelope"))
|
||||
)
|
||||
|
@ -47,6 +47,7 @@ export default createWidget("header-topic-info", {
|
|||
|
||||
const title = [h("h1", heading)];
|
||||
const category = topic.get("category");
|
||||
|
||||
if (loaded || category) {
|
||||
if (
|
||||
category &&
|
||||
|
@ -54,12 +55,15 @@ export default createWidget("header-topic-info", {
|
|||
!this.siteSettings.suppress_uncategorized_badge)
|
||||
) {
|
||||
const parentCategory = category.get("parentCategory");
|
||||
const categories = [];
|
||||
if (parentCategory) {
|
||||
title.push(
|
||||
categories.push(
|
||||
this.attach("category-link", { category: parentCategory })
|
||||
);
|
||||
}
|
||||
title.push(this.attach("category-link", { category }));
|
||||
categories.push(this.attach("category-link", { category }));
|
||||
|
||||
title.push(h("div.categories-wrapper", categories));
|
||||
}
|
||||
|
||||
let extra = [];
|
||||
|
|
|
@ -26,15 +26,15 @@ export default createWidget("home-logo", {
|
|||
const logoUrl = siteSettings.site_logo_url || "";
|
||||
const title = siteSettings.title;
|
||||
|
||||
if (!mobileView && this.attrs.minimized) {
|
||||
if (this.attrs.minimized) {
|
||||
const logoSmallUrl = siteSettings.site_logo_small_url || "";
|
||||
if (logoSmallUrl.length) {
|
||||
return h("img#site-logo.logo-small", {
|
||||
key: "logo-small",
|
||||
attributes: {
|
||||
src: Discourse.getURL(logoSmallUrl),
|
||||
width: 33,
|
||||
height: 33,
|
||||
width: 36,
|
||||
height: 36,
|
||||
alt: title
|
||||
}
|
||||
});
|
||||
|
@ -49,7 +49,7 @@ export default createWidget("home-logo", {
|
|||
} else if (logoUrl.length) {
|
||||
return h("img#site-logo.logo-big", {
|
||||
key: "logo-big",
|
||||
attributes: { src: Discourse.getURL(logoUrl), alt: title }
|
||||
attributes: { src: Discourse.getURL(logoUrl), height: 36, alt: title }
|
||||
});
|
||||
} else {
|
||||
return h("h1#site-text-logo.text-logo", { key: "logo-text" }, title);
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
.d-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
|
@ -6,35 +8,46 @@
|
|||
background-color: $header_background;
|
||||
box-shadow: shadow("header");
|
||||
|
||||
> .wrap {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
.contents {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.docked & {
|
||||
position: fixed;
|
||||
backface-visibility: hidden; /** do magic for scrolling performance **/
|
||||
}
|
||||
|
||||
.contents {
|
||||
margin: 8px 0;
|
||||
}
|
||||
|
||||
.title {
|
||||
float: left;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
a,
|
||||
a:visited {
|
||||
color: $header_primary;
|
||||
}
|
||||
}
|
||||
|
||||
// the logo height is set in the home-logo widget. This ensures we get a scaled
|
||||
// width that respects the aspect ratio of the image
|
||||
#site-logo {
|
||||
max-height: 2.8571em;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.d-icon-home {
|
||||
font-size: 1.643em;
|
||||
font-size: $font-up-5;
|
||||
}
|
||||
|
||||
.panel {
|
||||
float: right;
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex: 0 0 auto;
|
||||
margin-left: auto;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
|
@ -195,3 +208,88 @@
|
|||
#search-term::-ms-clear {
|
||||
display: none;
|
||||
}
|
||||
|
||||
// topic info in the header
|
||||
.extra-info-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex: 1 1 0%; // unit on flex-basis is required for IE11
|
||||
height: 100%;
|
||||
line-height: $line-height-medium;
|
||||
padding: 0 1.5em 0 0.5em;
|
||||
// we need to hide overflow in both to truncate the title in a flexbox
|
||||
overflow: hidden;
|
||||
.extra-info {
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
-webkit-animation: fadein 0.5s;
|
||||
animation: fadein 0.5s;
|
||||
}
|
||||
.topic-link {
|
||||
color: $header_primary;
|
||||
display: block;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
.topic-statuses {
|
||||
margin-top: -2px;
|
||||
float: left;
|
||||
padding: 0;
|
||||
i {
|
||||
color: $header_primary;
|
||||
}
|
||||
.d-icon-envelope {
|
||||
color: $danger;
|
||||
}
|
||||
.d-icon-lock {
|
||||
padding-top: 0.15em;
|
||||
}
|
||||
.unpinned {
|
||||
color: $header_primary;
|
||||
}
|
||||
}
|
||||
h1 {
|
||||
margin: 0 0 0.25em 0;
|
||||
font-size: $font-up-3;
|
||||
width: 100%;
|
||||
}
|
||||
.categories-wrapper {
|
||||
display: inline-flex;
|
||||
max-width: 100%;
|
||||
// only truncate the last category name.
|
||||
> a:last-of-type {
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
}
|
||||
.badge-wrapper {
|
||||
margin-right: 8px;
|
||||
}
|
||||
.badge-wrapper.bullet {
|
||||
.badge-category-parent-bg,
|
||||
.badge-category-bg {
|
||||
min-width: 5px;
|
||||
}
|
||||
}
|
||||
.topic-header-extra {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
max-width: 100%;
|
||||
flex: 1 0 0%; // unit on flex-basis is required for IE11
|
||||
.discourse-tags {
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
.discourse-tag {
|
||||
display: inline;
|
||||
}
|
||||
}
|
||||
}
|
||||
// if a topic has both categories and tags, the tag container should shrink
|
||||
// instead of wrapping to the next line.
|
||||
.categories-wrapper + .topic-header-extra {
|
||||
min-width: 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,19 +37,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
.topic-header-extra .discourse-tag {
|
||||
-webkit-animation: fadein 0.7s;
|
||||
animation: fadein 0.7s;
|
||||
}
|
||||
|
||||
.bullet + .topic-header-extra {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.box + .topic-header-extra {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.topic-category {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
|
|
@ -60,8 +60,6 @@
|
|||
.title-wrapper {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
width: 90%;
|
||||
align-items: flex-end;
|
||||
.btn-small {
|
||||
margin: 0 6px 0 0;
|
||||
}
|
||||
|
@ -151,12 +149,6 @@ a.badge-category {
|
|||
clear: both;
|
||||
}
|
||||
|
||||
.extra-info-wrapper {
|
||||
.badge-wrapper {
|
||||
float: left;
|
||||
}
|
||||
}
|
||||
|
||||
.has-pending-posts {
|
||||
padding: 0.5em;
|
||||
background-color: $highlight-medium;
|
||||
|
|
|
@ -8,10 +8,6 @@ body.widget-dragging {
|
|||
cursor: ns-resize;
|
||||
}
|
||||
|
||||
header {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
// Common classes
|
||||
.boxed {
|
||||
height: 100%;
|
||||
|
|
|
@ -4,16 +4,21 @@
|
|||
|
||||
.d-header {
|
||||
left: 0;
|
||||
padding-top: 3px;
|
||||
height: 4.2857em;
|
||||
.d-icon-home {
|
||||
padding: 8px;
|
||||
font-size: $font-up-5;
|
||||
}
|
||||
height: 4.2858em;
|
||||
margin-bottom: 15px;
|
||||
|
||||
.site-text-logo {
|
||||
position: relative;
|
||||
top: 10px;
|
||||
#site-text-logo {
|
||||
font-size: $font-up-3;
|
||||
margin: 0;
|
||||
}
|
||||
.extra-info {
|
||||
// header title should not be centered if there's no tags / categories
|
||||
&:not(.two-rows) {
|
||||
min-height: 2.75em;
|
||||
}
|
||||
h1 {
|
||||
margin: 0 0 0.125em 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -41,11 +46,3 @@
|
|||
color: dark-light-choose($primary-high, $secondary-low);
|
||||
}
|
||||
}
|
||||
|
||||
header {
|
||||
#site-text-logo {
|
||||
font-size: $font-up-3;
|
||||
margin-top: 0.4em;
|
||||
line-height: $line-height-medium;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,14 +11,6 @@ h1 .topic-statuses .topic-status i {
|
|||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.logo-small {
|
||||
margin-right: 8px;
|
||||
width: auto;
|
||||
max-width: 80px;
|
||||
height: auto;
|
||||
max-height: 40px;
|
||||
}
|
||||
|
||||
.topic-body {
|
||||
padding: 0;
|
||||
&:first-of-type {
|
||||
|
@ -506,64 +498,6 @@ video {
|
|||
}
|
||||
}
|
||||
|
||||
.extra-info-wrapper {
|
||||
overflow: hidden;
|
||||
.badge-wrapper,
|
||||
i,
|
||||
.topic-link {
|
||||
-webkit-animation: fadein 0.7s;
|
||||
animation: fadein 0.7s;
|
||||
}
|
||||
.topic-statuses {
|
||||
i {
|
||||
color: $header_primary;
|
||||
}
|
||||
.d-icon-envelope {
|
||||
color: $danger;
|
||||
}
|
||||
.d-icon-lock {
|
||||
padding-top: 0.15em;
|
||||
}
|
||||
.unpinned {
|
||||
color: $header_primary;
|
||||
}
|
||||
}
|
||||
.topic-link {
|
||||
color: $header_primary;
|
||||
display: block;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
.topic-header-extra {
|
||||
margin: 0 0 0 5px;
|
||||
}
|
||||
}
|
||||
|
||||
/* default docked header CSS for all topics, including those without categories */
|
||||
|
||||
.extra-info {
|
||||
h1 {
|
||||
margin: 5px 0 0 0;
|
||||
font-size: $font-up-3;
|
||||
line-height: $line-height-large;
|
||||
width: 100%;
|
||||
}
|
||||
.topic-statuses {
|
||||
margin-top: -2px;
|
||||
}
|
||||
}
|
||||
|
||||
/* override docked header CSS for topics with categories */
|
||||
|
||||
.extra-info.two-rows {
|
||||
h1 {
|
||||
line-height: $line-height-medium;
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.open > .dropdown-menu {
|
||||
display: block;
|
||||
}
|
||||
|
|
|
@ -149,9 +149,3 @@ blockquote {
|
|||
#simple-container {
|
||||
width: 90%;
|
||||
}
|
||||
|
||||
// somehow the image logo assumption inherits margins from earlier in the CSS
|
||||
// stack we must remove margins for text site titles
|
||||
h1#site-text-logo {
|
||||
margin: 0 0 0 10px;
|
||||
}
|
||||
|
|
|
@ -2,37 +2,50 @@
|
|||
// Discourse header
|
||||
// --------------------------------------------------
|
||||
|
||||
#site-text-logo {
|
||||
font-size: $font-up-3;
|
||||
}
|
||||
@include breakpoint(mobile-small) {
|
||||
#site-text-logo {
|
||||
font-size: $font-up-2;
|
||||
}
|
||||
}
|
||||
|
||||
.d-header {
|
||||
#site-logo {
|
||||
max-width: 8.8em;
|
||||
}
|
||||
height: 3.66em;
|
||||
|
||||
// some protection for text-only site titles
|
||||
.title {
|
||||
max-width: 50%;
|
||||
height: 39px;
|
||||
max-width: 75%;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
padding: 0;
|
||||
text-overflow: clip;
|
||||
display: table;
|
||||
text-overflow: ellipsis;
|
||||
-webkit-animation: fadein 0.5s;
|
||||
animation: fadein 0.5s;
|
||||
a {
|
||||
display: table-cell;
|
||||
vertical-align: middle;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
#site-text-logo {
|
||||
margin: 0;
|
||||
font-size: $font-up-1;
|
||||
}
|
||||
.extra-info-wrapper {
|
||||
.extra-info {
|
||||
// header title should not be centered if there's no tags / categories
|
||||
&:not(.two-rows) {
|
||||
min-height: 2.25em;
|
||||
}
|
||||
h1 {
|
||||
font-size: $font-0;
|
||||
}
|
||||
.private-message-glyph-wrapper {
|
||||
float: left;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
button.sign-up-button {
|
||||
display: none;
|
||||
}
|
||||
// styles for mobile scroll logo / topic
|
||||
.panel {
|
||||
-webkit-animation: fadein 0.5s;
|
||||
animation: fadein 0.5s;
|
||||
}
|
||||
&.scroll-down .panel {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.d-header-icons {
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
/* hide the reply border above the time gap notices */
|
||||
|
||||
.time-gap + .topic-post article {
|
||||
border-top: none;
|
||||
}
|
||||
|
@ -319,10 +318,6 @@ iframe {
|
|||
max-width: 100%;
|
||||
}
|
||||
|
||||
.extra-info {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.open > .dropdown-menu {
|
||||
display: block;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue