top of page
  • Writer's pictureSolve It

#2 StoreStreamUi17: Create a shared sidebar


In this guide, we'll explain how you can create a sidebar for the whole dashboard using Angular and Tailwind CSS



Setting the Stage: Shared Modules for Common Components


Our journey begins with the creation of a shared module. This module will be the home for all the common UI components we'll use across our application. The process is straightforward:

  • Navigate to the app directory:

cd src/app
  • Generate the shared module:

ng generate module shared

Crafting the Navbar Component


Next, we'll create a component for our navigation bar, which is an essential part of any application's UI:

  • Generate the navbar component inside the shared module:

ng generate component shared/navbar

Angular 17 introduces a game-changing feature: Standalone components. When you generate components in Angular 17, they are standalone by default. This means they aren't automatically added to any component's imports, freeing you from concerns about circular dependencies and enhancing modularity.


Integrating the Navbar into the AppComponent


Now that our navbar component is ready, let's integrate it into the AppComponent. Here's how:

  • Import necessary modules and the NavbarComponent in the AppComponent:

import { Component } from "@angular/core";
import { CommonModule } from "@angular/common";
import { RouterOutlet } from "@angular/router";
import { NavbarComponent } from "./shared/navbar/navbar.component";
  • Update the AppComponent decorator to include these imports:

@Component({
  selector: "app-root",
  standalone: true,
  imports: [CommonModule, RouterOutlet, NavbarComponent],
  templateUrl: "./app.component.html",
  styleUrl: "./app.component.scss",
})
export class AppComponent {
  title = "store_stream_ui17";
}

Adding Responsive Functionality to the Navbar


To make our navbar responsive, especially for mobile views, we need to add some logic for collapsing and expanding. Here's the code to add to navbar.component.html and navbar.component.ts:

  • HTML structure for the navbar:

<nav
  class="fixed top-0 z-50 w-full bg-white border-b border-gray-200 dark:bg-gray-800 dark:border-gray-700"
>
  <div class="px-3 py-3 lg:px-5 lg:pl-3">
    <div class="flex items-center justify-between">
      <div class="flex items-center justify-start rtl:justify-end">
        <button
          aria-controls="logo-sidebar"
          type="button"
          class="inline-flex items-center p-2 text-sm text-gray-500 rounded-lg sm:hidden hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-gray-200 dark:text-gray-400 dark:hover:bg-gray-700 dark:focus:ring-gray-600"
          (click)="toggleSidebar()"
        >
          <span class="sr-only">Open sidebar</span>
          <svg
            class="w-6 h-6"
            aria-hidden="true"
            fill="currentColor"
            viewBox="0 0 20 20"
            xmlns="http://www.w3.org/2000/svg"
          >
            <path
              clip-rule="evenodd"
              fill-rule="evenodd"
              d="M2 4.75A.75.75 0 012.75 4h14.5a.75.75 0 010 1.5H2.75A.75.75 0 012 4.75zm0 10.5a.75.75 0 01.75-.75h7.5a.75.75 0 010 1.5h-7.5a.75.75 0 01-.75-.75zM2 10a.75.75 0 01.75-.75h14.5a.75.75 0 010 1.5H2.75A.75.75 0 012 10z"
            ></path>
          </svg>
        </button>
        <a href="" class="flex ms-2 md:me-24">
          <img
            src="./assets/images/logo.svg"
            class="h-8 me-3"
            alt="Company Logo"
          />
          <span
            class="self-center text-xl font-semibold sm:text-2xl whitespace-nowrap dark:text-white"
            >Store Stream</span
          >
        </a>
      </div>
      <div class="flex items-center">
        <div class="flex items-center ms-3">
          <div>
            <button
              type="button"
              class="flex text-sm bg-gray-800 rounded-full focus:ring-4 focus:ring-gray-300 dark:focus:ring-gray-600"
              aria-expanded="false"
              (click)="toggleDropdown()"
            >
              <span class="sr-only">Open user menu</span>
              <img
                class="w-8 h-8 rounded-full"
                src="./assets/images/profile-picture.jpg"
                alt="user photo"
              />
            </button>
          </div>
          <div
            class="z-50 my-4 text-base list-none bg-white divide-y divide-gray-100 rounded shadow dark:bg-gray-700 dark:divide-gray-600"
            [class]="
              dropdownOpen
                ? 'absolute inset-[48px_0px_auto_auto] right-0 w-48 py-1 mt-2 overflow-hidden bg-white rounded shadow-xl dark:bg-gray-700 dark:divide-gray-600'
                : 'hidden'
            "
            id="dropdown-user"
          >
            <div class="px-4 py-3" role="none">
              <p class="text-sm text-gray-900 dark:text-white" role="none">
                John Doe
              </p>
              <p
                class="text-sm font-medium text-gray-900 truncate dark:text-gray-300"
                role="none"
              >
                s
              </p>
            </div>
            <ul class="py-1" role="none">
              <li>
                <a
                  href="#"
                  class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 dark:text-gray-300 dark:hover:bg-gray-600 dark:hover:text-white"
                  role="menuitem"
                  >Dashboard</a
                >
              </li>
              <li>
                <a
                  href="#"
                  class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 dark:text-gray-300 dark:hover:bg-gray-600 dark:hover:text-white"
                  role="menuitem"
                  >Settings</a
                >
              </li>
              <li>
                <a
                  href="#"
                  class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 dark:text-gray-300 dark:hover:bg-gray-600 dark:hover:text-white"
                  role="menuitem"
                  >Earnings</a
                >
              </li>
              <li>
                <a
                  href="#"
                  class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 dark:text-gray-300 dark:hover:bg-gray-600 dark:hover:text-white"
                  role="menuitem"
                  >Sign out</a
                >
              </li>
            </ul>
          </div>
        </div>
      </div>
    </div>
  </div>
</nav>

<aside
  id="logo-sidebar"
  [class]="
    sidebarOpen
      ? 'fixed top-0 left-0 z-40 w-64 h-screen pt-20 bg-white border-r border-gray-200 dark:bg-gray-800 dark:border-gray-700 sm:translate-x-0'
      : 'fixed top-0 left-0 z-40 w-64 h-screen pt-20 -translate-x-full transition-transform bg-white border-r border-gray-200 dark:bg-gray-800 dark:border-gray-700 sm:translate-x-0'
  "
  aria-label="Sidebar"
>
  <div class="h-full px-3 pb-4 overflow-y-auto bg-white dark:bg-gray-800">
    <ul class="space-y-2 font-medium">
      <li>
        <a
          href="#"
          class="flex items-center p-2 text-gray-900 rounded-lg dark:text-white hover:bg-gray-100 dark:hover:bg-gray-700 group"
        >
          <span class="ms-3">Dashboard</span>
        </a>
      </li>

      <li>
        <a
          href="#"
          class="flex items-center p-2 text-gray-900 rounded-lg dark:text-white hover:bg-gray-100 dark:hover:bg-gray-700 group"
        >
          <span class="flex-1 ms-3 whitespace-nowrap">Inbox</span>
          <span
            class="inline-flex items-center justify-center w-3 h-3 p-3 ms-3 text-sm font-medium text-blue-800 bg-blue-100 rounded-full dark:bg-blue-900 dark:text-blue-300"
            >3</span
          >
        </a>
      </li>
      <li>
        <a
          href="#"
          class="flex items-center p-2 text-gray-900 rounded-lg dark:text-white hover:bg-gray-100 dark:hover:bg-gray-700 group"
        >
          <span class="flex-1 ms-3 whitespace-nowrap">Users</span>
        </a>
      </li>
      <li>
        <a
          href="#"
          class="flex items-center p-2 text-gray-900 rounded-lg dark:text-white hover:bg-gray-100 dark:hover:bg-gray-700 group"
        >
          <span class="flex-1 ms-3 whitespace-nowrap">Products</span>
        </a>
      </li>
    </ul>
  </div>
</aside>

  • TypeScript logic for the toggle functionality:

import { Component, ElementRef, HostListener } from "@angular/core";

@Component({
  selector: "app-navbar",
  standalone: true,
  imports: [],
  templateUrl: "./navbar.component.html",
  styleUrl: "./navbar.component.scss",
})
export class NavbarComponent {
  sidebarOpen = false;
  dropdownOpen = false;

  constructor(private eRef: ElementRef) {}

  toggleSidebar() {
    this.sidebarOpen = !this.sidebarOpen;
  }
  toggleDropdown() {
    this.dropdownOpen = !this.dropdownOpen;
  }
  @HostListener("document:click", ["$event"])
  clickout(event: any) {
    if (!this.eRef.nativeElement.contains(event.target)) {
      this.dropdownOpen = false;
    }
  }
}

Incorporating the Navbar in the Main Layout


To use the navbar in our application, update the app.component.html to include the navbar component:

<app-navbar></app-navbar>

What's Next?


With our navbar in place and a shared module ready for future components, we've laid a solid foundation for our UI. In our next article, we'll delve into building the authentication pages, another critical part of any web application. Stay tuned!

You


dd





32 views0 comments

Recent Posts

See All

Comments


bottom of page