Skip to content

Commit e0b517e

Browse files
authored
Merge pull request #144 from braboj/feature/playbook-sidebar
feat: add playbook sidebar nav and fix theme FOUC
2 parents 57cdac8 + ea952bd commit e0b517e

5 files changed

Lines changed: 173 additions & 6 deletions

File tree

astro-site/src/components/Header.astro

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,7 @@ const base = import.meta.env.BASE_URL;
5757

5858
<script is:inline>
5959
const toggle = document.getElementById("theme-toggle");
60-
const saved = localStorage.getItem("theme") || "light";
61-
document.documentElement.setAttribute("data-theme", saved);
60+
const saved = document.documentElement.getAttribute("data-theme") || "light";
6261
updateToggleLabel(saved);
6362

6463
toggle.addEventListener("click", () => {
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
---
2+
interface Recipe {
3+
slug: string;
4+
title: string;
5+
}
6+
7+
interface Props {
8+
currentSection: string;
9+
}
10+
11+
const { currentSection } = Astro.props;
12+
const base = import.meta.env.BASE_URL;
13+
14+
const groups: { label: string; recipes: Recipe[] }[] = [
15+
{
16+
label: "Everyday",
17+
recipes: [
18+
{ slug: "playbook/undoing-changes", title: "Undoing Changes" },
19+
{ slug: "playbook/diffing", title: "Diffing" },
20+
{ slug: "playbook/history", title: "History" },
21+
{ slug: "playbook/stashing", title: "Stashing" },
22+
],
23+
},
24+
{
25+
label: "Branching and Merging",
26+
recipes: [
27+
{ slug: "playbook/branching", title: "Branching" },
28+
{ slug: "playbook/merging", title: "Merging" },
29+
{ slug: "playbook/rebasing", title: "Rebasing" },
30+
{ slug: "playbook/cherry-picking", title: "Cherry-Picking" },
31+
],
32+
},
33+
{
34+
label: "Remote",
35+
recipes: [
36+
{ slug: "playbook/remote-operations", title: "Remote Operations" },
37+
{ slug: "playbook/remote-management", title: "Remote Management" },
38+
],
39+
},
40+
{
41+
label: "Project Structure",
42+
recipes: [
43+
{ slug: "playbook/tagging", title: "Tagging" },
44+
{ slug: "playbook/submodules", title: "Submodules" },
45+
{ slug: "playbook/subtrees", title: "Subtrees" },
46+
],
47+
},
48+
{
49+
label: "Advanced",
50+
recipes: [
51+
{ slug: "playbook/selectors", title: "Selectors" },
52+
{ slug: "playbook/hooks", title: "Hooks" },
53+
{ slug: "playbook/debugging", title: "Debugging" },
54+
{ slug: "playbook/configuration", title: "Configuration" },
55+
],
56+
},
57+
];
58+
---
59+
60+
<nav class="playbook-nav">
61+
<div class="playbook-nav-title">
62+
<a href={`${base}playbook/`} class={currentSection === "playbook" ? "active" : ""}>Playbook</a>
63+
</div>
64+
{groups.map((group) => (
65+
<div class="playbook-nav-group">
66+
<div class="playbook-nav-group-label">{group.label}</div>
67+
<ul>
68+
{group.recipes.map((r) => (
69+
<li>
70+
<a
71+
href={`${base}${r.slug}/`}
72+
class={currentSection === r.slug ? "active" : ""}
73+
>
74+
{r.title}
75+
</a>
76+
</li>
77+
))}
78+
</ul>
79+
</div>
80+
))}
81+
</nav>

astro-site/src/layouts/DocLayout.astro

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
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";
56
import TutorialLinks from "../components/TutorialLinks.astro";
67
import Footer from "../components/Footer.astro";
78
import site from "../data/site.json";
@@ -11,10 +12,12 @@ interface Props {
1112
description?: string;
1213
headings?: { depth: number; slug: string; text: string }[];
1314
currentPath?: string;
15+
currentSection?: string;
1416
jsonLd?: Record<string, unknown>;
1517
}
1618
17-
const { title, description, headings = [], currentPath = "/", jsonLd } = Astro.props;
19+
const { title, description, headings = [], currentPath = "/", currentSection = "", jsonLd } = Astro.props;
20+
const isPlaybook = currentSection === "playbook" || currentSection.startsWith("playbook/");
1821
const pageDescription = description || site.description;
1922
const pageTitle = `${title} — ${site.title}`;
2023
const canonicalUrl = new URL(Astro.url.pathname, Astro.site);
@@ -54,6 +57,13 @@ const ogImage = new URL("/tutorial-git/images/og-banner.png", Astro.site);
5457
{jsonLd && (
5558
<script type="application/ld+json" set:html={JSON.stringify(jsonLd)} />
5659
)}
60+
61+
<script is:inline>
62+
document.documentElement.setAttribute(
63+
"data-theme",
64+
localStorage.getItem("theme") || "light"
65+
);
66+
</script>
5767
</head>
5868
<body>
5969
<a href="#main-content" class="skip-link">Skip to main content</a>
@@ -64,7 +74,11 @@ const ogImage = new URL("/tutorial-git/images/og-banner.png", Astro.site);
6474
<h1>{title}</h1>
6575
<slot />
6676
</main>
67-
<TutorialLinks />
77+
{isPlaybook ? (
78+
<PlaybookNav currentSection={currentSection} />
79+
) : (
80+
<TutorialLinks />
81+
)}
6882
</div>
6983
<Footer />
7084
</body>

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

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

astro-site/src/styles/global.css

Lines changed: 74 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
--space-2xl: 3rem;
3030

3131
/* Sizing */
32-
--sidebar-width: 12rem;
32+
--sidebar-width: 16rem;
3333
--header-height: 3rem;
3434
--tab-height: 2.5rem;
3535
--max-content: 50rem;
@@ -382,6 +382,77 @@ a:hover {
382382
content: "−";
383383
}
384384

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+
}
455+
385456
/* Content area */
386457
.content {
387458
padding: var(--space-xl) var(--space-2xl);
@@ -560,7 +631,8 @@ a:hover {
560631
}
561632

562633
.sidebar-toc,
563-
.sidebar-tutorials {
634+
.sidebar-tutorials,
635+
.playbook-nav {
564636
display: none;
565637
}
566638
}

0 commit comments

Comments
 (0)