refactor: simplify basic layout (#1039)

A dynamically expanding/collapsing topbar is difficult to maintain and not very useful.
This commit is contained in:
Cotes Chung 2023-05-17 01:59:34 +08:00 committed by GitHub
parent 52f5ee9cd3
commit d81f836b06
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 26 additions and 294 deletions

View file

@ -1,6 +1,6 @@
<!-- The paginator for post list on HomgPage. --> <!-- The paginator for post list on HomgPage. -->
<ul class="pagination align-items-center mt-4 ps-lg-2"> <ul class="pagination align-items-center my-4 ps-lg-2">
<!-- left arrow --> <!-- left arrow -->
{% if paginator.previous_page %} {% if paginator.previous_page %}
{% assign prev_url = paginator.previous_page_path | relative_url %} {% assign prev_url = paginator.previous_page_path | relative_url %}

View file

@ -3,7 +3,7 @@
<div id="topbar-wrapper"> <div id="topbar-wrapper">
<div <div
id="topbar" id="topbar"
class="container d-flex align-items-center justify-content-between h-100 px-3 px-md-4 px-xxl-5" class="container d-flex align-items-center justify-content-between h-100"
> >
<span id="breadcrumb"> <span id="breadcrumb">
{% assign paths = page.url | split: '/' %} {% assign paths = page.url | split: '/' %}

View file

@ -4,10 +4,7 @@
export function back2top() { export function back2top() {
$(window).on('scroll', () => { $(window).on('scroll', () => {
if ( if ($(window).scrollTop() > 50) {
$(window).scrollTop() > 50 &&
$('#sidebar-trigger').css('display') === 'none'
) {
$('#back-to-top').fadeIn(); $('#back-to-top').fadeIn();
} else { } else {
$('#back-to-top').fadeOut(); $('#back-to-top').fadeOut();

View file

@ -1,66 +0,0 @@
/**
* Top bar title auto change while scrolling up/down in mobile screens.
*/
const titleSelector = 'div.post>h1:first-of-type';
const $pageTitle = $(titleSelector);
const $topbarTitle = $('#topbar-title');
const defaultTitleText = $topbarTitle.text().trim();
export function convertTitle() {
if (
$pageTitle.length === 0 /* on Home page */ ||
$pageTitle.hasClass('dynamic-title') ||
$topbarTitle.is(':hidden')
) {
/* not in mobile views */
return;
}
let pageTitleText = $pageTitle.text().trim();
let hasScrolled = false;
let lastScrollTop = 0;
if ($('#page-category').length || $('#page-tag').length) {
/* The title in Category or Tag page will be "<title> <count_of_posts>" */
if (/\s/.test(pageTitleText)) {
pageTitleText = pageTitleText.replace(/[0-9]/g, '').trim();
}
}
// When the page is scrolled down and then refreshed, the topbar title needs to be initialized
if ($pageTitle.offset().top < $(window).scrollTop()) {
$topbarTitle.text(pageTitleText);
}
let options = {
rootMargin: '-48px 0px 0px 0px', // 48px equals to the topbar height (3rem)
threshold: [0, 1]
};
let observer = new IntersectionObserver((entries) => {
if (!hasScrolled) {
hasScrolled = true;
return;
}
let curScrollTop = $(window).scrollTop();
let isScrollDown = lastScrollTop < curScrollTop;
lastScrollTop = curScrollTop;
let heading = entries[0];
if (isScrollDown) {
if (heading.intersectionRatio === 0) {
$topbarTitle.text(pageTitleText);
}
} else {
if (heading.intersectionRatio === 1) {
$topbarTitle.text(defaultTitleText);
}
}
}, options);
observer.observe(document.querySelector(titleSelector));
/* Click title will scroll to top */
$topbarTitle.on('click', () => window.scrollTo(0, 0));
}

View file

@ -4,7 +4,7 @@
const $btnSbTrigger = $('#sidebar-trigger'); const $btnSbTrigger = $('#sidebar-trigger');
const $btnSearchTrigger = $('#search-trigger'); const $btnSearchTrigger = $('#search-trigger');
const $btnCancel = $('#search-cancel'); const $btnCancel = $('#search-cancel');
const $main = $('#main'); const $content = $('#main>.row');
const $topbarTitle = $('#topbar-title'); const $topbarTitle = $('#topbar-title');
const $searchWrapper = $('#search-wrapper'); const $searchWrapper = $('#search-wrapper');
const $resultWrapper = $('#search-result-wrapper'); const $resultWrapper = $('#search-result-wrapper');
@ -58,7 +58,7 @@ class ResultSwitch {
// the block method must be called before $(#main) unloaded. // the block method must be called before $(#main) unloaded.
ScrollBlocker.on(); ScrollBlocker.on();
$resultWrapper.removeClass(C_UNLOADED); $resultWrapper.removeClass(C_UNLOADED);
$main.addClass(C_UNLOADED); $content.addClass(C_UNLOADED);
ScrollBlocker.resultVisible = true; ScrollBlocker.resultVisible = true;
} }
} }
@ -70,7 +70,7 @@ class ResultSwitch {
$hints.removeClass(C_UNLOADED); $hints.removeClass(C_UNLOADED);
} }
$resultWrapper.addClass(C_UNLOADED); $resultWrapper.addClass(C_UNLOADED);
$main.removeClass(C_UNLOADED); $content.removeClass(C_UNLOADED);
// now the release method must be called after $(#main) display // now the release method must be called after $(#main) display
ScrollBlocker.off(); ScrollBlocker.off();

View file

@ -1,99 +0,0 @@
/**
* Hide Header on scroll down
*/
import ScrollHelper from './utils/scroll-helper';
const $searchInput = $('#search-input');
const delta = ScrollHelper.getTopbarHeight();
let lastScrollTop = 0;
function hasScrolled() {
let st = $(window).scrollTop();
/* Make sure they scroll more than delta */
if (Math.abs(lastScrollTop - st) <= delta) {
return;
}
if (st > lastScrollTop) {
/* Scroll down */
ScrollHelper.hideTopbar();
if ($searchInput.is(':focus')) {
$searchInput.trigger('blur'); /* remove focus */
}
} else {
/* Scroll up */
// has not yet scrolled to the bottom of the screen, that is, there is still space for scrolling
if (st + $(window).height() < $(document).height()) {
if (ScrollHelper.hasScrollUpTask()) {
return;
}
if (ScrollHelper.topbarLocked()) {
// avoid redundant scroll up event from smooth scrolling
ScrollHelper.unlockTopbar();
} else {
if (ScrollHelper.orientationLocked()) {
// avoid device auto scroll up on orientation change
ScrollHelper.unLockOrientation();
} else {
ScrollHelper.showTopbar();
}
}
}
}
lastScrollTop = st;
} // hasScrolled()
function handleLandscape() {
if ($(window).scrollTop() === 0) {
return;
}
ScrollHelper.lockOrientation();
ScrollHelper.hideTopbar();
}
export function switchTopbar() {
const orientation = screen.orientation;
let didScroll = false;
const handleOrientationChange = () => {
const type = orientation.type;
if (type === 'landscape-primary' || type === 'landscape-secondary') {
handleLandscape();
}
};
const handleWindowChange = () => {
if ($(window).width() < $(window).height()) {
// before rotating, it is still in portrait mode.
handleLandscape();
}
};
const handleScroll = () => {
didScroll = true;
};
const checkScroll = () => {
if (didScroll) {
hasScrolled();
didScroll = false;
}
};
if (orientation) {
orientation.addEventListener('change', handleOrientationChange);
} else {
// for the browsers that not support `window.screen.orientation` API
$(window).on('orientationchange', handleWindowChange);
}
$(window).on('scroll', handleScroll);
setInterval(checkScroll, 250);
}

View file

@ -1,64 +0,0 @@
/**
* A tool for smooth scrolling and topbar switcher
*/
const ATTR_TOPBAR_VISIBLE = 'data-topbar-visible';
const $body = $('body');
const $topbarWrapper = $('#topbar-wrapper');
export default class ScrollHelper {
static scrollUpCount = 0; // the number of times the scroll up was triggered by ToC or anchor
static topbarIsLocked = false;
static orientationIsLocked = false;
static hideTopbar() {
$body.attr(ATTR_TOPBAR_VISIBLE, 'false');
}
static showTopbar() {
$body.attr(ATTR_TOPBAR_VISIBLE, 'true');
}
// scroll up
static addScrollUpTask() {
ScrollHelper.scrollUpCount += 1;
if (!ScrollHelper.topbarIsLocked) {
ScrollHelper.topbarIsLocked = true;
}
}
static popScrollUpTask() {
ScrollHelper.scrollUpCount -= 1;
}
static hasScrollUpTask() {
return ScrollHelper.scrollUpCount > 0;
}
static topbarLocked() {
return ScrollHelper.topbarIsLocked === true;
}
static unlockTopbar() {
ScrollHelper.topbarIsLocked = false;
}
static getTopbarHeight() {
return $topbarWrapper.outerHeight();
}
// orientation change
static orientationLocked() {
return ScrollHelper.orientationIsLocked === true;
}
static lockOrientation() {
ScrollHelper.orientationIsLocked = true;
}
static unLockOrientation() {
ScrollHelper.orientationIsLocked = false;
}
}

View file

@ -1,9 +1,5 @@
import { convertTitle } from '../components/convert-title';
import { displaySearch } from '../components/search-display'; import { displaySearch } from '../components/search-display';
import { switchTopbar } from '../components/topbar-switcher';
export function initTopbar() { export function initTopbar() {
convertTitle();
displaySearch(); displaySearch();
switchTopbar();
} }

View file

@ -19,17 +19,16 @@ layout: compress
<html lang="{{ site.alt_lang | default: site.lang }}" {{ prefer_mode }}> <html lang="{{ site.alt_lang | default: site.lang }}" {{ prefer_mode }}>
{% include head.html %} {% include head.html %}
<body data-topbar-visible="true"> <body>
{% include sidebar.html lang=lang %} {% include sidebar.html lang=lang %}
{% include topbar.html lang=lang %}
<div id="main-wrapper" class="d-flex justify-content-center"> <div id="main-wrapper" class="d-flex justify-content-center">
<div id="main" class="container px-xxl-5"> <div id="main" class="container px-xxl-5">
{% include topbar.html lang=lang %}
{{ content }} {{ content }}
</div>
{% include search-results.html lang=lang %} {% include search-results.html lang=lang %}
</div> </div>
</div>
{% include footer.html lang=lang %} {% include footer.html lang=lang %}

View file

@ -252,10 +252,6 @@ i {
transition: all 0.3s ease-in; transition: all 0.3s ease-in;
} }
} }
[data-topbar-visible='true'] & > div {
top: 5.5rem;
}
} }
#access-lastmod { #access-lastmod {
@ -938,29 +934,7 @@ $btn-mb: 0.5rem;
#topbar-wrapper { #topbar-wrapper {
height: $topbar-height; height: $topbar-height;
position: fixed;
top: 0;
left: $sidebar-width; /* same as sidebar width */
right: 0;
transition: top 0.2s ease-in-out;
z-index: 50;
background-color: var(--topbar-bg); background-color: var(--topbar-bg);
[data-topbar-visible='false'] & {
top: -$topbar-height; /* same as topbar height. */
}
&::before {
$blur: 12px;
content: '';
position: absolute;
width: 100%;
height: $topbar-height;
z-index: -1;
-webkit-backdrop-filter: blur($blur);
backdrop-filter: blur($blur);
}
} }
#topbar { #topbar {
@ -1168,11 +1142,6 @@ $btn-mb: 0.5rem;
@include pl-pr(0); @include pl-pr(0);
} }
#core-wrapper,
#panel-wrapper {
margin-top: $topbar-height; /* same as the height of topbar */
}
#topbar-wrapper.row, #topbar-wrapper.row,
#main > .row, #main > .row,
#search-result-wrapper > .row { #search-result-wrapper > .row {
@ -1182,12 +1151,14 @@ $btn-mb: 0.5rem;
/* --- button back-to-top --- */ /* --- button back-to-top --- */
#back-to-top { #back-to-top {
$size: 2.7em; $size: 3rem;
display: none; display: none;
z-index: 1; z-index: 1;
cursor: pointer; cursor: pointer;
position: fixed; position: fixed;
right: 1rem;
bottom: 2rem;
background: var(--button-bg); background: var(--button-bg);
color: var(--btn-backtotop-color); color: var(--btn-backtotop-color);
padding: 0; padding: 0;
@ -1198,6 +1169,11 @@ $btn-mb: 0.5rem;
transition: transform 0.2s ease-out; transition: transform 0.2s ease-out;
-webkit-transition: transform 0.2s ease-out; -webkit-transition: transform 0.2s ease-out;
&:hover {
transform: translate3d(0, -5px, 0);
-webkit-transform: translate3d(0, -5px, 0);
}
i { i {
line-height: $size; line-height: $size;
position: relative; position: relative;
@ -1205,11 +1181,6 @@ $btn-mb: 0.5rem;
} }
} }
#back-to-top:hover {
transform: translate3d(0, -5px, 0);
-webkit-transform: translate3d(0, -5px, 0);
}
#notification { #notification {
@-webkit-keyframes popup { @-webkit-keyframes popup {
from { from {
@ -1344,11 +1315,14 @@ $btn-mb: 0.5rem;
transform: translateX(0); transform: translateX(0);
} }
#topbar-wrapper,
#main-wrapper, #main-wrapper,
footer { footer {
transform: translateX(#{$sidebar-width}); transform: translateX(#{$sidebar-width});
} }
#back-to-top {
visibility: hidden;
}
} }
#sidebar { #sidebar {
@ -1360,8 +1334,6 @@ $btn-mb: 0.5rem;
#main-wrapper { #main-wrapper {
@include slide; @include slide;
padding-top: $topbar-height;
} }
#topbar, #topbar,
@ -1413,12 +1385,6 @@ $btn-mb: 0.5rem;
} }
} /* max-width: 849px */ } /* max-width: 849px */
@media all and (max-width: 849px) and (orientation: portrait) {
[data-topbar-visible='false'] #topbar-wrapper {
top: 0;
}
}
/* Phone & Pad */ /* Phone & Pad */
@media all and (min-width: 577px) and (max-width: 1199px) { @media all and (min-width: 577px) and (max-width: 1199px) {
footer .d-flex > div { footer .d-flex > div {
@ -1470,8 +1436,8 @@ $btn-mb: 0.5rem;
} }
#search-result-wrapper { #search-result-wrapper {
margin-top: 3rem;
max-width: $main-content-max-width; max-width: $main-content-max-width;
justify-content: start !important;
} }
.post { .post {
@ -1596,7 +1562,6 @@ $btn-mb: 0.5rem;
); );
} }
#topbar,
#main, #main,
footer > .container { footer > .container {
max-width: $main-content-max-width; max-width: $main-content-max-width;

View file

@ -5,6 +5,10 @@
#post-list { #post-list {
margin-top: 2rem; margin-top: 2rem;
&:only-child {
margin-bottom: 3.75rem;
}
a.card-wrapper { a.card-wrapper {
display: block; display: block;