NavigationDrawer.svelte 11.3 KB
<script>
  import { page } from '$app/stores';
  import { onMount } from 'svelte';
  import { drawerOpen, closeDrawer } from '$lib/stores/drawer.js';

  let isDarkMode = $state(false);

  const clasificadores = [
    { href: '/clasificadores/institucional', nombre: 'Institucional', desc: 'Quién gasta' },
    { href: '/clasificadores/objeto-gasto', nombre: 'Objeto del Gasto', desc: 'En qué' },
    { href: '/clasificadores/rubros', nombre: 'Rubros', desc: 'Cuánto ingresa' },
    { href: '/clasificadores/funcional', nombre: 'Funcional', desc: 'Para qué' },
    { href: '/clasificadores/fuente', nombre: 'Fuente', desc: 'De dónde' },
    { href: '/clasificadores/organismo', nombre: 'Organismo', desc: 'Quién financia' },
    { href: '/clasificadores/sectores', nombre: 'Sectores', desc: 'Qué sector' },
  ];

  function isActive(href) {
    return $page.url.pathname.startsWith(href);
  }

  function toggleTheme() {
    isDarkMode = !isDarkMode;
    document.documentElement.classList.toggle('dark', isDarkMode);
    localStorage.setItem('theme', isDarkMode ? 'dark' : 'light');
  }

  onMount(() => {
    isDarkMode = document.documentElement.classList.contains('dark');

    const observer = new MutationObserver(() => {
      isDarkMode = document.documentElement.classList.contains('dark');
    });
    observer.observe(document.documentElement, {
      attributes: true,
      attributeFilter: ['class']
    });

    return () => observer.disconnect();
  });
</script>

<!-- Overlay (fondo oscuro) -->
{#if $drawerOpen}
  <div
    class="fixed inset-0 bg-black/40 z-[200]"
    style="opacity: {$drawerOpen ? '1' : '0'}; transition: opacity 0.2s ease-out;"
    onclick={closeDrawer}
    onkeydown={(e) => e.key === 'Escape' && closeDrawer()}
    role="button"
    tabindex="0"
    aria-label="Cerrar menú"
  ></div>
{/if}

<!-- Drawer -->
<aside
  class="fixed top-0 right-0 h-full w-80 border-l shadow-2xl z-[201] flex flex-col"
  style="
    background-color: var(--theme-body);
    border-color: rgba(0, 0, 0, 0.05);
    transform: {$drawerOpen ? 'translate3d(0, 0, 0)' : 'translate3d(100%, 0, 0)'};
    transition: transform 0.3s cubic-bezier(0.33, 1, 0.68, 1);
  "
>
  <!-- Header del Drawer -->
  <div class="py-3 md:py-4 px-4 md:px-6 border-b flex-shrink-0 relative" style="border-color: rgba(0, 0, 0, 0.05);">

    <!-- Theme Toggle - SOLO en móvil (arriba izquierda del drawer) -->
    <div class="absolute top-3 md:top-4 left-4 md:left-6 md:hidden">
      <button
        onclick={toggleTheme}
        class="p-2 rounded-full transition-all"
        style="background-color: transparent; color: var(--theme-texto); cursor: pointer;"
        onmouseenter={(e) => e.currentTarget.style.color = 'var(--theme-titulo)'}
        onmouseleave={(e) => e.currentTarget.style.color = 'var(--theme-texto)'}
        aria-label={isDarkMode ? 'Cambiar a modo claro' : 'Cambiar a modo oscuro'}
      >
        {#if isDarkMode}
          <svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20">
            <path d="M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z"/>
          </svg>
        {:else}
          <svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20">
            <path fill-rule="evenodd" d="M10 2a1 1 0 011 1v1a1 1 0 11-2 0V3a1 1 0 011-1zm4 8a4 4 0 11-8 0 4 4 0 018 0zm-.464 4.95l.707.707a1 1 0 001.414-1.414l-.707-.707a1 1 0 00-1.414 1.414zm2.12-10.607a1 1 0 010 1.414l-.706.707a1 1 0 11-1.414-1.414l.707-.707a1 1 0 011.414 0zM17 11a1 1 0 100-2h-1a1 1 0 100 2h1zm-7 4a1 1 0 011 1v1a1 1 0 11-2 0v-1a1 1 0 011-1zM5.05 6.464A1 1 0 106.465 5.05l-.708-.707a1 1 0 00-1.414 1.414l.707.707zm1.414 8.486l-.707.707a1 1 0 01-1.414-1.414l.707-.707a1 1 0 011.414 1.414zM4 11a1 1 0 100-2H3a1 1 0 000 2h1z" clip-rule="evenodd"/>
          </svg>
        {/if}
      </button>
    </div>

    <!-- Botón cerrar (X) - arriba derecha -->
    <div class="group absolute top-3 md:top-4 right-4 md:right-6">
      <button
        onclick={closeDrawer}
        class="p-2 rounded-lg transition-colors flex-shrink-0"
        style="color: var(--theme-texto); cursor: pointer;"
        onmouseenter={(e) => e.currentTarget.style.color = 'var(--theme-titulo)'}
        onmouseleave={(e) => e.currentTarget.style.color = 'var(--theme-texto)'}
        aria-label="Cerrar menú"
      >
        <svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="1.5">
          <path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12"/>
        </svg>
      </button>
      <!-- Tooltip del botón cerrar -->
      <div class="absolute left-1/2 -translate-x-1/2 top-full mt-2 px-3 py-1.5 bg-gray-900/90 text-white text-xs rounded-lg whitespace-nowrap opacity-0 invisible group-hover:opacity-100 group-hover:visible transition-all duration-200 pointer-events-none backdrop-blur-sm">
        Cerrar menú
        <div class="absolute left-1/2 -translate-x-1/2 -top-1 w-2 h-2 bg-gray-900/90 rotate-45"></div>
      </div>
    </div>

    <!-- Logo centrado (cambia según tema) -->
    <div class="flex flex-col items-center pt-8">
      {#if isDarkMode}
        <img
          src="/logos_oscuro/05_Imago MEFP horizontal espacio negativo.png"
          alt="MEFP"
          class="h-16 md:h-20 w-auto mb-3"
        />
      {:else}
        <img
          src="/logos_claro/06_Isologo MEFP horizontal escala de grises.png"
          alt="MEFP"
          class="h-16 md:h-20 w-auto mb-3"
        />
      {/if}
    </div>
  </div>

  <!-- Navigation -->
  <nav class="flex-1 overflow-y-auto p-4">
    <!-- Inicio -->
    <a
      href="/"
      onclick={closeDrawer}
      class="w-full flex items-center gap-3 px-3 py-3 rounded-lg transition-colors text-left mb-4"
      style="background-color: {$page.url.pathname === '/' ? 'var(--theme-fill)' : 'transparent'};"
      onmouseenter={(e) => e.currentTarget.style.backgroundColor = 'var(--theme-fill)'}
      onmouseleave={(e) => e.currentTarget.style.backgroundColor = $page.url.pathname === '/' ? 'var(--theme-fill)' : 'transparent'}
    >
      <svg class="w-4 h-4 flex-shrink-0" style="color: var(--theme-texto);" fill="currentColor" viewBox="0 0 20 20">
        <rect x="2" y="2" width="7" height="7" rx="1.5"/>
        <rect x="11" y="2" width="7" height="7" rx="1.5"/>
        <rect x="2" y="11" width="7" height="7" rx="1.5"/>
        <rect x="11" y="11" width="7" height="7" rx="1.5"/>
      </svg>
      <span class="font-medium text-sm" style="color: var(--theme-titulo);">Página principal</span>
    </a>

    <!-- Clasificadores -->
    <div class="mb-6">
      <h3 class="text-xs font-semibold uppercase tracking-wider mb-3 px-2" style="color: var(--theme-texto);">
        Clasificadores
      </h3>
      <div class="space-y-1">
        {#each clasificadores as c}
          <a
            href={c.href}
            onclick={closeDrawer}
            class="w-full flex items-center justify-between px-3 py-2.5 rounded-lg transition-colors text-left group"
            style="background-color: {isActive(c.href) ? 'var(--theme-fill)' : 'transparent'};"
            onmouseenter={(e) => e.currentTarget.style.backgroundColor = 'var(--theme-fill)'}
            onmouseleave={(e) => e.currentTarget.style.backgroundColor = isActive(c.href) ? 'var(--theme-fill)' : 'transparent'}
          >
            <div class="flex-1 min-w-0">
              <span class="text-sm font-medium block" style="color: var(--theme-titulo);">{c.nombre}</span>
              <span class="text-xs" style="color: var(--theme-texto);">{c.desc}</span>
            </div>
            <svg
              class="w-4 h-4 flex-shrink-0 opacity-0 group-hover:opacity-100 transition-opacity"
              style="color: var(--theme-texto);"
              fill="none"
              stroke="currentColor"
              viewBox="0 0 24 24"
              stroke-width="1.5"
            >
              <path stroke-linecap="round" stroke-linejoin="round" d="M8.25 4.5l7.5 7.5-7.5 7.5"/>
            </svg>
          </a>
        {/each}
      </div>
    </div>

    <!-- Ver todos los clasificadores -->
    <a
      href="/clasificadores"
      onclick={closeDrawer}
      class="w-full flex items-center gap-3 px-3 py-3 rounded-lg transition-colors text-left mb-6"
      style="background-color: {$page.url.pathname === '/clasificadores' ? 'var(--theme-fill)' : 'transparent'};"
      onmouseenter={(e) => e.currentTarget.style.backgroundColor = 'var(--theme-fill)'}
      onmouseleave={(e) => e.currentTarget.style.backgroundColor = $page.url.pathname === '/clasificadores' ? 'var(--theme-fill)' : 'transparent'}
    >
      <svg class="w-4 h-4 flex-shrink-0" style="color: var(--theme-accent);" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="1.5">
        <path stroke-linecap="round" stroke-linejoin="round" d="M3.75 6A2.25 2.25 0 016 3.75h2.25A2.25 2.25 0 0110.5 6v2.25a2.25 2.25 0 01-2.25 2.25H6a2.25 2.25 0 01-2.25-2.25V6zM3.75 15.75A2.25 2.25 0 016 13.5h2.25a2.25 2.25 0 012.25 2.25V18a2.25 2.25 0 01-2.25 2.25H6A2.25 2.25 0 013.75 18v-2.25zM13.5 6a2.25 2.25 0 012.25-2.25H18A2.25 2.25 0 0120.25 6v2.25A2.25 2.25 0 0118 10.5h-2.25a2.25 2.25 0 01-2.25-2.25V6zM13.5 15.75a2.25 2.25 0 012.25-2.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-2.25A2.25 2.25 0 0113.5 18v-2.25z"/>
      </svg>
      <span class="text-sm" style="color: var(--theme-accent);">Ver todos los clasificadores</span>
    </a>

    <!-- Separador -->
    <div class="border-t my-4" style="border-color: var(--theme-borde);"></div>

    <!-- Enlaces secundarios -->
    <div class="space-y-1">
      <a
        href="/metodologia"
        onclick={closeDrawer}
        class="w-full flex items-center gap-3 px-3 py-2.5 rounded-lg transition-colors text-left"
        onmouseenter={(e) => e.currentTarget.style.backgroundColor = 'var(--theme-fill)'}
        onmouseleave={(e) => e.currentTarget.style.backgroundColor = 'transparent'}
      >
        <svg class="w-4 h-4 flex-shrink-0" style="color: var(--theme-texto);" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="1.5">
          <path stroke-linecap="round" stroke-linejoin="round" d="M12 6.042A8.967 8.967 0 006 3.75c-1.052 0-2.062.18-3 .512v14.25A8.987 8.987 0 016 18c2.305 0 4.408.867 6 2.292m0-14.25a8.966 8.966 0 016-2.292c1.052 0 2.062.18 3 .512v14.25A8.987 8.987 0 0018 18a8.967 8.967 0 00-6 2.292m0-14.25v14.25"/>
        </svg>
        <span class="text-sm" style="color: var(--theme-titulo);">Metodología</span>
      </a>
      <a
        href="/acerca"
        onclick={closeDrawer}
        class="w-full flex items-center gap-3 px-3 py-2.5 rounded-lg transition-colors text-left"
        onmouseenter={(e) => e.currentTarget.style.backgroundColor = 'var(--theme-fill)'}
        onmouseleave={(e) => e.currentTarget.style.backgroundColor = 'transparent'}
      >
        <svg class="w-4 h-4 flex-shrink-0" style="color: var(--theme-texto);" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="1.5">
          <path stroke-linecap="round" stroke-linejoin="round" d="M11.25 11.25l.041-.02a.75.75 0 011.063.852l-.708 2.836a.75.75 0 001.063.853l.041-.021M21 12a9 9 0 11-18 0 9 9 0 0118 0zm-9-3.75h.008v.008H12V8.25z"/>
        </svg>
        <span class="text-sm" style="color: var(--theme-titulo);">Acerca de</span>
      </a>
    </div>
  </nav>

  <!-- Footer -->
  <div class="p-4 border-t flex-shrink-0" style="border-color: rgba(0, 0, 0, 0.05);">
    <p class="text-xs text-center" style="color: var(--theme-texto);">
      Ministerio de Economía y Finanzas Públicas
    </p>
  </div>
</aside>