REFACTOR: Remove position fixed from the header and use sticky instead (#10781)
This removes fixed positioning from d-header and the topic timeline. Plugins, themes and components that use the above/below header plugin outlet will likely need some margin/padding adjustments.
This commit is contained in:
parent
a74805d3f8
commit
da5841de0b
|
@ -373,7 +373,9 @@ const SiteHeaderComponent = MountWidget.extend(Docking, PanEvents, {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export default SiteHeaderComponent;
|
export default SiteHeaderComponent.extend({
|
||||||
|
classNames: ["d-header-wrap"],
|
||||||
|
});
|
||||||
|
|
||||||
export function headerHeight() {
|
export function headerHeight() {
|
||||||
const $header = $("header.d-header");
|
const $header = $("header.d-header");
|
||||||
|
|
|
@ -3,31 +3,29 @@ export function scrollTopFor(y) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function minimumOffset() {
|
export function minimumOffset() {
|
||||||
const $header = $("header.d-header");
|
const header = document.querySelector("header.d-header");
|
||||||
const headerHeight = $header.outerHeight(true) || 0;
|
return header ? header.offsetHeight : 0;
|
||||||
const headerPositionTop = $header.position().top;
|
|
||||||
return headerHeight + headerPositionTop;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function offsetCalculator() {
|
export default function offsetCalculator() {
|
||||||
const min = minimumOffset();
|
const min = minimumOffset();
|
||||||
|
|
||||||
// on mobile, just use the header
|
// on mobile, just use the header
|
||||||
if ($("html").hasClass("mobile-view")) {
|
if (document.querySelector("html").classList.contains("mobile-view")) {
|
||||||
return min;
|
return min;
|
||||||
}
|
}
|
||||||
|
|
||||||
const $window = $(window);
|
const windowHeight = window.innerHeight;
|
||||||
const windowHeight = $window.height();
|
const documentHeight = document.body.clientHeight;
|
||||||
const documentHeight = $(document).height();
|
const topicBottomOffsetTop = document.getElementById("topic-bottom")
|
||||||
const topicBottomOffsetTop = $("#topic-bottom").offset().top;
|
.offsetTop;
|
||||||
|
|
||||||
// the footer is bigger than the window, we can scroll down past the last post
|
// the footer is bigger than the window, we can scroll down past the last post
|
||||||
if (documentHeight - windowHeight > topicBottomOffsetTop) {
|
if (documentHeight - windowHeight > topicBottomOffsetTop) {
|
||||||
return min;
|
return min;
|
||||||
}
|
}
|
||||||
|
|
||||||
const scrollTop = $window.scrollTop();
|
const scrollTop = window.scrollY;
|
||||||
const visibleBottomHeight = scrollTop + windowHeight - topicBottomOffsetTop;
|
const visibleBottomHeight = scrollTop + windowHeight - topicBottomOffsetTop;
|
||||||
|
|
||||||
if (visibleBottomHeight > 0) {
|
if (visibleBottomHeight > 0) {
|
||||||
|
|
|
@ -128,7 +128,7 @@
|
||||||
}}
|
}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{#topic-navigation topic=model jumpToDate=(action "jumpToDate") jumpToIndex=(action "jumpToIndex") as |info|}}
|
{{#topic-navigation class="topic-navigation" topic=model jumpToDate=(action "jumpToDate") jumpToIndex=(action "jumpToIndex") as |info|}}
|
||||||
{{#if info.renderTimeline}}
|
{{#if info.renderTimeline}}
|
||||||
{{topic-timeline
|
{{topic-timeline
|
||||||
topic=model
|
topic=model
|
||||||
|
@ -299,6 +299,33 @@
|
||||||
categoryId=model.topic_timer.category_id
|
categoryId=model.topic_timer.category_id
|
||||||
removeTopicTimer=(action "removeTopicTimer" model.topic_timer.status_type "topic_timer")}}
|
removeTopicTimer=(action "removeTopicTimer" model.topic_timer.status_type "topic_timer")}}
|
||||||
|
|
||||||
|
{{#if showSelectedPostsAtBottom}}
|
||||||
|
<div class="selected-posts {{unless multiSelect "hidden"}}">
|
||||||
|
{{selected-posts
|
||||||
|
selectedPostsCount=selectedPostsCount
|
||||||
|
canSelectAll=canSelectAll
|
||||||
|
canDeselectAll=canDeselectAll
|
||||||
|
canDeleteSelected=canDeleteSelected
|
||||||
|
canMergeTopic=canMergeTopic
|
||||||
|
canChangeOwner=canChangeOwner
|
||||||
|
canMergePosts=canMergePosts
|
||||||
|
toggleMultiSelect=(action "toggleMultiSelect")
|
||||||
|
mergePosts=(action "mergePosts")
|
||||||
|
deleteSelected=(action "deleteSelected")
|
||||||
|
deselectAll=(action "deselectAll")
|
||||||
|
selectAll=(action "selectAll")
|
||||||
|
}}
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
{{/if}}
|
||||||
|
{{/conditional-loading-spinner}}
|
||||||
|
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
{{#if loadedAllPosts}}
|
||||||
{{#if session.showSignupCta}}
|
{{#if session.showSignupCta}}
|
||||||
{{! replace "Log In to Reply" with the infobox }}
|
{{! replace "Log In to Reply" with the infobox }}
|
||||||
{{signup-cta}}
|
{{signup-cta}}
|
||||||
|
@ -334,25 +361,6 @@
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
{{#if showSelectedPostsAtBottom}}
|
|
||||||
<div class="selected-posts {{unless multiSelect "hidden"}}">
|
|
||||||
{{selected-posts
|
|
||||||
selectedPostsCount=selectedPostsCount
|
|
||||||
canSelectAll=canSelectAll
|
|
||||||
canDeselectAll=canDeselectAll
|
|
||||||
canDeleteSelected=canDeleteSelected
|
|
||||||
canMergeTopic=canMergeTopic
|
|
||||||
canChangeOwner=canChangeOwner
|
|
||||||
canMergePosts=canMergePosts
|
|
||||||
toggleMultiSelect=(action "toggleMultiSelect")
|
|
||||||
mergePosts=(action "mergePosts")
|
|
||||||
deleteSelected=(action "deleteSelected")
|
|
||||||
deselectAll=(action "deselectAll")
|
|
||||||
selectAll=(action "selectAll")
|
|
||||||
}}
|
|
||||||
</div>
|
|
||||||
{{/if}}
|
|
||||||
|
|
||||||
{{plugin-outlet name="topic-above-suggested" args=(hash model=model)}}
|
{{plugin-outlet name="topic-above-suggested" args=(hash model=model)}}
|
||||||
<div class="{{if model.relatedMessages.length "related-messages-wrapper"}} {{if model.suggestedTopics.length "suggested-topics-wrapper"}}">
|
<div class="{{if model.relatedMessages.length "related-messages-wrapper"}} {{if model.suggestedTopics.length "suggested-topics-wrapper"}}">
|
||||||
{{#if model.relatedMessages.length}}
|
{{#if model.relatedMessages.length}}
|
||||||
|
@ -363,12 +371,6 @@
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{/conditional-loading-spinner}}
|
|
||||||
|
|
||||||
</section>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
{{else}}
|
{{else}}
|
||||||
<div class="container">
|
<div class="container">
|
||||||
{{#conditional-loading-spinner condition=noErrorYet}}
|
{{#conditional-loading-spinner condition=noErrorYet}}
|
||||||
|
|
|
@ -320,12 +320,6 @@ createWidget("topic-timeline-container", {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
buildAttributes(attrs) {
|
|
||||||
if (attrs.top) {
|
|
||||||
return { style: `top: ${attrs.top}px` };
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
html(attrs) {
|
html(attrs) {
|
||||||
return this.attach("topic-timeline", attrs);
|
return this.attach("topic-timeline", attrs);
|
||||||
},
|
},
|
||||||
|
|
|
@ -580,7 +580,11 @@ table {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Special elements
|
// Special elements
|
||||||
// Special elements
|
|
||||||
|
#main-outlet {
|
||||||
|
padding-top: 1.8em;
|
||||||
|
}
|
||||||
|
|
||||||
#main {
|
#main {
|
||||||
img.avatar {
|
img.avatar {
|
||||||
&.header {
|
&.header {
|
||||||
|
|
|
@ -1,12 +1,17 @@
|
||||||
|
.d-header-wrap {
|
||||||
|
@include sticky;
|
||||||
|
top: 0;
|
||||||
|
z-index: z("header");
|
||||||
|
}
|
||||||
|
|
||||||
.d-header {
|
.d-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
z-index: z("header");
|
z-index: z("header");
|
||||||
background-color: var(--header_background);
|
background-color: var(--header_background);
|
||||||
box-shadow: shadow("header");
|
box-shadow: shadow("header");
|
||||||
|
backface-visibility: hidden; /** do magic for scrolling performance **/
|
||||||
|
|
||||||
> .wrap {
|
> .wrap {
|
||||||
width: calc(100% - 16px); // accommodates for 8px vertical padding
|
width: calc(100% - 16px); // accommodates for 8px vertical padding
|
||||||
|
@ -35,11 +40,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.docked & {
|
|
||||||
position: fixed;
|
|
||||||
backface-visibility: hidden; /** do magic for scrolling performance **/
|
|
||||||
}
|
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
|
@ -16,6 +16,51 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.container.posts {
|
||||||
|
display: grid;
|
||||||
|
grid-template-areas: "posts timeline";
|
||||||
|
grid-template-columns: auto auto;
|
||||||
|
> .row {
|
||||||
|
grid-area: posts;
|
||||||
|
max-width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeline-container {
|
||||||
|
margin-left: unset !important;
|
||||||
|
/* This is a temporary override to ease the transition
|
||||||
|
to the sticky position timeline for themes with custom timeline positioning.
|
||||||
|
Without this those themes would render topics unreadable. */
|
||||||
|
}
|
||||||
|
|
||||||
|
// timeline
|
||||||
|
@media screen and (min-width: 925px) {
|
||||||
|
// at 925px viewport width and above the timeline is visible (see topic-navigation.js)
|
||||||
|
.topic-navigation {
|
||||||
|
grid-area: timeline;
|
||||||
|
align-self: start;
|
||||||
|
@include sticky;
|
||||||
|
top: 6em;
|
||||||
|
margin-left: 1em;
|
||||||
|
z-index: z("timeline");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// progress bar
|
||||||
|
@media screen and (max-width: 924px) {
|
||||||
|
// at 924px viewport width and below the progress bar is visible (see topic-navigation.js)
|
||||||
|
grid-template-areas: "posts posts";
|
||||||
|
.timeline-container:not(.timeline-fullscreen) {
|
||||||
|
display: none; // hiding this because sometimes the JS switch lags and causes layout issues
|
||||||
|
}
|
||||||
|
.timeline-container {
|
||||||
|
.timeline-scroller-content {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.progress-back-container {
|
.progress-back-container {
|
||||||
z-index: z("dropdown");
|
z-index: z("dropdown");
|
||||||
margin-right: 0;
|
margin-right: 0;
|
||||||
|
|
|
@ -75,6 +75,11 @@ $breakpoints: (
|
||||||
//
|
//
|
||||||
// --------------------------------------------------
|
// --------------------------------------------------
|
||||||
|
|
||||||
|
@mixin sticky {
|
||||||
|
position: -webkit-sticky;
|
||||||
|
position: sticky;
|
||||||
|
}
|
||||||
|
|
||||||
// Unselectable (avoids unwanted selections with iPad, touch laptops, etc)
|
// Unselectable (avoids unwanted selections with iPad, touch laptops, etc)
|
||||||
|
|
||||||
@mixin user-select($mode) {
|
@mixin user-select($mode) {
|
||||||
|
|
|
@ -5,22 +5,8 @@
|
||||||
.timeline-container {
|
.timeline-container {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
z-index: z("timeline");
|
z-index: z("timeline");
|
||||||
margin-left: 757px;
|
|
||||||
|
|
||||||
@include breakpoint(extra-large, min-width) {
|
|
||||||
margin-left: 820px;
|
|
||||||
}
|
|
||||||
@media all and (min-width: 1250px) {
|
|
||||||
margin-left: 900px;
|
|
||||||
}
|
|
||||||
|
|
||||||
position: fixed;
|
|
||||||
-webkit-transform: translate3d(0, 0, 0);
|
-webkit-transform: translate3d(0, 0, 0);
|
||||||
|
|
||||||
&.timeline-docked {
|
|
||||||
position: absolute;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.timeline-docked-bottom {
|
&.timeline-docked-bottom {
|
||||||
.timeline-footer-controls {
|
.timeline-footer-controls {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
|
@ -173,7 +159,6 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.topic-timeline {
|
.topic-timeline {
|
||||||
margin-left: 3em;
|
|
||||||
transition: opacity 0.2s ease-in;
|
transition: opacity 0.2s ease-in;
|
||||||
touch-action: none;
|
touch-action: none;
|
||||||
|
|
||||||
|
@ -181,6 +166,11 @@
|
||||||
margin-bottom: 1em;
|
margin-bottom: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.timeline-date-wrapper {
|
||||||
|
max-width: 9em;
|
||||||
|
overflow-wrap: anywhere;
|
||||||
|
}
|
||||||
|
|
||||||
.timeline-footer-controls {
|
.timeline-footer-controls {
|
||||||
margin-top: 1.5em;
|
margin-top: 1.5em;
|
||||||
transition: opacity 0.2s ease-in;
|
transition: opacity 0.2s ease-in;
|
||||||
|
@ -228,6 +218,7 @@
|
||||||
|
|
||||||
.timeline-scroller-content {
|
.timeline-scroller-content {
|
||||||
padding-left: 1em;
|
padding-left: 1em;
|
||||||
|
position: absolute; // prevents text length from impacting width
|
||||||
}
|
}
|
||||||
|
|
||||||
.timeline-ago {
|
.timeline-ago {
|
||||||
|
|
|
@ -168,9 +168,6 @@ input {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* bootstrap columns */
|
/* bootstrap columns */
|
||||||
.row {
|
|
||||||
@include clearfix;
|
|
||||||
}
|
|
||||||
|
|
||||||
.offset {
|
.offset {
|
||||||
&2 {
|
&2 {
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
.d-header {
|
.d-header {
|
||||||
left: 0;
|
left: 0;
|
||||||
height: 4em;
|
height: 4em;
|
||||||
margin-bottom: 15px;
|
|
||||||
#site-logo {
|
#site-logo {
|
||||||
height: 2.667em; // 40px with default 15px font size
|
height: 2.667em; // 40px with default 15px font size
|
||||||
}
|
}
|
||||||
|
@ -32,10 +31,6 @@
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
#main-outlet {
|
|
||||||
padding-top: 5.8572em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.search-link .blurb {
|
.search-link .blurb {
|
||||||
color: var(--secondary-medium);
|
color: var(--secondary-medium);
|
||||||
display: block;
|
display: block;
|
||||||
|
|
|
@ -207,13 +207,13 @@
|
||||||
z-index: z("dropdown");
|
z-index: z("dropdown");
|
||||||
}
|
}
|
||||||
|
|
||||||
@media all and (min-width: 400px) {
|
|
||||||
#topic-progress,
|
#topic-progress,
|
||||||
#topic-progress-expanded {
|
#topic-progress-expanded {
|
||||||
right: 0;
|
right: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media all and (min-width: 400px) {
|
||||||
#topic-footer-main-buttons {
|
#topic-footer-main-buttons {
|
||||||
max-width: 70%;
|
max-width: 70%;
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,7 +84,6 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
#main-outlet {
|
#main-outlet {
|
||||||
padding-top: 4.2857em;
|
|
||||||
@media only screen and (orientation: landscape) {
|
@media only screen and (orientation: landscape) {
|
||||||
padding-right: env(safe-area-inset-right);
|
padding-right: env(safe-area-inset-right);
|
||||||
padding-left: env(safe-area-inset-left);
|
padding-left: env(safe-area-inset-left);
|
||||||
|
|
Loading…
Reference in New Issue