Menu

Change language

GitHub repo

Tooltip

tooltipui

Small popover triggered by hover/focus, used for short labels — icon-button names, abbreviation expansions, keyboard shortcuts. Auto-positions and respects `prefers-reduced-motion`.

Installation

$npx shadcn-svelte@latest add https://uipkge.dev/r/svelte/tooltip.json
Manifest:https://uipkge.dev/r/svelte/tooltip.jsonInstalls to:src/lib/components/ui/tooltip/

Examples

Loading interactive previews…

Props

NameType / ValuesDefaultRequired
open

Controlled open state. Bind it for two-way updates.

boolean—optional
defaultOpen

Initial open state for uncontrolled use.

booleanfalseoptional
onOpenChange

Called whenever the open state changes.

(open: boolean) => void—optional
class

trigger child is full-width, like a sidebar menu button).

string—optional
childrenSnippet—optional

Used by

Files installed (6)

  • src/lib/components/ui/tooltip/Tooltip.svelte1.7 kB
    <script lang="ts" module>
      import type { Snippet } from 'svelte'
    
      export interface TooltipProps {
        /** Controlled open state. Bind it for two-way updates. */
        open?: boolean
        /** Initial open state for uncontrolled use. */
        defaultOpen?: boolean
        /** Called whenever the open state changes. */
        onOpenChange?: (open: boolean) => void
        /** Extra classes for the positioning wrapper (e.g. `w-full` when the
         *  trigger child is full-width, like a sidebar menu button). */
        class?: string
        children?: Snippet
      }
    </script>
    
    <script lang="ts">
      import { untrack } from 'svelte'
      import { cn } from '$lib/utils'
      import { TooltipRootState, getTooltipProviderState, setTooltipRootState } from './context.svelte'
    
      let { defaultOpen = false, open = $bindable(defaultOpen), onOpenChange, class: className, children }: TooltipProps = $props()
    
      const root = new TooltipRootState()
      root.provider = getTooltipProviderState()
      root.onOpenChange = (next) => {
        open = next
        onOpenChange?.(next)
      }
      setTooltipRootState(root)
    
      // Controlled mode: reflect the bound value. Untracked so internal
      // trigger/content updates (which already write through to `open`) don't
      // ping-pong back into the root.
      $effect(() => {
        const next = open
        untrack(() => {
          if (next !== root.open) root.setOpen(next)
        })
      })
    </script>
    
    <!-- Relative anchor for the absolutely-positioned content (no portal: the
         hand-rolled content renders inline and positions against this box). -->
    <span data-uipkge="" data-slot="tooltip" data-state={root.open ? 'open' : 'closed'} class={cn('relative inline-block', className)}>
      {@render children?.()}
    </span>
    
  • src/lib/components/ui/tooltip/TooltipContent.svelte3.8 kB
  • src/lib/components/ui/tooltip/TooltipProvider.svelte0.8 kB
  • src/lib/components/ui/tooltip/TooltipTrigger.svelte2.5 kB
  • src/lib/components/ui/tooltip/context.svelte.ts2 kB
  • src/lib/components/ui/tooltip/index.ts0.3 kB

Raw manifest:https://uipkge.dev/r/svelte/tooltip.json