secureweb/sweb/src/components/Sidebar.svelte
Mahmoud Emad 486b5ceb05 chore: Improve website UI and add .vscode to .gitignore
- Update website footer to improve responsiveness and layout.
- Improve the styling and layout of the Home page components.
- Update the Layout component to handle mobile sidebar better.
- Improve Markdown rendering for better responsiveness.
- Remove unused NavBar component.
- Remove svelte-vscode extension from extensions.json.
- Add .vscode folder to .gitignore to prevent accidental commits.
2025-05-11 17:43:11 +03:00

113 lines
4.1 KiB
Svelte

<script lang="ts">
import type { NavItem } from "../types/nav";
import { ChevronDown, X } from "lucide-svelte";
import { onMount } from "svelte";
export let navData: NavItem[] = [];
export let onNavItemClick: (path: string) => void = () => {};
export let visible: boolean = true;
export let isMobile: boolean = false;
// Track which sections are expanded
let expanded: Record<string, boolean> = {};
// Track active item
let activePath: string = "";
// Auto-expand the section containing the active item
$: if (activePath) {
// Find which section contains this path
navData.forEach((item) => {
if (item.children) {
const hasActivePath = item.children.some(
(child) => child.link === activePath,
);
if (hasActivePath) {
expanded[item.label] = true;
}
}
});
}
function toggleSection(label: string) {
expanded[label] = !expanded[label];
}
function handleNavItemClick(path: string, event: MouseEvent) {
event.preventDefault();
activePath = path;
// Convert URL path to document path
// Remove leading slash
const docPath = path.replace(/^\//, "");
// Call the event handler prop
onNavItemClick(docPath);
}
// Initialize with first section expanded
onMount(() => {
if (navData.length > 0) {
expanded[navData[0].label] = true;
}
});
</script>
<aside
class="sidebar bg-gray-50 border-r border-gray-200 h-screen fixed top-0 left-0 pt-16 overflow-y-auto shadow-sm z-20
{isMobile ? 'w-[85%] max-w-xs' : 'w-64'}
transition-transform duration-300 ease-in-out
{visible ? 'translate-x-0' : '-translate-x-full'}"
>
<nav class="w-full">
{#each navData as item}
{#if item.children && item.children.length > 0}
<div class="border-b border-gray-200">
<button
class="flex justify-between items-center w-full text-left p-3 sm:p-4 hover:bg-gray-100 text-gray-700 font-medium"
on:click={() => toggleSection(item.label)}
>
<span class="truncate">{item.label}</span>
<ChevronDown
class="h-4 w-4 flex-shrink-0 transition-transform duration-200 {expanded[
item.label
]
? 'rotate-180'
: ''}"
/>
</button>
{#if expanded[item.label]}
<div class="bg-gray-50">
{#each item.children as child}
<a
href={child.link}
class="block p-3 pl-6 sm:pl-8 hover:bg-gray-100 text-gray-600 border-t border-gray-100 truncate {activePath ===
child.link
? 'bg-blue-50 text-blue-700 font-medium'
: ''}"
on:click={(e) =>
handleNavItemClick(child.link, e)}
>
{child.label}
</a>
{/each}
</div>
{/if}
</div>
{:else}
<a
href={item.link}
class="block p-3 sm:p-4 hover:bg-gray-100 text-gray-700 border-b border-gray-200 truncate {activePath ===
item.link
? 'bg-blue-50 text-blue-700 font-medium'
: ''}"
on:click={(e) => handleNavItemClick(item.link, e)}
>
{item.label}
</a>
{/if}
{/each}
</nav>
</aside>