Basic Tooltip

Simple tooltip that appears on hover.

<div class="tooltip-wrapper">
  <button aria-describedby="tooltip-1">Hover me</button>
  <div class="tooltip" role="tooltip" id="tooltip-1">
    <span class="tooltip-content">This is a helpful tooltip</span>
    <div class="tooltip-arrow"></div>
  </div>
</div>

Positions

Tooltips can appear in four directions based on available space.

<div class="tooltip-wrapper tooltip-top">...</div>
<div class="tooltip-wrapper tooltip-right">...</div>
<div class="tooltip-wrapper tooltip-bottom">...</div>
<div class="tooltip-wrapper tooltip-left">...</div>

Icon Tooltips

Common pattern for icon buttons that need labels.

<div class="tooltip-wrapper tooltip-bottom">
  <button class="icon-btn" aria-label="Settings">
    <svg>...</svg>
  </button>
  <div class="tooltip" role="tooltip">
    <span class="tooltip-content">Settings</span>
    <div class="tooltip-arrow"></div>
  </div>
</div>

Keyboard Shortcut Tooltips

Show keyboard shortcuts with styled key badges.

<div class="tooltip tooltip-wide">
  <span class="tooltip-content">
    Save changes
    <span class="tooltip-keys">
      <kbd>⌘</kbd><kbd>S</kbd>
    </span>
  </span>
</div>

Rich Content Tooltip

Tooltips with more detailed content for complex explanations.

<div class="tooltip tooltip-rich">
  <span class="tooltip-content">
    <strong>Ferni AI</strong>
    <p>Your personal AI companion...</p>
  </span>
</div>

Persona-Themed Tooltips

Tooltips styled with persona accent colors.

<div class="tooltip tooltip-ferni">...</div>
<div class="tooltip tooltip-maya">...</div>
<div class="tooltip tooltip-jordan">...</div>

Delayed Tooltip

Add a delay before showing to prevent accidental triggers.

/* CSS delay */
.tooltip-delayed .tooltip {
  transition-delay: 500ms;
}

.tooltip-delayed:hover .tooltip {
  transition-delay: 500ms;
}

CSS Implementation

/* Tooltip Wrapper */
.tooltip-wrapper {
  position: relative;
  display: inline-block;
}

/* Base Tooltip */
.tooltip {
  position: absolute;
  z-index: 1000;
  padding: var(--space-2) var(--space-3);
  background: var(--bg-inverse);
  color: var(--text-inverse);
  font-size: var(--text-sm);
  border-radius: var(--radius-md);
  white-space: nowrap;
  pointer-events: none;
  opacity: 0;
  transform: translateY(4px);
  transition: opacity var(--duration-fast) var(--ease-ease-out),
              transform var(--duration-fast) var(--ease-ease-out);
}

.tooltip-wrapper:hover .tooltip,
.tooltip-wrapper:focus-within .tooltip {
  opacity: 1;
  transform: translateY(0);
}

/* Arrow */
.tooltip-arrow {
  position: absolute;
  width: 8px;
  height: 8px;
  background: inherit;
  transform: rotate(45deg);
}

/* Positions */
.tooltip-top .tooltip {
  bottom: 100%;
  left: 50%;
  transform: translateX(-50%) translateY(-8px);
  margin-bottom: var(--space-2);
}

.tooltip-top .tooltip-arrow {
  bottom: -4px;
  left: 50%;
  margin-left: -4px;
}

.tooltip-bottom .tooltip {
  top: 100%;
  left: 50%;
  transform: translateX(-50%) translateY(8px);
  margin-top: var(--space-2);
}

.tooltip-bottom .tooltip-arrow {
  top: -4px;
  left: 50%;
  margin-left: -4px;
}

.tooltip-left .tooltip {
  right: 100%;
  top: 50%;
  transform: translateY(-50%) translateX(-8px);
  margin-right: var(--space-2);
}

.tooltip-left .tooltip-arrow {
  right: -4px;
  top: 50%;
  margin-top: -4px;
}

.tooltip-right .tooltip {
  left: 100%;
  top: 50%;
  transform: translateY(-50%) translateX(8px);
  margin-left: var(--space-2);
}

.tooltip-right .tooltip-arrow {
  left: -4px;
  top: 50%;
  margin-top: -4px;
}

/* Hover States */
.tooltip-wrapper:hover .tooltip-top .tooltip,
.tooltip-top.tooltip-wrapper:hover .tooltip {
  transform: translateX(-50%) translateY(0);
}

.tooltip-wrapper:hover .tooltip-bottom .tooltip,
.tooltip-bottom.tooltip-wrapper:hover .tooltip {
  transform: translateX(-50%) translateY(0);
}

/* Keyboard Shortcuts */
.tooltip-keys {
  display: inline-flex;
  gap: 2px;
  margin-left: var(--space-2);
}

.tooltip-keys kbd {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 20px;
  height: 20px;
  padding: 0 var(--space-1);
  background: rgba(255, 255, 255, 0.2);
  border-radius: var(--radius-sm);
  font-family: var(--font-body);
  font-size: var(--text-xs);
}

/* Rich Tooltip */
.tooltip-rich {
  white-space: normal;
  max-width: 240px;
  text-align: left;
}

.tooltip-rich strong {
  display: block;
  margin-bottom: var(--space-1);
}

.tooltip-rich p {
  margin: 0;
  font-size: var(--text-xs);
  opacity: 0.9;
}

/* Persona Colors */
.tooltip-ferni { background: var(--persona-ferni); }
.tooltip-maya { background: var(--persona-maya); }
.tooltip-jordan { background: var(--persona-jordan); }

Accessibility

  • aria-describedby: Link trigger elements to tooltips using aria-describedby
  • role="tooltip": Identify the element as a tooltip for assistive technology
  • Keyboard access: Show tooltips on focus, not just hover
  • No essential info: Don't put critical information only in tooltips
  • Sufficient delay: Add delay before hiding to allow reading time
  • Escape to dismiss: Allow users to dismiss tooltips with Escape key

Usage Guidelines

✓ Do

  • Use for supplementary, non-critical info
  • Keep tooltip text brief (1-2 lines max)
  • Position to avoid viewport overflow
  • Show on both hover and keyboard focus

✗ Don't

  • Put essential content in tooltips
  • Use on touch-only devices (no hover)
  • Create tooltips that block interaction
  • Use for complex interactive content