feat(ui): add responsive navigation and mobile layout improvements

Add hamburger menu toggle with ARIA support for mobile nav. Introduce
responsive breakpoints at 768px (tablet) and 480px (phone) with stacked
nav, adjusted spacing, and full-width elements. Add table overflow
protection and responsive refinements across all page layouts.
This commit is contained in:
2026-05-26 18:34:42 +02:00
parent 46bd3cc2fd
commit ca47c7bae9
9 changed files with 733 additions and 19 deletions
+170 -8
View File
@@ -145,6 +145,7 @@ a {
.nav { .nav {
display: flex; display: flex;
gap: var(--space-xl); gap: var(--space-xl);
align-items: center;
} }
.nav a { .nav a {
@@ -153,6 +154,7 @@ a {
font-size: 0.9rem; font-size: 0.9rem;
letter-spacing: 0.02em; letter-spacing: 0.02em;
position: relative; position: relative;
white-space: nowrap;
} }
.nav a::after { .nav a::after {
@@ -176,8 +178,26 @@ a {
width: 100%; width: 100%;
} }
/* Hamburger menu toggle (hidden by default, visible on mobile) */
.nav-toggle {
display: none;
background: none;
border: 1px solid var(--color-border);
color: var(--color-text);
font-size: 1.5rem;
cursor: pointer;
padding: 0.4rem 0.6rem;
line-height: 1;
border-radius: 4px;
transition: border-color 0.2s ease, color 0.2s ease;
}
.nav-toggle:hover {
border-color: var(--color-accent);
color: var(--color-accent);
}
.nav-download { .nav-download {
margin-left: auto;
color: var(--color-bg) !important; color: var(--color-bg) !important;
background: var(--color-accent); background: var(--color-accent);
padding: 0.65rem 1.75rem; padding: 0.65rem 1.75rem;
@@ -201,6 +221,14 @@ a {
box-shadow: 0 2px 12px rgba(0, 221, 119, 0.3); box-shadow: 0 2px 12px rgba(0, 221, 119, 0.3);
} }
/* Table overflow protection */
table {
display: block;
overflow-x: auto;
-webkit-overflow-scrolling: touch;
max-width: 100%;
}
/* ===== Hero Section ===== */ /* ===== Hero Section ===== */
.hero { .hero {
position: relative; position: relative;
@@ -671,7 +699,7 @@ section {
.feature-row { .feature-row {
display: grid; display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
gap: var(--space-lg); gap: var(--space-lg);
} }
@@ -781,7 +809,7 @@ section {
.arch-grid { .arch-grid {
display: grid; display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: var(--space-xl); gap: var(--space-xl);
margin-top: var(--space-2xl); margin-top: var(--space-2xl);
} }
@@ -1096,7 +1124,7 @@ section {
.download-grid { .download-grid {
display: grid; display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
gap: var(--space-lg); gap: var(--space-lg);
margin-bottom: var(--space-xl); margin-bottom: var(--space-xl);
} }
@@ -1303,19 +1331,63 @@ section {
} }
} }
/* Tablet and smaller */
@media (max-width: 768px) { @media (max-width: 768px) {
.site-header { .site-header {
padding: var(--space-sm) 0; padding: var(--space-sm) 0;
} }
.header-content {
flex-wrap: wrap;
gap: var(--space-sm);
}
.logo-image {
height: 32px;
max-width: 140px;
}
/* Show hamburger toggle, hide nav by default */
.nav-toggle {
display: block;
}
.nav { .nav {
gap: var(--space-md); display: none;
font-size: 0.8rem; flex-direction: column;
gap: 0;
width: 100%;
order: 3;
padding-top: var(--space-sm);
background: var(--color-bg);
border: 1px solid var(--color-border);
border-radius: 4px;
overflow: hidden;
}
.nav.nav-open {
display: flex;
}
.nav a {
font-size: 0.85rem;
padding: 0.75rem var(--space-md);
border-bottom: 1px solid var(--color-border);
}
.nav a:last-child {
border-bottom: none;
}
.nav a::after {
display: none;
} }
.nav-download { .nav-download {
padding: 0.5rem 1rem; border-radius: 0;
font-size: 0.75rem !important; text-align: center;
padding: 0.75rem var(--space-md) !important;
font-size: 0.85rem !important;
letter-spacing: 0.06em !important; letter-spacing: 0.06em !important;
} }
@@ -1371,8 +1443,14 @@ section {
grid-template-columns: 1fr; grid-template-columns: 1fr;
gap: var(--space-lg); gap: var(--space-lg);
} }
.download-disclaimer {
flex-direction: column;
text-align: center;
}
} }
/* Small phones */
@media (max-width: 480px) { @media (max-width: 480px) {
.container, .container,
.features-layout, .features-layout,
@@ -1381,10 +1459,65 @@ section {
padding: 0 var(--space-md); padding: 0 var(--space-md);
} }
.site-header {
padding: var(--space-xs) 0;
}
.logo-image {
height: 28px;
max-width: 120px;
}
.nav a {
font-size: 0.8rem;
padding: 0.6rem var(--space-sm);
}
.nav-download {
padding: 0.6rem var(--space-sm) !important;
font-size: 0.8rem !important;
white-space: nowrap;
text-align: center;
}
.nav-toggle {
padding: 0.3rem 0.5rem;
font-size: 1.25rem;
}
.hero {
padding-top: calc(var(--space-xl) + 60px);
padding-bottom: var(--space-xl);
}
.hero-label {
font-size: 0.75rem;
}
.hero-description {
font-size: 1rem;
}
section {
padding: var(--space-xl) 0;
}
.section-title {
font-size: clamp(1.75rem, 8vw, 2.5rem);
}
.feature-primary, .feature-primary,
.pricing-block { .pricing-block {
padding: var(--space-lg); padding: var(--space-lg);
} }
.feature-item {
padding: var(--space-lg);
}
.feature-content h3 {
font-size: 1.5rem;
}
.pricing-features { .pricing-features {
flex-direction: column; flex-direction: column;
@@ -1394,6 +1527,35 @@ section {
width: 100%; width: 100%;
text-align: center; text-align: center;
} }
.pricing-action {
width: 100%;
justify-content: center;
}
.platform-card {
padding: var(--space-lg);
}
.platform-name {
font-size: 1.25rem;
}
.footer-section {
text-align: center;
}
.footer-section a {
padding-left: 0;
}
.footer-section a::before {
display: none;
}
.footer-bottom {
font-size: 0.75rem;
}
} }
/* ===== Animations & Effects ===== */ /* ===== Animations & Effects ===== */
+25 -1
View File
@@ -67,7 +67,10 @@ const isActiveRoute = (path: string) => currentPath === normalizePath(path);
<a href="/" class="logo"> <a href="/" class="logo">
<img src="/zblade-logo.png" alt="Zaguán Blade" class="logo-image" /> <img src="/zblade-logo.png" alt="Zaguán Blade" class="logo-image" />
</a> </a>
<nav class="nav"> <button class="nav-toggle" id="nav-toggle" aria-label="Toggle navigation" aria-expanded="false">
<span class="nav-toggle-icon">☰</span>
</button>
<nav class="nav" id="nav-menu">
<a href="/#philosophy">Why Blade</a> <a href="/#philosophy">Why Blade</a>
<a href="/docs" class={isActiveRoute('/docs') ? 'active' : undefined} aria-current={isActiveRoute('/docs') ? 'page' : undefined}>Docs</a> <a href="/docs" class={isActiveRoute('/docs') ? 'active' : undefined} aria-current={isActiveRoute('/docs') ? 'page' : undefined}>Docs</a>
<a href="/blog" class={isActiveRoute('/blog') ? 'active' : undefined} aria-current={isActiveRoute('/blog') ? 'page' : undefined}>Blog</a> <a href="/blog" class={isActiveRoute('/blog') ? 'active' : undefined} aria-current={isActiveRoute('/blog') ? 'page' : undefined}>Blog</a>
@@ -116,5 +119,26 @@ const isActiveRoute = (path: string) => currentPath === normalizePath(path);
<img referrerpolicy="no-referrer-when-downgrade" src="https://kekepower.com/mtr/matomo.php?idsite=19&amp;rec=1" style="border:0" alt="" /> <img referrerpolicy="no-referrer-when-downgrade" src="https://kekepower.com/mtr/matomo.php?idsite=19&amp;rec=1" style="border:0" alt="" />
</noscript> </noscript>
<!-- End Matomo --> <!-- End Matomo -->
<script is:inline>
(function() {
var toggle = document.getElementById('nav-toggle');
var menu = document.getElementById('nav-menu');
if (!toggle || !menu) return;
toggle.addEventListener('click', function() {
var expanded = toggle.getAttribute('aria-expanded') === 'true';
toggle.setAttribute('aria-expanded', String(!expanded));
menu.classList.toggle('nav-open', !expanded);
toggle.querySelector('.nav-toggle-icon').textContent = expanded ? '☰' : '✕';
});
// Close menu when a nav link is clicked
menu.querySelectorAll('a').forEach(function(link) {
link.addEventListener('click', function() {
toggle.setAttribute('aria-expanded', 'false');
menu.classList.remove('nav-open');
toggle.querySelector('.nav-toggle-icon').textContent = '☰';
});
});
})();
</script>
</body> </body>
</html> </html>
+94
View File
@@ -226,4 +226,98 @@ const { post } = Astro.props;
.post-content :global(tr:hover td) { .post-content :global(tr:hover td) {
background: var(--color-bg-elevated); background: var(--color-bg-elevated);
} }
@media (max-width: 768px) {
.blog-post {
padding-top: 100px;
}
.post-container {
padding: 0 var(--space-md);
padding-bottom: var(--space-xl);
}
.post-title {
font-size: 2rem;
}
.post-description {
font-size: 1rem;
}
.hero-image {
max-height: 250px;
}
.post-content {
font-size: 1rem;
}
.post-content :global(h2) {
font-size: 1.35rem;
}
.post-content :global(h3) {
font-size: 1.15rem;
}
.post-content :global(table) {
font-size: 0.85rem;
}
.post-content :global(th),
.post-content :global(td) {
padding: var(--space-xs) var(--space-sm);
}
}
@media (max-width: 480px) {
.blog-post {
padding-top: 80px;
}
.post-container {
padding: 0 var(--space-sm);
padding-bottom: var(--space-lg);
}
.post-title {
font-size: 1.6rem;
}
.post-description {
font-size: 0.95rem;
}
.hero-image {
max-height: 180px;
}
.post-meta {
flex-direction: column;
gap: var(--space-xs);
font-size: 0.8rem;
}
.post-content {
font-size: 0.95rem;
}
.post-content :global(h2) {
font-size: 1.2rem;
}
.post-content :global(h3) {
font-size: 1.05rem;
}
.post-content :global(table) {
font-size: 0.8rem;
}
.post-content :global(th),
.post-content :global(td) {
padding: var(--space-xxs) var(--space-xs);
}
}
</style> </style>
+20 -1
View File
@@ -127,7 +127,7 @@ const posts = (await getCollection('blog', ({ data }) => {
.posts-grid { .posts-grid {
display: grid; display: grid;
gap: var(--space-lg); gap: var(--space-lg);
grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
} }
/* Post Card */ /* Post Card */
@@ -218,5 +218,24 @@ const posts = (await getCollection('blog', ({ data }) => {
.posts-grid { .posts-grid {
grid-template-columns: 1fr; grid-template-columns: 1fr;
} }
.post-title {
font-size: 1.1rem;
}
}
@media (max-width: 480px) {
.blog-hero {
padding-top: calc(var(--space-lg) + 60px);
padding-bottom: var(--space-md);
}
.blog-section {
padding: var(--space-md) 0;
}
.post-content {
padding: var(--space-sm);
}
} }
</style> </style>
+65
View File
@@ -1735,6 +1735,71 @@ import BaseLayout from '../layouts/BaseLayout.astro';
} }
} }
@media (max-width: 480px) {
.changelog-hero {
padding-top: calc(var(--space-xl) + 60px);
padding-bottom: var(--space-md);
}
.title-line-1 {
font-size: clamp(1.5rem, 7vw, 2rem);
}
.title-accent {
font-size: 0.8rem;
}
.hero-description {
font-size: 0.9rem;
}
.version-card {
padding: var(--space-md);
}
.version-number {
font-size: 1.35rem;
}
.version-date {
font-size: 0.85rem;
}
.version-badge {
font-size: 0.65rem;
padding: 0.3rem 0.5rem;
}
.product-heading {
font-size: 0.95rem;
padding: var(--space-xs) var(--space-sm);
}
.changes-title,
.changes-toggle {
font-size: 0.85rem;
}
.changes-list li {
font-size: 0.85rem;
padding-left: var(--space-sm);
}
.updates-table {
font-size: 0.75rem;
}
.updates-table th,
.updates-table td {
padding: var(--space-xs);
}
.breaking-updates-list li {
padding: var(--space-xs);
font-size: 0.85rem;
}
}
/* Screenshot Showcase */ /* Screenshot Showcase */
.screenshot-showcase { .screenshot-showcase {
padding: var(--space-2xl) 0; padding: var(--space-2xl) 0;
+68 -8
View File
@@ -798,7 +798,7 @@ import BaseLayout from '../layouts/BaseLayout.astro';
.concept-grid { .concept-grid {
display: grid; display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: var(--space-lg); gap: var(--space-lg);
} }
@@ -835,7 +835,7 @@ import BaseLayout from '../layouts/BaseLayout.astro';
/* Steps Grid */ /* Steps Grid */
.steps-grid { .steps-grid {
display: grid; display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
gap: var(--space-lg); gap: var(--space-lg);
} }
@@ -937,7 +937,7 @@ import BaseLayout from '../layouts/BaseLayout.astro';
/* Interface Grid */ /* Interface Grid */
.interface-grid { .interface-grid {
display: grid; display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: var(--space-lg); gap: var(--space-lg);
} }
@@ -1025,7 +1025,7 @@ import BaseLayout from '../layouts/BaseLayout.astro';
/* Shortcuts */ /* Shortcuts */
.shortcuts-layout { .shortcuts-layout {
display: grid; display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
gap: var(--space-lg); gap: var(--space-lg);
} }
@@ -1079,7 +1079,7 @@ import BaseLayout from '../layouts/BaseLayout.astro';
/* Commands */ /* Commands */
.commands-grid { .commands-grid {
display: grid; display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
gap: var(--space-lg); gap: var(--space-lg);
} }
@@ -1175,7 +1175,7 @@ import BaseLayout from '../layouts/BaseLayout.astro';
/* Settings */ /* Settings */
.settings-grid { .settings-grid {
display: grid; display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
gap: var(--space-lg); gap: var(--space-lg);
} }
@@ -1330,7 +1330,7 @@ import BaseLayout from '../layouts/BaseLayout.astro';
/* Known Bugs */ /* Known Bugs */
.bugs-grid { .bugs-grid {
display: grid; display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: var(--space-lg); gap: var(--space-lg);
margin-bottom: var(--space-xl); margin-bottom: var(--space-xl);
} }
@@ -1434,7 +1434,7 @@ import BaseLayout from '../layouts/BaseLayout.astro';
/* Screenshot Capture */ /* Screenshot Capture */
.screenshot-grid { .screenshot-grid {
display: grid; display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: var(--space-lg); gap: var(--space-lg);
margin-bottom: var(--space-xl); margin-bottom: var(--space-xl);
} }
@@ -1704,11 +1704,28 @@ import BaseLayout from '../layouts/BaseLayout.astro';
padding-top: calc(var(--space-xl) + 60px); padding-top: calc(var(--space-xl) + 60px);
padding-bottom: var(--space-md); padding-bottom: var(--space-md);
} }
.docs-section {
padding: var(--space-xl) 0;
}
.concept-card,
.support-card {
padding: var(--space-lg);
}
.concept-header { .concept-header {
flex-direction: column; flex-direction: column;
align-items: flex-start; align-items: flex-start;
} }
.concept-header h2 {
font-size: 1.5rem;
}
.concept-lead {
font-size: 1rem;
}
.support-header { .support-header {
flex-direction: column; flex-direction: column;
@@ -1723,5 +1740,48 @@ import BaseLayout from '../layouts/BaseLayout.astro';
width: 100%; width: 100%;
justify-content: space-between; justify-content: space-between;
} }
.tool-calls-link {
flex-direction: column;
text-align: center;
gap: var(--space-md);
}
.step-options {
flex-wrap: wrap;
}
.section-title {
font-size: clamp(1.5rem, 6vw, 2rem);
}
}
@media (max-width: 480px) {
.docs-hero {
padding-top: calc(var(--space-lg) + 60px);
}
.concept-card,
.support-card,
.ai-block,
.step-card,
.setting-card,
.feature-detail,
.screenshot-notes {
padding: var(--space-md);
}
.code-block pre {
padding: var(--space-sm);
font-size: 0.8rem;
}
.code-block code {
font-size: 0.75rem;
}
.step-num {
font-size: 2rem;
}
} }
</style> </style>
+212 -1
View File
@@ -282,4 +282,215 @@ const version = pkg.version ?? "";
</div> </div>
</section> </section>
</main> </main>
</BaseLayout> </BaseLayout>
<style>
/* Index Page Responsive */
@media (max-width: 768px) {
.hero-content {
max-width: 100%;
}
.hero-label {
font-size: 0.75rem;
}
.hero-title {
margin-bottom: var(--space-md);
}
.hero-description {
font-size: 1rem;
max-width: 100%;
}
.hero-actions {
flex-direction: column;
}
.action-primary,
.action-secondary {
width: 100%;
justify-content: center;
}
.hero-meta {
gap: var(--space-xs);
}
.meta-item {
font-size: 0.65rem;
padding: 0.3rem 0.6rem;
}
.meta-divider {
display: none;
}
/* Video container */
.hero .container + .container {
margin-top: var(--space-xl) !important;
}
.features-header .section-title {
font-size: clamp(1.75rem, 8vw, 2.5rem);
}
.feature-primary {
padding: var(--space-lg);
}
.feature-content h3 {
font-size: 1.5rem;
}
.feature-content p {
font-size: 1rem;
}
.feature-row {
grid-template-columns: 1fr;
}
.feature-item h3 {
font-size: 1.1rem;
}
.feature-banner {
padding: var(--space-lg);
}
.feature-banner p {
font-size: 0.9rem !important;
}
.arch-grid {
grid-template-columns: 1fr;
gap: var(--space-md);
}
.arch-node {
padding: var(--space-lg);
}
.arch-node h3 {
font-size: 1.25rem;
}
.pricing-block {
padding: var(--space-lg);
}
.pricing-title {
font-size: clamp(1.75rem, 8vw, 3rem);
}
.pricing-grid {
grid-template-columns: 1fr;
gap: var(--space-md);
}
.pricing-divider {
width: 100%;
height: 2px;
}
.pricing-features {
flex-direction: column;
}
.pricing-features span {
width: 100%;
text-align: center;
}
.pricing-action {
width: 100%;
justify-content: center;
}
.download-title {
font-size: clamp(1.75rem, 8vw, 2.5rem);
}
.download-grid {
grid-template-columns: 1fr;
}
.platform-card {
padding: var(--space-lg);
}
.platform-name {
font-size: 1.25rem;
}
.download-disclaimer {
flex-direction: column;
text-align: center;
}
}
@media (max-width: 480px) {
.hero {
padding-top: calc(var(--space-xl) + 60px);
padding-bottom: var(--space-xl);
}
.hero-description {
font-size: 0.9rem;
}
.hero-title .title-line-1,
.hero-title .title-line-2 {
font-size: clamp(1.5rem, 9vw, 2.5rem);
}
.feature-primary {
padding: var(--space-md);
border-width: 1px;
}
.feature-item {
padding: var(--space-md);
}
.feature-banner .banner-text {
font-size: 0.9rem;
}
.arch-node h3 {
font-size: 1.1rem;
}
.arch-node p {
font-size: 0.8rem;
}
.pricing-block {
padding: var(--space-md);
border-width: 1px;
}
.pricing-value {
font-size: 1rem;
}
.pricing-label {
font-size: 0.65rem;
}
.platform-icon {
font-size: 2rem;
}
.section-title {
font-size: clamp(1.5rem, 8vw, 2rem);
}
.section-label {
font-size: 0.65rem;
}
}
</style>
+28
View File
@@ -365,4 +365,32 @@ import BaseLayout from '../layouts/BaseLayout.astro';
grid-template-columns: 1fr; grid-template-columns: 1fr;
} }
} }
@media (max-width: 480px) {
.privacy-hero .section-title {
font-size: 1.8rem;
}
.privacy-hero {
padding-top: calc(var(--space-xl) + 60px);
padding-bottom: var(--space-md);
}
.privacy-content {
padding: 0 var(--space-sm);
}
.privacy-section h2 {
font-size: 1.2rem;
}
.privacy-section h3 {
font-size: 1rem;
}
.privacy-section p,
.privacy-section li {
font-size: 0.9rem;
}
}
</style> </style>
+51
View File
@@ -1597,4 +1597,55 @@ To use a tool, respond with:
width: auto; width: auto;
} }
} }
@media (max-width: 480px) {
.tools-hero {
padding-top: calc(var(--space-xl) + 60px);
padding-bottom: var(--space-md);
}
.tool-card {
padding: 0;
}
.tool-header {
padding: var(--space-sm);
}
.tool-body {
padding: var(--space-sm);
}
.tool-name {
font-size: 1.25rem;
}
.tool-name .slug {
font-size: 0.75rem;
}
.tool-desc {
font-size: 0.9rem;
}
.param-name {
font-size: 0.8rem;
}
.param-desc code {
font-size: 0.75rem;
}
.example-label {
font-size: 0.75rem;
}
.breadcrumb-trail {
flex-wrap: wrap;
}
.params-table {
font-size: 0.75rem;
}
}
</style> </style>