Tooltip

Tooltip — это всплывающая подсказка, которая отображается при наведении на элемент или взаимодействии с ним, предоставляя дополнительную информацию пользователю. В SvelteKit работа с tooltip становится гибкой и удобной благодаря реактивной модели и компонентной архитектуре.

Основные принципы работы

В SvelteKit tooltip обычно реализуется как отдельный компонент, который управляет своим состоянием видимости через реактивные переменные или store. Ключевое отличие от традиционных библиотек — возможность легко связывать tooltip с любым DOM-элементом через binding и actions.

Пример базовой структуры компонента Tooltip:

<script>
  import { onMount } from 'svelte';
  export let text = '';
  let visible = false;

  function show() {
    visible = true;
  }

  function hide() {
    visible = false;
  }
</script>

<div on:mouseenter={show} on:mouseleave={hide} class="tooltip-container">
  <slot></slot>
  {#if visible}
    <div class="tooltip-content">{text}</div>
  {/if}
</div>

<style>
  .tooltip-container { position: relative; display: inline-block; }
  .tooltip-content {
    position: absolute;
    bottom: 100%;
    left: 50%;
    transform: translateX(-50%);
    background-color: #333;
    color: #fff;
    padding: 6px 12px;
    border-radius: 4px;
    white-space: nowrap;
    font-size: 0.875rem;
    z-index: 1000;
    opacity: 0.9;
  }
</style>

Связывание с DOM через actions

SvelteKit actions позволяют управлять tooltip без создания лишних обёрток. Это особенно полезно для динамически создаваемых элементов.

<script>
  import { tooltip } from './tooltipAction.js';
</script>

<button use:tooltip={'Нажмите для сохранения'}>Сохранить</button>

tooltipAction.js может выглядеть так:

export function tooltip(node, text) {
  let tooltipEl;

  function mouseEnter() {
    tooltipEl = document.createElement('div');
    tooltipEl.textContent = text;
    tooltipEl.className = 'tooltip-content';
    node.appendChild(tooltipEl);
    const rect = node.getBoundingClientRect();
    tooltipEl.style.position = 'absolute';
    tooltipEl.style.top = `${rect.top - tooltipEl.offsetHeight}px`;
    tooltipEl.style.left = `${rect.left + rect.width / 2 - tooltipEl.offsetWidth / 2}px`;
  }

  function mouseLeave() {
    tooltipEl?.remove();
    tooltipEl = null;
  }

  node.addEventListener('mouseenter', mouseEnter);
  node.addEventListener('mouseleave', mouseLeave);

  return {
    destroy() {
      node.removeEventListener('mouseenter', mouseEnter);
      node.removeEventListener('mouseleave', mouseLeave);
    }
  };
}

Позиционирование и адаптивность

Tooltip должен правильно адаптироваться к положению окна и размеру элемента. Для этого часто используют реактивные вычисления координат и проверку границ viewport.

$: tooltipStyle = visible
  ? `top: ${elementRect.top - tooltipEl.offsetHeight}px; left: ${elementRect.left + elementRect.width / 2 - tooltipEl.offsetWidth / 2}px;`
  : '';

Можно использовать сторонние утилиты, например Popper.js, для более сложного позиционирования с поддержкой смещений, выравнивания по краям и автоматического изменения направления при выходе за границы экрана.

Анимации появления

SvelteKit обеспечивает плавные анимации через встроенные transitions. Для tooltip это особенно полезно, чтобы появление и исчезновение выглядело естественно:

<script>
  import { fade } from 'svelte/transition';
</script>

{#if visible}
  <div class="tooltip-content" transition:fade>{{text}}</div>
{/if}

Можно настраивать длительность и easing:

transition:fade={{ duration: 200, easing: cubicOut }}

Управление состоянием через store

Для глобальных tooltip, когда несколько элементов должны управляться централизованно, удобно использовать Svelte store:

import { writable } from 'svelte/store';
export const tooltipStore = writable({ text: '', visible: false, x: 0, y: 0 });

В компоненте можно подписываться на store и обновлять положение tooltip в реальном времени.

Дополнительные возможности

  • Интерактивные tooltip: содержимое может включать кнопки, ссылки и формы.
  • Динамический контент: tooltip может подгружать данные асинхронно.
  • Темизация: стили легко переключаются через CSS-переменные или props.
  • Мобильная поддержка: использование click или touchstart вместо hover для устройств с сенсорными экранами.

Рекомендации по производительности

  • Создавать tooltip только при наведении (ленивая генерация DOM).
  • Использовать position: fixed для улучшения производительности при скролле.
  • Минимизировать рендеринг сложного содержимого через условные блоки {#if}.

Tooltip в SvelteKit сочетает простоту реализации и гибкость настройки благодаря реактивности, компонентной архитектуре и возможностям actions и transitions. Это позволяет создавать как базовые, так и сложные динамические подсказки с минимальным количеством кода и высокой производительностью.