Skip to content

Commit

Permalink
Final touches to mini title dynamics
Browse files Browse the repository at this point in the history
  • Loading branch information
ekiefl committed Jan 10, 2025
1 parent 10963f8 commit 68bd515
Show file tree
Hide file tree
Showing 5 changed files with 145 additions and 133 deletions.
15 changes: 14 additions & 1 deletion assets/css/article.css
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,20 @@ div.sourceCode:hover::before {
body .page-columns {
display: grid;
gap: 0;
grid-template-columns: [screen-start] 1.5em [screen-start-inset] 3fr [page-start page-start-inset] min(450px, 8vw) [body-start-outset] 35px [body-start] 1.5em [body-content-start] minmax(500px, calc(850px - 3em)) [body-content-end] 1.5em [body-end] 35px [body-end-outset] minmax(75px, 145px) [page-end-inset] min(450px, 8vw) [page-end] 3fr [screen-end-inset] 1.5em [screen-end];
grid-template-columns:
[screen-start] var(--grid-margin)
[screen-start-inset] var(--grid-edge-col)
[page-start page-start-inset] var(--grid-page-margin)
[body-start-outset] var(--grid-body-outset)
[body-start] var(--grid-body-padding)
[body-content-start] var(--grid-body-content)
[body-content-end] var(--grid-body-padding)
[body-end] var(--grid-body-outset)
[body-end-outset] var(--grid-sidebar-width)
[page-end-inset] var(--grid-page-margin)
[page-end] var(--grid-edge-col)
[screen-end-inset] var(--grid-margin)
[screen-end];
}

/* Callout colors */
Expand Down
15 changes: 12 additions & 3 deletions assets/css/main.css
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
/* Import other CSS files */
@import url('./navbar.css');
@import url('./mini-title.css');
@import url('./frontmatter.css');
@import url('./sidebar.css');
@import url('./article.css');
@import url('./footer.css');
@import url('./colors.css');

:root {
--arcadia-logo-size: 2rem;
/* Fonts */
--grid-margin: 1.5em;
--grid-edge-col: 3fr;
--grid-page-margin: min(450px, 2vw);
--grid-body-outset: 35px;
--grid-body-padding: 1.5em;
--grid-body-content: minmax(500px, calc(850px - 3em));
--grid-sidebar-width: minmax(75px, 145px);

--nb-header-font-family: "Georgia";
--nb-header-font-weight: 100;
--nb-h1-font-size: 2.5rem;
Expand All @@ -21,10 +28,12 @@
--bs-code-border-color: #e6e6e6;
--bs-code-left-border-color: #003B4F99;
--bs-link-color-rgb: var(--arcadia-dusk);
/* Callouts */

--callout-note-rgb: var(--arcadia-pewter);
--callout-warning-rgb: var(--arcadia-mustard);
--callout-important-rgb: var(--arcadia-dragon);
--callout-tip-rgb: var(--arcadia-teal);
--callout-caution-rgb: var(--arcadia-tumbleweed);

--arcadia-logo-size: 2rem;
}
81 changes: 81 additions & 0 deletions assets/css/mini-title.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
.mini-title {
position: fixed;
top: 0;
left: 0;
right: 0;
background-color: var(--arcadia-pewter);
color: white;
z-index: 1020;
height: var(--mini-title-height);
transform: translateY(-100%);
transition: transform 0.3s ease-out, top 0.2s ease-out;
}

/* When navbar is visible, position mini title below it */
.navbar-visible .mini-title {
top: var(--navbar-height);
}

.mini-title.visible {
transform: translateY(0);
}

.mini-title-content {
grid-column: page-start/page-end-inset;
display: flex;
align-items: center;
justify-content: center; /* Center the flex container */
opacity: 0.0;
width: 100%;
height: 100%;
font-family: var(--nb-banner-title-font-family) !important;
font-weight: 250 !important;
font-size: 1.2rem;
}

.mini-title.visible .mini-title-content {
opacity: 1.0;
transition: opacity 1s ease-in-out;
}

/* Logo - stays its natural size */
.mini-title-logo-wrapper {
flex: 0 0 auto;
margin-right: 1rem;
display: flex;
justify-content: flex-end;
}

.mini-title-logo-wrapper img {
height: 1.5rem;
width: auto;
}

/* Title - takes available space but doesn't force expansion */
.mini-title-content p {
flex: 0 1 auto;
text-align: center;
margin: 0;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
min-width: 0;
max-width: fit-content; /* Only take needed space */
}

/* Version control - stays its natural size */
#mini-version-control {
flex: 0 0 auto;
margin-left: 1rem;
display: flex;
justify-content: flex-start;
}

#mini-version-control .nav-link {
color: white;
padding: 0;
}

#mini-version-control iconify-icon {
font-size: 0.7em;
}
74 changes: 0 additions & 74 deletions assets/css/navbar.css
Original file line number Diff line number Diff line change
Expand Up @@ -85,77 +85,3 @@ li.nav-item.dropdown {
color: var(--arcadia-black) !important;
}

.sticky-mini-title {
position: fixed;
top: 0;
left: 0;
right: 0;
background-color: var(--arcadia-pewter);
color: white;
z-index: 1020;
height: var(--mini-title-height);
transform: translateY(-100%);
transition: transform 0.2s ease-out, top 0.2s ease-out;
}

/* When navbar is visible, position mini title below it */
.navbar-visible .sticky-mini-title {
top: var(--navbar-height);
}

.sticky-mini-title.visible {
transform: translateY(0);
}

.sticky-mini-title-content {
display: flex;
align-items: center;
max-width: 1200px;
margin: 0 auto;
width: 100%;
padding: 0 1rem;
height: 100%;
}

.logo-wrapper {
flex: 0 0 auto;
margin-right: 2rem;
}

.logo-wrapper img {
height: 1.5rem;
width: auto;
}

.sticky-mini-title-content p {
flex: 1;
text-align: center;
margin: 0;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
min-width: 0;
}

#mini-version-control {
flex: 0 0 auto;
margin-left: 2rem;
}

#mini-version-control .nav-link {
color: white;
padding: 0;
}

#mini-version-control iconify-icon {
font-size: 0.7em;
}

/* Adjust body padding when both navbar and mini title are visible */
body.mini-title-visible.navbar-visible {
padding-top: var(--total-header-height);
}

body.mini-title-visible:not(.navbar-visible) {
padding-top: var(--mini-title-height);
}
93 changes: 38 additions & 55 deletions assets/mini-title.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<template id="sticky-mini-title-template">
<div class="sticky-mini-title">
<div class="sticky-mini-title-content">
<div class="logo-wrapper">
<template id="mini-title-template">
<div class="mini-title page-columns page-full">
<div class="mini-title-content">
<div class="mini-title-logo-wrapper">
<img src="./assets/logo_white.png" alt="Logo">
</div>
<p>{{< var pub.title>}}</p>
Expand All @@ -13,18 +13,19 @@

<script>
document.addEventListener('DOMContentLoaded', function () {
const template = document.getElementById('sticky-mini-title-template');
const titleBanner = document.querySelector('.quarto-title-banner .quarto-title .title');
// Get required elements
const template = document.getElementById('mini-title-template');
const titleBanner = document.querySelector('.quarto-title-banner');
const abstract = document.querySelector('.abstract');
const navbar = document.querySelector('#quarto-header');
const persistentHeight = 50;
let prevRatio = {appear: 1, disappear: 1};

if (template && titleBanner && abstract && navbar) {
// Add the mini title to the document body
const miniTitleContent = document.importNode(template.content, true);
document.body.appendChild(miniTitleContent);

// Clone the version control dropdown if it exists
// Clone version control dropdown if it exists
const originalDropdown = document.querySelector('.navbar-nav .nav-item.dropdown:has(iconify-icon[icon="qlementine-icons:version-control-16"])');
if (originalDropdown) {
const clonedDropdown = originalDropdown.cloneNode(true);
Expand All @@ -45,10 +46,9 @@
}
}

const stickyMiniTitle = document.querySelector('.sticky-mini-title');
console.log("Sticky mini title found:", !!stickyMiniTitle);
const stickyMiniTitle = document.querySelector('.mini-title');

// Function to check navbar visibility
// Navbar state management
function updateNavbarState() {
const isNavbarPinned = navbar.classList.contains('headroom--pinned');
const isNavbarTop = !navbar.classList.contains('headroom--not-top');
Expand All @@ -60,66 +60,49 @@
}
}

// Create observer for navbar
const navbarObserver = new MutationObserver(() => {
updateNavbarState();
});

// Observe navbar class changes
const navbarObserver = new MutationObserver(updateNavbarState);
navbarObserver.observe(navbar, {
attributes: true,
attributeFilter: ['class']
});
updateNavbarState(); // Initial state

// Initial navbar state check
updateNavbarState();

function expandMiniTitle() {
document.body.classList.add('mini-title-visible');
stickyMiniTitle.classList.add('visible');
// Mini title visibility functions
function toggleMiniTitle(show) {
document.body.classList.toggle('mini-title-visible', show);
stickyMiniTitle.classList.toggle('visible', show);
}

function collapseMiniTitle() {
document.body.classList.remove('mini-title-visible');
stickyMiniTitle.classList.remove('visible');
}

// Create appear observer (triggers when abstract hits top)
const appearObserver = new IntersectionObserver(
(entries) => {
// Create intersection observer with configurable options
function createIntersectionObserver(type, rootMargin) {
return new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (!entry.isIntersecting && entry.boundingClientRect.top <= persistentHeight) {
expandMiniTitle();
}
});
},
{
threshold: [0],
rootMargin: "0px"
}
);
const currentRatio = entry.intersectionRatio;

// Create disappear observer (original title banner logic)
const disappearObserver = new IntersectionObserver(
(entries) => {
entries.forEach(entry => {
const visibleHeight = entry.intersectionRect.height;
if (visibleHeight > persistentHeight) {
collapseMiniTitle();
if (prevRatio[type] === 0 && currentRatio > 0) {
toggleMiniTitle(false);
} else if (prevRatio[type] > 0 && currentRatio === 0) {
toggleMiniTitle(true);
}

prevRatio[type] = currentRatio;
});
},
{
threshold: Array.from({length: 100}, (_, i) => i / 100),
rootMargin: "0px"
}
);
}, {
threshold: [0, 0.1],
rootMargin
});
}

// Create observers with different root margins
const appearObserver = createIntersectionObserver('appear', '-48px');
const disappearObserver = createIntersectionObserver('disappear', '48px');

// Start observing both elements
// Start observing title banner with both observers
appearObserver.observe(titleBanner);
disappearObserver.observe(titleBanner);

// Cleanup function
// Cleanup
window.addEventListener('beforeunload', () => {
navbarObserver.disconnect();
appearObserver.disconnect();
Expand Down

0 comments on commit 68bd515

Please sign in to comment.