mirror of
https://github.com/harvard-edge/cs249r_book.git
synced 2026-03-11 17:49:25 -05:00
feat(navbar): implement active state detection for navbar navigation
- Simplify navbar to textbook-focused design: Labs, Kits, PDF + GitHub tools - Move 'Edit this page', 'Report issue' from buried TOC to accessible GitHub dropdown - Add CSS styling for navbar active states with crimson highlighting - Implement JavaScript active state detection handling .qmd→.html URL conversion - Fix URL matching for localhost development environment - Ensure proper visual feedback when navigating between Labs/Kits sections - Maintain clean, academic navbar design appropriate for textbook format
This commit is contained in:
@@ -53,4 +53,43 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
});
|
||||
}, delay);
|
||||
});
|
||||
|
||||
// Handle navbar active states
|
||||
function setNavbarActiveState() {
|
||||
const currentUrl = window.location.href;
|
||||
const currentPath = window.location.pathname;
|
||||
const navbarLinks = document.querySelectorAll('.navbar-nav .nav-link');
|
||||
|
||||
navbarLinks.forEach(link => {
|
||||
// Remove existing active classes
|
||||
link.classList.remove('active');
|
||||
link.removeAttribute('aria-current');
|
||||
|
||||
const href = link.getAttribute('href');
|
||||
if (href && !href.includes('mlsysbook.ai')) { // Skip external PDF link
|
||||
let linkUrl = href;
|
||||
|
||||
// If it's a relative path, make it absolute for comparison
|
||||
if (!href.startsWith('http')) {
|
||||
linkUrl = window.location.origin + '/' + href.replace(/^\//, '');
|
||||
}
|
||||
|
||||
// Convert .qmd to .html for comparison since that's what gets rendered
|
||||
linkUrl = linkUrl.replace(/\.qmd$/, '.html');
|
||||
|
||||
// Check for exact match
|
||||
if (currentUrl === linkUrl || currentPath === new URL(linkUrl).pathname) {
|
||||
link.classList.add('active');
|
||||
link.setAttribute('aria-current', 'page');
|
||||
console.log('Setting active:', link.textContent.trim(), 'Current:', currentUrl, 'Link:', linkUrl);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Set initial active state
|
||||
setNavbarActiveState();
|
||||
|
||||
// Also check after a brief delay in case page is still loading
|
||||
setTimeout(setNavbarActiveState, 500);
|
||||
});
|
||||
@@ -39,10 +39,10 @@ a {
|
||||
}
|
||||
}
|
||||
|
||||
// Sidebar link styles - strong typography matching TOC
|
||||
// Sidebar link styles - readable but secondary to main content
|
||||
.sidebar-navigation .sidebar-item a {
|
||||
color: #2c3e50; // Strong dark color like TOC
|
||||
font-weight: 500; // Medium weight for consistency
|
||||
color: #495057; // Readable but not competing with main content
|
||||
font-weight: 400; // Normal weight - supportive not dominant
|
||||
display: block;
|
||||
padding: 4px 8px; // More padding for better touch targets
|
||||
margin: 1px 0; // Small margin for breathing room
|
||||
@@ -50,33 +50,33 @@ a {
|
||||
transition: all 0.15s ease;
|
||||
|
||||
&:hover {
|
||||
color: $crimson; // Crimson hover like TOC
|
||||
color: $crimson; // Crimson hover for interaction
|
||||
background-color: rgba($crimson, 0.08);
|
||||
font-weight: 600; // Bold on hover like TOC
|
||||
font-weight: 500; // Medium weight on hover
|
||||
text-decoration: none;
|
||||
transform: translateX(2px);
|
||||
}
|
||||
|
||||
// Strong active state like TOC
|
||||
// Clear active state without overpowering
|
||||
&.active,
|
||||
&[aria-current="page"] {
|
||||
color: $crimson;
|
||||
font-weight: 600; // Bold for active state
|
||||
font-weight: 500; // Medium weight for active state
|
||||
background-color: rgba($crimson, 0.12);
|
||||
}
|
||||
}
|
||||
|
||||
// Section headers - strong like TOC main sections
|
||||
// Section headers - clear hierarchy but not overpowering
|
||||
.sidebar-navigation .sidebar-item a[data-bs-toggle="collapse"] {
|
||||
font-weight: 600; // Bold like TOC main sections
|
||||
color: #1a252f; // Very dark like TOC main sections
|
||||
font-size: 0.95rem; // Slightly larger for hierarchy
|
||||
letter-spacing: 0.02em; // Subtle spacing for readability
|
||||
font-weight: 500; // Medium weight - clear but supportive
|
||||
color: #2c3e50; // Dark but not competing with main content
|
||||
font-size: 0.9rem; // Slightly larger for hierarchy
|
||||
letter-spacing: 0.01em; // Subtle spacing for readability
|
||||
|
||||
&:hover {
|
||||
color: $crimson; // Crimson hover
|
||||
background-color: rgba($crimson, 0.08);
|
||||
font-weight: 700; // Extra bold on hover
|
||||
font-weight: 600; // Bold on hover but not excessive
|
||||
text-decoration: none;
|
||||
transform: translateX(2px);
|
||||
}
|
||||
@@ -99,14 +99,14 @@ a {
|
||||
}
|
||||
}
|
||||
|
||||
// Content area link styles - consistent with navigation
|
||||
// Content area link styles - balanced with navigation
|
||||
.content a {
|
||||
color: $link-color;
|
||||
font-weight: 500; // Medium weight for consistency
|
||||
font-weight: 400; // Normal weight - content should be primary focus
|
||||
|
||||
&:hover {
|
||||
color: $link-hover-color;
|
||||
font-weight: 600; // Bold on hover like navigation
|
||||
font-weight: 500; // Medium weight on hover
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
@@ -232,11 +232,11 @@ nav[role="doc-toc"] {
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
// All links - consistent with main content typography
|
||||
// All links - readable but secondary to main content
|
||||
a,
|
||||
.nav-link {
|
||||
color: #2c3e50; // Strong, dark color like main content
|
||||
font-weight: 500; // Stronger weight for consistency
|
||||
color: #495057; // Readable but not competing with main content
|
||||
font-weight: 400; // Normal weight - supportive navigation
|
||||
text-decoration: none;
|
||||
display: block;
|
||||
padding: 0.2rem 0; // Slightly more padding
|
||||
@@ -249,53 +249,53 @@ nav[role="doc-toc"] {
|
||||
box-shadow: none !important;
|
||||
|
||||
&:hover {
|
||||
color: $crimson; // Crimson hover like main content
|
||||
font-weight: 600;
|
||||
color: $crimson; // Crimson hover for interaction
|
||||
font-weight: 500; // Medium weight on hover
|
||||
}
|
||||
}
|
||||
|
||||
// Main sections (H2) - strong like main content headers
|
||||
// Main sections (H2) - clear but not overpowering
|
||||
> ul > li {
|
||||
margin-bottom: 0.6rem;
|
||||
margin-bottom: 0.5rem;
|
||||
|
||||
> a {
|
||||
font-weight: 600; // Bold like main headers
|
||||
color: #1a252f; // Very dark, strong presence
|
||||
font-size: 0.95rem; // Slightly larger
|
||||
margin-bottom: 0.3rem;
|
||||
letter-spacing: 0.02em; // Subtle spacing for readability
|
||||
font-weight: 500; // Medium weight - clear hierarchy
|
||||
color: #2c3e50; // Dark but balanced
|
||||
font-size: 0.9rem; // Appropriate size
|
||||
margin-bottom: 0.25rem;
|
||||
letter-spacing: 0.01em; // Subtle spacing
|
||||
}
|
||||
}
|
||||
|
||||
// Sub-sections (H3) - medium weight, readable
|
||||
// Sub-sections (H3) - supportive weight
|
||||
ul ul {
|
||||
margin-left: 0.75rem;
|
||||
margin-top: 0.3rem;
|
||||
margin-top: 0.25rem;
|
||||
|
||||
li {
|
||||
margin-bottom: 0.2rem;
|
||||
margin-bottom: 0.15rem;
|
||||
}
|
||||
|
||||
a {
|
||||
font-size: 0.85rem; // Slightly larger
|
||||
color: #34495e; // Darker, more readable
|
||||
font-weight: 500; // Medium weight
|
||||
padding: 0.15rem 0;
|
||||
font-size: 0.8rem; // Appropriate size
|
||||
color: #6c757d; // Lighter but readable
|
||||
font-weight: 400; // Normal weight
|
||||
padding: 0.1rem 0;
|
||||
}
|
||||
|
||||
// Deep nesting (H4+) - still strong enough
|
||||
// Deep nesting (H4+) - subtle but readable
|
||||
ul a {
|
||||
font-size: 0.8rem;
|
||||
color: #5a6c7d; // Still readable but lighter
|
||||
font-weight: 450; // Slightly lighter but not too light
|
||||
font-size: 0.75rem;
|
||||
color: #8e959c; // Light but still readable
|
||||
font-weight: 400; // Normal weight
|
||||
}
|
||||
}
|
||||
|
||||
// Active section - clean crimson highlight, no lines
|
||||
// Active section - clear but balanced crimson highlight
|
||||
.active,
|
||||
.nav-link.active {
|
||||
color: $crimson !important;
|
||||
font-weight: 500 !important;
|
||||
font-weight: 500 !important; // Medium weight for active state
|
||||
border: none !important;
|
||||
border-left: none !important;
|
||||
border-right: none !important;
|
||||
@@ -618,4 +618,33 @@ figcaption.quarto-float-caption-top {
|
||||
}
|
||||
}
|
||||
|
||||
// Navbar active states for Labs, Kits, PDF
|
||||
.navbar-nav .nav-link {
|
||||
color: #6c757d !important;
|
||||
font-weight: 400;
|
||||
transition: all 0.2s ease;
|
||||
|
||||
&:hover {
|
||||
color: $crimson !important;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
&.active, &[aria-current="page"] {
|
||||
color: $crimson !important;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure navbar right side (Labs, Kits, PDF) get active states
|
||||
.navbar .navbar-nav .nav-item .nav-link {
|
||||
&:hover {
|
||||
color: $crimson !important;
|
||||
}
|
||||
|
||||
&.active {
|
||||
color: $crimson !important;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -26,13 +26,6 @@ project:
|
||||
preview:
|
||||
browser: true
|
||||
navigate: true
|
||||
render:
|
||||
- index.qmd
|
||||
- contents/frontmatter/foreword.qmd
|
||||
- contents/frontmatter/about/about.qmd
|
||||
- contents/frontmatter/changelog/changelog.qmd
|
||||
- contents/frontmatter/acknowledgements/acknowledgements.qmd
|
||||
- contents/core/introduction/introduction.qmd
|
||||
|
||||
website:
|
||||
# High-level navigation enhancements
|
||||
@@ -40,7 +33,7 @@ website:
|
||||
reader-mode: false
|
||||
back-to-top-navigation: true
|
||||
bread-crumbs: true
|
||||
|
||||
|
||||
# Announcement bar configuration
|
||||
announcement:
|
||||
icon: megaphone
|
||||
@@ -94,13 +87,13 @@ website:
|
||||
aria-label: "Donate & Support"
|
||||
- icon: github
|
||||
menu:
|
||||
- text: "🐛 Report Issue"
|
||||
href: https://github.com/harvard-edge/cs249r_book/issues
|
||||
- text: "🤝 Contribute Code"
|
||||
href: https://github.com/harvard-edge/cs249r_book/blob/main/docs/contribute.md
|
||||
- text: "✏️ Edit this page"
|
||||
href: https://github.com/harvard-edge/cs249r_book
|
||||
- text: "🐛 Report an issue"
|
||||
href: https://github.com/harvard-edge/cs249r_book/issues/new
|
||||
- text: "💬 Discussions"
|
||||
href: https://github.com/harvard-edge/cs249r_book/discussions
|
||||
- text: "🔍 View Source"
|
||||
- text: "🔍 View source"
|
||||
href: https://github.com/harvard-edge/cs249r_book
|
||||
|
||||
favicon: assets/images/icons/favicon.png
|
||||
@@ -123,9 +116,7 @@ website:
|
||||
- href: contents/frontmatter/about/about.qmd
|
||||
- href: contents/frontmatter/changelog/changelog.qmd
|
||||
- href: contents/frontmatter/acknowledgements/acknowledgements.qmd
|
||||
- text: "---"
|
||||
- href: contents/frontmatter/socratiq/socratiq.qmd
|
||||
- text: "---"
|
||||
|
||||
# <!------------------------------------------------->
|
||||
# <!-- Division: Mainmatter — Part I: Systems Foundations -->
|
||||
@@ -195,9 +186,7 @@ website:
|
||||
contents:
|
||||
#- href: contents/core/frontiers/frontiers.qmd
|
||||
- href: contents/core/conclusion/conclusion.qmd
|
||||
|
||||
- text: "---"
|
||||
|
||||
|
||||
# <!------------------------------------------------->
|
||||
# <!-- Division: Mainmatter — Part VII: Laboratory Exercises Overview -->
|
||||
# <!------------------------------------------------->
|
||||
@@ -371,7 +360,7 @@ filters:
|
||||
- ../config/lua/sidenote.lua # ⚠️ INFO: In HTML, this should not needed.
|
||||
- ../config/lua/inject_parts.lua
|
||||
- ../config/lua/inject_quizzes.lua
|
||||
# - pandoc-ext/diagram
|
||||
- pandoc-ext/diagram
|
||||
- ../config/lua/inject_crossrefs.lua # ⚠️ WARNING: This must come before custom-numbered-blocks (relies on \ref{...})
|
||||
- custom-numbered-blocks
|
||||
- ../config/lua/margin-connections.lua # ⚠️ WARNING: This filter must come after custom-numbered-blocks
|
||||
|
||||
Reference in New Issue
Block a user