generated from corrad-software/corrad-af-2024
558 lines
22 KiB
Vue
558 lines
22 KiB
Vue
<script setup>
|
|
import { ref, computed } from 'vue';
|
|
import { useDmsStore } from '~/stores/dms';
|
|
|
|
const store = useDmsStore();
|
|
const expandedSections = ref({
|
|
'public-cabinet': true,
|
|
'my-cabinets': true,
|
|
'private-cabinets': true
|
|
});
|
|
|
|
const showAccessRequestDialog = ref(false);
|
|
const currentCabinetForAccess = ref(null);
|
|
const accessRequestReason = ref('');
|
|
|
|
// Toggle expanded state of a section
|
|
const toggleSection = (sectionId) => {
|
|
expandedSections.value[sectionId] = !expandedSections.value[sectionId];
|
|
};
|
|
|
|
// Navigate to a cabinet
|
|
const navigateToCabinet = (cabinetId) => {
|
|
// In a real implementation, this would navigate to the cabinet
|
|
console.log(`Navigating to cabinet: ${cabinetId}`);
|
|
};
|
|
|
|
// Request access to a private cabinet
|
|
const requestAccess = (cabinet) => {
|
|
currentCabinetForAccess.value = cabinet;
|
|
showAccessRequestDialog.value = true;
|
|
};
|
|
|
|
// Submit access request
|
|
const submitAccessRequest = async () => {
|
|
if (!accessRequestReason.value.trim()) {
|
|
alert('Please provide a reason for your request');
|
|
return;
|
|
}
|
|
|
|
try {
|
|
await store.requestCabinetAccess(
|
|
currentCabinetForAccess.value.id,
|
|
accessRequestReason.value
|
|
);
|
|
|
|
// Reset form
|
|
accessRequestReason.value = '';
|
|
currentCabinetForAccess.value = null;
|
|
showAccessRequestDialog.value = false;
|
|
|
|
// Show success message
|
|
alert('Access request submitted successfully');
|
|
} catch (error) {
|
|
console.error('Failed to submit access request:', error);
|
|
alert('Failed to submit access request. Please try again.');
|
|
}
|
|
};
|
|
|
|
// Get access status icon
|
|
const getAccessStatusIcon = (cabinet) => {
|
|
if (cabinet.accessType === 'public') {
|
|
return { name: 'check-circle', color: 'text-green-500' };
|
|
}
|
|
|
|
if (cabinet.accessType === 'personal') {
|
|
return { name: 'check-circle', color: 'text-green-500' };
|
|
}
|
|
|
|
if (cabinet.accessType === 'private') {
|
|
if (cabinet.hasAccess) {
|
|
return { name: 'check-circle', color: 'text-green-500' };
|
|
}
|
|
|
|
if (cabinet.isLocked) {
|
|
return { name: 'lock', color: 'text-red-500' };
|
|
}
|
|
|
|
return { name: 'clock', color: 'text-amber-500' };
|
|
}
|
|
|
|
return null;
|
|
};
|
|
|
|
// Render cabinet recursively
|
|
const renderCabinet = (cabinet, level = 0) => {
|
|
const paddingStyle = { paddingLeft: `${level * 16 + 8}px` };
|
|
const hasChildren = cabinet.children && cabinet.children.length > 0;
|
|
const isExpanded = expandedSections.value[cabinet.id];
|
|
|
|
return (
|
|
<div class="cabinet-item">
|
|
<div
|
|
class="cabinet-header flex items-center py-2 px-2 hover:bg-gray-100 dark:hover:bg-gray-800 cursor-pointer"
|
|
style={paddingStyle}
|
|
onClick={() => hasChildren ? toggleSection(cabinet.id) : navigateToCabinet(cabinet.id)}
|
|
>
|
|
{hasChildren && (
|
|
<svg
|
|
class={`mr-1 text-gray-500 transition-transform ${isExpanded ? 'transform rotate-90' : ''}`}
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
width="16"
|
|
height="16"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
stroke-width="2"
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
>
|
|
<polyline points="9 18 15 12 9 6"></polyline>
|
|
</svg>
|
|
)}
|
|
|
|
<span class={`ml-${hasChildren ? '0' : '4'} flex-1`}>
|
|
{cabinet.type === 'tag' ? (
|
|
<span class="flex items-center">
|
|
<span class="w-2 h-2 rounded-full bg-purple-500 mr-1"></span>
|
|
<span class="text-sm">{cabinet.name}</span>
|
|
</span>
|
|
) : (
|
|
<span class="flex items-center">
|
|
{cabinet.type === 'cabinet' && (
|
|
<svg
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
width="16"
|
|
height="16"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
stroke-width="2"
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
class="mr-1"
|
|
>
|
|
<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>
|
|
)}
|
|
<span class="text-sm">{cabinet.name}</span>
|
|
</span>
|
|
)}
|
|
</span>
|
|
|
|
{/* Status icon */}
|
|
{cabinet.accessType === 'private' && !cabinet.hasAccess && (
|
|
<button
|
|
class="text-blue-500 hover:text-blue-700 p-1"
|
|
onClick={(e) => {
|
|
e.stopPropagation();
|
|
requestAccess(cabinet);
|
|
}}
|
|
disabled={cabinet.accessRequestStatus === 'rejected'}
|
|
>
|
|
<svg
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
width="16"
|
|
height="16"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
stroke-width="2"
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
>
|
|
<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>
|
|
</button>
|
|
)}
|
|
|
|
{getAccessStatusIcon(cabinet) && (
|
|
<span class={getAccessStatusIcon(cabinet).color}>
|
|
<svg
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
width="16"
|
|
height="16"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
stroke-width="2"
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
>
|
|
{getAccessStatusIcon(cabinet).name === 'check-circle' && (
|
|
<path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"></path>
|
|
<polyline points="22 4 12 14.01 9 11.01"></polyline>
|
|
)}
|
|
|
|
{getAccessStatusIcon(cabinet).name === 'clock' && (
|
|
<circle cx="12" cy="12" r="10"></circle>
|
|
<polyline points="12 6 12 12 16 14"></polyline>
|
|
)}
|
|
|
|
{getAccessStatusIcon(cabinet).name === 'lock' && (
|
|
<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>
|
|
</span>
|
|
)}
|
|
</div>
|
|
|
|
{hasChildren && isExpanded && (
|
|
<div class="cabinet-children">
|
|
{cabinet.children.map(child => renderCabinet(child, level + 1))}
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
};
|
|
</script>
|
|
|
|
<template>
|
|
<div class="cabinet-navigation h-full overflow-y-auto">
|
|
<!-- Public cabinets -->
|
|
<div class="navigation-section">
|
|
<div
|
|
@click="toggleSection('public-cabinet')"
|
|
class="section-header flex items-center p-2 cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-800"
|
|
>
|
|
<svg
|
|
class="mr-1 text-gray-500"
|
|
:class="expandedSections['public-cabinet'] ? 'transform rotate-90' : ''"
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
width="16"
|
|
height="16"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
stroke-width="2"
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
>
|
|
<polyline points="9 18 15 12 9 6"></polyline>
|
|
</svg>
|
|
<span class="font-medium text-sm">📁 Public Cabinet</span>
|
|
</div>
|
|
|
|
<div v-if="expandedSections['public-cabinet']" class="section-content">
|
|
<div v-for="cabinet in store.cabinets.filter(c => c.accessType === 'public')" :key="cabinet.id">
|
|
<div v-for="child in cabinet.children" :key="child.id" class="menu-item">
|
|
<div
|
|
class="flex items-center pl-8 pr-3 py-2 cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-800"
|
|
@click="navigateToCabinet(child.id)"
|
|
>
|
|
<svg class="mr-2 text-gray-500" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
<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>
|
|
<span class="text-sm">{{ child.name }}</span>
|
|
<span class="ml-auto text-green-500">
|
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
<path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"></path>
|
|
<polyline points="22 4 12 14.01 9 11.01"></polyline>
|
|
</svg>
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- My Cabinets -->
|
|
<div class="navigation-section">
|
|
<div
|
|
@click="toggleSection('my-cabinets')"
|
|
class="section-header flex items-center p-2 cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-800"
|
|
>
|
|
<svg
|
|
class="mr-1 text-gray-500"
|
|
:class="expandedSections['my-cabinets'] ? 'transform rotate-90' : ''"
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
width="16"
|
|
height="16"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
stroke-width="2"
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
>
|
|
<polyline points="9 18 15 12 9 6"></polyline>
|
|
</svg>
|
|
<span class="font-medium text-sm">📁 My Cabinets</span>
|
|
</div>
|
|
|
|
<div v-if="expandedSections['my-cabinets']" class="section-content">
|
|
<template v-if="store.personalCabinets">
|
|
<div v-for="cabinet in store.personalCabinets.children" :key="cabinet.id">
|
|
<div
|
|
class="flex items-center pl-8 pr-3 py-2 cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-800"
|
|
@click="() => {
|
|
toggleSection(cabinet.id);
|
|
navigateToCabinet(cabinet.id);
|
|
}"
|
|
>
|
|
<svg
|
|
v-if="cabinet.children && cabinet.children.length > 0"
|
|
class="mr-2 text-gray-500"
|
|
:class="expandedSections[cabinet.id] ? 'transform rotate-90' : ''"
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
width="16"
|
|
height="16"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
stroke-width="2"
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
>
|
|
<polyline points="9 18 15 12 9 6"></polyline>
|
|
</svg>
|
|
<svg v-else class="mr-2 text-gray-500" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
<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>
|
|
<span class="text-sm">{{ cabinet.name }}</span>
|
|
<span class="ml-auto text-green-500">
|
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
<path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"></path>
|
|
<polyline points="22 4 12 14.01 9 11.01"></polyline>
|
|
</svg>
|
|
</span>
|
|
</div>
|
|
|
|
<!-- Recursive children -->
|
|
<template v-if="expandedSections[cabinet.id] && cabinet.children && cabinet.children.length > 0">
|
|
<div
|
|
v-for="child in cabinet.children"
|
|
:key="child.id"
|
|
class="pl-4"
|
|
>
|
|
<div
|
|
class="flex items-center pl-8 pr-3 py-2 cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-800"
|
|
@click="() => {
|
|
if (child.children && child.children.length > 0) {
|
|
toggleSection(child.id);
|
|
}
|
|
navigateToCabinet(child.id);
|
|
}"
|
|
>
|
|
<svg
|
|
v-if="child.children && child.children.length > 0"
|
|
class="mr-2 text-gray-500"
|
|
:class="expandedSections[child.id] ? 'transform rotate-90' : ''"
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
width="16"
|
|
height="16"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
stroke-width="2"
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
>
|
|
<polyline points="9 18 15 12 9 6"></polyline>
|
|
</svg>
|
|
<svg v-else class="mr-2 text-gray-500" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
<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>
|
|
<span class="text-sm">{{ child.name }}</span>
|
|
</div>
|
|
|
|
<!-- Third level -->
|
|
<template v-if="expandedSections[child.id] && child.children && child.children.length > 0">
|
|
<div
|
|
v-for="grandchild in child.children"
|
|
:key="grandchild.id"
|
|
class="pl-4"
|
|
>
|
|
<!-- Display tag groups -->
|
|
<template v-if="grandchild.type === 'cabinet'">
|
|
<div
|
|
class="flex items-center pl-12 pr-3 py-2 cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-800"
|
|
@click="() => {
|
|
if (grandchild.children && grandchild.children.length > 0) {
|
|
toggleSection(grandchild.id);
|
|
}
|
|
navigateToCabinet(grandchild.id);
|
|
}"
|
|
>
|
|
<svg
|
|
v-if="grandchild.children && grandchild.children.length > 0"
|
|
class="mr-2 text-gray-500"
|
|
:class="expandedSections[grandchild.id] ? 'transform rotate-90' : ''"
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
width="16"
|
|
height="16"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
stroke-width="2"
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
>
|
|
<polyline points="9 18 15 12 9 6"></polyline>
|
|
</svg>
|
|
<svg v-else class="mr-2 text-gray-500" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
<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>
|
|
<span class="text-sm">{{ grandchild.name }}</span>
|
|
</div>
|
|
|
|
<!-- Tags -->
|
|
<template v-if="expandedSections[grandchild.id] && grandchild.children && grandchild.children.length > 0">
|
|
<div
|
|
v-for="tag in grandchild.children"
|
|
:key="tag.id"
|
|
@click="navigateToCabinet(tag.id)"
|
|
class="flex items-center pl-16 pr-3 py-2 cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-800"
|
|
>
|
|
<span class="w-2 h-2 rounded-full bg-purple-500 mr-2"></span>
|
|
<span class="text-sm">{{ tag.name }}</span>
|
|
</div>
|
|
</template>
|
|
</template>
|
|
</div>
|
|
</template>
|
|
</div>
|
|
</template>
|
|
</div>
|
|
</template>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Private Cabinets -->
|
|
<div class="navigation-section">
|
|
<div
|
|
@click="toggleSection('private-cabinets')"
|
|
class="section-header flex items-center p-2 cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-800"
|
|
>
|
|
<svg
|
|
class="mr-1 text-gray-500"
|
|
:class="expandedSections['private-cabinets'] ? 'transform rotate-90' : ''"
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
width="16"
|
|
height="16"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
stroke-width="2"
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
>
|
|
<polyline points="9 18 15 12 9 6"></polyline>
|
|
</svg>
|
|
<span class="font-medium text-sm">🔒 Private Cabinets</span>
|
|
</div>
|
|
|
|
<div v-if="expandedSections['private-cabinets']" class="section-content">
|
|
<template v-if="store.privateCabinets">
|
|
<div v-for="cabinet in store.privateCabinets.children" :key="cabinet.id">
|
|
<div
|
|
class="flex items-center pl-8 pr-3 py-2 cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-800"
|
|
@click="cabinet.hasAccess ? navigateToCabinet(cabinet.id) : null"
|
|
>
|
|
<svg class="mr-2 text-gray-500" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
<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>
|
|
<span class="text-sm">{{ cabinet.name }}</span>
|
|
|
|
<!-- Status indicators -->
|
|
<div class="ml-auto flex items-center gap-1">
|
|
<!-- Request access button -->
|
|
<button
|
|
v-if="!cabinet.hasAccess && cabinet.accessRequestStatus !== 'rejected'"
|
|
@click.stop="requestAccess(cabinet)"
|
|
class="text-blue-500 hover:text-blue-700 p-1"
|
|
>
|
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
<path d="M21 2l-2 2m-7.61 7.61a5.5 5.5 0 1 1-7.778 7.778 5.5 5.5 0 0 1 7.777-7.777zm0 0L15.5 7.5m0 0l3 3L22 7l-3-3m-3.5 3.5L19 4"></path>
|
|
</svg>
|
|
</button>
|
|
|
|
<!-- Access status indicator -->
|
|
<span
|
|
v-if="cabinet.accessRequestStatus === 'pending'"
|
|
class="text-amber-500"
|
|
title="Access request pending"
|
|
>
|
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
<circle cx="12" cy="12" r="10"></circle>
|
|
<polyline points="12 6 12 12 16 14"></polyline>
|
|
</svg>
|
|
</span>
|
|
|
|
<span
|
|
v-else-if="cabinet.isLocked"
|
|
class="text-red-500"
|
|
title="Access locked"
|
|
>
|
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
<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>
|
|
</span>
|
|
|
|
<span
|
|
v-else-if="cabinet.hasAccess"
|
|
class="text-green-500"
|
|
title="Access granted"
|
|
>
|
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
<path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"></path>
|
|
<polyline points="22 4 12 14.01 9 11.01"></polyline>
|
|
</svg>
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Access request dialog -->
|
|
<rs-dialog v-model="showAccessRequestDialog" title="Request Access">
|
|
<template v-if="currentCabinetForAccess">
|
|
<p class="mb-4">You are requesting access to: <strong>{{ currentCabinetForAccess.name }}</strong></p>
|
|
|
|
<div class="mb-4">
|
|
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
|
|
Reason for Access Request
|
|
</label>
|
|
<textarea
|
|
v-model="accessRequestReason"
|
|
rows="3"
|
|
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-primary focus:ring focus:ring-primary focus:ring-opacity-50"
|
|
placeholder="Please provide a reason for your request..."
|
|
></textarea>
|
|
</div>
|
|
</template>
|
|
|
|
<template #footer>
|
|
<div class="flex justify-end gap-2">
|
|
<rs-button color="secondary" @click="showAccessRequestDialog = false">
|
|
Cancel
|
|
</rs-button>
|
|
<rs-button color="primary" @click="submitAccessRequest">
|
|
Submit Request
|
|
</rs-button>
|
|
</div>
|
|
</template>
|
|
</rs-dialog>
|
|
</div>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.cabinet-navigation {
|
|
width: 260px;
|
|
position: relative;
|
|
}
|
|
|
|
.section-header {
|
|
font-weight: 500;
|
|
border-bottom: 1px solid rgba(0, 0, 0, 0.05);
|
|
}
|
|
|
|
.menu-item {
|
|
transition: all 0.2s ease;
|
|
}
|
|
</style> |