Skip to main content

UI Tooltip System

The unified tooltip system provides consistent styling and behavior across all UI panels in Hyperscape. Centralized style utilities ensure visual consistency for inventory, equipment, bank, spells, prayer, skills, trade, store, and loot panels.

Overview

Previously, each panel implemented its own tooltip styling, leading to ~500 lines of duplicated code and inconsistent visual appearance. The new system provides a set of style utility functions that generate consistent React CSSProperties objects based on the current theme.

Key Features

  • Centralized Styling: Single source of truth for tooltip appearance
  • Theme-Aware: All styles adapt to current theme (Hyperscape, Dark, Light)
  • Consistent Hierarchy: Clear visual distinction between titles, metadata, body text, and status indicators
  • Tone Support: Status indicators support success/danger/warning tones
  • Zero Duplication: Eliminates ~500 lines of duplicated styling code

API Reference

Module: packages/client/src/ui/core/tooltip/tooltipStyles.ts

getTooltipTitleStyle()

Generate title text styling for tooltip headers.
Parameters:
  • theme - Current theme object
  • accentColor - Optional accent color (defaults to theme.colors.accent.secondary)
Returns: CSSProperties object with title styling Style Properties:
  • color: Accent color (default: theme.colors.accent.secondary)
  • fontWeight: 700 (bold)
  • fontSize: “13px”
  • lineHeight: 1.2
Example:

getTooltipMetaStyle()

Generate metadata/secondary text styling.
Parameters:
  • theme - Current theme object
Returns: CSSProperties object with metadata styling Style Properties:
  • color: theme.colors.text.muted
  • fontSize: “11px”
  • lineHeight: 1.3
Use Cases:
  • Item quantities (“x5”, “x100”)
  • Level requirements (“Level 40 Attack”)
  • Contextual hints (“Drag to reorder”)
Example:

getTooltipBodyStyle()

Generate body content styling for descriptions and details.
Parameters:
  • theme - Current theme object
Returns: CSSProperties object with body text styling Style Properties:
  • color: theme.colors.text.secondary
  • fontSize: “11px”
  • lineHeight: 1.45
Use Cases:
  • Item descriptions
  • Spell effects
  • Stat bonuses
  • Detailed information
Example:

getTooltipDividerStyle()

Generate section divider styling with optional accent color.
Parameters:
  • theme - Current theme object
  • accentColor - Optional accent color for divider (defaults to theme.colors.border.default)
Returns: CSSProperties object with divider styling Style Properties:
  • borderTop: 1px solid ${accentColor}33
  • marginTop: “8px”
  • paddingTop: “8px”
Use Cases:
  • Separating tooltip sections
  • Visual hierarchy between content blocks
  • Grouping related information
Example:

getTooltipTagStyle()

Generate tag/badge styling for labels and categories.
Parameters:
  • theme - Current theme object
Returns: CSSProperties object with tag styling Style Properties:
  • display: “inline-flex”
  • alignItems: “center”
  • padding: “2px 6px”
  • borderRadius: theme.borderRadius.sm
  • background: ${theme.colors.background.tertiary}cc
  • border: 1px solid ${theme.colors.border.default}33
  • color: theme.colors.text.secondary
  • fontSize: “10px”
  • lineHeight: 1.2
Use Cases:
  • Rune costs (“5x Air Rune”, “3x Fire Rune”)
  • Item categories (“Weapon”, “Armor”, “Food”)
  • Skill requirements
Example:

getTooltipStatusStyle()

Generate status indicator styling with tone-based coloring.
Parameters:
  • theme - Current theme object
  • tone - Status tone (default/success/danger/warning)
Returns: CSSProperties object with status indicator styling Style Properties:
  • marginTop: “8px”
  • padding: “5px 8px”
  • borderRadius: theme.borderRadius.sm
  • background: Tone-specific background color with transparency
  • border: Tone-specific border color
  • color: Tone-specific text color
  • fontSize: “10px”
  • lineHeight: 1.3
  • textAlign: “center”
  • fontWeight: 600
Tone Colors:
  • success: Green (theme.colors.state.success)
  • danger: Red (theme.colors.state.danger)
  • warning: Yellow (theme.colors.state.warning)
  • default: Accent (theme.colors.accent.secondary)
Use Cases:
  • Level requirements (“Requires level 60 Attack”)
  • Active states (“Currently Active”)
  • Warnings (“Not enough runes”)
  • Success messages (“Quest Complete!”)
Example:

Usage Patterns

Basic Item Tooltip

Equipment Tooltip with Bonuses

Spell Tooltip with Rune Costs

Integration with CursorTooltip

The style utilities are designed to work with the CursorTooltip component:

Performance Considerations

Hover State Management

Each tooltip-enabled component manages its own hover state:
Important: onMouseMove fires at 60+ Hz, creating a new object on every event. For performance-critical components (e.g., bank slots with hundreds of items):
  1. Throttle position updates: Only update when position changes by >2px
  2. Lift state to parent: Parent manages hover state, children call onHoverStart/onHoverMove/onHoverEnd
  3. Use React.memo: Wrap slot components to prevent unnecessary re-renders
Example (lifted state pattern):

Migration Guide

From Inline Styles

Before:
After:

From Custom Tooltip Components

Before:
After:

Panels Using Unified Tooltips

The following panels have been migrated to use the unified tooltip system:
  • ActionBarPanel - Action bar slots and rubbish bin
  • ActionPanel - Draggable action slots
  • BankPanel - Bank items, tabs, and equipment sidebar
  • EquipmentPanel - Equipment slots and paperdoll
  • InventoryPanel - Inventory slots and coin pouch
  • LootWindowPanel - Loot items
  • PrayerPanel - Prayer icons and descriptions
  • SkillsPanel - Skill icons and XP progress
  • SpellsPanel - Spell icons and rune costs
  • StorePanel - Store items
  • TradePanel - Trade slots and inventory items

Customization

Adding New Tone Colors

To add a new tone (e.g., “info”), update getToneColors():

Extending Style Functions

To add new style utilities, follow the existing pattern:

Best Practices

1. Use Semantic Style Functions

Choose the style function that matches the content’s semantic meaning:

2. Avoid Redundant Spreads

When the style function is the only property source, use it directly:

3. Combine Styles Appropriately

When combining with custom styles, spread the utility function first:

4. Use Consistent Spacing

Follow the established spacing patterns:

Troubleshooting

Tooltip styles not applying: Cause: Theme not passed correctly or style function not imported. Fix: Verify imports and theme access:
Inconsistent tooltip appearance across panels: Cause: Panel using custom inline styles instead of utility functions. Fix: Replace inline styles with utility functions:
Performance issues with many tooltips: Cause: Each slot managing its own hover state causes excessive re-renders. Fix: Lift hover state to parent component (see Performance Considerations).

See Also

  • packages/client/src/ui/core/tooltip/CursorTooltip.tsx - Tooltip component
  • packages/client/src/ui/theme/themes.ts - Theme definitions
  • packages/client/src/game/panels/ - Panel implementations using unified tooltips