From 3616fef130ef0bc2c5e745b092c6fa364194c6c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emanuel=20L=C3=A1zaro?= Date: Wed, 11 Mar 2026 02:04:32 +0000 Subject: [PATCH 1/3] feat(ui): add minimalist mobile responsiveness to archweb templates MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit introduces a responsive overlay for mobile devices (screens < 850px) while ensuring 100% visual parity for desktop views. Changes include: - templates/base.html: Added viewport meta tag for proper mobile scaling. - templates/base.html: Implemented a CSS-only hamburger menu using the "Checkbox Hack" (input#anb-toggle + label#anb-label). - sitestatic/archweb-mobile.css: Created a new override stylesheet containing all responsive logic to avoid modifying the archlinux_common_style submodule. - Homepage UX: Utilized Flexbox 'order' and 'display: contents' to resequence sections vertically: Hero -> Package Search -> Recent Updates -> Latest News. - Navigation: Added a minimalist "☰" icon for the main navbar that triggers a vertical dropdown menu on small screens. - Search: Fixed the package search typeahead (autocomplete) positioning by overriding viewport-relative JS coordinates with absolute CSS values. - Global Spacing: Applied a consistent 1.5em vertical gap between the navbar and content across all templates (Packages, News, Details, etc.). All mobile-specific elements are hidden by default (display: none) to ensure zero impact on the existing desktop design. Detailed technical documentation is included as comments within sitestatic/archweb-mobile.css for future maintenance. --- .gitignore | 2 + sitestatic/archweb-mobile.css | 213 ++++++++++++++++++++++++++++++++++ templates/base.html | 8 +- 3 files changed, 222 insertions(+), 1 deletion(-) create mode 100644 sitestatic/archweb-mobile.css diff --git a/.gitignore b/.gitignore index ca440617..3c8f42c0 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,5 @@ htmlcov # coverage .coverage + +.devcontainer \ No newline at end of file diff --git a/sitestatic/archweb-mobile.css b/sitestatic/archweb-mobile.css new file mode 100644 index 00000000..b1c8d50d --- /dev/null +++ b/sitestatic/archweb-mobile.css @@ -0,0 +1,213 @@ +/** + * Archweb Mobile Responsive Overrides + * + * This stylesheet provides minimalist mobile responsiveness for archweb. + * It is included after all other CSS to allow for surgical overrides. + * + * Design Constraints: + * 1. ZERO impact on desktop views (>= 850px). + * 2. Pure CSS implementation for the mobile menu (Checkbox Hack). + * 3. Coordination with archlinux_common_style without modifying the submodule. + */ + +/* Hide mobile-only interactive elements on desktop to prevent layout shifts */ +#anb-toggle, #anb-label { + display: none; +} + +@media (max-width: 849px) { + /* Global Reset: Remove fixed min-widths and ensure fluid containers */ + body { + min-width: 0 !important; + padding: 0 !important; + } + + /* Main Content Container: Uniform spacing and flex-column layout for stacking */ + #content { + width: 100% !important; + padding: 0 10px !important; + box-sizing: border-box !important; + display: flex !important; + flex-direction: column !important; + margin-top: 1.5em !important; /* Standardized vertical gap across all templates */ + } + + /* + * Layout Reordering: + * Uses 'display: contents' on wrapper divs to allow children to participate + * directly in the #content flexbox, enabling precise reordering via 'order'. + */ + #content-left-wrapper, + #content-left, + #content-right { + display: contents !important; + float: none !important; + width: auto !important; + margin: 0 !important; + } + + /* Homepage Element Sequence: Intro -> Search -> Updates -> News */ + #intro { + order: 1 !important; + margin-top: 0 !important; + } + #pkgsearch { + order: 2 !important; + position: static !important; + } + #pkg-updates { + order: 3 !important; + } + #news { + order: 4 !important; + } + #nav-sidebar { order: 5 !important; } + .widget { order: 6 !important; } + #footer { order: 7 !important; } + + header { + position: relative !important; + margin-bottom: 0 !important; + } + + /* Suppress empty developer navbar margins to prevent excessive whitespace */ + #archdev-navbar { + margin: 0 !important; + display: none !important; + } + + /* News Feed: Clear floats and restore logical horizontal flow for headers/icons */ + #news h3 { + float: left !important; + display: block !important; + width: auto !important; + margin-bottom: 0.5em !important; + } + #news .rss-icon { + float: right !important; + display: block !important; + margin-top: 0.5em !important; + margin-bottom: 0.5em !important; + } + #news h4 { + clear: both !important; + } + + /** + * Mobile Navigation (Hamburger Menu) + * Implementation: Uses a simple "☰" character to avoid external assets. + * Positioning: Anchored to the far right of the relative header wrapper. + */ + #anb-label { + display: block !important; + position: absolute !important; + top: 10px !important; + right: 15px !important; + left: auto !important; + width: 40px !important; + height: 40px !important; + line-height: 40px !important; + text-align: right !important; + color: #fff !important; + font-size: 32px !important; + cursor: pointer !important; + z-index: 1001 !important; + font-weight: 300 !important; + } + #anb-label::before { + content: "☰"; + } + #anb-label span { + display: none !important; + } + + /* Dropdown Toggle: Displays #archnavbarmenu when checkbox is checked */ + #archnavbarmenu { + display: none !important; + width: 100% !important; + background: #333 !important; + clear: both !important; + padding-top: 10px !important; + } + + #anb-toggle:checked ~ #archnavbar #archnavbarmenu { + display: block !important; + } + + #archnavbar { + position: relative !important; + padding: 10px 15px !important; + height: auto !important; + text-align: left !important; + } + + /* Transform horizontal list to vertical stacked items */ + #archnavbarlist { + text-align: left !important; + } + + #archnavbarlist li { + display: block !important; + padding: 10px 0 !important; + border-bottom: 1px solid #444 !important; + padding-top: 10px !important; + padding-bottom: 10px !important; + } + + #archnavbarlist li:last-child { + border-bottom: none !important; + } + + /* Input Fields: Ensure full-width fluid behavior on small screens */ + input[type=text], input[type=password], textarea { + max-width: 100% !important; + box-sizing: border-box !important; + } + + #sys-message { + width: 90% !important; + box-sizing: border-box !important; + } + + /* Tables: Enable horizontal scrolling for overflow-prone data grids */ + table { + display: block !important; + overflow-x: auto !important; + width: 100% !important; + } + + /** + * Package Search Autocomplete + * Override: homepage.js calculates coordinates relative to the viewport. + * Here we force absolute positioning relative to the form container. + */ + #pkgsearch-form { + position: relative !important; + display: block !important; + } + #pkgsearch fieldset { + margin: 0 !important; + padding: 0 !important; + } + #pkgsearch input { + float: none !important; + width: 100% !important; + margin-top: 0.5em !important; + box-sizing: border-box !important; + } + + /* Force dropdown visibility and alignment directly under the search input */ + .pkgsearch-typeahead { + top: 100% !important; + left: 0 !important; + width: 100% !important; + box-sizing: border-box !important; + position: absolute !important; + display: none; + margin-top: 0 !important; + background: #f6f9fc !important; + border: 1px solid #09c !important; + z-index: 2000 !important; + text-align: left !important; + } +} diff --git a/templates/base.html b/templates/base.html index 2d8adf02..ab064c6a 100644 --- a/templates/base.html +++ b/templates/base.html @@ -3,10 +3,12 @@ + {% block title %}Arch Linux{% endblock %} + @@ -18,7 +20,11 @@
From 32ef313c973fbfe8425a94b4e1bdf6122ba9a1da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emanuel=20L=C3=A1zaro?= Date: Wed, 11 Mar 2026 02:22:14 +0000 Subject: [PATCH 2/3] feat(ui): animate mobile hamburger menu to X on toggle MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replaced the static ☰ and ✕ characters with a CSS-based animated hamburger icon to provide immediate visual feedback and a smoother transition. This eliminates the perceived delay when opening and closing the mobile menu. Implemented 0.2s ease-in-out transition for the bar-to-X transformation. --- sitestatic/archweb-mobile.css | 39 ++++++++++++++++++++++++++++------- 1 file changed, 31 insertions(+), 8 deletions(-) diff --git a/sitestatic/archweb-mobile.css b/sitestatic/archweb-mobile.css index b1c8d50d..6e522df9 100644 --- a/sitestatic/archweb-mobile.css +++ b/sitestatic/archweb-mobile.css @@ -106,19 +106,42 @@ left: auto !important; width: 40px !important; height: 40px !important; - line-height: 40px !important; - text-align: right !important; - color: #fff !important; - font-size: 32px !important; cursor: pointer !important; z-index: 1001 !important; - font-weight: 300 !important; } - #anb-label::before { - content: "☰"; + #anb-label span, + #anb-label span::before, + #anb-label span::after { + display: block !important; + position: absolute !important; + width: 25px !important; + height: 2px !important; + background: #fff !important; + transition: all 0.2s ease-in-out !important; } #anb-label span { - display: none !important; + top: 19px !important; + right: 7px !important; + } + #anb-label span::before { + content: "" !important; + top: -8px !important; + } + #anb-label span::after { + content: "" !important; + top: 8px !important; + } + + #anb-toggle:checked ~ #anb-label span { + background: transparent !important; + } + #anb-toggle:checked ~ #anb-label span::before { + top: 0 !important; + transform: rotate(45deg) !important; + } + #anb-toggle:checked ~ #anb-label span::after { + top: 0 !important; + transform: rotate(-45deg) !important; } /* Dropdown Toggle: Displays #archnavbarmenu when checkbox is checked */ From 3f62c8d8bf374a143a38fecfb7a11ce307a1de3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emanuel=20L=C3=A1zaro?= Date: Wed, 11 Mar 2026 12:13:51 +0000 Subject: [PATCH 3/3] fix(ui): remove !important declaration --- sitestatic/archweb-mobile.css | 204 +++++++++++++++++----------------- 1 file changed, 102 insertions(+), 102 deletions(-) diff --git a/sitestatic/archweb-mobile.css b/sitestatic/archweb-mobile.css index 6e522df9..e6b86278 100644 --- a/sitestatic/archweb-mobile.css +++ b/sitestatic/archweb-mobile.css @@ -18,18 +18,18 @@ @media (max-width: 849px) { /* Global Reset: Remove fixed min-widths and ensure fluid containers */ body { - min-width: 0 !important; - padding: 0 !important; + min-width: 0; + padding: 0; } /* Main Content Container: Uniform spacing and flex-column layout for stacking */ #content { - width: 100% !important; - padding: 0 10px !important; - box-sizing: border-box !important; - display: flex !important; - flex-direction: column !important; - margin-top: 1.5em !important; /* Standardized vertical gap across all templates */ + width: 100%; + padding: 0 10px; + box-sizing: border-box; + display: flex; + flex-direction: column; + margin-top: 1.5em; /* Standardized vertical gap across all templates */ } /* @@ -40,57 +40,57 @@ #content-left-wrapper, #content-left, #content-right { - display: contents !important; - float: none !important; - width: auto !important; - margin: 0 !important; + display: contents; + float: none; + width: auto; + margin: 0; } /* Homepage Element Sequence: Intro -> Search -> Updates -> News */ #intro { - order: 1 !important; - margin-top: 0 !important; + order: 1; + margin-top: 0; } #pkgsearch { - order: 2 !important; - position: static !important; + order: 2; + position: static; } #pkg-updates { - order: 3 !important; + order: 3; } #news { - order: 4 !important; + order: 4; } - #nav-sidebar { order: 5 !important; } - .widget { order: 6 !important; } - #footer { order: 7 !important; } + #nav-sidebar { order: 5; } + .widget { order: 6; } + #footer { order: 7; } header { - position: relative !important; - margin-bottom: 0 !important; + position: relative; + margin-bottom: 0; } /* Suppress empty developer navbar margins to prevent excessive whitespace */ #archdev-navbar { - margin: 0 !important; - display: none !important; + margin: 0; + display: none; } /* News Feed: Clear floats and restore logical horizontal flow for headers/icons */ #news h3 { - float: left !important; - display: block !important; - width: auto !important; - margin-bottom: 0.5em !important; + float: left; + display: block; + width: auto; + margin-bottom: 0.5em; } #news .rss-icon { - float: right !important; - display: block !important; - margin-top: 0.5em !important; - margin-bottom: 0.5em !important; + float: right; + display: block; + margin-top: 0.5em; + margin-bottom: 0.5em; } #news h4 { - clear: both !important; + clear: both; } /** @@ -99,104 +99,104 @@ * Positioning: Anchored to the far right of the relative header wrapper. */ #anb-label { - display: block !important; - position: absolute !important; - top: 10px !important; - right: 15px !important; - left: auto !important; - width: 40px !important; - height: 40px !important; - cursor: pointer !important; - z-index: 1001 !important; + display: block; + position: absolute; + top: 10px; + right: 15px; + left: auto; + width: 40px; + height: 40px; + cursor: pointer; + z-index: 1001; } #anb-label span, #anb-label span::before, #anb-label span::after { - display: block !important; - position: absolute !important; - width: 25px !important; - height: 2px !important; - background: #fff !important; - transition: all 0.2s ease-in-out !important; + display: block; + position: absolute; + width: 25px; + height: 2px; + background: #fff; + transition: all 0.2s ease-in-out; } #anb-label span { - top: 19px !important; - right: 7px !important; + top: 19px; + right: 7px; } #anb-label span::before { - content: "" !important; - top: -8px !important; + content: ""; + top: -8px; } #anb-label span::after { - content: "" !important; - top: 8px !important; + content: ""; + top: 8px; } #anb-toggle:checked ~ #anb-label span { - background: transparent !important; + background: transparent; } #anb-toggle:checked ~ #anb-label span::before { - top: 0 !important; - transform: rotate(45deg) !important; + top: 0; + transform: rotate(45deg); } #anb-toggle:checked ~ #anb-label span::after { - top: 0 !important; - transform: rotate(-45deg) !important; + top: 0; + transform: rotate(-45deg); } /* Dropdown Toggle: Displays #archnavbarmenu when checkbox is checked */ #archnavbarmenu { - display: none !important; - width: 100% !important; - background: #333 !important; - clear: both !important; - padding-top: 10px !important; + display: none; + width: 100%; + background: #333; + clear: both; + padding-top: 10px; } #anb-toggle:checked ~ #archnavbar #archnavbarmenu { - display: block !important; + display: block; } #archnavbar { - position: relative !important; - padding: 10px 15px !important; - height: auto !important; - text-align: left !important; + position: relative; + padding: 10px 15px; + height: auto; + text-align: left; } /* Transform horizontal list to vertical stacked items */ #archnavbarlist { - text-align: left !important; + text-align: left; } #archnavbarlist li { - display: block !important; - padding: 10px 0 !important; - border-bottom: 1px solid #444 !important; - padding-top: 10px !important; - padding-bottom: 10px !important; + display: block; + padding: 10px 0; + border-bottom: 1px solid #444; + padding-top: 10px; + padding-bottom: 10px; } #archnavbarlist li:last-child { - border-bottom: none !important; + border-bottom: none; } /* Input Fields: Ensure full-width fluid behavior on small screens */ input[type=text], input[type=password], textarea { - max-width: 100% !important; - box-sizing: border-box !important; + max-width: 100%; + box-sizing: border-box; } #sys-message { - width: 90% !important; - box-sizing: border-box !important; + width: 90%; + box-sizing: border-box; } /* Tables: Enable horizontal scrolling for overflow-prone data grids */ table { - display: block !important; - overflow-x: auto !important; - width: 100% !important; + display: block; + overflow-x: auto; + width: 100%; } /** @@ -205,32 +205,32 @@ * Here we force absolute positioning relative to the form container. */ #pkgsearch-form { - position: relative !important; - display: block !important; + position: relative; + display: block; } #pkgsearch fieldset { - margin: 0 !important; - padding: 0 !important; + margin: 0; + padding: 0; } #pkgsearch input { - float: none !important; - width: 100% !important; - margin-top: 0.5em !important; - box-sizing: border-box !important; + float: none; + width: 100%; + margin-top: 0.5em; + box-sizing: border-box; } /* Force dropdown visibility and alignment directly under the search input */ .pkgsearch-typeahead { - top: 100% !important; - left: 0 !important; - width: 100% !important; - box-sizing: border-box !important; - position: absolute !important; + top: 100%; + left: 0; + width: 100%; + box-sizing: border-box; + position: absolute; display: none; - margin-top: 0 !important; - background: #f6f9fc !important; - border: 1px solid #09c !important; - z-index: 2000 !important; - text-align: left !important; + margin-top: 0; + background: #f6f9fc; + border: 1px solid #09c; + z-index: 2000; + text-align: left; } }