From 564f5f0dca003acd1ae33ae65f73bd2601b2027d Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Mon, 1 Sep 2025 07:56:38 +0000 Subject: [PATCH] feat: Convert navbar to Bootstrap 5.1 offcanvas menu This commit changes the navbar to use the Bootstrap 5.1 offcanvas component. The following changes were made: - Modified `app/views/layouts/_header.html.haml` to update the navbar-toggler to trigger the offcanvas menu. - Modified `app/views/layouts/_menu.haml` to wrap the menu in an offcanvas component. --- app/views/layouts/_header.html.haml | 2 +- app/views/layouts/_menu.haml | 186 ++++++++++++++-------------- 2 files changed, 96 insertions(+), 92 deletions(-) diff --git a/app/views/layouts/_header.html.haml b/app/views/layouts/_header.html.haml index d4ad1e6845..c88f317124 100644 --- a/app/views/layouts/_header.html.haml +++ b/app/views/layouts/_header.html.haml @@ -6,6 +6,6 @@ %span.site-name Growstuff .nav= render 'crops/search_bar' .nav - %button.navbar-toggler{ "aria-controls" => "navbarSupportedContent", "aria-expanded" => "false", "aria-label" => "Toggle navigation", "data-bs-target" => "#navbarSupportedContent", "data-bs-toggle" => "collapse", type: "button" } + %button.navbar-toggler{ "aria-controls" => "offcanvasNavbar", "aria-label" => "Toggle navigation", "data-bs-target" => "#offcanvasNavbar", "data-bs-toggle" => "offcanvas", type: "button" } %i.fas.fa-ellipsis-v.navbar-toggler-icon = render 'layouts/menu' diff --git a/app/views/layouts/_menu.haml b/app/views/layouts/_menu.haml index 2846249018..55087c2f0b 100644 --- a/app/views/layouts/_menu.haml +++ b/app/views/layouts/_menu.haml @@ -1,98 +1,102 @@ -#navbarSupportedContent.collapse.navbar-collapse - %ul.navbar-nav.mr-auto - - if signed_in? - %li.nav-item - = link_to timeline_index_path, method: :get, class: 'nav-link text-white' do - = image_tag 'icons/notification.svg', class: 'img img-icon', alt: "Notifications" - %li.nav-item - = link_to member_gardens_path(current_member), class: 'nav-link text-white', title: "My gardens" do - = image_icon 'gardens' - %li.nav-item.dropdown - %a.nav-link.dropdown-toggle{"aria-expanded" => "false", "aria-haspopup" => "true", "data-bs-toggle" => "dropdown", href: "#", role: "button"} - = image_tag "icons/gardener.svg", class: 'img img-icon', alt: t('.record'), aria: { hidden: "true" } - = t('.record') - .dropdown-menu - = link_to new_planting_path, class: 'dropdown-item' do - = image_icon('planting-add') - = t('buttons.new_planting') - = link_to new_harvest_path, class: 'dropdown-item' do - = image_icon('harvest-add') - = t('buttons.new_harvest') - = link_to new_activity_path, class: 'dropdown-item' do - = image_icon('activity-add') - = t('buttons.new_activity') - = link_to new_seed_path, class: 'dropdown-item' do - = image_icon('seed-add') - = t('buttons.new_seeds') - = link_to new_post_path, class: 'dropdown-item' do - = post_icon - = t('buttons.new_post') - - - cache("everyone-menu", expires_in: 1.week) do - %li.nav-item.dropdown - %a.nav-link.dropdown-toggle{"aria-expanded" => "false", "aria-haspopup" => "true", "data-bs-toggle" => "dropdown", href: "#", role: "button"}= t('.crops') - .dropdown-menu - = link_to crops_path, class: 'dropdown-item' do - = t('.browse_crops') - = link_to seeds_path, class: 'dropdown-item' do - = seed_icon - = t('.seeds') - = link_to plantings_path, class: 'dropdown-item' do - = planting_icon - = t('.plantings') - = link_to harvests_path, class: 'dropdown-item' do - = harvest_icon - = t('.harvests') - %li.nav-item.dropdown - %a.nav-link.dropdown-toggle{"aria-expanded" => "false", "aria-haspopup" => "true", "data-bs-toggle" => "dropdown", href: "#", role: "button"}= t('.community') - .dropdown-menu{"aria-labelledby" => "navbarDropdown"} - = link_to t('.community_map'), places_path, class: 'dropdown-item' - = link_to t('.browse_members'), members_path, class: 'dropdown-item' - = link_to t('.posts'), posts_path, class: 'dropdown-item' - = link_to t('.forums'), forums_path, class: 'dropdown-item' +.offcanvas.offcanvas-start#offcanvasNavbar{ 'aria-labelledby' => 'offcanvasNavbarLabel', 'tabindex' => '-1' } + .offcanvas-header + %h5.offcanvas-title#offcanvasNavbarLabel Menu + %button.btn-close.text-reset{ 'data-bs-dismiss' => 'offcanvas', 'aria-label' => 'Close' } + .offcanvas-body + %ul.navbar-nav.mr-auto + - if signed_in? + %li.nav-item + = link_to timeline_index_path, method: :get, class: 'nav-link' do + = image_tag 'icons/notification.svg', class: 'img img-icon', alt: "Notifications" + %li.nav-item + = link_to member_gardens_path(current_member), class: 'nav-link', title: "My gardens" do + = image_icon 'gardens' + %li.nav-item.dropdown + %a.nav-link.dropdown-toggle{"aria-expanded" => "false", "aria-haspopup" => "true", "data-bs-toggle" => "dropdown", href: "#", role: "button"} + = image_tag "icons/gardener.svg", class: 'img img-icon', alt: t('.record'), aria: { hidden: "true" } + = t('.record') + .dropdown-menu + = link_to new_planting_path, class: 'dropdown-item' do + = image_icon('planting-add') + = t('buttons.new_planting') + = link_to new_harvest_path, class: 'dropdown-item' do + = image_icon('harvest-add') + = t('buttons.new_harvest') + = link_to new_activity_path, class: 'dropdown-item' do + = image_icon('activity-add') + = t('buttons.new_activity') + = link_to new_seed_path, class: 'dropdown-item' do + = image_icon('seed-add') + = t('buttons.new_seeds') + = link_to new_post_path, class: 'dropdown-item' do + = post_icon + = t('buttons.new_post') - - if member_signed_in? - - if current_member.role?(:crop_wrangler) || current_member.role?(:admin) + - cache("everyone-menu", expires_in: 1.week) do + %li.nav-item.dropdown + %a.nav-link.dropdown-toggle{"aria-expanded" => "false", "aria-haspopup" => "true", "data-bs-toggle" => "dropdown", href: "#", role: "button"}= t('.crops') + .dropdown-menu + = link_to crops_path, class: 'dropdown-item' do + = t('.browse_crops') + = link_to seeds_path, class: 'dropdown-item' do + = seed_icon + = t('.seeds') + = link_to plantings_path, class: 'dropdown-item' do + = planting_icon + = t('.plantings') + = link_to harvests_path, class: 'dropdown-item' do + = harvest_icon + = t('.harvests') %li.nav-item.dropdown - %a.nav-link.dropdown-toggle{"aria-expanded" => "false", "aria-haspopup" => "true", "data-bs-toggle" => "dropdown", href: "#", role: "button"}= t('.admin') + %a.nav-link.dropdown-toggle{"aria-expanded" => "false", "aria-haspopup" => "true", "data-bs-toggle" => "dropdown", href: "#", role: "button"}= t('.community') .dropdown-menu{"aria-labelledby" => "navbarDropdown"} - - if current_member.role?(:crop_wrangler) - = link_to t('.crop_wrangling'), wrangle_crops_path, class: 'dropdown-item' - - if current_member.role?(:admin) - = link_to t('.admin'), admin_path, class: 'dropdown-item' + = link_to t('.community_map'), places_path, class: 'dropdown-item' + = link_to t('.browse_members'), members_path, class: 'dropdown-item' + = link_to t('.posts'), posts_path, class: 'dropdown-item' + = link_to t('.forums'), forums_path, class: 'dropdown-item' - %li.nav-item.dropdown - %a.nav-link.dropdown-toggle{"aria-expanded" => "false", "aria-haspopup" => "true", "data-bs-toggle" => "dropdown", href: "#", role: "button"} - = image_tag(avatar_uri(current_member, 50), alt: 'Avatar of current member', height: 25, width: 25, aria: { hidden: "true" }) - = current_member.login_name - - if current_member.unread_count.positive? - %span.badge.badge-info= current_member.unread_count - .dropdown-menu{"aria-labelledby" => "navbarDropdown"} - = link_to member_path(current_member), class: 'dropdown-item' do - = t('.profile') - = link_to member_activities_path(current_member), class: 'dropdown-item' do - = t('.activities') - = link_to member_gardens_path(current_member), class: 'dropdown-item' do - = t('.gardens') - = link_to member_plantings_path(current_member), class: 'dropdown-item' do - = t('.plantings') - = link_to member_harvests_path(current_member), class: 'dropdown-item' do - = t('.harvest') - = link_to member_seeds_path(current_member), class: 'dropdown-item' do - = t('.seeds') - = link_to t('.posts'), member_posts_path(current_member), class: 'dropdown-item' + - if member_signed_in? + - if current_member.role?(:crop_wrangler) || current_member.role?(:admin) + %li.nav-item.dropdown + %a.nav-link.dropdown-toggle{"aria-expanded" => "false", "aria-haspopup" => "true", "data-bs-toggle" => "dropdown", href: "#", role: "button"}= t('.admin') + .dropdown-menu{"aria-labelledby" => "navbarDropdown"} + - if current_member.role?(:crop_wrangler) + = link_to t('.crop_wrangling'), wrangle_crops_path, class: 'dropdown-item' + - if current_member.role?(:admin) + = link_to t('.admin'), admin_path, class: 'dropdown-item' + + %li.nav-item.dropdown + %a.nav-link.dropdown-toggle{"aria-expanded" => "false", "aria-haspopup" => "true", "data-bs-toggle" => "dropdown", href: "#", role: "button"} + = image_tag(avatar_uri(current_member, 50), alt: 'Avatar of current member', height: 25, width: 25, aria: { hidden: "true" }) + = current_member.login_name + - if current_member.unread_count.positive? + %span.badge.badge-info= current_member.unread_count + .dropdown-menu{"aria-labelledby" => "navbarDropdown"} + = link_to member_path(current_member), class: 'dropdown-item' do + = t('.profile') + = link_to member_activities_path(current_member), class: 'dropdown-item' do + = t('.activities') + = link_to member_gardens_path(current_member), class: 'dropdown-item' do + = t('.gardens') + = link_to member_plantings_path(current_member), class: 'dropdown-item' do + = t('.plantings') + = link_to member_harvests_path(current_member), class: 'dropdown-item' do + = t('.harvest') + = link_to member_seeds_path(current_member), class: 'dropdown-item' do + = t('.seeds') + = link_to t('.posts'), member_posts_path(current_member), class: 'dropdown-item' - - if current_member.unread_count.positive? + - if current_member.unread_count.positive? + .dropdown-divider + %strong + = link_to(conversations_path, class: 'dropdown-item') do + = t('.inbox') + %span.badge.badge-info= current_member.unread_count + - else + = link_to t('.inbox'), conversations_path, class: 'dropdown-item' .dropdown-divider - %strong - = link_to(conversations_path, class: 'dropdown-item') do - = t('.inbox') - %span.badge.badge-info= current_member.unread_count - - else - = link_to t('.inbox'), conversations_path, class: 'dropdown-item' - .dropdown-divider - = link_to t('.sign_out'), destroy_member_session_path, method: :delete, class: 'dropdown-item' + = link_to t('.sign_out'), destroy_member_session_path, method: :delete, class: 'dropdown-item' - - else - %li.nav-item= link_to t('.sign_in'), new_member_session_path, id: 'navbar-signin', class: 'btn btn-signin' - %li.nav-item= link_to t('.sign_up'), new_member_registration_path, id: 'navbar-signup', class: 'btn btn-signup' + - else + %li.nav-item= link_to t('.sign_in'), new_member_session_path, id: 'navbar-signin', class: 'btn btn-signin' + %li.nav-item= link_to t('.sign_up'), new_member_registration_path, id: 'navbar-signup', class: 'btn btn-signup'