These patterns help make your app interactive and user-friendly. Click-outside closes menus when clicking outside them. Tooltip shows helpful info when hovering or focusing on elements.
Common action patterns (click-outside, tooltip) in Svelte
function clickOutside(node) { const handleClick = event => { if (!node.contains(event.target)) { node.dispatchEvent(new CustomEvent('outclick')); } }; document.addEventListener('click', handleClick, true); return { destroy() { document.removeEventListener('click', handleClick, true); } }; } function tooltip(node, text) { let tooltipDiv; function mouseOver() { if (tooltipDiv) { tooltipDiv.remove(); } tooltipDiv = document.createElement('div'); tooltipDiv.textContent = text; tooltipDiv.style.position = 'absolute'; tooltipDiv.style.background = 'black'; tooltipDiv.style.color = 'white'; tooltipDiv.style.padding = '0.25rem 0.5rem'; tooltipDiv.style.borderRadius = '0.25rem'; tooltipDiv.style.fontSize = '0.75rem'; tooltipDiv.style.zIndex = '1000'; document.body.appendChild(tooltipDiv); const rect = node.getBoundingClientRect(); tooltipDiv.style.top = `${rect.bottom + 5}px`; tooltipDiv.style.left = `${rect.left}px`; } function mouseOut() { if (tooltipDiv) { tooltipDiv.remove(); tooltipDiv = null; } } node.addEventListener('mouseover', mouseOver); node.addEventListener('mouseout', mouseOut); node.addEventListener('focus', mouseOver); node.addEventListener('blur', mouseOut); return { destroy() { if (tooltipDiv) { tooltipDiv.remove(); tooltipDiv = null; } node.removeEventListener('mouseover', mouseOver); node.removeEventListener('mouseout', mouseOut); node.removeEventListener('focus', mouseOver); node.removeEventListener('blur', mouseOut); } }; }
The clickOutside action listens for clicks outside the element and triggers a custom event.
The tooltip action creates a small popup near the element on hover or focus, improving accessibility.
clickOutside action.<script> import { clickOutside } from './actions.js'; let open = false; function toggle() { open = !open; } function close() { open = false; } </script> <button on:click={toggle}>Toggle Menu</button> {#if open} <div use:clickOutside on:outclick={close} tabindex="0"> <p>This menu closes when clicking outside.</p> </div> {/if}
<script> import { tooltip } from './actions.js'; </script> <button use:tooltip={'Click me for info'} aria-describedby="tip1">Hover or focus me</button>
This Svelte component shows a button with a tooltip. When clicked, it opens a menu. Clicking outside the menu closes it. The menu and tooltip improve user experience and accessibility.
<script> // Actions defined inside the component for simplicity function clickOutside(node) { const handleClick = event => { if (!node.contains(event.target)) { node.dispatchEvent(new CustomEvent('outclick')); } }; document.addEventListener('click', handleClick, true); return { destroy() { document.removeEventListener('click', handleClick, true); } }; } function tooltip(node, text) { let tooltipDiv; function mouseOver() { if (tooltipDiv) { tooltipDiv.remove(); } tooltipDiv = document.createElement('div'); tooltipDiv.textContent = text; tooltipDiv.style.position = 'absolute'; tooltipDiv.style.background = 'black'; tooltipDiv.style.color = 'white'; tooltipDiv.style.padding = '0.25rem 0.5rem'; tooltipDiv.style.borderRadius = '0.25rem'; tooltipDiv.style.fontSize = '0.75rem'; tooltipDiv.style.zIndex = '1000'; document.body.appendChild(tooltipDiv); const rect = node.getBoundingClientRect(); tooltipDiv.style.top = `${rect.bottom + 5}px`; tooltipDiv.style.left = `${rect.left}px`; } function mouseOut() { if (tooltipDiv) { tooltipDiv.remove(); tooltipDiv = null; } } node.addEventListener('mouseover', mouseOver); node.addEventListener('mouseout', mouseOut); node.addEventListener('focus', mouseOver); node.addEventListener('blur', mouseOut); return { destroy() { if (tooltipDiv) { tooltipDiv.remove(); tooltipDiv = null; } node.removeEventListener('mouseover', mouseOver); node.removeEventListener('mouseout', mouseOut); node.removeEventListener('focus', mouseOver); node.removeEventListener('blur', mouseOut); } }; } let menuOpen = false; function toggleMenu() { menuOpen = !menuOpen; } function closeMenu() { menuOpen = false; } </script> <button on:click={toggleMenu} use:tooltip={'Toggle menu'} aria-haspopup="true" aria-expanded={menuOpen}>Menu</button> {#if menuOpen} <div use:clickOutside on:outclick={closeMenu} tabindex="0" style="border: 1px solid #ccc; padding: 1rem; margin-top: 0.5rem; width: 200px; background: #f9f9f9;"> <p>This menu closes when clicking outside.</p> <button on:click={closeMenu}>Close</button> </div> {/if}
Use tabindex="0" on elements with clickOutside to make them focusable for keyboard users.
Tooltips should appear on keyboard focus as well as mouse hover for accessibility.
Remember to clean up event listeners in the destroy method to avoid memory leaks.
Click-outside helps close menus or popups when clicking outside them.
Tooltip shows helpful info on hover or focus, improving user experience.
Both patterns improve accessibility and interactivity in your Svelte apps.