VibeCoderzVibeCoderz
Все промпты
Side drawer navigation UI Preview
mobile appnavigationlayout

Side drawer navigation

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

Автор: Shirley LouЖивое превью

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>
~~~
Все промпты