Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 23 additions & 16 deletions site/src/components/DocsSidebar.astro
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ function isParentActive(item: NavItem): boolean {
<div id="sidebar-overlay" class="fixed inset-0 z-40 bg-black/50 hidden lg:hidden" aria-hidden="true"></div>

<!-- Mobile sidebar drawer -->
<aside id="docs-sidebar-mobile" class="fixed top-16 left-0 bottom-0 z-50 w-72 bg-surface-container-lowest border-r border-outline-variant transform -translate-x-full transition-transform duration-200 lg:hidden overflow-y-auto">
<aside id="docs-sidebar-mobile" class="fixed top-16 left-0 bottom-14 md:bottom-0 z-50 w-72 bg-surface-container-lowest border-r border-outline-variant transform -translate-x-full transition-transform duration-200 lg:hidden overflow-y-auto">

Copilot AI Mar 23, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bottom-14 reserves space for a 56px bottom nav, but the nav also adds padding-bottom: env(safe-area-inset-bottom). On devices with a bottom safe-area inset, the sidebar can overlap the bottom nav/home-indicator region. Consider including the safe-area inset in the sidebar’s bottom offset (or add equivalent padding to the sidebar) to prevent content from being hidden.

Suggested change
<aside id="docs-sidebar-mobile" class="fixed top-16 left-0 bottom-14 md:bottom-0 z-50 w-72 bg-surface-container-lowest border-r border-outline-variant transform -translate-x-full transition-transform duration-200 lg:hidden overflow-y-auto">
<aside id="docs-sidebar-mobile" class="fixed top-16 left-0 bottom-[calc(3.5rem+env(safe-area-inset-bottom))] md:bottom-0 z-50 w-72 bg-surface-container-lowest border-r border-outline-variant transform -translate-x-full transition-transform duration-200 lg:hidden overflow-y-auto">

Copilot uses AI. Check for mistakes.
<nav class="py-6 px-4" aria-label="Documentation sidebar mobile">
{docsNav.map((group) => (
<div class="mb-8">
Expand All @@ -111,7 +111,7 @@ function isParentActive(item: NavItem): boolean {
<a
href={item.href}
class:list={[
'flex items-center justify-between px-3 py-1.5 text-[13px] transition-colors',
'flex items-center justify-between px-3 py-2 text-sm transition-colors',
active
? 'text-primary font-medium border-l-2 border-primary bg-primary/5'
: 'text-on-surface-variant hover:text-on-surface border-l-2 border-transparent hover:border-outline-variant',
Expand Down Expand Up @@ -140,7 +140,7 @@ function isParentActive(item: NavItem): boolean {
<a
href={child.href}
class:list={[
'block pl-6 pr-3 py-1 text-[12px] transition-colors',
'block pl-6 pr-3 py-1.5 text-[13px] transition-colors',
childActive
? 'text-primary font-medium border-l-2 border-primary bg-primary/5'
: 'text-on-surface-variant/80 hover:text-on-surface border-l-2 border-outline-variant/30 hover:border-outline-variant',
Expand All @@ -159,32 +159,39 @@ function isParentActive(item: NavItem): boolean {
</ul>
</div>
))}

<!-- Site navigation -->
<div class="mt-4 pt-4 border-t border-outline-variant">
<h4 class="text-[10px] font-headline font-bold uppercase tracking-[0.15em] text-on-surface-variant/60 mb-3 px-3">
Site
</h4>
<ul>
<li>
<a href="/" class="flex items-center gap-2 px-3 py-2 text-sm text-on-surface-variant hover:text-on-surface transition-colors">
Home
</a>
</li>
<li>
<a href="https://github.com/dvflw/mantle" class="flex items-center gap-2 px-3 py-2 text-sm text-on-surface-variant hover:text-on-surface transition-colors">
GitHub
</a>
</li>
</ul>
</div>
</nav>
</aside>

<script is:inline>
function initSidebar() {
const toggleBtn = document.getElementById('sidebar-toggle');
const mobileSidebar = document.getElementById('docs-sidebar-mobile');
const overlay = document.getElementById('sidebar-overlay');
if (!toggleBtn || !mobileSidebar || !overlay) return;
if (!mobileSidebar || !overlay) return;

function openSidebar() {
mobileSidebar.classList.remove('-translate-x-full');
overlay.classList.remove('hidden');
}
function closeSidebar() {
mobileSidebar.classList.add('-translate-x-full');
overlay.classList.add('hidden');
}

const newBtn = toggleBtn.cloneNode(true);
toggleBtn.parentNode?.replaceChild(newBtn, toggleBtn);
newBtn.addEventListener('click', () => {
const isOpen = !mobileSidebar.classList.contains('-translate-x-full');
if (isOpen) closeSidebar(); else openSidebar();
});

const newOverlay = overlay.cloneNode(true);
overlay.parentNode?.replaceChild(newOverlay, overlay);
newOverlay.addEventListener('click', closeSidebar);
Expand Down
65 changes: 48 additions & 17 deletions site/src/components/Nav.astro
Original file line number Diff line number Diff line change
Expand Up @@ -31,39 +31,70 @@ const isDocs = !isHome;
</a>
</div>

<!-- Mobile hamburger -->
<button id="mobile-menu-btn" class="md:hidden text-on-surface-variant hover:text-on-surface" aria-label="Menu">
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"/></svg>
</button>
</div>
</nav>

<!-- Mobile menu -->
<div id="mobile-menu" class="hidden md:hidden border-t border-outline-variant bg-surface/95 backdrop-blur-md">
<div class="px-6 py-4 flex flex-col gap-3">
<a href={`${prefix}#how-it-works`} class="text-sm text-on-surface-variant hover:text-on-surface transition-colors">How It Works</a>
<a href={`${prefix}#connectors`} class="text-sm text-on-surface-variant hover:text-on-surface transition-colors">Connectors</a>
<a href={`${prefix}#comparison`} class="text-sm text-on-surface-variant hover:text-on-surface transition-colors">Compare</a>
<a href="/docs/getting-started" class:list={["text-sm transition-colors", isDocs ? "text-primary font-medium" : "text-on-surface-variant hover:text-on-surface"]}>Docs</a>
<a href={`${prefix}#get-started`} class="inline-flex justify-center px-4 py-2 bg-primary text-on-primary text-sm font-medium mt-2">Get Started</a>
</div>
<!-- Mobile bottom navigation bar -->
<nav id="mobile-bottom-nav" class="fixed bottom-0 left-0 right-0 z-50 md:hidden border-t border-outline-variant bg-surface/95 backdrop-blur-md">
<div class="flex items-center justify-around h-14 px-2">
<a href="/" class:list={["bottom-nav-item flex flex-col items-center gap-0.5 px-3 py-1 text-[11px] transition-colors", isHome ? "text-primary" : "text-on-surface-variant hover:text-on-surface"]}>
<svg class="w-5 h-5" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M2.25 12l8.954-8.955a1.126 1.126 0 011.591 0L21.75 12M4.5 9.75v10.125c0 .621.504 1.125 1.125 1.125H9.75v-4.875c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125V21h4.125c.621 0 1.125-.504 1.125-1.125V9.75M8.25 21h8.25"/></svg>
<span>Home</span>
</a>
{isDocs && (
<button id="bottom-nav-docs-btn" class="bottom-nav-item flex flex-col items-center gap-0.5 px-3 py-1 text-[11px] text-on-surface-variant hover:text-on-surface transition-colors" aria-label="Documentation menu">
<svg class="w-5 h-5" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5"/></svg>
<span>Menu</span>
</button>
)}
<a href="/docs/getting-started" class:list={["bottom-nav-item flex flex-col items-center gap-0.5 px-3 py-1 text-[11px] transition-colors", isDocs ? "text-primary" : "text-on-surface-variant hover:text-on-surface"]}>
<svg class="w-5 h-5" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M12 6.042A8.967 8.967 0 006 3.75c-1.052 0-2.062.18-3 .512v14.25A8.987 8.987 0 016 18c2.305 0 4.408.867 6 2.292m0-14.25a8.966 8.966 0 016-2.292c1.052 0 2.062.18 3 .512v14.25A8.987 8.987 0 0018 18a8.967 8.967 0 00-6 2.292m0-14.25v14.25"/></svg>
<span>Docs</span>
</a>
<a href="https://github.com/dvflw/mantle" class="bottom-nav-item flex flex-col items-center gap-0.5 px-3 py-1 text-[11px] text-on-surface-variant hover:text-on-surface transition-colors" aria-label="GitHub">
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 24 24"><path d="M12 0C5.37 0 0 5.37 0 12c0 5.31 3.435 9.795 8.205 11.385.6.105.825-.255.825-.57 0-.285-.015-1.23-.015-2.235-3.015.555-3.795-.735-4.035-1.41-.135-.345-.72-1.41-1.23-1.695-.42-.225-1.02-.78-.015-.795.945-.015 1.62.87 1.845 1.23 1.08 1.815 2.805 1.305 3.495.99.105-.78.42-1.305.765-1.605-2.67-.3-5.46-1.335-5.46-5.925 0-1.305.465-2.385 1.23-3.225-.12-.3-.54-1.53.12-3.18 0 0 1.005-.315 3.3 1.23.96-.27 1.98-.405 3-.405s2.04.135 3 .405c2.295-1.56 3.3-1.23 3.3-1.23.66 1.65.24 2.88.12 3.18.765.84 1.23 1.905 1.23 3.225 0 4.605-2.805 5.625-5.475 5.925.435.375.81 1.095.81 2.22 0 1.605-.015 2.895-.015 3.3 0 .315.225.69.825.57A12.02 12.02 0 0024 12c0-6.63-5.37-12-12-12z"/></svg>
<span>GitHub</span>
</a>
Comment on lines +37 to +57

Copilot AI Mar 23, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR description mentions the mobile bottom bar includes “home, menu, and search” actions, but the implemented bottom nav has Home, Menu (docs only), Docs, and GitHub — no search action/link. Either update the PR description to match what shipped, or add the intended search affordance to the bottom nav.

Copilot uses AI. Check for mistakes.
</div>
</nav>

<style>
.nav-inner {
transition: max-width 0.3s ease;
}
#mobile-bottom-nav {
padding-bottom: env(safe-area-inset-bottom, 0px);
}
.bottom-nav-item {
-webkit-tap-highlight-color: transparent;
min-width: 3.5rem;
}
.bottom-nav-item:active {
opacity: 0.7;
}
</style>

<script is:inline>
function initNav() {
const btn = document.getElementById('mobile-menu-btn');
const menu = document.getElementById('mobile-menu');
if (!btn || !menu) return;
const btn = document.getElementById('bottom-nav-docs-btn');
const docsSidebar = document.getElementById('docs-sidebar-mobile');
const overlay = document.getElementById('sidebar-overlay');
if (!btn || !docsSidebar || !overlay) return;

// Remove old listeners by cloning
const newBtn = btn.cloneNode(true);
btn.parentNode?.replaceChild(newBtn, btn);
newBtn.addEventListener('click', () => menu.classList.toggle('hidden'));

newBtn.addEventListener('click', () => {
const isOpen = !docsSidebar.classList.contains('-translate-x-full');
if (isOpen) {
docsSidebar.classList.add('-translate-x-full');
overlay.classList.add('hidden');
} else {
docsSidebar.classList.remove('-translate-x-full');
overlay.classList.remove('hidden');
}
Comment on lines +79 to +96

Copilot AI Mar 23, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

initNav() captures a reference to #sidebar-overlay, but DocsSidebar.astro replaces that element via cloneNode/replaceChild. That leaves this handler toggling classes on a detached node, so the overlay (and menu close behavior) can break. Prefer not replacing #sidebar-overlay at all, or re-query the current overlay element inside the click handler (or ensure only one component owns overlay event binding).

Copilot uses AI. Check for mistakes.
});
}
initNav();
document.addEventListener('astro:after-swap', initNav);
Expand Down
16 changes: 2 additions & 14 deletions site/src/layouts/Docs.astro
Original file line number Diff line number Diff line change
Expand Up @@ -24,20 +24,8 @@ const { prev, next } = getPrevNext(currentPath);

<Base title={`${title} - Mantle Docs`}>
<Nav />
<div class="mx-auto max-w-[1280px] px-4 sm:px-6">
<div class="flex min-h-screen pt-16">
<!-- Mobile sidebar toggle -->
<button
id="sidebar-toggle"
class="lg:hidden fixed bottom-6 left-6 z-50 flex items-center gap-2 px-4 py-2.5 bg-surface-container-high border border-outline-variant text-on-surface text-sm font-medium shadow-lg"
aria-label="Toggle sidebar"
>
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
</svg>
Menu
</button>

<div class="mx-auto max-w-[1280px] px-4 sm:px-6 overflow-x-hidden">

Copilot AI Mar 23, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

overflow-x-hidden on the docs container can clip any horizontally overflowing content (notably wide markdown tables). Since the new table-scrolling styles currently target a .table-wrapper that isn’t present, this may result in table content being cut off with no way to scroll. Consider removing overflow-x-hidden or ensuring tables/code blocks have an internal horizontal scroll container before hiding overflow on the page wrapper.

Suggested change
<div class="mx-auto max-w-[1280px] px-4 sm:px-6 overflow-x-hidden">
<div class="mx-auto max-w-[1280px] px-4 sm:px-6">

Copilot uses AI. Check for mistakes.
<div class="flex min-h-screen pt-16 pb-16 md:pb-0">

Copilot AI Mar 23, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The pb-16 added for the mobile bottom nav doesn’t include env(safe-area-inset-bottom), so on iOS the last content can still sit under the nav (nav adds safe-area padding in Nav.astro). Consider using padding that includes the safe-area inset (or a shared CSS var) so the docs content always clears the bottom bar.

Suggested change
<div class="flex min-h-screen pt-16 pb-16 md:pb-0">
<div class="flex min-h-screen pt-16 pb-[calc(4rem+env(safe-area-inset-bottom))] md:pb-0">

Copilot uses AI. Check for mistakes.
<DocsSidebar currentPath={currentPath} />

<!-- Main content -->
Expand Down
2 changes: 1 addition & 1 deletion site/src/pages/index.astro
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import Footer from '../components/Footer.astro';
---
<Base title="Mantle — Headless AI Workflow Automation">
<Nav isHome={true} />
<main id="main-content">
<main id="main-content" class="pb-16 md:pb-0">

Copilot AI Mar 23, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new bottom padding (pb-16) doesn’t account for env(safe-area-inset-bottom). On devices with a home indicator, the bottom nav height becomes h-14 + safe-area, so 4rem padding may still allow content to be obscured. Consider using a calc that includes the safe-area inset (e.g., pb-[calc(4rem+env(safe-area-inset-bottom))]) or a shared CSS variable derived from the bottom-nav height.

Suggested change
<main id="main-content" class="pb-16 md:pb-0">
<main id="main-content" class="pb-[calc(4rem+env(safe-area-inset-bottom))] md:pb-0">

Copilot uses AI. Check for mistakes.
<Hero />
<Features />
<HowItWorks />
Expand Down
36 changes: 35 additions & 1 deletion site/src/styles/global.css
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,17 @@ body {
margin-top: 0;
}

/* Tables */
/* Tables — horizontally scrollable on small screens */
.prose .table-wrapper {
overflow-x: auto;
-webkit-overflow-scrolling: touch;
margin-top: 1.5em;
}

.prose .table-wrapper table {
margin-top: 0;
}
Comment on lines +320 to +329

Copilot AI Mar 23, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new .prose .table-wrapper styles won’t have any effect unless tables are actually wrapped in an element with class="table-wrapper" (search in site/src shows no usage). If the goal is to make markdown tables scroll on mobile, consider applying overflow-x: auto/display: block directly to .prose table under a small-screen media query or adding a markdown/rehype transform that wraps generated tables.

Copilot uses AI. Check for mistakes.

.prose table {
width: 100%;
border-collapse: collapse;
Expand Down Expand Up @@ -365,6 +375,30 @@ body {
border: 1px solid var(--color-outline-variant);
}

/* Mobile prose adjustments */
@media (max-width: 640px) {
.prose h1 {
font-size: 1.5rem;
}

.prose h2 {
font-size: 1.25rem;
}

.prose h3 {
font-size: 1.1rem;
}

.prose pre {
font-size: 0.8125rem;
padding: 0.75em 1em;
}

.prose code {
word-break: break-word;
}
}

/* Definition lists (used in some docs) */
.prose dt {
font-weight: 600;
Expand Down
Loading