Skip to content

Commit 4cd7d09

Browse files
committed
Foldable lesson list menu
1 parent 1915975 commit 4cd7d09

File tree

3 files changed

+75
-3
lines changed

3 files changed

+75
-3
lines changed

src/components/Header.astro

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
---
22
import { SITE_TITLE } from '../consts';
3+
import HeaderLessonsFolder from './HeaderLessonsFolder.astro';
34
import HeaderLink from './HeaderLink.astro';
45
---
56

@@ -8,7 +9,7 @@ import HeaderLink from './HeaderLink.astro';
89
<h2><a href="/">{SITE_TITLE}</a></h2>
910
<div class="internal-links">
1011
<HeaderLink href="/">Home</HeaderLink>
11-
<HeaderLink href="/lessons">Lessons</HeaderLink>
12+
<HeaderLessonsFolder title="Lessons" />
1213
<HeaderLink href="/project">Project</HeaderLink>
1314
</div>
1415
<div class="social-links">
@@ -65,13 +66,13 @@ import HeaderLink from './HeaderLink.astro';
6566
align-items: center;
6667
justify-content: space-between;
6768
}
68-
nav a {
69+
nav :is(a,.nav-link-folder) {
6970
padding: 1em 0.5em;
7071
color: var(--black);
7172
border-bottom: 4px solid transparent;
7273
text-decoration: none;
7374
}
74-
nav a.active {
75+
nav :is(a,.nav-link-folder).active {
7576
text-decoration: none;
7677
border-bottom-color: var(--accent);
7778
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
---
2+
import type { HTMLAttributes } from 'astro/types';
3+
import HeaderLink from './HeaderLink.astro';
4+
import { getCollection } from 'astro:content';
5+
6+
const { class: className, title, ...props } = Astro.props;
7+
8+
const pathname = Astro.url.pathname.replace(import.meta.env.BASE_URL, '');
9+
const prefix = 'lessons';
10+
const isActive = pathname === prefix || pathname.startsWith(prefix + '/')
11+
const id = pathname.replace(/.*\//g, '')
12+
13+
const lessons = (await getCollection('lessons')).filter(
14+
(l) => !(l.data.tags ?? []).includes('draft')
15+
).sort(
16+
(a, b) => (a.data.order ?? 1000) - (b.data.order ?? 1000),
17+
);
18+
19+
---
20+
21+
<input type="checkbox" id="lessons-folder-toggle" style="display: none" />
22+
<div class:list={['nav-link-folder', className, { active: isActive}]} {...props}>
23+
<label for="lessons-folder-toggle">{ title }</label>
24+
{
25+
lessons.map(entry => (
26+
<HeaderLink href={`/${prefix}/${entry.id}`} class:list={['nav-link', { active: id === entry.id} ]} >{entry.data.menu ?? entry.data.title}</HeaderLink>
27+
))
28+
}
29+
</div>

src/styles/global.css

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,3 +177,45 @@ details {
177177
}
178178
}
179179

180+
/* Menu that unfolds on click (no javascript, pure-css, checkbox-based hack) */
181+
.nav-link-folder {
182+
&, label {
183+
cursor: pointer;
184+
}
185+
&.active label {
186+
font-weight: bold;
187+
}
188+
display: inline-flex;
189+
flex-direction: column;
190+
align-items: left;
191+
192+
input:not(:checked) + & {
193+
label::before {
194+
content: "▸";
195+
margin-right: 0.2em;
196+
}
197+
.nav-link {
198+
display: none;
199+
}
200+
}
201+
input:checked + & {
202+
label::before {
203+
content: "▾";
204+
margin-right: 0.2em;
205+
}
206+
.nav-link {
207+
opacity: 1;
208+
margin: 0 -20vw 0 0.15em;
209+
background-color: white;
210+
z-index: 10;
211+
text-decoration: none;
212+
color: rgb(var(--black));
213+
214+
padding-left: .6em;
215+
border-left: 4px solid rgba(var(--black), 15%);
216+
&.active {
217+
border-left-color: var(--accent);
218+
}
219+
}
220+
}
221+
}

0 commit comments

Comments
 (0)