Component

Floating Menu

Contextual floating menu that appears at click position with screen-edge detection and backdrop blur.

  • Component
  • Tailwind
  • HTML
  • MIT

Preview

Live component

Interactive preview
Open preview
9:41 100%
devsnips.dev/library/tailwind/components/dropdowns/floating-menu/
fluid · no fixed width 100%
No dependencies Production-ready

Install

Add to your project

terminal
npx devsnips add Tailwind/Components/Dropdowns/floating-menu
registry path: Tailwind/Components/Dropdowns/floating-menu

Source

Implementation

code.html
<!-- Floating Menu (Contextual Tool Palette) -->
<div class="relative">
  <div
    id="floating-trigger"
    class="w-full max-w-md mx-auto p-16 bg-gradient-to-br from-gray-50 to-gray-100 border-2 border-dashed border-gray-300 rounded-2xl text-center"
  >
    <p class="text-gray-500 mb-4">Click anywhere on this card to open the floating menu</p>
    <p class="text-sm text-gray-400">The menu will appear at your click position</p>
  </div>

  <!-- Floating Menu (appears at click position) -->
  <div
    id="floating-menu"
    class="hidden fixed z-50 w-64 bg-white rounded-2xl shadow-2xl border border-gray-100 overflow-hidden backdrop-blur-sm bg-white/95"
    style="left: 0; top: 0;"
  >
    <!-- Header -->
    <div class="px-4 py-3 bg-gradient-to-r from-blue-600 to-indigo-600">
      <div class="flex items-center gap-3">
        <div class="w-10 h-10 rounded-xl bg-white/20 flex items-center justify-center">
          <svg class="w-5 h-5 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z"></path>
          </svg>
        </div>
        <div>
          <p class="text-white font-semibold">Quick Tools</p>
          <p class="text-blue-100 text-xs">Select an action</p>
        </div>
      </div>
    </div>

    <!-- Tool List -->
    <div class="py-2">
      <button class="w-full flex items-center gap-3 px-4 py-3 text-gray-700 hover:bg-blue-50 transition-colors">
        <div class="w-8 h-8 rounded-lg bg-blue-100 flex items-center justify-center text-blue-600">
          <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z"></path>
          </svg>
        </div>
        <span class="text-sm font-medium">Edit</span>
        <span class="ml-auto text-xs text-gray-400">⌘E</span>
      </button>

      <button class="w-full flex items-center gap-3 px-4 py-3 text-gray-700 hover:bg-blue-50 transition-colors">
        <div class="w-8 h-8 rounded-lg bg-emerald-100 flex items-center justify-center text-emerald-600">
          <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z"></path>
          </svg>
        </div>
        <span class="text-sm font-medium">Duplicate</span>
        <span class="ml-auto text-xs text-gray-400">⌘D</span>
      </button>

      <button class="w-full flex items-center gap-3 px-4 py-3 text-gray-700 hover:bg-blue-50 transition-colors">
        <div class="w-8 h-8 rounded-lg bg-purple-100 flex items-center justify-center text-purple-600">
          <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8.684 13.342C8.886 12.938 9 12.482 9 12c0-.482-.114-.938-.316-1.342m0 2.684a3 3 0 110-2.684m0 2.684l6.632 3.316m-6.632-6l6.632-3.316m0 0a3 3 0 105.367-2.684 3 3 0 00-5.367 2.684zm0 9.316a3 3 0 105.368 2.684 3 3 0 00-5.368-2.684z"></path>
          </svg>
        </div>
        <span class="text-sm font-medium">Share</span>
        <span class="ml-auto text-xs text-gray-400">⌘⇧S</span>
      </button>
    </div>

    <!-- Divider -->
    <div class="border-t border-gray-100"></div>

    <!-- Secondary Actions -->
    <div class="py-2">
      <button class="w-full flex items-center gap-3 px-4 py-3 text-gray-700 hover:bg-gray-50 transition-colors">
        <div class="w-8 h-8 rounded-lg bg-gray-100 flex items-center justify-center text-gray-600">
          <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4"></path>
          </svg>
        </div>
        <span class="text-sm">Download</span>
      </button>

      <button class="w-full flex items-center gap-3 px-4 py-3 text-red-600 hover:bg-red-50 transition-colors">
        <div class="w-8 h-8 rounded-lg bg-red-100 flex items-center justify-center text-red-600">
          <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"></path>
          </svg>
        </div>
        <span class="text-sm">Delete</span>
      </button>
    </div>
  </div>
</div>

<script>
  const trigger = document.getElementById('floating-trigger');
  const menu = document.getElementById('floating-menu');

  trigger.addEventListener('click', function(event) {
    menu.classList.remove('hidden');
    
    // Position menu at click location
    const rect = trigger.getBoundingClientRect();
    let x = event.clientX;
    let y = event.clientY;
    
    // Adjust if menu would go off screen
    const menuWidth = 256;
    const menuHeight = menu.offsetHeight;
    
    if (x + menuWidth > window.innerWidth) {
      x = window.innerWidth - menuWidth - 10;
    }
    if (y + menuHeight > window.innerHeight) {
      y = window.innerHeight - menuHeight - 10;
    }
    
    menu.style.left = x + 'px';
    menu.style.top = y + 'px';
    
    // Add appear animation
    menu.style.opacity = '0';
    menu.style.transform = 'scale(0.9)';
    menu.style.transition = 'all 0.2s ease-out';
    
    requestAnimationFrame(() => {
      menu.style.opacity = '1';
      menu.style.transform = 'scale(1)';
    });
  });

  document.addEventListener('click', function(event) {
    if (!menu.contains(event.target) && !trigger.contains(event.target)) {
      menu.classList.add('hidden');
    }
  });
</script>
133 lines UTF-8 · LF · Spaces: 2

AI-ready

Available to your agent.

This component is reachable through the DevSnips CLI, MCP server and Skills integrations — one registry, one resource path.

Resource path

devsnips://components/dropdowns/floating-menu

Continue browsing

View all