Saltar al contenido
VEXA
Overlays

Tooltip

Hoja cliente

A brief, supplementary label revealed on hover or focus.

Vista previa en vivo

Renderizado desde el código fuente instalado de VEXA — los mismos archivos que recibes.

Escritorio

Instalación

Añade el código del componente a tu proyecto. Las dependencias del registry se resuelven automáticamente.

npx shadcn@latest add https://vexa.valfiguer.com/r/tooltip.json

Se instala en components/vexa/tooltip.tsx

Dependencias npm

  • @radix-ui/react-tooltip

Dependencias del registry

  • @vexa/utils

Otros items de VEXA que necesita este componente. Instálalos primero — la CLI los resuelve automáticamente.

Código

Cópialo a su ruta destino, o instálalo con el comando de arriba.

components/vexa/tooltip.tsx
"use client";

import type * as React from "react";
import * as TooltipPrimitive from "@radix-ui/react-tooltip";

import { cn } from "@/lib/utils";

/**
 * Tooltip — a brief, supplementary label revealed on hover or focus.
 *
 * Client leaf. Wrap your app (or a subtree) in a single `TooltipProvider`.
 * Radix reveals the tooltip on both pointer hover and keyboard focus and hides
 * it on Escape, per APG. A tooltip must only enhance an already-labelled
 * control — never use it as the sole accessible name of an interactive element,
 * and never place interactive content inside it.
 */
export function TooltipProvider({
  delayDuration = 200,
  ...props
}: React.ComponentProps<typeof TooltipPrimitive.Provider>) {
  return (
    <TooltipPrimitive.Provider
      data-slot="tooltip-provider"
      delayDuration={delayDuration}
      {...props}
    />
  );
}

export function Tooltip(
  props: React.ComponentProps<typeof TooltipPrimitive.Root>,
) {
  return <TooltipPrimitive.Root data-slot="tooltip" {...props} />;
}

export function TooltipTrigger(
  props: React.ComponentProps<typeof TooltipPrimitive.Trigger>,
) {
  return <TooltipPrimitive.Trigger data-slot="tooltip-trigger" {...props} />;
}

export function TooltipContent({
  className,
  sideOffset = 6,
  children,
  ...props
}: React.ComponentProps<typeof TooltipPrimitive.Content>) {
  return (
    <TooltipPrimitive.Portal>
      <TooltipPrimitive.Content
        data-slot="tooltip-content"
        sideOffset={sideOffset}
        className={cn(
          "z-50 max-w-xs rounded-vexa-sm bg-vexa-primary px-2.5 py-1.5 text-xs font-medium text-vexa-primary-foreground shadow-vexa-md",
          "transition-opacity duration-[var(--vexa-duration-fast)] ease-[var(--vexa-ease-standard)] motion-reduce:transition-none",
          "data-[state=closed]:opacity-0 data-[state=delayed-open]:opacity-100 data-[state=instant-open]:opacity-100",
          className,
        )}
        {...props}
      >
        {children}
        <TooltipPrimitive.Arrow className="fill-vexa-primary" />
      </TooltipPrimitive.Content>
    </TooltipPrimitive.Portal>
  );
}
JSON del registryr/tooltip.json
r/tooltip.json
{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "tooltip",
  "type": "registry:ui",
  "title": "Tooltip",
  "description": "A brief, supplementary label revealed on hover or focus.",
  "dependencies": [
    "@radix-ui/react-tooltip"
  ],
  "registryDependencies": [
    "@vexa/utils"
  ],
  "files": [
    {
      "path": "registry/default/ui/tooltip.tsx",
      "type": "registry:ui",
      "target": "components/vexa/tooltip.tsx",
      "content": "\"use client\";\n\nimport type * as React from \"react\";\nimport * as TooltipPrimitive from \"@radix-ui/react-tooltip\";\n\nimport { cn } from \"@/lib/utils\";\n\n/**\n * Tooltip — a brief, supplementary label revealed on hover or focus.\n *\n * Client leaf. Wrap your app (or a subtree) in a single `TooltipProvider`.\n * Radix reveals the tooltip on both pointer hover and keyboard focus and hides\n * it on Escape, per APG. A tooltip must only enhance an already-labelled\n * control — never use it as the sole accessible name of an interactive element,\n * and never place interactive content inside it.\n */\nexport function TooltipProvider({\n  delayDuration = 200,\n  ...props\n}: React.ComponentProps<typeof TooltipPrimitive.Provider>) {\n  return (\n    <TooltipPrimitive.Provider\n      data-slot=\"tooltip-provider\"\n      delayDuration={delayDuration}\n      {...props}\n    />\n  );\n}\n\nexport function Tooltip(\n  props: React.ComponentProps<typeof TooltipPrimitive.Root>,\n) {\n  return <TooltipPrimitive.Root data-slot=\"tooltip\" {...props} />;\n}\n\nexport function TooltipTrigger(\n  props: React.ComponentProps<typeof TooltipPrimitive.Trigger>,\n) {\n  return <TooltipPrimitive.Trigger data-slot=\"tooltip-trigger\" {...props} />;\n}\n\nexport function TooltipContent({\n  className,\n  sideOffset = 6,\n  children,\n  ...props\n}: React.ComponentProps<typeof TooltipPrimitive.Content>) {\n  return (\n    <TooltipPrimitive.Portal>\n      <TooltipPrimitive.Content\n        data-slot=\"tooltip-content\"\n        sideOffset={sideOffset}\n        className={cn(\n          \"z-50 max-w-xs rounded-vexa-sm bg-vexa-primary px-2.5 py-1.5 text-xs font-medium text-vexa-primary-foreground shadow-vexa-md\",\n          \"transition-opacity duration-[var(--vexa-duration-fast)] ease-[var(--vexa-ease-standard)] motion-reduce:transition-none\",\n          \"data-[state=closed]:opacity-0 data-[state=delayed-open]:opacity-100 data-[state=instant-open]:opacity-100\",\n          className,\n        )}\n        {...props}\n      >\n        {children}\n        <TooltipPrimitive.Arrow className=\"fill-vexa-primary\" />\n      </TooltipPrimitive.Content>\n    </TooltipPrimitive.Portal>\n  );\n}\n"
    }
  ],
  "meta": {
    "frameworks": [
      "react",
      "next"
    ],
    "rsc": "client",
    "exports": [
      "TooltipProvider",
      "Tooltip",
      "TooltipTrigger",
      "TooltipContent"
    ],
    "cssVars": [
      "--vexa-primary",
      "--vexa-primary-foreground"
    ],
    "a11y": "Reveals on hover AND keyboard focus and hides on Escape. Only enhances an already-labelled control — never the sole accessible name, and no interactive content inside. Wrap a subtree in one TooltipProvider.",
    "example": "<TooltipProvider><Tooltip><TooltipTrigger asChild><IconButton aria-label=\"Info\"><InfoIcon /></IconButton></TooltipTrigger><TooltipContent>More details</TooltipContent></Tooltip></TooltipProvider>",
    "tests": "planned — see docs/README.md#roadmap"
  }
}

Detalles

Accesibilidad

Reveals on hover AND keyboard focus and hides on Escape. Only enhances an already-labelled control — never the sole accessible name, and no interactive content inside. Wrap a subtree in one TooltipProvider.

Uso

A brief text hint that enhances an already-labelled control on hover or focus.

Anatomía

TooltipProvider
Wrap a subtree once to share timing.
Tooltip
Root; owns the open state.
TooltipTrigger
The control the tooltip describes.
TooltipContent
The hint text.

Accesibilidad

role=tooltip — supplementary only; never the sole accessible name.

Teclado

TeclaAcción
EscapeHide the tooltip

Foco: Reveals on hover AND keyboard focus; hides on Escape.

  • Content on hover/focus must be dismissible, hoverable and persistent (WCAG 1.4.13). No interactive content inside.

Buenas prácticas

Recomendado

  • Wrap the subtree once in a TooltipProvider.
  • Use it to add non-essential detail.
  • Trigger it from a control that already has a label.

Evitar

  • Don't put links or buttons inside a tooltip.
  • Don't use it as a control's only label.
  • Don't hide essential information behind hover only.
Editar esta página

¿Te ha resultado útil esta página?

Guardado localmente en este navegador. Sin cuenta ni servidor.