💬 Tooltips & Popovers Design Guide

Tooltips та popovers provide contextual help without cluttering interface. Tooltips (small, text-only) appear on hover for brief labels або explanations. Popovers (larger, може contain titles/paragraphs/images) appear on click для detailed information. For mushroom education site, tooltips clarify: technical terms ("What is mycelium?"), dosage units ("mg psilocybin"), safety icons. Popovers present: detailed species warnings, cultivation tip expansions, reference citations. Effective tooltip/popover design balances discoverability (clear triggers), positioning (not obscuring content), brevity (concise text), та accessibility (keyboard invocation, screen reader support). Цей guide охоплює CSS-only та JavaScript implementations, arrow positioning, mobile behavior (tap-to-show), та ARIA patterns.

🎨 Tooltips Demo

Hover over highlighted terms to see tooltips:

Mycelium colonizes substrate during cultivation. Proper sterile technique prevents contamination.

Dosage calculator helps determine appropriate dose based на body weight та desired intensity.

📋 Popovers Demo

Click button to trigger popover:

Important Safety Guidelines

• Start з low dose (1-2g dried)
• Ensure safe, comfortable environment
• Have trusted trip sitter present
• Never mix з alcohol або other drugs
• Avoid if personal/family history of psychosis

💻 CSS Implementation

CSS-Only Tooltip:

/* HTML */
<span data-tooltip="Tooltip text">Hover me</span>

/* CSS */
[data-tooltip] {
  position: relative;
  cursor: help;
  border-bottom: 1px dotted currentColor; /* Indicate clickability */
}

/* Tooltip box */
[data-tooltip]::after {
  content: attr(data-tooltip); /* Use data attribute */
  position: absolute;
  bottom: 100%;
  left: 50%;
  transform: translateX(-50%) translateY(-8px);
  
  background: #2c3e50;
  color: white;
  padding: 8px 12px;
  border-radius: 6px;
  font-size: 0.875em;
  white-space: nowrap;
  
  /* Hidden by default */
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.3s, transform 0.3s;
  
  z-index: 1000;
}

/* Arrow */
[data-tooltip]::before {
  content: '';
  position: absolute;
  bottom: 100%;
  left: 50%;
  transform: translateX(-50%);
  
  border: 6px solid transparent;
  border-top-color: #2c3e50; /* Arrow pointing down */
  
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.3s;
}

/* Show on hover */
[data-tooltip]:hover::after,
[data-tooltip]:hover::before {
  opacity: 1;
}

Tooltip Positioning Variants:

/* Top tooltip (default above) */
[data-tooltip-top]::after {
  bottom: 100%;
  left: 50%;
  transform: translateX(-50%) translateY(-8px);
}

/* Bottom tooltip */
[data-tooltip-bottom]::after {
  top: 100%;
  left: 50%;
  transform: translateX(-50%) translateY(8px);
}

/* Left tooltip */
[data-tooltip-left]::after {
  right: 100%;
  top: 50%;
  transform: translateX(-8px) translateY(-50%);
}

/* Right tooltip */
[data-tooltip-right]::after {
  left: 100%;
  top: 50%;
  transform: translateX(8px) translateY(-50%);
}

JavaScript Popover:

/* HTML */
<button onclick="togglePopover('myPopover')">Open Popover</button>
<div class="popover" id="myPopover">
  <div class="popover-title">Title</div>
  <div class="popover-content">Content...</div>
</div>

/* CSS */
.popover {
  position: absolute;
  background: white;
  border: 2px solid #e9ecef;
  border-radius: 12px;
  box-shadow: 0 8px 30px rgba(0, 0, 0, 0.15);
  padding: 20px;
  width: 300px;
  
  /* Hidden by default */
  display: none;
  z-index: 1000;
}

.popover.active {
  display: block;
  animation: popoverFadeIn 0.3s;
}

@keyframes popoverFadeIn {
  від { opacity: 0; transform: translateY(-10px); }
  до { opacity: 1; transform: translateY(0); }
}

/* JavaScript */
function togglePopover(id) {
  const popover = document.getElementById(id);
  popover.classList.toggle('active');
}

// Close on outside click
document.addEventListener('click', (e) => {
  if (!e.target.closest('.popover') && !e.target.closest('.popover-trigger')) {
    document.querySelectorAll('.popover').forEach(p => p.classList.remove('active'));
  }
});

Positioning Library (Popper.js):

/* For advanced positioning, use Popper.js */
<script src="https://unpkg.com/@popperjs/core@2"></script>

const button = document.querySelector('.popover-trigger');
const tooltip = document.querySelector('.popover');

const popperInstance = Popper.createPopper(button, tooltip, {
  placement: 'top', // або 'bottom', 'left', 'right'
  modifiers: [
    {
      name: 'offset',
      options: {
        offset: [0, 8], /* X, Y offset */
      },
    },
  ],
});

♿ Accessibility

ARIA для Tooltips:

<!-- Tooltip з aria-describedby -->
<button aria-describedby="tooltip1">
  Hover me
</button>
<div id="tooltip1" role="tooltip" hidden>
  Tooltip text
</div>

/* Show/hide з JavaScript */
button.addEventListener('mouseenter', () => {
  tooltip.removeAttribute('hidden');
});

button.addEventListener('mouseleave', () => {
  tooltip.setAttribute('hidden', '');
});

Keyboard Accessibility:

/* Show tooltip на focus (keyboard users) */
[data-tooltip]:focus::after,
[data-tooltip]:focus::before {
  opacity: 1;
}

/* Ensure focusable */
[data-tooltip] {
  tabindex: 0; /* Make focusable */
  outline: none; /* Remove default outline */
}

[data-tooltip]:focus {
  outline: 2px solid #a8edea; /* Custom focus indicator */
  outline-offset: 2px;
}

Mobile Considerations:

/* Mobile: Tap to show (no hover) */
@media (max-width: 768px) {
  [data-tooltip]::after,
  [data-tooltip]::before {
    /* Show on active (tap) */
    opacity: 0;
  }
  
  [data-tooltip]:active::after,
  [data-tooltip]:active::before {
    opacity: 1;
  }
}

/* Alternative: JavaScript click handler для mobile */
if ('ontouchstart' in window) {
  document.querySelectorAll('[data-tooltip]').forEach(el => {
    el.addEventListener('click', function(e) {
      e.preventDefault();
      this.classList.toggle('tooltip-active');
    });
  });
}

✅ Tooltips та Popovers Checklist

Tooltips Checklist:

  • ☐ Brief text (1-2 sentences maximum)
  • ☐ Appears on hover + focus
  • ☐ Arrow points до trigger element
  • ☐ Positioned не obscure content
  • ☐ Smooth fadeвід/fadeOut (0.3s)
  • ☐ High z-index (1000+)
  • ☐ Mobile: Tap-to-show або avoid

Popovers Checklist:

  • ☐ Triggered by click (not hover)
  • ☐ Close button visible
  • ☐ Close на outside click
  • ☐ Close на ESC key
  • ☐ Может contain rich content (title, paragraphs, buttons)
  • ☐ Positioned dynamically (Popper.js recommended)
  • ☐ Max-width set (250-400px)
  • ☐ ARIA: role="dialog" або role="tooltip"