From b582e7c9df39ee889b578a962f93ae17b7a4c849 Mon Sep 17 00:00:00 2001 From: Wil Wade Date: Mon, 4 Nov 2024 16:41:19 -0500 Subject: [PATCH] Switch to Grid and Footer (#97) Problem ======= Needed to do the footer, but had to change a good amount to make it work. Closes #83 Solution ======== - Added a grid - Moved the old menu icons to the left as a column - Shifted around a few things for the grid. - Kept the resize - Kept the sidebar animation - Kept the touch controls for mobile (swipe to get the sidebar) - Added the footer --- book.toml | 1 + css/discord.svg | 1 + css/footer.css | 92 ++++++++++++++++ css/header.css | 24 +++-- css/side-nav.css | 5 + css/x.svg | 1 + theme/book.js | 63 ----------- theme/css/chrome.css | 228 ++++++++++++++++++---------------------- theme/css/general.css | 24 +---- theme/css/print.css | 8 ++ theme/css/variables.css | 16 +-- theme/header.hbs | 19 ++-- theme/index.hbs | 172 +++++++++++++++++------------- 13 files changed, 339 insertions(+), 315 deletions(-) create mode 100644 css/discord.svg create mode 100644 css/footer.css create mode 100644 css/x.svg diff --git a/book.toml b/book.toml index 64ad53c..3f8e92f 100644 --- a/book.toml +++ b/book.toml @@ -18,6 +18,7 @@ preferred-dark-theme = "coal" additional-css = [ "css/side-nav.css", "css/header.css", + "css/footer.css", "css/extended.css", "css/highlight.css", "css/highlight-dark.css", diff --git a/css/discord.svg b/css/discord.svg new file mode 100644 index 0000000..f455b72 --- /dev/null +++ b/css/discord.svg @@ -0,0 +1 @@ + diff --git a/css/footer.css b/css/footer.css new file mode 100644 index 0000000..31cf3ba --- /dev/null +++ b/css/footer.css @@ -0,0 +1,92 @@ +/* Custom CSS for the Footer Component */ + +:root { + --footer-color-primary: #000; + --footer-color-primary-inverted: #fff; + --footer-color-secondary: #19455e; + --footer-section-margin-bottom: 3rem; +} + +.frqcy-footer { + background: var(--footer-color-primary-inverted); + z-index: 1; + display: flex; + flex-direction: column; + align-items: center; + color: var(--footer-color-primary); + padding: var(--footer-section-margin-bottom) 1rem; +} + +#frqcy-footer-logo { + display: block; + max-width: 257px; + width: 100%; + color: var(--footer-color-primary); + margin-bottom: var(--footer-section-margin-bottom); +} + +#frqcy-footer-copyright { + display: flex; + flex-direction: column; + justify-content: center; + text-align: center; + width: 100%; + line-height: 1; + margin: 0 1rem var(--footer-section-margin-bottom) 1rem; +} + +#frqcy-footer-copyright div.frqcy-footer-vbar { + width: 10%; + height: 2px; + background: var(--footer-color-primary); + justify-self: stretch; + margin: 1rem auto; +} + +#frqcy-footer-copyright a { + color: var(--footer-color-primary); + padding: 0; +} + +#frqcy-footer-copyright a:hover, +#frqcy-footer-copyright a:visited:hover { + color: var(--footer-color-secondary); +} + +.frqcy-footer .frqcy-footer-social-links { + display: flex; + flex-direction: row; + margin-bottom: var(--footer-section-margin-bottom); + width: 100%; + justify-content: center; +} + +.frqcy-footer .frqcy-footer-social-links a { + cursor: pointer; + display: flex; + height: 100%; + margin: 1rem; + padding: 0.5rem; + border-radius: 0.5rem; + flex: 0 0 32px; + background: var(--footer-color-primary); + color: var(--footer-color-primary-inverted); +} + +.frqcy-footer .frqcy-footer-social-links a:hover, +.frqcy-footer .frqcy-footer-social-links a:visited:hover { + background: var(--footer-color-secondary); +} + +/* Desktop */ +@media only screen and (min-width: 620px) { + #frqcy-footer-copyright { + flex-direction: row; + } + + #frqcy-footer-copyright div.frqcy-footer-vbar { + width: 2px; + height: 100%; + margin: 0 2rem; + } +} diff --git a/css/header.css b/css/header.css index 3cbe358..1966fe8 100644 --- a/css/header.css +++ b/css/header.css @@ -9,27 +9,30 @@ /* Everything is scoped to .frqcy-header */ .frqcy-header { + height: var(--header-height); + position: sticky; + top: 0; + + width: 100vw; + padding: 0 16px; + font-family: "Newake", "Arial Black", Arial, sans-serif; text-transform: uppercase; color: var(--header-color-primary); - height: 80px; - background-color: var(--header-background); - box-shadow: 0 4px 4px 0 #00000040; - width: 100vw; - position: fixed; - top: 0; - left: 0; - z-index: 1000; display: flex; justify-content: space-between; align-items: center; - padding: 0 20px 0 40px; box-sizing: border-box; + + background-color: var(--header-background); + box-shadow: 0 4px 4px 0 #00000040; + width: 100vw; + z-index: 1000; } @media (min-width: 800px) { .frqcy-header { - padding: 0 80px; + padding: 0 62px; } } @@ -38,7 +41,6 @@ } .frqcy-header .header-logo { - padding-right: 16px; height: auto; width: 236px; color: var(--header-color-secondary); diff --git a/css/side-nav.css b/css/side-nav.css index 87b3929..c7566ff 100644 --- a/css/side-nav.css +++ b/css/side-nav.css @@ -73,6 +73,11 @@ margin-block-start: 4.5rem; } +/* n(1) is hidden, so we need to remove the margin from n(2) */ +#toc > .chapter li.chapter-item:nth-child(2) { + margin-block-start: 0; +} + #toc > .chapter > li > a:first-of-type { padding-inline-start: 1rem; font-weight: bold; diff --git a/css/x.svg b/css/x.svg new file mode 100644 index 0000000..0ddfd95 --- /dev/null +++ b/css/x.svg @@ -0,0 +1 @@ + diff --git a/theme/book.js b/theme/book.js index c28b50d..78dd5cc 100644 --- a/theme/book.js +++ b/theme/book.js @@ -604,66 +604,3 @@ function playground_text(playground, hidden = true) { document.scrollingElement.scrollTo({ top: 0, behavior: "smooth" }); }); })(); - -(function controllMenu() { - var menu = document.getElementById("menu-bar"); - - (function controllPosition() { - var scrollTop = document.scrollingElement.scrollTop; - var prevScrollTop = scrollTop; - var minMenuY = -menu.clientHeight - 50; - // When the script loads, the page can be at any scroll (e.g. if you reforesh it). - menu.style.top = scrollTop + "px"; - // Same as parseInt(menu.style.top.slice(0, -2), but faster - var topCache = menu.style.top.slice(0, -2); - menu.classList.remove("sticky"); - var stickyCache = false; // Same as menu.classList.contains('sticky'), but faster - document.addEventListener( - "scroll", - function () { - scrollTop = Math.max(document.scrollingElement.scrollTop, 0); - // `null` means that it doesn't need to be updated - var nextSticky = null; - var nextTop = null; - var scrollDown = scrollTop > prevScrollTop; - var menuPosAbsoluteY = topCache - scrollTop; - if (scrollDown) { - nextSticky = false; - if (menuPosAbsoluteY > 0) { - nextTop = prevScrollTop; - } - } else { - if (menuPosAbsoluteY > 0) { - nextSticky = true; - } else if (menuPosAbsoluteY < minMenuY) { - nextTop = prevScrollTop + minMenuY; - } - } - if (nextSticky === true && stickyCache === false) { - menu.classList.add("sticky"); - stickyCache = true; - } else if (nextSticky === false && stickyCache === true) { - menu.classList.remove("sticky"); - stickyCache = false; - } - if (nextTop !== null) { - menu.style.top = nextTop + "px"; - topCache = nextTop; - } - prevScrollTop = scrollTop; - }, - { passive: true }, - ); - })(); - (function controllBorder() { - function updateBorder() { - if (menu.offsetTop === 0) { - menu.classList.remove("bordered"); - } else { - menu.classList.add("bordered"); - } - } - updateBorder(); - document.addEventListener("scroll", updateBorder, { passive: true }); - })(); -})(); diff --git a/theme/css/chrome.css b/theme/css/chrome.css index 2a292cc..70c0f19 100644 --- a/theme/css/chrome.css +++ b/theme/css/chrome.css @@ -2,6 +2,54 @@ @import "variables.css"; +:target { + scroll-margin-top: calc(var(--header-height) + 20px); +} + +/* GRID */ +#body-container { + min-height: 100vh; + display: grid; + grid: + [row1-start] "header header header header" auto [row1-end] + [row2-start] "sidebar sidebar-resize menu-bar content" 1fr [row2-end] + [row3-start] "footer footer footer footer" auto [row3-end] + / 0 0 auto 1fr; +} + +.no-js #body-container { + display: grid; + grid: + [row1-start] "header header header" auto [row1-end] + [row2-start] "sidebar sidebar-resize menu-bar content" auto [row2-end] + [row3-start] "footer footer footer" auto [row3-end] + / 0 0 auto 1fr; +} + +#header { + grid-area: header; +} + +#sidebar { + grid-area: sidebar; +} + +#sidebar-resize-handle { + grid-area: sidebar-resize; +} + +#content { + grid-area: content; +} + +#footer { + grid-area: footer; +} + +#menu-bar { + grid-area: menu-bar; +} + ::-webkit-scrollbar { background: var(--bg); } @@ -34,44 +82,22 @@ a > .hljs { will want to reposition the viewport in a weird way. */ overflow-x: clip; + transition: 200ms; } /* Menu Bar */ -#menu-bar, -#menu-bar-hover-placeholder { - z-index: 101; - margin: auto calc(0px - var(--page-padding)); -} - #menu-bar { position: relative; - display: flex; - flex-wrap: wrap; background-color: var(--bg); - border-block-end-color: var(--bg); - border-block-end-width: 1px; - border-block-end-style: solid; -} - -#menu-bar.sticky, -.js #menu-bar-hover-placeholder:hover + #menu-bar, -.js #menu-bar:hover, -.js.sidebar-visible #menu-bar { - position: -webkit-sticky; - position: sticky; - top: 80px !important; } -#menu-bar-hover-placeholder { +.menu-bar-inner { position: sticky; - position: -webkit-sticky; - top: 0; - height: var(--menu-bar-height); -} - -#menu-bar.bordered { - border-block-end-color: var(--table-border-color); + top: var(--header-height); + display: flex; + align-items: flex-start; + flex-direction: column; } #menu-bar i, @@ -102,38 +128,8 @@ a > .hljs { margin: 0; } -.right-buttons { - margin: 0 15px; -} - -.right-buttons a { - text-decoration: none; -} - -.left-buttons { - display: flex; - margin: 0 5px; -} - -.no-js .left-buttons button { - display: none; -} - .menu-title { display: none; - font-weight: 300; - font-size: 2.4rem; - line-height: var(--menu-bar-height); - text-align: center; - margin: 0; - flex: 1; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -.js .menu-title { - cursor: pointer; } .menu-bar, @@ -153,6 +149,11 @@ a > .hljs { color: var(--icons-hover); } +.no-js #theme-toggle, +.no-js #search-toggle { + display: none; +} + /* Nav Icons */ .nav-chapters { @@ -355,6 +356,12 @@ pre > .result { /* Search */ +#search-wrapper { + position: sticky; + top: var(--header-height); + background-color: var(--bg); +} + #searchresults a { text-decoration: none; } @@ -454,22 +461,24 @@ ul#searchresults span.teaser em { /* Sidebar */ .sidebar { - position: fixed; - left: 0; - top: 0; - bottom: 0; - width: var(--sidebar-width); font-size: 0.875em; box-sizing: border-box; - -webkit-overflow-scrolling: touch; - overscroll-behavior-y: contain; background-color: var(--sidebar-bg); color: var(--sidebar-fg); + position: relative; } -[dir="rtl"] .sidebar { - left: unset; - right: 0; +.sidebar .sidebar-scrollbox { + position: sticky; + top: 80px; + max-height: 100vh; + overflow-x: hidden; + -webkit-overflow-scrolling: touch; + overscroll-behavior-y: contain; +} + +.sidebar .sidebar-contents { + padding: 10px 20px; } .sidebar-resizing { @@ -479,61 +488,25 @@ ul#searchresults span.teaser em { user-select: none; } -.no-js .sidebar, -.js:not(.sidebar-resizing) .sidebar { - transition: transform 0.3s; - /* Animation: slide away */ -} - .sidebar code { line-height: 2em; } -.sidebar .sidebar-scrollbox { - overflow-y: auto; - position: absolute; - top: 0; - bottom: 0; - left: 0; - right: 0; - padding: 10px 20px; -} - -.sidebar .sidebar-resize-handle { - position: absolute; +.sidebar-resize-handle { cursor: col-resize; - width: 0; - right: calc(var(--sidebar-resize-indicator-width) * -1); - top: 0; - bottom: 0; display: flex; align-items: center; + margin-left: var(--sidebar-resize-indicator-space); + width: var(--sidebar-resize-indicator-width); } .sidebar-resize-handle .sidebar-resize-indicator { - width: 100%; + display: none; + position: fixed; + top: 50%; + width: var(--sidebar-resize-indicator-width); height: 12px; background-color: var(--icons); - margin-inline-start: var(--sidebar-resize-indicator-space); -} - -[dir="rtl"] .sidebar .sidebar-resize-handle { - left: calc(var(--sidebar-resize-indicator-width) * -1); - right: unset; -} - -.js .sidebar .sidebar-resize-handle { - cursor: col-resize; - width: calc(var(--sidebar-resize-indicator-width) - var(--sidebar-resize-indicator-space)); -} - -/* sidebar-hidden */ -#sidebar-toggle-anchor:not(:checked) ~ .sidebar { - transform: translateX(calc(0px - var(--sidebar-width) - var(--sidebar-resize-indicator-width))); - z-index: -1; -} -[dir="rtl"] #sidebar-toggle-anchor:not(:checked) ~ .sidebar { - transform: translateX(calc(var(--sidebar-width) + var(--sidebar-resize-indicator-width))); } .sidebar::-webkit-scrollbar { @@ -545,27 +518,28 @@ ul#searchresults span.teaser em { } /* sidebar-visible */ -#sidebar-toggle-anchor:checked ~ .page-wrapper { - transform: translateX(calc(var(--sidebar-width) + var(--sidebar-resize-indicator-width))); -} -[dir="rtl"] #sidebar-toggle-anchor:checked ~ .page-wrapper { - transform: translateX(calc(0px - var(--sidebar-width) - var(--sidebar-resize-indicator-width))); +#sidebar-toggle-anchor:checked ~ #body-container { + /* On Mobile, max the width of the sidebar, but always leave room for the menu button */ + grid-template-columns: var(--sidebar-width-mobile) 0 auto minmax(300px, 1fr); } +/* Desktop sidebar visible */ @media only screen and (min-width: 620px) { - #sidebar-toggle-anchor:checked ~ .page-wrapper { - transform: none; - margin-inline-start: calc(var(--sidebar-width) + var(--sidebar-resize-indicator-width)); + #sidebar-toggle-anchor:checked ~ #body-container { + grid-template-columns: + var(--sidebar-width) var(--sidebar-resize-indicator-width) auto + minmax(300px, 1fr); } - [dir="rtl"] #sidebar-toggle-anchor:checked ~ .page-wrapper { - transform: none; + + .sidebar-resize-handle .sidebar-resize-indicator { + display: inherit; } } .chapter { list-style: none outside none; padding-inline-start: 0; - line-height: 2.2em; + line-height: 1; } .chapter ol { @@ -682,11 +656,11 @@ ul#searchresults span.teaser em { .theme-popup { position: absolute; left: 10px; - top: var(--menu-bar-height); + top: 0; z-index: 1000; border-radius: 4px; font-size: 0.7em; - color: var(--fg); + color: var(--sidebar-fg); background: var(--theme-popup-bg); border: 1px solid var(--theme-popup-border); margin: 0; @@ -757,8 +731,10 @@ ul#searchresults span.teaser em { height: 0.1em; width: 100%; opacity: 0; - transition: opacity 300ms, transform 300ms; - content: ''; + transition: + opacity 300ms, + transform 300ms; + content: ""; transform: translate3d(-100%, 0, 0); } diff --git a/theme/css/general.css b/theme/css/general.css index 0e78732..e31669a 100644 --- a/theme/css/general.css +++ b/theme/css/general.css @@ -121,15 +121,9 @@ h6:target::before { scroll-margin-top: calc(var(--menu-bar-height)); } -.page { - outline: 0; - padding: 0 var(--page-padding); - margin-block-start: calc(0px - var(--menu-bar-height)); /* Compensate for the #menu-bar-hover-placeholder */ -} .page-wrapper { box-sizing: border-box; background-color: var(--bg); - padding-top: 80px; } .page-header { @@ -159,22 +153,6 @@ h6:target::before { width: 236px; } -.sidebar{ - margin-top: 80px -} - -.no-js .page-wrapper, -.js:not(.sidebar-resizing) .page-wrapper { - transition: - margin-left 0.3s ease, - transform 0.3s ease; /* Animation: slide away */ -} -[dir="rtl"] .js:not(.sidebar-resizing) .page-wrapper { - transition: - margin-right 0.3s ease, - transform 0.3s ease; /* Animation: slide away */ -} - .content { overflow-y: auto; padding: 0 15px; @@ -203,7 +181,7 @@ h6:target::before { } .content a { text-decoration: none; - color: var(--links) + color: var(--links); } .content a:hover { text-decoration: underline; diff --git a/theme/css/print.css b/theme/css/print.css index e971616..9b51bf0 100644 --- a/theme/css/print.css +++ b/theme/css/print.css @@ -1,3 +1,11 @@ +#body-container { + min-height: 100vh; + display: grid; + grid: + [row2-start] "content" 1fr [row2-end] + / auto; +} + #sidebar, #menu-bar, .nav-chapters, diff --git a/theme/css/variables.css b/theme/css/variables.css index b3e31e6..e91242c 100644 --- a/theme/css/variables.css +++ b/theme/css/variables.css @@ -2,13 +2,15 @@ :root { --sidebar-width: 360px; - --sidebar-resize-indicator-width: 8px; + --sidebar-width-mobile: calc(100vw - 50px); + --sidebar-resize-indicator-width: 4px; --sidebar-resize-indicator-space: 2px; --page-padding: 15px; --content-max-width: 950px; --menu-bar-height: 50px; --mono-font: "Source Code Pro", Consolas, "Ubuntu Mono", Menlo, "DejaVu Sans Mono", monospace, monospace; --code-font-size: 0.875em /* please adjust the ace font size accordingly in editor.js */; + --header-height: 80px; } /* Themes */ @@ -29,13 +31,14 @@ --icons: #f1f1f1; --icons-hover: #4ba0a5; - --links: var(--sidebar-active); + --links: var(--sidebar-fg); + --links-hover: var(--sidebar-active); --inline-code-color: #c5c8c6; --theme-popup-bg: var(--sidebar-bg); --theme-popup-border: var(--links); - --theme-hover: var(--links); + --theme-hover: var(--sidebar-active); --quote-bg: hsl(234, 21%, 18%); --quote-border: hsl(234, 21%, 23%); @@ -69,7 +72,6 @@ --bg: #fff; --fg: #000; --headers: #19455e; - --headers-alt: #f77c47; --sidebar-bg: #19455e; --sidebar-fg: #fff; @@ -82,14 +84,14 @@ --icons: #19455e; --icons-hover: #4ba0a5; - --links: var(--sidebar-active); - --links-hover: var(--headers-alt); + --links: var(--sidebar-fg); + --links-hover: var(--sidebar-active); --inline-code-color: #301900; --theme-popup-bg: var(--sidebar-bg); --theme-popup-border: var(--links); - --theme-hover: var(--links); + --theme-hover: var(--sidebar-active); --quote-bg: hsl(197, 37%, 96%); --quote-border: hsl(197, 37%, 91%); diff --git a/theme/header.hbs b/theme/header.hbs index 8e272d8..baeab65 100644 --- a/theme/header.hbs +++ b/theme/header.hbs @@ -1,16 +1,11 @@ -
+