Skip to content

Commit d15b225

Browse files
authored
Merge pull request #7 from flexion/worktree-mobile-menu
Add responsive mobile navigation
2 parents d25a960 + f7acf63 commit d15b225

5 files changed

Lines changed: 496 additions & 1 deletion

File tree

Lines changed: 256 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,256 @@
1+
# Mobile Navigation Implementation Plan
2+
3+
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
4+
5+
**Goal:** Add a responsive hamburger menu that collapses the navigation into a popover card below 36rem viewport width, fixing mobile overflow.
6+
7+
**Architecture:** HTML `popover` API for zero-JS toggle. Single `<nav>` with a popover wrapper `<div>` that becomes `display: contents` at desktop. Media query at 36rem breakpoint controls visibility of button vs inline nav.
8+
9+
**Tech Stack:** Hono JSX (TSX), CSS (layers, custom properties, logical properties), HTML popover API.
10+
11+
---
12+
13+
### Task 1: Update Header Component HTML
14+
15+
**Files:**
16+
- Modify: `src/design/components/header/index.tsx`
17+
18+
- [ ] **Step 1: Add hamburger button and popover wrapper to header**
19+
20+
Replace the entire content of `src/design/components/header/index.tsx` with:
21+
22+
```tsx
23+
import { Link } from '../link'
24+
import { url } from '../../../build/config'
25+
import type { SiteConfig } from '../../../build/config'
26+
27+
export function Header({ config }: { config: SiteConfig }) {
28+
return (
29+
<header class="site-header">
30+
<a href={url('/', config.basePath)} class="site-brand">
31+
<img
32+
src={url('/assets/flexion_tornado.svg', config.basePath)}
33+
alt=""
34+
class="site-brand__logo"
35+
width="38"
36+
height="38"
37+
/>
38+
<span>Flexion Labs</span>
39+
</a>
40+
<button
41+
class="mobile-nav-toggle"
42+
popovertarget="mobile-nav"
43+
aria-label="Menu"
44+
>
45+
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true">
46+
<line x1="3" y1="6" x2="21" y2="6" />
47+
<line x1="3" y1="12" x2="21" y2="12" />
48+
<line x1="3" y1="18" x2="21" y2="18" />
49+
</svg>
50+
</button>
51+
<nav aria-label="Primary">
52+
<div id="mobile-nav" popover>
53+
<ul>
54+
<li>
55+
<a href={url('/work/', config.basePath)}>Work</a>
56+
</li>
57+
<li>
58+
<a href={url('/commitment/', config.basePath)}>Commitment</a>
59+
</li>
60+
<li>
61+
<a href={url('/about/', config.basePath)}>About</a>
62+
</li>
63+
<li>
64+
<Link href="https://github.com/flexion" external>
65+
GitHub
66+
</Link>
67+
</li>
68+
</ul>
69+
</div>
70+
</nav>
71+
</header>
72+
)
73+
}
74+
```
75+
76+
- [ ] **Step 2: Run tests to verify no build breakage**
77+
78+
Run: `bun test --filter smoke`
79+
Expected: PASS — the build still produces valid HTML pages.
80+
81+
- [ ] **Step 3: Commit**
82+
83+
```bash
84+
git add src/design/components/header/index.tsx
85+
git commit -m "feat(header): add hamburger button and popover wrapper for mobile nav"
86+
```
87+
88+
---
89+
90+
### Task 2: Add Mobile/Desktop Media Queries to Layout CSS
91+
92+
**Files:**
93+
- Modify: `src/design/layout.css`
94+
95+
- [ ] **Step 1: Add responsive nav rules to layout.css**
96+
97+
At the end of the `@layer layout { ... }` block (before the closing `}`), add:
98+
99+
```css
100+
/* ---- Responsive navigation ---- */
101+
@media (min-width: 36rem) {
102+
.mobile-nav-toggle {
103+
display: none;
104+
}
105+
#mobile-nav {
106+
display: contents;
107+
}
108+
}
109+
@media (max-width: 36rem) {
110+
.site-header nav ul {
111+
flex-direction: column;
112+
gap: var(--space-3);
113+
}
114+
#mobile-nav {
115+
position: absolute;
116+
inset-block-start: 100%;
117+
inset-inline-end: var(--space-5);
118+
margin: 0;
119+
padding: var(--space-4);
120+
background: var(--color-surface);
121+
border: 1px solid var(--color-surface-alt);
122+
border-radius: var(--radius-md);
123+
box-shadow: var(--shadow-card);
124+
}
125+
}
126+
```
127+
128+
Note: The `position: absolute` on `#mobile-nav` positions the popover card relative to the header. The `.site-header` needs `position: relative` added so the popover anchors correctly.
129+
130+
- [ ] **Step 2: Add position relative to .site-header**
131+
132+
In `layout.css`, inside the existing `.site-header` rule block, add `position: relative;`:
133+
134+
Change:
135+
```css
136+
.site-header {
137+
inline-size: var(--measure-wide);
138+
margin-inline: auto;
139+
padding: var(--space-4) var(--space-5);
140+
display: flex;
141+
align-items: center;
142+
justify-content: space-between;
143+
gap: var(--space-5);
144+
border-block-end: 1px solid var(--color-surface-alt);
145+
}
146+
```
147+
148+
To:
149+
```css
150+
.site-header {
151+
position: relative;
152+
inline-size: var(--measure-wide);
153+
margin-inline: auto;
154+
padding: var(--space-4) var(--space-5);
155+
display: flex;
156+
align-items: center;
157+
justify-content: space-between;
158+
gap: var(--space-5);
159+
border-block-end: 1px solid var(--color-surface-alt);
160+
}
161+
```
162+
163+
- [ ] **Step 3: Run tests**
164+
165+
Run: `bun test --filter smoke`
166+
Expected: PASS
167+
168+
- [ ] **Step 4: Commit**
169+
170+
```bash
171+
git add src/design/layout.css
172+
git commit -m "feat(layout): add responsive nav media queries at 36rem breakpoint"
173+
```
174+
175+
---
176+
177+
### Task 3: Style the Hamburger Button
178+
179+
**Files:**
180+
- Modify: `src/design/components/header/styles.css`
181+
182+
- [ ] **Step 1: Add mobile-nav-toggle styles**
183+
184+
Append to `src/design/components/header/styles.css`:
185+
186+
```css
187+
.mobile-nav-toggle {
188+
display: inline-flex;
189+
align-items: center;
190+
justify-content: center;
191+
background: none;
192+
border: none;
193+
padding: var(--space-2);
194+
cursor: pointer;
195+
color: var(--color-ink);
196+
border-radius: var(--radius-sm);
197+
}
198+
.mobile-nav-toggle:focus-visible {
199+
outline: 2px solid var(--color-focus-ring);
200+
outline-offset: 2px;
201+
}
202+
```
203+
204+
Note: The `display: none` at desktop is handled by the media query in `layout.css`. These styles define appearance when visible.
205+
206+
- [ ] **Step 2: Run tests**
207+
208+
Run: `bun test --filter smoke`
209+
Expected: PASS
210+
211+
- [ ] **Step 3: Commit**
212+
213+
```bash
214+
git add src/design/components/header/styles.css
215+
git commit -m "feat(header): style hamburger menu toggle button"
216+
```
217+
218+
---
219+
220+
### Task 4: Visual Verification
221+
222+
**Files:** None (testing only)
223+
224+
- [ ] **Step 1: Build the site**
225+
226+
Run: `bun run build`
227+
228+
- [ ] **Step 2: Serve and verify in browser**
229+
230+
Run: `bunx serve dist` (or equivalent static server)
231+
232+
Verify at mobile width (375px in DevTools):
233+
1. Hamburger button appears, nav links are hidden.
234+
2. Tapping hamburger opens popover card with stacked links.
235+
3. Pressing Escape or clicking outside closes the popover.
236+
4. "Flexion Labs" brand stays on one line.
237+
5. Page does not overflow the viewport horizontally.
238+
239+
Verify at desktop width (>576px):
240+
1. Hamburger button is hidden.
241+
2. Nav links display horizontally as before.
242+
3. No visual regression from the popover wrapper.
243+
244+
- [ ] **Step 3: Run full test suite**
245+
246+
Run: `bun test`
247+
Expected: 67 pass (the a11y test may still fail due to needing a fresh build — that's pre-existing).
248+
249+
- [ ] **Step 4: Commit any fixes if needed, then final commit**
250+
251+
If all looks good:
252+
```bash
253+
git log --oneline worktree-mobile-menu ^main
254+
```
255+
256+
Expected: 3 commits (header HTML, layout CSS, button styles).

0 commit comments

Comments
 (0)