Skip to content

Commit 9668f5d

Browse files
authored
Merge pull request #145 from braboj/feature/resizable-sidebar
feat: add resizable sidebars and fix FOUC
2 parents e0b517e + e0ce3ea commit 9668f5d

4 files changed

Lines changed: 65 additions & 172 deletions

File tree

astro-site/src/components/PlaybookNav.astro

Lines changed: 0 additions & 81 deletions
This file was deleted.

astro-site/src/layouts/DocLayout.astro

Lines changed: 46 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
import "../styles/global.css";
33
import Header from "../components/Header.astro";
44
import TableOfContents from "../components/TableOfContents.astro";
5-
import PlaybookNav from "../components/PlaybookNav.astro";
65
import TutorialLinks from "../components/TutorialLinks.astro";
76
import Footer from "../components/Footer.astro";
87
import site from "../data/site.json";
@@ -12,12 +11,10 @@ interface Props {
1211
description?: string;
1312
headings?: { depth: number; slug: string; text: string }[];
1413
currentPath?: string;
15-
currentSection?: string;
1614
jsonLd?: Record<string, unknown>;
1715
}
1816
19-
const { title, description, headings = [], currentPath = "/", currentSection = "", jsonLd } = Astro.props;
20-
const isPlaybook = currentSection === "playbook" || currentSection.startsWith("playbook/");
17+
const { title, description, headings = [], currentPath = "/", jsonLd } = Astro.props;
2118
const pageDescription = description || site.description;
2219
const pageTitle = `${title} — ${site.title}`;
2320
const canonicalUrl = new URL(Astro.url.pathname, Astro.site);
@@ -31,6 +28,7 @@ const ogImage = new URL("/tutorial-git/images/og-banner.png", Astro.site);
3128
<meta name="viewport" content="width=device-width, initial-scale=1" />
3229
<title>{pageTitle}</title>
3330
<meta name="description" content={pageDescription} />
31+
<link rel="icon" href={`${import.meta.env.BASE_URL}favicon.svg`} type="image/svg+xml" />
3432
<link rel="canonical" href={canonicalUrl} />
3533

3634
<!-- Open Graph -->
@@ -47,12 +45,7 @@ const ogImage = new URL("/tutorial-git/images/og-banner.png", Astro.site);
4745
<meta name="twitter:description" content={pageDescription} />
4846
<meta name="twitter:image" content={ogImage} />
4947

50-
<link rel="preconnect" href="https://fonts.googleapis.com" />
51-
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
52-
<link
53-
href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;600;700&family=Roboto+Mono:wght@400;500&display=swap"
54-
rel="stylesheet"
55-
/>
48+
5649

5750
{jsonLd && (
5851
<script type="application/ld+json" set:html={JSON.stringify(jsonLd)} />
@@ -70,16 +63,54 @@ const ogImage = new URL("/tutorial-git/images/og-banner.png", Astro.site);
7063
<Header currentPath={currentPath} />
7164
<div class="site-main">
7265
<TableOfContents headings={headings} />
66+
<div class="resize-handle" data-side="left"></div>
7367
<main class="content" id="main-content">
7468
<h1>{title}</h1>
7569
<slot />
7670
</main>
77-
{isPlaybook ? (
78-
<PlaybookNav currentSection={currentSection} />
79-
) : (
80-
<TutorialLinks />
81-
)}
71+
<div class="resize-handle" data-side="right"></div>
72+
<TutorialLinks />
8273
</div>
8374
<Footer />
75+
76+
<script is:inline>
77+
(function () {
78+
var root = document.documentElement;
79+
document.querySelectorAll(".resize-handle").forEach(function (handle) {
80+
var side = handle.getAttribute("data-side");
81+
handle.addEventListener("mousedown", function (e) {
82+
e.preventDefault();
83+
var startX = e.clientX;
84+
var col = side === "left" ? 0 : 4;
85+
var grid = handle.parentElement;
86+
var current = grid.querySelectorAll(
87+
side === "left" ? ".sidebar-toc" : ".sidebar-tutorials"
88+
)[0];
89+
var startWidth = current ? current.offsetWidth : 256;
90+
91+
function onMove(e) {
92+
var delta = e.clientX - startX;
93+
var newWidth = side === "left" ? startWidth + delta : startWidth - delta;
94+
newWidth = Math.max(140, Math.min(400, newWidth));
95+
var cols = getComputedStyle(grid).gridTemplateColumns.split(" ");
96+
cols[col] = newWidth + "px";
97+
grid.style.gridTemplateColumns = cols.join(" ");
98+
}
99+
100+
function onUp() {
101+
document.removeEventListener("mousemove", onMove);
102+
document.removeEventListener("mouseup", onUp);
103+
document.body.style.userSelect = "";
104+
document.body.style.cursor = "";
105+
}
106+
107+
document.body.style.userSelect = "none";
108+
document.body.style.cursor = "col-resize";
109+
document.addEventListener("mousemove", onMove);
110+
document.addEventListener("mouseup", onUp);
111+
});
112+
});
113+
})();
114+
</script>
84115
</body>
85116
</html>

astro-site/src/pages/[...slug].astro

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@ const jsonLd = {
4747
description={entry.data.description}
4848
headings={headings}
4949
currentPath={sectionPath}
50-
currentSection={page.section}
5150
jsonLd={jsonLd}
5251
>
5352
<Content />

astro-site/src/styles/global.css

Lines changed: 19 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@
3535
--max-content: 50rem;
3636

3737
/* Typography */
38-
--font-text: "Roboto", system-ui, sans-serif;
39-
--font-code: "Roboto Mono", ui-monospace, monospace;
38+
--font-text: system-ui, -apple-system, sans-serif;
39+
--font-code: ui-monospace, "Cascadia Code", "Fira Code", monospace;
4040
--font-size-sm: 0.8125rem;
4141
--font-size-base: 0.875rem;
4242
--font-size-lg: 1rem;
@@ -277,7 +277,7 @@ a:hover {
277277
font-weight: 500;
278278
text-transform: uppercase;
279279
letter-spacing: 0.04em;
280-
padding: 0 var(--space-sm);
280+
padding: 0 0.75rem;
281281
height: var(--tab-height);
282282
display: flex;
283283
align-items: center;
@@ -299,12 +299,26 @@ a:hover {
299299
/* Three-column layout */
300300
.site-main {
301301
display: grid;
302-
grid-template-columns: var(--sidebar-width) minmax(0, 1fr) var(--sidebar-width);
302+
grid-template-columns: var(--sidebar-width) 4px minmax(0, 1fr) 4px var(--sidebar-width);
303303
max-width: calc(var(--max-content) + 2 * var(--sidebar-width) + 2 * var(--space-xl));
304304
margin: 0 auto;
305305
min-height: calc(100vh - var(--header-height) - var(--tab-height));
306306
}
307307

308+
/* Resize handles */
309+
.resize-handle {
310+
width: 4px;
311+
cursor: col-resize;
312+
background: transparent;
313+
transition: background 0.15s;
314+
z-index: 10;
315+
}
316+
317+
.resize-handle:hover,
318+
.resize-handle:active {
319+
background: var(--color-primary-light);
320+
}
321+
308322
/* Left sidebar — TOC */
309323
.sidebar-toc {
310324
position: sticky;
@@ -382,76 +396,6 @@ a:hover {
382396
content: "−";
383397
}
384398

385-
/* Right sidebar — Playbook navigation */
386-
.playbook-nav {
387-
position: sticky;
388-
top: calc(var(--header-height) + var(--tab-height));
389-
height: calc(100vh - var(--header-height) - var(--tab-height));
390-
overflow-y: auto;
391-
padding: var(--space-lg) var(--space-md);
392-
border-left: 1px solid var(--color-border);
393-
font-size: var(--font-size-sm);
394-
}
395-
396-
.playbook-nav-title {
397-
font-size: var(--font-size-sm);
398-
font-weight: 700;
399-
text-transform: uppercase;
400-
letter-spacing: 0.05em;
401-
margin-bottom: var(--space-md);
402-
}
403-
404-
.playbook-nav-title a {
405-
color: var(--color-fg-muted);
406-
}
407-
408-
.playbook-nav-title a:hover,
409-
.playbook-nav-title a.active {
410-
color: var(--color-primary-light);
411-
text-decoration: none;
412-
}
413-
414-
.playbook-nav-group {
415-
margin-bottom: var(--space-md);
416-
}
417-
418-
.playbook-nav-group-label {
419-
font-size: 0.75rem;
420-
font-weight: 600;
421-
text-transform: uppercase;
422-
letter-spacing: 0.04em;
423-
color: var(--color-fg-faint);
424-
margin-bottom: var(--space-xs);
425-
}
426-
427-
.playbook-nav ul {
428-
list-style: none;
429-
margin: 0;
430-
padding: 0;
431-
}
432-
433-
.playbook-nav li {
434-
margin-bottom: 1px;
435-
}
436-
437-
.playbook-nav li a {
438-
display: block;
439-
color: var(--color-fg-muted);
440-
padding: var(--space-xs) var(--space-sm);
441-
border-radius: 3px;
442-
}
443-
444-
.playbook-nav li a:hover {
445-
color: var(--color-primary-light);
446-
background: var(--color-bg-hover);
447-
text-decoration: none;
448-
}
449-
450-
.playbook-nav li a.active {
451-
color: var(--color-primary);
452-
background: var(--color-bg-alt);
453-
font-weight: 500;
454-
}
455399

456400
/* Content area */
457401
.content {
@@ -632,7 +576,7 @@ a:hover {
632576

633577
.sidebar-toc,
634578
.sidebar-tutorials,
635-
.playbook-nav {
579+
.resize-handle {
636580
display: none;
637581
}
638582
}

0 commit comments

Comments
 (0)