All Prompts
All Prompts

mobile appnavigationlayout
Role-Based Side Drawer Navigation
Контекстная боковая панель навигации. Динамически адаптирует пункты меню под роль пользователя, сохраняя структуру. Идеально для CRM и enterprise-приложений.
by Shirley LouLive Preview
Prompt
# Role-Based 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>Role-Based Navigation Drawer</title>
<script src="https://cdn.tailwindcss.com"></script>
<link href="https://fonts.googleapis.com/css2?family=Manrope:wght@400;500;600;700&display=swap" rel="stylesheet">
<script src="https://code.iconify.design/iconify-icon/1.0.7/iconify-icon.min.js"></script>
<style>
body {
font-family: 'Manrope', sans-serif;
margin: 0;
padding: 0;
background-color: #F3F4F6;
}
/* Custom scrollbar for clean look */
.hide-scrollbar::-webkit-scrollbar {
display: none;
}
.hide-scrollbar {
-ms-overflow-style: none;
scrollbar-width: none;
}
/* Smooth fade in for drawer content */
@keyframes slideIn {
from { transform: translateX(-100%); }
to { transform: translateX(0); }
}
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
.drawer-animate {
animation: slideIn 0.4s cubic-bezier(0.16, 1, 0.3, 1) forwards;
}
.backdrop-animate {
animation: fadeIn 0.4s ease-out forwards;
}
</style>
</head>
<body>
<!-- Root Container (Mobile Viewport) -->
<div class="w-full h-screen relative bg-white overflow-hidden flex flex-col">
<!-- BACKGROUND APP CONTENT (Context Layer) -->
<!-- This represents the app behind the drawer, blurred and dimmed -->
<main class="flex-1 bg-gray-50 flex flex-col w-full h-full relative">
<header class="pt-14 px-5 pb-4 flex justify-between items-center bg-white border-b border-gray-100">
<button id="drawer-open-btn" class="w-10 h-10 flex items-center justify-center rounded-lg hover:bg-gray-100 transition-colors" aria-label="Open menu">
<iconify-icon icon="lucide:menu" class="text-2xl text-gray-900"></iconify-icon>
</button>
<div class="w-8 h-8 rounded-full bg-gray-200"></div>
</header>
<div class="p-5 space-y-4">
<div class="h-40 w-full bg-white rounded-xl border border-gray-200 shadow-sm"></div>
<div class="h-24 w-full bg-white rounded-xl border border-gray-200 shadow-sm"></div>
<div class="h-56 w-full bg-white rounded-xl border border-gray-200 shadow-sm"></div>
</div>
</main>
<!-- DRAWER OVERLAY SYSTEM -->
<!-- Backdrop -->
<div id="drawer-backdrop" class="absolute inset-0 bg-gray-900/40 backdrop-blur-[2px] z-40 opacity-0 pointer-events-none transition-opacity duration-300"></div>
<!-- Side Drawer Panel -->
<nav id="side-drawer" class="absolute top-0 left-0 bottom-0 w-[320px] bg-white z-50 shadow-2xl flex flex-col -translate-x-full transition-transform duration-300 ease-in-out border-r border-gray-100">
<!-- 1. USER CONTEXT AREA -->
<div class="pt-14 pb-6 px-6 border-b border-gray-100 flex items-center gap-4 bg-white">
<div class="relative">
<div class="w-12 h-12 rounded-full bg-gray-100 flex items-center justify-center border border-gray-200">
<!-- Placeholder Avatar Icon -->
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" class="text-gray-400" stroke-width="1.5">
<path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"></path>
<circle cx="12" cy="7" r="4"></circle>
</svg>
</div>
<!-- Online Status Dot -->
<div class="absolute bottom-0 right-0 w-3 h-3 bg-emerald-500 border-2 border-white rounded-full"></div>
</div>
<div class="flex-1 min-w-0">
<h2 class="text-gray-900 font-bold text-base truncate">Alex Morgan</h2>
<div class="flex items-center gap-2 mt-0.5">
<span class="bg-black text-white text-[10px] font-bold px-2 py-0.5 rounded-full uppercase tracking-wider">Editor</span>
<span class="text-xs text-gray-500">@design_lead</span>
</div>
</div>
</div>
<!-- SCROLLABLE NAVIGATION CONTENT -->
<div class="flex-1 overflow-y-auto hide-scrollbar py-6 px-4 space-y-8">
<!-- 2. SECTION: DISCOVER -->
<div class="space-y-1">
<h3 class="px-3 text-xs font-bold text-gray-400 uppercase tracking-widest mb-3">Discover</h3>
<!-- Nav Item: Active State -->
<a href="#" class="flex items-center gap-3 px-3 py-3 bg-gray-50 rounded-lg text-gray-900 group transition-colors">
<div class="w-5 h-5 flex items-center justify-center">
<svg class="w-5 h-5 text-gray-900" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<rect x="3" y="3" width="7" height="7" rx="1"></rect>
<rect x="14" y="3" width="7" height="7" rx="1"></rect>
<rect x="14" y="14" width="7" height="7" rx="1"></rect>
<rect x="3" y="14" width="7" height="7" rx="1"></rect>
</svg>
</div>
<span class="font-semibold text-sm">Dashboard</span>
</a>
<!-- Nav Item: Default -->
<a href="#" class="flex items-center gap-3 px-3 py-3 text-gray-600 hover:bg-gray-50 hover:text-gray-900 rounded-lg transition-colors">
<div class="w-5 h-5 flex items-center justify-center">
<svg class="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<circle cx="12" cy="12" r="10"></circle>
<line x1="12" y1="8" x2="12" y2="12"></line>
<line x1="12" y1="16" x2="12.01" y2="16"></line>
</svg>
</div>
<span class="font-medium text-sm">Updates</span>
<span class="ml-auto bg-gray-100 text-gray-600 text-[10px] font-bold px-1.5 py-0.5 rounded">4</span>
</a>
<a href="#" class="flex items-center gap-3 px-3 py-3 text-gray-600 hover:bg-gray-50 hover:text-gray-900 rounded-lg transition-colors">
<div class="w-5 h-5 flex items-center justify-center">
<svg class="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"></path>
</svg>
</div>
<span class="font-medium text-sm">Messages</span>
</a>
</div>
<!-- 3. SECTION: WORKSPACE (Expandable Groups) -->
<div class="space-y-1">
<h3 class="px-3 text-xs font-bold text-gray-400 uppercase tracking-widest mb-3">Workspace</h3>
<!-- Expandable Group: OPEN -->
<div class="space-y-1">
<button id="toggle-design-system" class="w-full flex items-center gap-3 px-3 py-3 text-gray-900 rounded-lg hover:bg-gray-50 transition-colors">
<div class="w-5 h-5 flex items-center justify-center">
<svg class="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"></path>
</svg>
</div>
<span class="font-semibold text-sm flex-1 text-left">Design System</span>
<svg class="w-4 h-4 text-gray-400 transform rotate-180 transition-transform" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<polyline points="6 9 12 15 18 9"></polyline>
</svg>
</button>
<!-- Nested Items (Indented) -->
<div id="content-design-system" class="pl-11 pr-2 space-y-1 overflow-hidden transition-all duration-300">
<a href="#" class="block py-2 text-sm text-gray-500 hover:text-gray-900 font-medium">Components</a>
<a href="#" class="block py-2 text-sm text-gray-900 font-semibold border-l-2 border-black pl-3 -ml-3">Typography</a>
<a href="#" class="block py-2 text-sm text-gray-500 hover:text-gray-900 font-medium">Color Palette</a>
</div>
</div>
<!-- Expandable Group: COLLAPSED -->
<div>
<button id="toggle-documentation" class="w-full flex items-center gap-3 px-3 py-3 text-gray-600 rounded-lg hover:bg-gray-50 transition-colors">
<div class="w-5 h-5 flex items-center justify-center">
<svg class="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
<polyline points="14 2 14 8 20 8"></polyline>
<line x1="16" y1="13" x2="8" y2="13"></line>
<line x1="16" y1="17" x2="8" y2="17"></line>
<polyline points="10 9 9 9 8 9"></polyline>
</svg>
</div>
<span class="font-medium text-sm flex-1 text-left">Documentation</span>
<svg class="w-4 h-4 text-gray-400 transition-transform" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<polyline points="6 9 12 15 18 9"></polyline>
</svg>
</button>
<div id="content-documentation" class="pl-11 pr-2 space-y-1 overflow-hidden h-0 transition-all duration-300 opacity-0">
<a href="#" id="doc-api-link" class="block py-2 text-sm text-gray-500 hover:text-gray-900 font-medium">API Reference</a>
<a href="#" id="doc-guides-link" class="block py-2 text-sm text-gray-500 hover:text-gray-900 font-medium">User Guides</a>
</div>
</div>
</div>
<!-- 4. SECTION: ADMIN (Permission Gated) -->
<div class="space-y-1">
<div class="flex items-center justify-between px-3 mb-3">
<h3 class="text-xs font-bold text-gray-400 uppercase tracking-widest">Admin</h3>
<!-- Role Indicator -->
<span class="text-[10px] text-gray-400 font-medium flex items-center gap-1">
<svg class="w-3 h-3" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<rect x="3" y="11" width="18" height="11" rx="2" ry="2"></rect>
<path d="M7 11V7a5 5 0 0 1 10 0v4"></path>
</svg>
Restricted
</span>
</div>
<!-- Permitted Item -->
<a href="#" class="flex items-center gap-3 px-3 py-3 text-gray-600 hover:bg-gray-50 hover:text-gray-900 rounded-lg transition-colors">
<div class="w-5 h-5 flex items-center justify-center">
<svg class="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"></path>
<circle cx="9" cy="7" r="4"></circle>
<path d="M23 21v-2a4 4 0 0 0-3-3.87"></path>
<path d="M16 3.13a4 4 0 0 1 0 7.75"></path>
</svg>
</div>
<span class="font-medium text-sm">Team Members</span>
</a>
<!-- Locked/Restricted Item (Visual permission handling) -->
<div class="group relative flex items-center gap-3 px-3 py-3 rounded-lg opacity-50 cursor-not-allowed">
<div class="w-5 h-5 flex items-center justify-center">
<svg class="w-5 h-5 text-gray-400" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<rect x="2" y="5" width="20" height="14" rx="2"></rect>
<line x1="2" y1="10" x2="22" y2="10"></line>
</svg>
</div>
<span class="font-medium text-sm text-gray-400">Billing & Plans</span>
<div class="ml-auto">
<svg class="w-3.5 h-3.5 text-gray-400" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2.5">
<rect x="3" y="11" width="18" height="11" rx="2" ry="2"></rect>
<path d="M7 11V7a5 5 0 0 1 10 0v4"></path>
</svg>
</div>
</div>
<!-- Hidden Item Placeholder (Shows logic of conditional rendering) -->
<!-- <div class="hidden">Audit Logs</div> -->
</div>
</div>
<!-- DRAWER FOOTER (Bottom Safe Area) -->
<div class="pb-[34px] bg-white">
<div class="px-6 py-4 border-t border-gray-100">
<a href="#" class="flex items-center gap-3 text-gray-500 hover:text-gray-900 transition-colors">
<div class="w-5 h-5 flex items-center justify-center">
<svg class="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path d="M18.36 6.64a9 9 0 1 1-12.73 0"></path>
<line x1="12" y1="2" x2="12" y2="12"></line>
</svg>
</div>
<span class="font-medium text-sm">Log Out</span>
</a>
</div>
</div>
</nav>
</div>
<script>
const drawer = document.getElementById('side-drawer');
const backdrop = document.getElementById('drawer-backdrop');
const openBtn = document.getElementById('drawer-open-btn');
const closeBtn = document.getElementById('drawer-open-btn'); // Reuse or specific logout/close if added
const toggleDrawer = (isOpen) => {
if (isOpen) {
drawer.classList.remove('-translate-x-full');
backdrop.classList.remove('opacity-0', 'pointer-events-none');
backdrop.classList.add('opacity-100');
} else {
drawer.classList.add('-translate-x-full');
backdrop.classList.remove('opacity-100');
backdrop.classList.add('opacity-0', 'pointer-events-none');
}
};
openBtn.addEventListener('click', () => toggleDrawer(true));
backdrop.addEventListener('click', () => toggleDrawer(false));
const setupToggle = (btnId, contentId) => {
const btn = document.getElementById(btnId);
const content = document.getElementById(contentId);
const arrow = btn.querySelector('svg:last-child');
btn.addEventListener('click', () => {
const isExpanded = content.style.height !== '0px' && content.style.height !== '';
if (isExpanded) {
content.style.height = '0px';
content.style.opacity = '0';
arrow.style.transform = 'rotate(0deg)';
btn.classList.replace('text-gray-900', 'text-gray-600');
btn.classList.remove('font-semibold');
} else {
content.style.height = content.scrollHeight + 'px';
content.style.opacity = '1';
arrow.style.transform = 'rotate(180deg)';
btn.classList.replace('text-gray-600', 'text-gray-900');
btn.classList.add('font-semibold');
}
});
};
setupToggle('toggle-design-system', 'content-design-system');
setupToggle('toggle-documentation', 'content-documentation');
// Initial state for Documentation (it was closed by default in prompt)
document.getElementById('content-documentation').style.height = '0px';
</script>
</body>
</html>
~~~