How to make a responsive side nav like Gmail with Bootstrap 5?

Cenk 1,001 Reputation points
2024-08-30T08:17:57.5333333+00:00

Hi,How can I make my side menu in a Blazor Server application like Gmail's left menu, where only icons are displayed at first, and expanding the menu displays names, without narrowing the main body section? I have included my current menu and CSS files.

Here is my current menu

Left Nav Menu

Here is the NavMenu.razor:

<main class="sidebarmain">
    
    <div class="flex-shrink-0 p-3" style="width: 280px;">
        <a href="/" class="d-flex align-items-center pb-3 mb-3 link-dark text-decoration-none border-bottom">
            <svg class="bi me-2" width="30" height="24">
                <use xlink:href="#bootstrap"></use>
            </svg>
            @*<span class="fs-5 fw-semibold">Collapsible</span>*@
        </a>
        <ul class="list-unstyled ps-0">
            <li class="mb-1">
                <button class="btn btn-toggle align-items-center rounded" data-bs-toggle="collapse" data-bs-target="#home-collapse" aria-expanded="true">
                    Home
                </button>
                <div class="collapse show" id="home-collapse">
                    <ul class="btn-toggle-nav list-unstyled fw-normal pb-1 small">
                        @* <li>
                            <a href="/" class="link-dark rounded">Dashboard</a>
                        </li> *@
                        <li>
                            <NavLink href="/" class="link-dark rounded">Dashboard</NavLink>
                        </li>
                        
                    </ul>
                </div>
            </li>
            <li class="mb-1">
                <button class="btn btn-toggle align-items-center rounded collapsed" data-bs-toggle="collapse" data-bs-target="#dashboard-collapse" aria-expanded="false">
                    Orders
                </button>
                <div class="collapse" id="dashboard-collapse" style="">
                    <ul class="btn-toggle-nav list-unstyled fw-normal pb-1 small">
                        @* <li>
                            <a href="/orders" class="link-dark rounded">Order List</a>
                        </li> *@
                        <li>
                            <NavLink href="/orderlist" class="link-dark rounded" Match="NavLinkMatch.Prefix">Order List</NavLink>
                        </li>
                        @* <li>
                            <a href="/upload" class="link-dark rounded">File Upload/Download</a>
                        </li> *@
                        <li>
                            <NavLink href="/upload" class="link-dark rounded" Match="NavLinkMatch.Prefix">File Upload/Download</NavLink>
                        </li>
                       @*  <li>
                            <a href="/report" class="link-dark rounded">Report</a>
                        </li> *@
                        <li>
                            <NavLink href="/report" class="link-dark rounded" Match="NavLinkMatch.All">Report</NavLink>
                        </li>
                    </ul>
                </div>
            </li>
            <li class="mb-1">
                <button class="btn btn-toggle align-items-center rounded collapsed" data-bs-toggle="collapse" data-bs-target="#vendors-collapse" aria-expanded="false">
                    Vendors
                </button>
                <div class="collapse" id="vendors-collapse">
                    <ul class="btn-toggle-nav list-unstyled fw-normal pb-1 small">
                        <li>
                            <a href="/vendors" class="link-dark rounded">Vendor Management</a>
                        </li>
                        
                    </ul>
                </div>
            </li>
            <li class="mb-1">
                <button class="btn btn-toggle align-items-center rounded collapsed" data-bs-toggle="collapse" data-bs-target="#customers-collapse" aria-expanded="false">
                    Customers
                </button>
                <div class="collapse" id="customers-collapse">
                    <ul class="btn-toggle-nav list-unstyled fw-normal pb-1 small">
                        <li>
                            <a href="/customers" class="link-dark rounded">Customer Management</a>
                        </li>
                    </ul>
                </div>
            </li>
            <AuthorizeView Roles="Administrators">
                <li class="border-top my-3" id="admin"></li>
            <li class="mb-1">
                <button id="administrator" class="btn btn-toggle align-items-center rounded collapsed" data-bs-toggle="collapse" data-bs-target="#account-collapse" aria-expanded="false">
                    Administration
                </button>
                <div class="collapse" id="account-collapse">
                    <ul class="btn-toggle-nav list-unstyled fw-normal pb-1 small">
                        <li>
                            <a href="/administration" class="link-dark rounded">User Management</a>
                        </li>
                        <li>
                                <a href="/warehouseaddress" class="link-dark rounded">Warehouse Management</a>
                        </li>
                        
                    </ul>
                </div>
            </li>
            </AuthorizeView>
        </ul>
    </div>
</main>

Here is the MainLayout.razor:

@inherits LayoutComponentBase
<PageTitle>Vorlance</PageTitle>
<style>
    .pb-3,
    .py-3 {
        padding-bottom: 0.93rem !important;
    }
</style>
<div class="page">
    <div class="sidebar @NavMenuCssClass">
        <NavMenu />
    </div>
    <main>
        <div class="top-row px-4 auth navbar-light">
            <div class="container-fluid toggler-container">
                <button title="Navigation menu" class="navbar-toggler custom-toggler" @onclick="ToggleNavMenu">
                    <span class="navbar-toggler-icon"></span>
                </button>
                <span class="navbar-brand mx-auto" href="#">
                    <img src="/css/images/logo.png" alt="" width="220" height="73" >
                </span>
                
            </div> 
            @*<a href="Identity/Account/Register">Register</a>
            <a href="Identity/Account/Login">Log in</a>*@
            <LoginDisplay/>
         
        </div>
        <article class="content px-4">
            @Body
            <RadzenDialog />
            <RadzenNotification/>
        </article>
    </main>
</div>
@code {
    private bool collapseNavMenu = true;
    private string? NavMenuCssClass => collapseNavMenu ? "collapse" : null;
    private void ToggleNavMenu()
    {
        collapseNavMenu = !collapseNavMenu;
    }
}

Here is the sidebar.css:

body {
  min-height: 100vh;
  min-height: -webkit-fill-available;
}
html {
  height: -webkit-fill-available;
}
/*main {
  display: flex;
  flex-wrap: nowrap;
  height: 100vh;
  height: -webkit-fill-available;
  max-height: 100vh;
  overflow-x: auto;
  overflow-y: hidden;
}*/
.sidebarmain {
    display: flex;
    flex-wrap: nowrap;
    height: 100vh;
    height: -webkit-fill-available;
    max-height: 100vh;
    overflow-x: hidden;
    overflow-y: hidden;
    background-color: #ced0da !important;
}
.b-example-divider {
  flex-shrink: 0;
  width: 1.5rem;
  height: 100vh;
  background-color: rgba(0, 0, 0, .1);
  border: solid rgba(0, 0, 0, .15);
  border-width: 1px 0;
  box-shadow: inset 0 .5em 1.5em rgba(0, 0, 0, .1), inset 0 .125em .5em rgba(0, 0, 0, .15);
}
.bi {
  vertical-align: -.125em;
  pointer-events: none;
  fill: currentColor;
}
.dropdown-toggle { outline: 0; }
.nav-flush .nav-link {
  border-radius: 0;
}
.btn-toggle {
  display: inline-flex;
  align-items: center;
  padding: .25rem .5rem;
  font-weight: 600;
  color: rgba(0, 0, 0, .65);
  background-color: transparent;
  border: 0;
}
.btn-toggle:hover,
.btn-toggle:focus {
  color: rgba(0, 0, 0, .85);
  background-color: #679fd2;
}
#administrator:hover, #administrator:focus {
    color: rgba(0, 0, 0, .85);
    background-color: #ff0000;
}
.btn-toggle::before {
  width: 1.25em;
  line-height: 0;
  content: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='rgba%280,0,0,.5%29' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M5 14l6-6-6-6'/%3e%3c/svg%3e");
  transition: transform .35s ease;
  transform-origin: .5em 50%;
}
.btn-toggle[aria-expanded="true"] {
  color: rgba(0, 0, 0, .85);
}
.btn-toggle[aria-expanded="true"]::before {
  transform: rotate(90deg);
}
.btn-toggle-nav a {
  display: inline-flex;
  padding: .1875rem .5rem;
  margin-top: .125rem;
  margin-left: 1.25rem;
  text-decoration: none;
}
.btn-toggle-nav a:hover,
.btn-toggle-nav a:focus {
  background-color: #98dbe8;
}
.scrollarea {
  overflow-y: auto;
}
.fw-semibold { font-weight: 600; }
.lh-tight { line-height: 1.25; }
#admin {
    border-top: 0.1rem solid white !important;
}

Here is the Gmail left menu:

Gmail left Menu

ASP.NET Core
ASP.NET Core
A set of technologies in the .NET Framework for building web applications and XML web services.
4,514 questions
Blazor
Blazor
A free and open-source web framework that enables developers to create web apps using C# and HTML being developed by Microsoft.
1,555 questions
0 comments No comments
{count} votes

1 answer

Sort by: Most helpful
  1. JasonPan - MSFT 5,456 Reputation points Microsoft Vendor
    2024-08-30T12:07:42.61+00:00

    Hi @Cenk,

    I found you are using Radzen, so I create a brand new sample, here is my test code. Please check the test result first.

    User's image

    @inherits LayoutComponentBase
    @using Radzen
    @using Radzen.Blazor
    <RadzenComponents @rendermode="InteractiveServer" />
    <RadzenLayout>
        <RadzenHeader>
            <RadzenStack Orientation="Orientation.Horizontal" AlignItems="AlignItems.Center" Gap="0">
                <RadzenSidebarToggle />
                <RadzenLabel Text="Header" />
            </RadzenStack>
        </RadzenHeader>
        <RadzenSidebar 
            Responsive="false" 
            Style="width: max-content" 
            @onmouseover="ExpandSidebar" 
            @onmouseout="CollapseSidebar">
            <RadzenPanelMenu DisplayStyle="@(sidebarExpanded ? MenuItemDisplayStyle.IconAndText : MenuItemDisplayStyle.Icon)" ShowArrow="false">
                <RadzenPanelMenuItem Text="Overview" Icon="home" Path="/" />
                <RadzenPanelMenuItem Text="Dashboard" Icon="dashboard" Path="/counter"/>
                <RadzenPanelMenuItem Text="UI Fundamentals" Icon="auto_awesome">
                    <RadzenPanelMenuItem Text="Themes" Icon="color_lens" />
                    <RadzenPanelMenuItem Text="Colors" Icon="invert_colors" />
                </RadzenPanelMenuItem>
            </RadzenPanelMenu>
        </RadzenSidebar>
        <RadzenBody Style="position: absolute">
             <div class="rz-p-8 rz-ml-8 rz-mt-8">
                @Body
            </div>
        </RadzenBody>
        <RadzenFooter>
            Footer
        </RadzenFooter>
    </RadzenLayout>
    @code {
        bool sidebarExpanded = false;
        void ExpandSidebar()
        {
            sidebarExpanded = true;
            StateHasChanged();
        }
        void CollapseSidebar()
        {
            sidebarExpanded = false;
            StateHasChanged();
        }
    }
    

    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    Best regards,

    Jason


Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.