VibeCoderzVibeCoderz
Telegram
All Prompts
Side drawer navigation UI Preview
mobile appnavigationlayout

Side drawer navigation

Боковая навигационная панель для мобильных приложений. Скрывает меню, сохраняя чистоту основного экрана. Идеальна для сложных интерфейсов.

by Shirley LouLive Preview

Prompt

# Side drawer navigation

Here is a reference implementation:

~~~html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Wireframe Navigation Drawer</title>
  <script src="https://cdn.tailwindcss.com"></script>
  <script src="https://code.iconify.design/iconify-icon/1.0.7/iconify-icon.min.js"></script>
  <link href="https://fonts.googleapis.com/css2?family=Manrope:wght@300;400;500;600;700&display=swap" rel="stylesheet">
  <style>
    body {
      font-family: 'Manrope', sans-serif;
      -webkit-font-smoothing: antialiased;
    }
    /* Hide scrollbar for cleaner UI */
    .no-scrollbar::-webkit-scrollbar {
      display: none;
    }
    .no-scrollbar {
      -ms-overflow-style: none;
      scrollbar-width: none;
    }
  </style>
</head>
<body>
  <!-- ROOT CONTAINER: Mobile Screen (375x812) -->
  <div class="w-full h-screen bg-white text-gray-900 overflow-hidden relative flex flex-col">
    
    <!-- BACKGROUND LAYER (The "Closed State" Content) -->
    <div class="flex-1 flex flex-col w-full h-full transform transition-transform duration-300">
      
      <!-- Header -->
      <header class="shrink-0 pt-14 px-6 pb-4 flex items-center justify-between border-b border-gray-100">
        <button id="btn-open-menu" class="w-10 h-10 -ml-2 flex items-center justify-center rounded-full hover:bg-gray-100 text-gray-900 transition-colors">
          <iconify-icon icon="lucide:menu" class="text-2xl"></iconify-icon>
        </button>
        <span class="text-base font-semibold tracking-tight text-gray-900">Dashboard</span>
        <button id="btn-notifications" class="w-10 h-10 -mr-2 flex items-center justify-center rounded-full hover:bg-gray-100 text-gray-900 transition-colors">
          <iconify-icon icon="lucide:bell" class="text-xl"></iconify-icon>
        </button>
      </header>

      <!-- Main Content (Simulated Feed) -->
      <main class="flex-1 overflow-y-auto px-6 pt-6 pb-[34px] space-y-8 no-scrollbar">
        <!-- Welcome Section -->
        <div class="space-y-2">
          <div class="h-8 w-2/3 bg-gray-200 rounded-md animate-pulse"></div>
          <div class="h-4 w-1/2 bg-gray-100 rounded-md"></div>
        </div>

        <!-- Stats Grid (Wireframe) -->
        <div class="grid grid-cols-2 gap-4">
          <div class="aspect-[4/3] bg-gray-50 border border-gray-200 rounded-xl p-4 flex flex-col justify-between">
            <div class="w-8 h-8 rounded-full bg-gray-200"></div>
            <div class="space-y-2">
              <div class="h-6 w-12 bg-gray-300 rounded"></div>
              <div class="h-3 w-16 bg-gray-200 rounded"></div>
            </div>
          </div>
          <div class="aspect-[4/3] bg-gray-50 border border-gray-200 rounded-xl p-4 flex flex-col justify-between">
            <div class="w-8 h-8 rounded-full bg-gray-200"></div>
            <div class="space-y-2">
              <div class="h-6 w-12 bg-gray-300 rounded"></div>
              <div class="h-3 w-16 bg-gray-200 rounded"></div>
            </div>
          </div>
        </div>

        <!-- Recent List (Wireframe) -->
        <div class="space-y-4">
          <div class="flex items-center justify-between">
            <div class="h-5 w-24 bg-gray-200 rounded"></div>
            <div class="h-4 w-12 bg-gray-100 rounded"></div>
          </div>
          <!-- List Items -->
          <div class="space-y-3">
            <div class="h-20 w-full border border-gray-100 rounded-xl p-3 flex items-center gap-4">
              <div class="w-14 h-14 bg-gray-100 rounded-lg shrink-0"></div>
              <div class="flex-1 space-y-2">
                <div class="h-4 w-3/4 bg-gray-200 rounded"></div>
                <div class="h-3 w-1/2 bg-gray-100 rounded"></div>
              </div>
            </div>
            <div class="h-20 w-full border border-gray-100 rounded-xl p-3 flex items-center gap-4">
              <div class="w-14 h-14 bg-gray-100 rounded-lg shrink-0"></div>
              <div class="flex-1 space-y-2">
                <div class="h-4 w-2/3 bg-gray-200 rounded"></div>
                <div class="h-3 w-1/2 bg-gray-100 rounded"></div>
              </div>
            </div>
            <div class="h-20 w-full border border-gray-100 rounded-xl p-3 flex items-center gap-4">
              <div class="w-14 h-14 bg-gray-100 rounded-lg shrink-0"></div>
              <div class="flex-1 space-y-2">
                <div class="h-4 w-3/4 bg-gray-200 rounded"></div>
                <div class="h-3 w-1/3 bg-gray-100 rounded"></div>
              </div>
            </div>
          </div>
        </div>
      </main>
    </div>

    <!-- FOREGROUND LAYER: Navigation Drawer System -->
    <!-- Initially hidden: pointer-events-none + opacity/transform states -->
    <div id="drawer-overlay" class="absolute inset-0 z-50 flex overflow-hidden pointer-events-none">
      
      <!-- Backdrop (Tap outside to dismiss) -->
      <!-- Initial State: opacity-0 -->
      <div id="drawer-backdrop" class="absolute inset-0 bg-black/30 backdrop-blur-[2px] opacity-0 transition-opacity duration-300" aria-hidden="true"></div>

      <!-- Side Drawer Panel -->
      <!-- Initial State: -translate-x-full -->
      <div id="drawer-panel" class="relative w-[82%] max-w-[320px] bg-white h-full shadow-2xl flex flex-col -translate-x-full transform transition-transform duration-300 ease-out">
        
        <!-- Drawer Header: User Profile -->
        <div class="shrink-0 pt-16 pb-8 px-6 border-b border-gray-100">
          <div class="flex items-center gap-4">
            <div class="w-12 h-12 rounded-full bg-gray-200 flex items-center justify-center text-gray-500 overflow-hidden border border-gray-300">
              <iconify-icon icon="lucide:user" class="text-2xl"></iconify-icon>
            </div>
            <div class="flex flex-col">
              <span class="font-bold text-gray-900 text-lg leading-tight">Alex Morgan</span>
              <span class="text-sm text-gray-500">Pro Member</span>
            </div>
          </div>
        </div>

        <!-- Scrollable Navigation Content -->
        <nav class="flex-1 overflow-y-auto px-4 py-6 space-y-8 no-scrollbar" id="drawer-nav-content">
          
          <!-- Group 1: Main -->
          <div class="space-y-1">
            <p class="px-3 text-xs font-bold text-gray-400 uppercase tracking-widest mb-2">Discover</p>
            <a href="#" id="nav-link-dashboard" class="nav-item flex items-center gap-4 px-3 py-3 rounded-lg bg-gray-100 text-gray-900 font-medium">
              <iconify-icon icon="lucide:layout-grid" class="text-xl"></iconify-icon>
              <span>Dashboard</span>
            </a>
            <a href="#" id="nav-link-explore" class="nav-item flex items-center gap-4 px-3 py-3 rounded-lg text-gray-600 hover:bg-gray-50 hover:text-gray-900 transition-colors font-medium">
              <iconify-icon icon="lucide:compass" class="text-xl"></iconify-icon>
              <span>Explore</span>
            </a>
            <a href="#" id="nav-link-saved" class="nav-item flex items-center gap-4 px-3 py-3 rounded-lg text-gray-600 hover:bg-gray-50 hover:text-gray-900 transition-colors font-medium">
              <iconify-icon icon="lucide:bookmark" class="text-xl"></iconify-icon>
              <span>Saved Items</span>
            </a>
          </div>

          <!-- Group 2: Account -->
          <div class="space-y-1">
            <p class="px-3 text-xs font-bold text-gray-400 uppercase tracking-widest mb-2">Personal</p>
            <a href="#" id="nav-link-messages" class="nav-item flex items-center gap-4 px-3 py-3 rounded-lg text-gray-600 hover:bg-gray-50 hover:text-gray-900 transition-colors font-medium">
              <iconify-icon icon="lucide:message-square" class="text-xl"></iconify-icon>
              <span>Messages</span>
              <span class="ml-auto bg-gray-900 text-white text-[10px] font-bold px-1.5 py-0.5 rounded-full">3</span>
            </a>
            <a href="#" id="nav-link-analytics" class="nav-item flex items-center gap-4 px-3 py-3 rounded-lg text-gray-600 hover:bg-gray-50 hover:text-gray-900 transition-colors font-medium">
              <iconify-icon icon="lucide:bar-chart-2" class="text-xl"></iconify-icon>
              <span>Analytics</span>
            </a>
            <a href="#" id="nav-link-billing" class="nav-item flex items-center gap-4 px-3 py-3 rounded-lg text-gray-600 hover:bg-gray-50 hover:text-gray-900 transition-colors font-medium">
              <iconify-icon icon="lucide:credit-card" class="text-xl"></iconify-icon>
              <span>Billing</span>
            </a>
          </div>

          <!-- Group 3: App -->
          <div class="space-y-1">
            <p class="px-3 text-xs font-bold text-gray-400 uppercase tracking-widest mb-2">System</p>
            <a href="#" id="nav-link-settings" class="nav-item flex items-center gap-4 px-3 py-3 rounded-lg text-gray-600 hover:bg-gray-50 hover:text-gray-900 transition-colors font-medium">
              <iconify-icon icon="lucide:settings" class="text-xl"></iconify-icon>
              <span>Settings</span>
            </a>
            <a href="#" id="nav-link-support" class="nav-item flex items-center gap-4 px-3 py-3 rounded-lg text-gray-600 hover:bg-gray-50 hover:text-gray-900 transition-colors font-medium">
              <iconify-icon icon="lucide:help-circle" class="text-xl"></iconify-icon>
              <span>Support</span>
            </a>
          </div>

        </nav>

        <!-- Drawer Footer -->
        <div class="shrink-0 p-6 border-t border-gray-100">
          <button id="btn-logout" class="nav-item flex items-center gap-3 text-gray-500 hover:text-gray-900 transition-colors text-sm font-semibold w-full">
            <iconify-icon icon="lucide:log-out" class="text-lg"></iconify-icon>
            <span>Log Out</span>
          </button>
          <p class="mt-4 text-xs text-gray-400 font-medium">v4.2.0 (Build 3902)</p>
        </div>

      </div>
      
      <!-- Close Button Area (Visual cue + dismiss zone) -->
      <!-- Initial State: opacity-0 -->
      <div id="drawer-close-area" class="flex-1 h-full relative opacity-0 transition-opacity duration-300 cursor-pointer">
        <button id="btn-close-drawer" class="absolute top-14 left-4 w-10 h-10 rounded-full bg-white/20 backdrop-blur-md flex items-center justify-center text-white border border-white/30 hover:bg-white/30 transition-colors">
           <iconify-icon icon="lucide:x" class="text-xl"></iconify-icon>
        </button>
      </div>

    </div>

  </div>

  <script>
    // Interactive Logic for Navigation Drawer
    document.addEventListener('DOMContentLoaded', () => {
      const openBtn = document.getElementById('btn-open-menu');
      const closeBtn = document.getElementById('btn-close-drawer');
      const overlay = document.getElementById('drawer-overlay');
      const backdrop = document.getElementById('drawer-backdrop');
      const panel = document.getElementById('drawer-panel');
      const closeArea = document.getElementById('drawer-close-area');
      const navItems = document.querySelectorAll('.nav-item');

      // Open Drawer
      function openDrawer() {
        // Enable pointer events on the overlay container
        overlay.classList.remove('pointer-events-none');
        
        // Fade in backdrop and close area
        backdrop.classList.remove('opacity-0');
        closeArea.classList.remove('opacity-0');
        
        // Slide in panel
        panel.classList.remove('-translate-x-full');
      }

      // Close Drawer
      function closeDrawer() {
        // Disable pointer events after transition (delay managed by CSS transition, but logic implies immediate toggle of state classes)
        // We keep pointer-events-none off until fully closed? No, immediate prevention is better for UX to avoid stray clicks.
        // Actually, let's delay the pointer-events-none to allow animation if needed, but for "pointer-events-none" it's safe to apply immediately to stop interaction, 
        // but that might kill the close button click if we are not careful? 
        // No, the close button is inside the overlay. If we add pointer-events-none to overlay, the close button stops working immediately? 
        // Yes. So we should rely on the visual transition, and toggle pointer-events-none only after animation completes, 
        // OR just toggle the state and let the user wait. 
        // BETTER: Toggle the visual states immediately. The pointer-events-none should be applied *after* the transition to avoid cutting off the click event? 
        // Actually, if I add pointer-events-none, it applies to children unless they override. 
        // Let's use a timeout for the clean up of pointer-events, or just let it stay interactive until it fades out? 
        // Simplest: Toggle state classes. Use 'pointer-events-none' to control whether the overlay blocks the main content.
        
        backdrop.classList.add('opacity-0');
        closeArea.classList.add('opacity-0');
        panel.classList.add('-translate-x-full');
        
        // Wait for transition (300ms) before hiding interaction
        setTimeout(() => {
          overlay.classList.add('pointer-events-none');
        }, 300);
      }

      // Event Listeners
      openBtn.addEventListener('click', openDrawer);
      closeBtn.addEventListener('click', (e) => {
        e.stopPropagation(); // Prevent triggering other clicks
        closeDrawer();
      });
      backdrop.addEventListener('click', closeDrawer);
      
      // Close when clicking the empty area around the close button
      closeArea.addEventListener('click', (e) => {
        if (e.target === closeArea) {
          closeDrawer();
        }
      });

      // Close when clicking any navigation item
      navItems.forEach(item => {
        item.addEventListener('click', closeDrawer);
      });
    });
  </script>
</body>
</html>
~~~
All Prompts