Skip to content

Commit 3273e28

Browse files
Martin Mahnerclaude
authored andcommitted
Implement responsive mobile navigation
- **Mobile Menu**: Add burger menu and responsive navigation layout - Collapsible menu for screens < 640px - Smooth transitions using Alpine.js - Unified navigation structure for mobile and desktop - **Changelog**: Update Unreleased section with new features - **Styles**: Minor formatting updates to default.css 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 6ddef23 commit 3273e28

4 files changed

Lines changed: 177 additions & 123 deletions

File tree

CHANGELOG.md

Lines changed: 36 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,28 @@
88
- Allows setting custom footer text instead of automatic build timestamp
99
- Example: `microdocs README.md --footer "v1.1 2025-01-01"`
1010
- Falls back to timestamp if not provided
11-
12-
### Fixed
13-
14-
- **TOC deep linking across sections** - Fixed table of contents links navigating to wrong section
15-
- Heading IDs are now prefixed with section name (e.g., `readme-deep-dive`, `guide-deep-dive`)
16-
- Prevents TOC links from jumping to identically-named headings in other sections
17-
- Added custom `slugify` function to markdown `toc` extension for ID prefixing
18-
- Added Playwright test to verify TOC navigation stays within correct section
19-
- **Sticky header overlap** - Fixed headings appearing under sticky navigation when scrolling via TOC
20-
- Added `scroll-padding-top: 86px` to CSS for proper anchor positioning
21-
- Added `scroll-behavior: smooth` for smooth scrolling
22-
- Configured Tocbot with `headingsOffset: 86` for accurate scroll spy detection
23-
- Set `scrollSmooth: false` to let browser handle native scrolling behavior
24-
- **Header title navigation** - Clicking the documentation title now returns to first section and scrolls to top
25-
- Uses Alpine.js to set active section and scroll to page top
26-
- Provides intuitive way to return to beginning of documentation
11+
- **Mobile Navigation** - Added responsive burger menu for mobile devices
12+
- Collapsible navigation menu for screens smaller than 640px
13+
- Smooth transition animations for menu toggle
14+
- Includes action buttons (theme toggle, repo link) in mobile view
15+
- Maintains clean row layout for desktop view
16+
- **Playwright testing infrastructure** for end-to-end template testing
17+
- `playwright/build-test-template.js` - Script to build and test templates with real content
18+
- `playwright/fixtures/` - Sample markdown files for testing
19+
- `playwright/playwright.config.js` - Playwright configuration
20+
- Playwright dependencies added to `package.json`
21+
- Test results directories added to `.gitignore`
22+
- **Vite configuration** (`vite.config.js`)
23+
- Auto-discovers template directories
24+
- Configures single-file builds with viteSingleFile plugin
25+
- Removes module attributes from inlined scripts
26+
- Minifies output with Terser
27+
- **Package build configuration** - Excluded development files from PyPI distribution
28+
- Excludes: `playwright/`, `templates_src/`, `node_modules/`, config files
29+
- **Image Row Detection** - Automatically detects and styles paragraphs containing only linked images
30+
- Applies `.image-row` class to paragraphs containing only linked images or SVGs
31+
- Supports multiple images per link (e.g. for complex badges)
32+
- Ensures proper alignment and spacing for badge rows
2733

2834
### Changed
2935

@@ -39,7 +45,6 @@
3945
- Consolidated mobile and desktop navigation into single responsive component
4046
- Removed duplicate `id="mobile-nav"` - now uses single `id="main-nav"` that adapts
4147
- Reduced HTML payload by ~3KB and eliminated code duplication
42-
4348
- **Markdown rendering improvements** - Enhanced markdown processing with GitHub-flavored features
4449
- Added `mdx-truly-sane-lists` extension for proper nested list rendering with 2-space indentation
4550
- Lists now render with correct `<ul>` nesting instead of flattening all items into a single list
@@ -81,25 +86,21 @@
8186
- Updated CLAUDE.md with Vite workflow instructions
8287
- Updated README.md with simplified template usage section
8388

84-
### Added
89+
### Fixed
8590

86-
- **Playwright testing infrastructure** for end-to-end template testing
87-
- `playwright/build-test-template.js` - Script to build and test templates with real content
88-
- `playwright/fixtures/` - Sample markdown files for testing
89-
- `playwright/playwright.config.js` - Playwright configuration
90-
- Playwright dependencies added to `package.json`
91-
- Test results directories added to `.gitignore`
92-
- **Vite configuration** (`vite.config.js`)
93-
- Auto-discovers template directories
94-
- Configures single-file builds with viteSingleFile plugin
95-
- Removes module attributes from inlined scripts
96-
- Minifies output with Terser
97-
- **Package build configuration** - Excluded development files from PyPI distribution
98-
- Excludes: `playwright/`, `templates_src/`, `node_modules/`, config files
99-
- **Image Row Detection** - Automatically detects and styles paragraphs containing only linked images
100-
- Applies `.image-row` class to paragraphs containing only linked images or SVGs
101-
- Supports multiple images per link (e.g. for complex badges)
102-
- Ensures proper alignment and spacing for badge rows
91+
- **TOC deep linking across sections** - Fixed table of contents links navigating to wrong section
92+
- Heading IDs are now prefixed with section name (e.g., `readme-deep-dive`, `guide-deep-dive`)
93+
- Prevents TOC links from jumping to identically-named headings in other sections
94+
- Added custom `slugify` function to markdown `toc` extension for ID prefixing
95+
- Added Playwright test to verify TOC navigation stays within correct section
96+
- **Sticky header overlap** - Fixed headings appearing under sticky navigation when scrolling via TOC
97+
- Added `scroll-padding-top: 86px` to CSS for proper anchor positioning
98+
- Added `scroll-behavior: smooth` for smooth scrolling
99+
- Configured Tocbot with `headingsOffset: 86` for accurate scroll spy detection
100+
- Set `scrollSmooth: false` to let browser handle native scrolling behavior
101+
- **Header title navigation** - Clicking the documentation title now returns to first section and scrolls to top
102+
- Uses Alpine.js to set active section and scroll to page top
103+
- Provides intuitive way to return to beginning of documentation
103104

104105
### Removed
105106

microdocs/templates/default/default.html

Lines changed: 65 additions & 38 deletions
Large diffs are not rendered by default.

templates_src/default/default.css

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ html {
2929
.image-row {
3030
@apply flex flex-wrap gap-1.5 align-middle;
3131

32-
a > img {
32+
a>img {
3333
@apply m-0;
3434
}
3535
}
@@ -50,17 +50,24 @@ html {
5050
@apply no-underline text-purple-600 dark:text-purple-400;
5151
}
5252

53-
a:hover, a:active {
53+
a:hover,
54+
a:active {
5455
@apply underline;
5556
}
5657

5758
/* Headings use custom font */
5859

59-
h1, h2, h3, h4, h5, h6 {
60+
h1,
61+
h2,
62+
h3,
63+
h4,
64+
h5,
65+
h6 {
6066
@apply font-heading font-semibold;
6167
}
6268

63-
h1, h2 {
69+
h1,
70+
h2 {
6471
@apply pb-2 border-b-1 border-b-gray-300 dark:border-b-gray-700;
6572
}
6673

@@ -74,15 +81,7 @@ html {
7481
* Tocbot TOC styling
7582
* -------------------------------------------------------------------------- */
7683
.js-toc .toc-list {
77-
list-style: none;
78-
padding: 0;
79-
margin: 0;
80-
font-size: 0.875rem;
81-
line-height: 1.25;
82-
}
83-
84-
.js-toc .toc-link {
85-
@apply no-underline block py-1 pl-3;
84+
@apply .js-toc .toc-link @apply no-underline { } block m-0 p-0 py-1 pl-3 text-sm leading-5 list-none;
8685
@apply text-gray-600 dark:text-gray-400;
8786
@apply border-l-2 border-gray-300 dark:border-gray-700;
8887
@apply duration-150 transition-colors;

templates_src/default/default.html

Lines changed: 64 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -21,51 +21,78 @@
2121
x-init="MicrodocsApp.init($data)"
2222
>
2323
<!-- Header -->
24-
<header class="z-50 sticky top-0 bg-white border-b border-gray-300 dark:bg-gray-950 dark:border-gray-700">
24+
<header
25+
class="z-50 sticky top-0 bg-white border-b border-gray-300 dark:bg-gray-950 dark:border-gray-700"
26+
x-data="{ mobileMenuOpen: false }"
27+
>
2528
<div class="max-w-5xl mx-auto px-4 py-3 sm:px-6 sm:py-4">
26-
<div class="flex flex-col gap-3 sm:flex-row sm:gap-8 sm:items-center">
27-
<!-- Logo/Title -->
28-
<h1 class="font-heading font-semibold text-lg text-gray-900 dark:text-gray-50 sm:text-xl">
29-
<a @click="activeSection = '{{ sections[0].id }}'; window.scrollTo(0, 0)" class="cursor-pointer">{{ title }}</a>
30-
</h1>
29+
<div class="flex flex-col sm:flex-row sm:gap-8 sm:items-center">
3130

32-
<!-- Navigation -->
33-
<nav id="main-nav" class="flex-1 overflow-x-auto scrollbar-hide -mx-4 px-4 sm:overflow-visible sm:mx-0 sm:px-0">
34-
<ul class="flex gap-1 sm:gap-1">
35-
{% for section in sections %}
36-
<li class="shrink-0" data-section-id="{{ section.id }}">
37-
<button
38-
@click="activeSection = '{{ section.id }}'"
39-
:class="activeSection === '{{ section.id }}' ? 'font-semibold text-gray-900 dark:text-gray-50 bg-gray-300/20 dark:bg-gray-700/20 sm:bg-transparent' : 'text-gray-600 dark:text-gray-400'"
40-
class="px-3 py-1.5 text-sm whitespace-nowrap rounded-md transition-colors cursor-pointer dark:hover:text-gray-50 sm:px-3 sm:py-1 sm:rounded-none hover:text-gray-900"
41-
>
42-
{{ section.name }}
43-
</button>
44-
</li>
45-
{% endfor %}
46-
</ul>
47-
</nav>
31+
<!-- Top Row: Logo + Burger -->
32+
<div class="flex items-center justify-between">
33+
<!-- Logo/Title -->
34+
<h1 class="font-heading font-semibold text-lg text-gray-900 dark:text-gray-50 sm:text-xl">
35+
<a @click="activeSection = '{{ sections[0].id }}'; window.scrollTo(0, 0)" class="cursor-pointer">{{ title }}</a>
36+
</h1>
4837

49-
<!-- Action Buttons -->
50-
<div class="hidden shrink-0 gap-3 items-center sm:flex">
51-
<!-- Theme Toggle -->
52-
<button @click="theme = theme === 'light' ? 'dark' : 'light'" class="text-gray-600 transition-colors dark:text-gray-400 dark:hover:text-gray-50 hover:text-gray-900" title="Toggle theme">
53-
<svg x-show="theme === 'light'" class="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
54-
<path stroke-linecap="round" stroke-linejoin="round" d="M21.752 15.002A9.72 9.72 0 0 1 18 15.75c-5.385 0-9.75-4.365-9.75-9.75 0-1.33.266-2.597.748-3.752A9.753 9.753 0 0 0 3 11.25C3 16.635 7.365 21 12.75 21a9.753 9.753 0 0 0 9.002-5.998Z" />
38+
<!-- Burger Button (Mobile Only) -->
39+
<button
40+
@click="mobileMenuOpen = !mobileMenuOpen"
41+
class="-mr-1 p-1 text-gray-600 rounded-md dark:text-gray-400 dark:hover:text-gray-50 dark:hover:bg-gray-800 sm:hidden hover:text-gray-900 hover:bg-gray-100"
42+
aria-label="Toggle navigation"
43+
>
44+
<svg x-show="!mobileMenuOpen" class="w-6 h-6" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
45+
<path stroke-linecap="round" stroke-linejoin="round" d="M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5" />
5546
</svg>
56-
<svg x-show="theme === 'dark'" class="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
57-
<path stroke-linecap="round" stroke-linejoin="round" d="M12 3v2.25m6.364.386-1.591 1.591M21 12h-2.25m-.386 6.364-1.591-1.591M12 18.75V21m-4.773-4.227-1.591 1.591M5.25 12H3m4.227-4.773L5.636 5.636M15.75 12a3.75 3.75 0 1 1-7.5 0 3.75 3.75 0 0 1 7.5 0Z" />
47+
<svg x-show="mobileMenuOpen" class="w-6 h-6" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" style="display: none;">
48+
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" />
5849
</svg>
5950
</button>
51+
</div>
52+
53+
<!-- Navigation & Actions Container -->
54+
<div
55+
class="flex flex-col gap-4 pt-4 pb-2 sm:flex-1 sm:flex-row sm:gap-8 sm:items-center sm:justify-between sm:pt-0 sm:pb-0"
56+
:class="'flex' 'hidden ? mobileMenuOpen sm:flex' :"
57+
>
58+
<!-- Navigation -->
59+
<nav id="main-nav" class="flex-1">
60+
<ul class="flex flex-col gap-1 sm:flex-row sm:gap-1">
61+
{% for section in sections %}
62+
<li class="shrink-0" data-section-id="{{ section.id }}">
63+
<button
64+
@click="activeSection = '{{ section.id }}'; mobileMenuOpen = false"
65+
:class="activeSection === '{{ section.id }}' ? 'font-semibold text-gray-900 dark:text-gray-50 bg-gray-100 dark:bg-gray-800 sm:bg-transparent sm:dark:bg-transparent' : 'text-gray-600 dark:text-gray-400'"
66+
class="w-full px-3 py-2 text-left text-sm rounded-md transition-colors cursor-pointer sm:dark:hover:bg-transparent dark:hover:text-gray-50 dark:hover:bg-gray-800 sm:w-auto sm:px-3 sm:py-1 sm:rounded-none sm:hover:text-gray-900 sm:hover:bg-transparent hover:bg-gray-50"
67+
>
68+
{{ section.name }}
69+
</button>
70+
</li>
71+
{% endfor %}
72+
</ul>
73+
</nav>
6074

61-
<!-- Repository Link -->
62-
{% if repo_url %}
63-
<a href="{{ repo_url }}" target="_blank" rel="noopener noreferrer" class="text-gray-600 transition-colors dark:text-gray-400 dark:hover:text-gray-50 hover:text-gray-900" title="Repository">
64-
<svg class="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
65-
<path stroke-linecap="round" stroke-linejoin="round" d="M17.25 6.75 22.5 12l-5.25 5.25m-10.5 0L1.5 12l5.25-5.25m7.5-3-4.5 16.5" />
75+
<!-- Action Buttons -->
76+
<div class="flex gap-3 items-center mt-2 px-3 pt-4 border-t border-gray-100 dark:border-gray-800 sm:mt-0 sm:px-0 sm:pt-0 sm:border-0">
77+
<!-- Theme Toggle -->
78+
<button @click="theme = theme === 'light' ? 'dark' : 'light'" class="text-gray-600 transition-colors dark:text-gray-400 dark:hover:text-gray-50 hover:text-gray-900" title="Toggle theme">
79+
<svg x-show="theme === 'light'" class="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
80+
<path stroke-linecap="round" stroke-linejoin="round" d="M21.752 15.002A9.72 9.72 0 0 1 18 15.75c-5.385 0-9.75-4.365-9.75-9.75 0-1.33.266-2.597.748-3.752A9.753 9.753 0 0 0 3 11.25C3 16.635 7.365 21 12.75 21a9.753 9.753 0 0 0 9.002-5.998Z" />
81+
</svg>
82+
<svg x-show="theme === 'dark'" class="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" style="display: none;">
83+
<path stroke-linecap="round" stroke-linejoin="round" d="M12 3v2.25m6.364.386-1.591 1.591M21 12h-2.25m-.386 6.364-1.591-1.591M12 18.75V21m-4.773-4.227-1.591 1.591M5.25 12H3m4.227-4.773L5.636 5.636M15.75 12a3.75 3.75 0 1 1-7.5 0 3.75 3.75 0 0 1 7.5 0Z" />
6684
</svg>
67-
</a>
68-
{% endif %}
85+
</button>
86+
87+
<!-- Repository Link -->
88+
{% if repo_url %}
89+
<a href="{{ repo_url }}" target="_blank" rel="noopener noreferrer" class="text-gray-600 transition-colors dark:text-gray-400 dark:hover:text-gray-50 hover:text-gray-900" title="Repository">
90+
<svg class="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
91+
<path stroke-linecap="round" stroke-linejoin="round" d="M17.25 6.75 22.5 12l-5.25 5.25m-10.5 0L1.5 12l5.25-5.25m7.5-3-4.5 16.5" />
92+
</svg>
93+
</a>
94+
{% endif %}
95+
</div>
6996
</div>
7097
</div>
7198
</div>

0 commit comments

Comments
 (0)